From 4c92f4e0705e173adf3d6ced229bcd25ce0931c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BE=99=E5=A4=A7?= Date: Thu, 16 Apr 2026 14:27:41 +0800 Subject: [PATCH] =?UTF-8?q?v1.2.100=20-=20=E6=80=A7=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=B8=8E=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=20-=20=E4=BF=AE=E5=A4=8D=E8=97=8F=E5=93=81=E5=88=97=E8=A1=A8N+?= =?UTF-8?q?1=E6=9F=A5=E8=AF=A2=E9=97=AE=E9=A2=98=EF=BC=88=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E9=A2=84=E5=8A=A0=E8=BD=BD=EF=BC=89=20-=20Stats=20API?= =?UTF-8?q?=E6=94=B9=E7=94=A8SQL=E8=81=9A=E5=90=88=E6=9F=A5=E8=AF=A2=20-?= =?UTF-8?q?=20=E6=96=B0=E5=A2=9E=E6=88=90=E4=BA=A4=E8=A1=8C=E6=83=85?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E6=B1=87=E6=80=BBAPI=20-=20Cookie=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=94=AF=E6=8C=81=EF=BC=88=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?webview=E5=85=BC=E5=AE=B9=EF=BC=89=20-=20=E5=AF=BB=E9=85=8D?= =?UTF-8?q?=E5=8F=B7=E7=BD=91=E7=BB=9C=E5=8C=B9=E9=85=8D=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E5=88=B0=E6=89=80=E6=9C=89=E8=97=8F=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION | 1 + backend/.dockerignore | 9 + backend/.env.example | 26 + backend/Dockerfile | 25 + backend/README.md | 42 + backend/VERSION | 1 + backend/app/core/__init__.py | 0 backend/app/core/auth.py | 89 + backend/app/core/coolbot_db.py | 37 + backend/app/core/database.py | 69 + backend/app/core/error_handler.py | 174 ++ backend/app/core/logging_config.py | 113 + backend/app/main.py | 115 + backend/app/middleware/logging.py | 88 + backend/app/models/__init__.py | 0 backend/app/models/deal_info.py | 54 + backend/app/models/models.py | 268 +++ backend/app/models/seek_info.py | 39 + backend/app/routers/__init__.py | 0 backend/app/routers/auth.py | 254 ++ backend/app/routers/collections.py | 887 +++++++ backend/app/routers/deal.py | 302 +++ backend/app/routers/information.py | 1066 +++++++++ backend/app/routers/information.py.bak | 1065 ++++++++ backend/app/routers/news.py | 128 + backend/app/routers/ocr.py | 384 +++ backend/app/routers/operations.py | 104 + backend/app/routers/seek.py | 189 ++ backend/app/routers/users.py | 305 +++ backend/app/routers/yichens.py | 377 +++ backend/app/schemas/__init__.py | 0 backend/app/schemas/schemas.py | 231 ++ backend/app/services/oss.py | 126 + backend/app/services/sms.py | 106 + backend/app/utils/number_category.py | 132 + backend/logs/app.log | 47 + backend/requirements.txt | 13 + backend/uploads/.gitkeep | 0 frontend/README.md | 47 + frontend/VERSION | 1 + frontend/index.html | 31 + frontend/package-lock.json | 2132 +++++++++++++++++ frontend/package.json | 21 + frontend/package.txt | 1 + frontend/postbuild.js | 20 + frontend/public/images/jiachenlong-logo.png | Bin 0 -> 136602 bytes frontend/public/images/title_logo.svg | 26 + .../public/static/icons/apple-touch-icon.png | Bin 0 -> 136602 bytes frontend/public/static/icons/favicon.ico | 0 frontend/public/static/icons/favicon.png | Bin 0 -> 136602 bytes .../public/static/images/jiachenlong-logo.png | Bin 0 -> 136602 bytes frontend/public/user_agreement.html | 115 + frontend/src/App.jsx | 115 + frontend/src/config/version.js | 1 + frontend/src/index.css | 1 + frontend/src/main.jsx | 23 + frontend/src/pages/Add.jsx | 1083 +++++++++ frontend/src/pages/Admin.jsx | 590 +++++ frontend/src/pages/Detail.jsx | 388 +++ frontend/src/pages/Edit.jsx | 491 ++++ frontend/src/pages/Home.jsx | 501 ++++ frontend/src/pages/List.jsx | 948 ++++++++ frontend/src/pages/Login.jsx | 695 ++++++ frontend/src/pages/News.jsx | 1244 ++++++++++ frontend/src/pages/News_YichensBoard.jsx | 218 ++ frontend/src/pages/Settings.jsx | 434 ++++ frontend/src/pages/Stats.jsx | 292 +++ frontend/src/pages/YichensBoard.jsx | 255 ++ frontend/src/pages/news.py | 128 + frontend/src/utils/api.js | 267 +++ frontend/src/utils/errorCodes.js | 165 ++ frontend/src/utils/numberCategory.js | 129 + frontend/static/images/.gitkeep | 0 frontend/static/images/LOGO_GUIDE.md | 240 ++ frontend/static/images/README.md | 36 + frontend/static/images/jiachenlong-logo.png | Bin 0 -> 136602 bytes frontend/static/images/title_logo.svg | 26 + frontend/vite.config.js | 59 + 78 files changed, 17589 insertions(+) create mode 100644 VERSION create mode 100644 backend/.dockerignore create mode 100644 backend/.env.example create mode 100644 backend/Dockerfile create mode 100644 backend/README.md create mode 100644 backend/VERSION create mode 100644 backend/app/core/__init__.py create mode 100644 backend/app/core/auth.py create mode 100644 backend/app/core/coolbot_db.py create mode 100644 backend/app/core/database.py create mode 100644 backend/app/core/error_handler.py create mode 100644 backend/app/core/logging_config.py create mode 100644 backend/app/main.py create mode 100644 backend/app/middleware/logging.py create mode 100644 backend/app/models/__init__.py create mode 100644 backend/app/models/deal_info.py create mode 100644 backend/app/models/models.py create mode 100644 backend/app/models/seek_info.py create mode 100644 backend/app/routers/__init__.py create mode 100644 backend/app/routers/auth.py create mode 100644 backend/app/routers/collections.py create mode 100644 backend/app/routers/deal.py create mode 100644 backend/app/routers/information.py create mode 100644 backend/app/routers/information.py.bak create mode 100644 backend/app/routers/news.py create mode 100644 backend/app/routers/ocr.py create mode 100644 backend/app/routers/operations.py create mode 100644 backend/app/routers/seek.py create mode 100644 backend/app/routers/users.py create mode 100644 backend/app/routers/yichens.py create mode 100644 backend/app/schemas/__init__.py create mode 100644 backend/app/schemas/schemas.py create mode 100644 backend/app/services/oss.py create mode 100644 backend/app/services/sms.py create mode 100644 backend/app/utils/number_category.py create mode 100644 backend/logs/app.log create mode 100644 backend/requirements.txt create mode 100644 backend/uploads/.gitkeep create mode 100644 frontend/README.md create mode 100644 frontend/VERSION create mode 100644 frontend/index.html create mode 100644 frontend/package-lock.json create mode 100644 frontend/package.json create mode 100644 frontend/package.txt create mode 100644 frontend/postbuild.js create mode 100644 frontend/public/images/jiachenlong-logo.png create mode 100644 frontend/public/images/title_logo.svg create mode 100644 frontend/public/static/icons/apple-touch-icon.png create mode 100644 frontend/public/static/icons/favicon.ico create mode 100644 frontend/public/static/icons/favicon.png create mode 100644 frontend/public/static/images/jiachenlong-logo.png create mode 100644 frontend/public/user_agreement.html create mode 100644 frontend/src/App.jsx create mode 100644 frontend/src/config/version.js create mode 100644 frontend/src/index.css create mode 100644 frontend/src/main.jsx create mode 100644 frontend/src/pages/Add.jsx create mode 100644 frontend/src/pages/Admin.jsx create mode 100644 frontend/src/pages/Detail.jsx create mode 100644 frontend/src/pages/Edit.jsx create mode 100644 frontend/src/pages/Home.jsx create mode 100644 frontend/src/pages/List.jsx create mode 100644 frontend/src/pages/Login.jsx create mode 100644 frontend/src/pages/News.jsx create mode 100644 frontend/src/pages/News_YichensBoard.jsx create mode 100644 frontend/src/pages/Settings.jsx create mode 100644 frontend/src/pages/Stats.jsx create mode 100644 frontend/src/pages/YichensBoard.jsx create mode 100644 frontend/src/pages/news.py create mode 100644 frontend/src/utils/api.js create mode 100644 frontend/src/utils/errorCodes.js create mode 100644 frontend/src/utils/numberCategory.js create mode 100644 frontend/static/images/.gitkeep create mode 100644 frontend/static/images/LOGO_GUIDE.md create mode 100644 frontend/static/images/README.md create mode 100644 frontend/static/images/jiachenlong-logo.png create mode 100644 frontend/static/images/title_logo.svg create mode 100644 frontend/vite.config.js diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..85de19b --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.2.100 diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..73f416f --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,9 @@ +__pycache__/ +*.pyc +*.pyo +.git +.env +uploads/* +!uploads/.gitkeep +logs/* +*.log diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..9f5443e --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,26 @@ +# 数据库配置 +DATABASE_URL=postgresql://postgres:postgres@localhost:5432/zodiac + +# JWT配置 +SECRET_KEY=your-production-secret-key-change-this +ACCESS_TOKEN_EXPIRE_MINUTES=60 + +# 阿里云 DashScope OCR API(必须配置!) +DASHSCOPE_API_KEY=sk-9389024a37da4f7bb455ac9a6b28776f + +# 阿里云 OSS配置 +OSS_ACCESS_KEY_ID=LTAI5t6HUnpFBLEK9194kPVG +OSS_ACCESS_KEY_SECRET=LEr4Q8yRxb8D5b24cKfCwlt4MMoke1 +OSS_BUCKET_NAME=jiachenlong-oss +OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com +OSS_PUBLIC_URL=https://jiachenlong-oss.oss-cn-hangzhou.aliyuncs.com + +# 阿里云短信配置(必须配置!) +SMS_ACCESS_KEY_ID=LTAI5tQAx5niD7JQVqGE5acE +SMS_ACCESS_KEY_SECRET=QsQFAEKBkaNynIoKyvdIi3BUyWVZu1 +SMS_SIGN_NAME=苏州算力 +SMS_TEMPLATE_CODE=SMS_501590956 + +# 服务配置 +PORT=3000 +HOST=0.0.0.0 diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..f4c2a67 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,25 @@ +# FastAPI 后端 Docker 镜像 +FROM python:3.12-slim + +WORKDIR /app + +# 安装系统依赖 +RUN apt-get update && apt-get install -y \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# 安装 Python 依赖 +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# 复制应用代码 +COPY . . + +# 创建上传目录 +RUN mkdir -p uploads + +# 暴露端口 +EXPOSE 3000 + +# 启动命令 +CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "3000"] diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..834be5c --- /dev/null +++ b/backend/README.md @@ -0,0 +1,42 @@ +# 后端服务 - FastAPI + +## 启动方式 + +### 开发环境 + +```bash +# 安装依赖 +pip install -r requirements.txt + +# 启动服务 +python -m uvicorn app.main:app --port 3000 --host 0.0.0.0 --reload +``` + +### 生产环境 + +```bash +# 后台运行 +nohup python -m uvicorn app.main:app --port 3000 --host 0.0.0.0 > /tmp/uvicorn.log 2>&1 & + +# 或使用 systemd +sudo systemctl start zodiac-backend +``` + +## 配置说明 + +编辑 `.env` 文件: + +```ini +# 数据库 +DATABASE_URL=postgresql://postgres:密码@localhost:5432/zodiac + +# JWT +SECRET_KEY=你的密钥 + +# OCR API +DASHSCOPE_API_KEY=sk-你的密钥 +``` + +## API 文档 + +启动后访问:http://localhost:3000/docs diff --git a/backend/VERSION b/backend/VERSION new file mode 100644 index 0000000..85de19b --- /dev/null +++ b/backend/VERSION @@ -0,0 +1 @@ +1.2.100 diff --git a/backend/app/core/__init__.py b/backend/app/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/core/auth.py b/backend/app/core/auth.py new file mode 100644 index 0000000..2fe7a71 --- /dev/null +++ b/backend/app/core/auth.py @@ -0,0 +1,89 @@ +# 认证模块 +import os +import bcrypt +from datetime import datetime, timedelta +from typing import Optional +from fastapi import Depends, HTTPException, status +from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials +from jose import JWTError, jwt +from sqlalchemy.orm import Session +from app.core.database import SessionLocal +from app.models.models import User + +# 配置 +SECRET_KEY = os.getenv("SECRET_KEY") +if not SECRET_KEY: + raise ValueError("SECRET_KEY environment variable is not set. Please configure it in production!") +ALGORITHM = "HS256" +ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "10080")) # 7天 + +# HTTP Bearer 认证 +security = HTTPBearer(auto_error=False) + + +def verify_password(plain_password: str, hashed_password: str) -> bool: + """验证密码""" + try: + return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password.encode('utf-8')) + except Exception: + return False + + +def get_password_hash(password: str) -> str: + """生成密码哈希""" + return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') + + +def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str: + """创建访问令牌""" + to_encode = data.copy() + if expires_delta: + expire = datetime.utcnow() + expires_delta + else: + expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) + + to_encode.update({"exp": expire}) + encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) + return encoded_jwt + + +def decode_access_token(token: str) -> Optional[dict]: + """解码访问令牌""" + try: + payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) + return payload + except JWTError: + return None + + +def get_current_user( + credentials: Optional[HTTPAuthorizationCredentials] = Depends(security), + db: Session = Depends(lambda: SessionLocal()) +) -> Optional[User]: + """获取当前用户(可返回None)""" + if not credentials: + return None + + token = credentials.credentials + payload = decode_access_token(token) + + if not payload: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="无效的令牌", + headers={"WWW-Authenticate": "Bearer"}, + ) + + user_id: str = payload.get("sub") + if not user_id: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="无效的令牌", + headers={"WWW-Authenticate": "Bearer"}, + ) + + user = db.query(User).filter(User.f99_90_id == user_id).first() + if not user: + return None + + return user diff --git a/backend/app/core/coolbot_db.py b/backend/app/core/coolbot_db.py new file mode 100644 index 0000000..a0b9014 --- /dev/null +++ b/backend/app/core/coolbot_db.py @@ -0,0 +1,37 @@ +import os +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from sqlalchemy.pool import QueuePool + +COOLBOT_DB_URL = os.getenv( + "COOLBOT_DB_URL", + "postgresql://coolbot:Coolbot123@pgm-bp1t1008h019ez6cno.pg.rds.aliyuncs.com:5432/coolbot_data" +) + +coolbot_engine = create_engine( + COOLBOT_DB_URL, + poolclass=QueuePool, + pool_size=10, + max_overflow=20, + pool_timeout=30, + pool_recycle=1800, + pool_pre_ping=True, + echo=False, + connect_args={ + "connect_timeout": 10, + "application_name": "zodiac-coolbot" + } +) + +CoolbotSession = sessionmaker(autocommit=False, autoflush=False, bind=coolbot_engine) + +def get_coolbot_db(): + """获取coolbot数据库会话""" + db = CoolbotSession() + try: + yield db + except Exception: + db.rollback() + raise + finally: + db.close() diff --git a/backend/app/core/database.py b/backend/app/core/database.py new file mode 100644 index 0000000..8683b0b --- /dev/null +++ b/backend/app/core/database.py @@ -0,0 +1,69 @@ +import os +import time +from sqlalchemy import create_engine, event +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker +from sqlalchemy.pool import QueuePool +from typing import Generator +import logging + +logger = logging.getLogger(__name__) + +DATABASE_URL = os.getenv( + "DATABASE_URL", + "postgresql://postgres:postgres@127.0.0.1:5432/zodiac" +) + +# 增强版数据库引擎配置 +engine = create_engine( + DATABASE_URL, + # 连接池配置 + poolclass=QueuePool, + pool_size=20, # 常规连接数 + max_overflow=40, # 允许超出的连接数(高并发时) + pool_timeout=30, # 获取连接超时时间(秒) + pool_recycle=1800, # 连接回收时间(30分钟),避免连接过期 + pool_pre_ping=True, # 每次获取连接前检查连接是否有效 + echo=False, + # 连接参数优化 + connect_args={ + "connect_timeout": 10, + "application_name": "zodiac-api", + "options": "-c statement_timeout=30000" # 查询超时30秒 + } +) + +# 添加连接事件监听器 +@event.listens_for(engine, "connect") +def set_connect_timeout(dbapi_conn, connection_record): + """设置连接参数""" + cursor = dbapi_conn.cursor() + cursor.execute("SET statement_timeout = 30000") + cursor.close() + +@event.listens_for(engine, "checkout") +def check_connection(dbapi_conn, connection_record, connection_proxy): + """检出连接时检查""" + try: + cursor = dbapi_conn.cursor() + cursor.execute("SELECT 1") + cursor.close() + except Exception as e: + logger.warning(f"连接检查失败: {e}") + raise Exception("数据库连接无效") + +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +Base = declarative_base() + +def get_db() -> Generator: + """获取数据库会话,带错误处理""" + db = SessionLocal(expire_on_commit=False) + try: + yield db + except Exception as e: + logger.error(f"数据库会话错误: {e}") + db.rollback() + raise + finally: + db.close() diff --git a/backend/app/core/error_handler.py b/backend/app/core/error_handler.py new file mode 100644 index 0000000..c3d29ca --- /dev/null +++ b/backend/app/core/error_handler.py @@ -0,0 +1,174 @@ +# 统一错误处理 +from fastapi import FastAPI, Request, HTTPException, status +from fastapi.responses import JSONResponse +from fastapi.exceptions import RequestValidationError +from pydantic import ValidationError +from app.core.logging_config import logger + +# 错误码定义 +ERROR_CODES = { + # 认证错误 (10-19) + 401: "E00010", # 未授权 + 403: "E00014", # 禁止访问 + + # 验证错误 (20-29) + 400: "E00000", # 请求错误 + 422: "E00000", # 验证错误 + + # 资源错误 (30-39) + 404: "E00033", # 资源不存在 + + # 服务器错误 (50-59) + 500: "E00003", # 服务器内部错误 +} + +# 错误信息映射 +ERROR_MESSAGES = { + "E00010": "未登录或登录已过期", + "E00011": "用户名或密码错误", + "E00012": "验证码错误", + "E00014": "无权访问此资源", + "E00015": "令牌无效或已过期", + "E00020": "请输入用户名和密码", + "E00021": "用户名至少 3 个字符", + "E00022": "密码至少 6 个字符", + "E00023": "用户名已存在", + "E00024": "邮箱已被注册", + "E00030": "藏品名称不能为空", + "E00031": "藏品名称至少 2 个字符", + "E00032": "藏品分类不能为空", + "E00033": "藏品不存在", + "E00034": "禁止重复:此冠字号已存在", + "E00035": "成本价格必须>=0", + "E00036": "目标价格必须>=0", + "E00037": "发行年份必须是 4 位数字", + "E00040": "请选择图片文件", + "E00041": "图片尺寸太小,无法识别", + "E00042": "OCR 识别失败,请重试", + "E00050": "仅管理员可访问", + "E00051": "用户不存在", + "E00000": "请求失败", + "E00001": "网络连接失败", + "E00003": "服务器内部错误", +} + +def setup_error_handlers(app: FastAPI): + """设置全局错误处理器""" + + @app.exception_handler(HTTPException) + async def http_exception_handler(request: Request, exc: HTTPException): + """处理 HTTP 异常""" + # 从 detail 中提取错误码 + detail = exc.detail + error_code = ERROR_CODES.get(exc.status_code, "E00000") + + # 如果 detail 已经包含错误码,直接使用 + if isinstance(detail, str) and detail.startswith("E"): + parts = detail.split(":", 1) + error_code = parts[0] + message = parts[1].strip() if len(parts) > 1 else ERROR_MESSAGES.get(error_code, detail) + else: + message = ERROR_MESSAGES.get(error_code, detail if isinstance(detail, str) else "请求失败") + + return JSONResponse( + status_code=exc.status_code, + content={ + "error": { + "code": error_code, + "message": message, + "status": exc.status_code + } + } + ) + + @app.exception_handler(RequestValidationError) + async def validation_exception_handler(request: Request, exc: RequestValidationError): + """处理请求验证错误""" + errors = exc.errors() + if errors: + error = errors[0] + field = ".".join(str(x) for x in error.get("loc", [])) + msg = error.get("msg", "验证失败") + + # 根据字段和消息匹配错误码 + # 先检查请求路径,区分用户接口和藏品接口 + path = request.url.path + + if "cost_price" in field or "价格" in msg: + error_code = "E00035" + message = "成本价格必须>=0" + elif "target_price" in field: + error_code = "E00036" + message = "目标价格必须>=0" + elif "issue_year" in field or "年份" in msg: + error_code = "E00037" + message = "发行年份必须是 4 位数字" + elif "name" in field: + # 根据路径区分用户 name 和藏品 name + if "/auth/" in path or "/users/" in path or "/admin/users/" in path: + error_code = "E00021" + message = "用户名至少 3 个字符" + else: + error_code = "E00031" + message = "藏品名称至少 2 个字符" + elif "category" in field: + error_code = "E00032" + message = "藏品分类不能为空" + else: + error_code = "E00000" + message = f"{field}: {msg}" + + return JSONResponse( + status_code=422, + content={ + "error": { + "code": error_code, + "message": message, + "status": 422, + "field": field + } + } + ) + + return JSONResponse( + status_code=422, + content={ + "error": { + "code": "E00000", + "message": "验证失败", + "status": 422 + } + } + ) + + @app.exception_handler(404) + async def not_found_handler(request: Request, exc: Exception): + """处理 404 错误""" + return JSONResponse( + status_code=404, + content={ + "error": { + "code": "E00033", + "message": "接口不存在", + "status": 404 + } + } + ) + + @app.exception_handler(Exception) + async def general_exception_handler(request: Request, exc: Exception): + """处理未捕获的异常""" + import traceback + error_trace = traceback.format_exc() + logger.error(f"未捕获异常:{str(exc)}\n{error_trace}") + + return JSONResponse( + status_code=500, + content={ + "error": { + "code": "E00003", + "message": "服务器内部错误", + "status": 500 + } + } + ) diff --git a/backend/app/core/logging_config.py b/backend/app/core/logging_config.py new file mode 100644 index 0000000..d5b2960 --- /dev/null +++ b/backend/app/core/logging_config.py @@ -0,0 +1,113 @@ +# 日志系统配置 +import logging +import json +import os +from datetime import datetime +from typing import Optional +import uuid +from logging.handlers import RotatingFileHandler + +class JSONFormatter(logging.Formatter): + """JSON 格式日志处理器""" + + def format(self, record): + log_data = { + 'timestamp': datetime.utcnow().isoformat() + 'Z', + 'level': record.levelname, + 'logger': record.name, + 'message': record.getMessage(), + 'trace_id': getattr(record, 'trace_id', str(uuid.uuid4())), + 'user_id': getattr(record, 'user_id', None), + 'request_id': getattr(record, 'request_id', str(uuid.uuid4())), + 'ip_address': getattr(record, 'ip_address', None), + 'duration_ms': getattr(record, 'duration_ms', None), + } + + # 添加额外字段 + if hasattr(record, 'data'): + log_data['data'] = record.data + + # 添加异常信息 + if record.exc_info: + log_data['exception'] = self.formatException(record.exc_info) + + return json.dumps(log_data, ensure_ascii=False, default=str) + + +def setup_logging( + log_file: str = 'logs/app.log', + level: str = 'INFO', + max_bytes: int = 10*1024*1024, # 10MB + backup_count: int = 5 +): + """配置日志系统""" + + # 创建日志目录 + os.makedirs(os.path.dirname(log_file), exist_ok=True) + + # 根日志器 + logger = logging.getLogger() + logger.setLevel(level) + + # 清空现有处理器 + logger.handlers.clear() + + # 文件处理器(带轮转) + file_handler = RotatingFileHandler( + log_file, + maxBytes=max_bytes, + backupCount=backup_count, + encoding='utf-8' + ) + file_handler.setFormatter(JSONFormatter()) + logger.addHandler(file_handler) + + # 控制台处理器(仅开发环境) + if os.getenv('ENV', 'development') == 'development': + console_handler = logging.StreamHandler() + console_handler.setFormatter(JSONFormatter()) + logger.addHandler(console_handler) + + return logger + + +# 创建日志器实例 +logger = setup_logging() + + +# 日志装饰器 +def log_operation(operation_name: str): + """记录操作日志的装饰器""" + def decorator(func): + import functools + @functools.wraps(func) + def wrapper(*args, **kwargs): + import time + start_time = time.time() + + try: + result = func(*args, **kwargs) + duration = (time.time() - start_time) * 1000 + + logger.info( + f"{operation_name} 成功", + extra={ + 'duration_ms': duration, + 'data': {'function': func.__name__} + } + ) + return result + + except Exception as e: + duration = (time.time() - start_time) * 1000 + logger.error( + f"{operation_name} 失败:{str(e)}", + extra={ + 'duration_ms': duration, + 'data': {'function': func.__name__, 'error': str(e)} + }, + exc_info=True + ) + raise + return wrapper + return decorator diff --git a/backend/app/main.py b/backend/app/main.py new file mode 100644 index 0000000..0587121 --- /dev/null +++ b/backend/app/main.py @@ -0,0 +1,115 @@ +# FastAPI 应用入口 +import os +from pathlib import Path +from dotenv import load_dotenv +load_dotenv() + +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from fastapi.staticfiles import StaticFiles + +from app.core.database import engine, Base +from app.core.logging_config import logger, setup_logging +from app.core.error_handler import setup_error_handlers +from app.middleware.logging import logging_middleware +from app.routers import auth, collections, operations +from app.routers import ocr as ocr_router +from app.routers import users as users_router +from app.routers import information as information_router +from app.routers import yichens as yichens_router +from app.routers import seek as seek_router +from app.routers import deal as deal_router + +# 版本信息 - 从 config/VERSION 文件读取 +def get_version(): + """从 config/VERSION 文件读取版本号""" + try: + version_file = Path(__file__).parent.parent.parent / "config" / "VERSION" + if version_file.exists(): + with open(version_file, 'r', encoding='utf-8') as f: + for line in f: + if line.startswith('VERSION='): + return line.strip().split('=', 1)[1] + except Exception as e: + logger.error(f"读取 VERSION 文件失败:{e}") + return "0.0.0" # 默认版本号 + +__version__ = get_version() +__app_name__ = "甲辰收藏系统 FastAPI 后端" + +# 启动时创建数据库表 +Base.metadata.create_all(bind=engine) + +# 初始化日志系统 +setup_logging() +logger.info(f"{__app_name__} v{__version__} 启动成功") + +# 创建 FastAPI 应用 +app = FastAPI( + title=__app_name__, + version=__version__, + description="生肖纪念钞收藏管理系统后端 API" +) + +# 设置全局错误处理器 +setup_error_handlers(app) + +# CORS 配置 - 生产环境限制域名 +ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS", "http://47.103.29.111,http://120.55.81.21,https://socoolbot.com").split(",") +app.add_middleware( + CORSMiddleware, + allow_origins=ALLOWED_ORIGINS, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# 挂载静态文件目录(图片上传和项目静态资源) +uploads_dir = "uploads" +os.makedirs(uploads_dir, exist_ok=True) +app.mount("/uploads", StaticFiles(directory=uploads_dir), name="uploads") + +# 挂载项目静态资源目录 +static_dir = Path(__file__).parent.parent / "static" +if static_dir.exists(): + app.mount("/static", StaticFiles(directory=str(static_dir)), name="static") + +# 添加日志中间件 +app.middleware("http")(logging_middleware) + +# 注册路由 +app.include_router(auth.router) +app.include_router(collections.router) +app.include_router(operations.router) +app.include_router(ocr_router.router) # OCR 识别 +app.include_router(users_router.router) # 当前用户接口 +app.include_router(users_router.admin_router) # 管理员用户管理 +app.include_router(information_router.router) +app.include_router(yichens_router.router) # 一尘看板 +app.include_router(seek_router.router) # 寻配号 +app.include_router(deal_router.router) # 成交行情 + + +@app.get("/") +def root(): + """根路径""" + return { + "name": __app_name__, + "version": __version__, + "status": "running" + } + + +@app.get("/health") +def health_check(): + """健康检查""" + return {"status": "healthy"} + + +if __name__ == "__main__": + import uvicorn + port = int(os.getenv("PORT", "3000")) + uvicorn.run(app, host="0.0.0.0", port=port) + +from app.routers import seek as seek_router +from app.routers import deal as deal_router diff --git a/backend/app/middleware/logging.py b/backend/app/middleware/logging.py new file mode 100644 index 0000000..684a55a --- /dev/null +++ b/backend/app/middleware/logging.py @@ -0,0 +1,88 @@ +# 请求日志中间件 - 优化版 +import time +import uuid +from fastapi import Request, Response +from app.core.logging_config import logger + + +async def logging_middleware(request: Request, call_next): + """记录所有 API 请求的日志 - 优化版""" + + # 生成请求 ID + request_id = str(uuid.uuid4()) + start_time = time.time() + + # 获取用户信息(如果已登录) + user_id = None + try: + auth_header = request.headers.get('Authorization', '') + if auth_header.startswith('Bearer '): + user_id = "authenticated" + except Exception as e: + # 静默失败,不影响主流程 + pass + + # 执行请求 + response_status = 500 + try: + response = await call_next(request) + response_status = response.status_code + except Exception as e: + duration = (time.time() - start_time) * 1000 + try: + logger.error( + f"API 请求异常:{request.method} {request.url.path}", + extra={ + 'request_id': request_id, + 'user_id': user_id, + 'ip_address': request.client.host if request.client else None, + 'duration_ms': duration, + 'data': { + 'method': request.method, + 'path': request.url.path, + 'query': str(request.query_params), + 'error': str(e) + } + }, + exc_info=True + ) + except: + pass # 日志记录失败不影响主流程 + raise + + # 记录响应 + duration = (time.time() - start_time) * 1000 + + try: + log_level = 'INFO' + if response_status >= 500: + log_level = 'ERROR' + elif response_status >= 400: + log_level = 'WARNING' + + getattr(logger, log_level)( + f"API 请求完成:{request.method} {request.url.path}", + extra={ + 'request_id': request_id, + 'user_id': user_id, + 'ip_address': request.client.host if request.client else None, + 'duration_ms': duration, + 'data': { + 'method': request.method, + 'path': request.url.path, + 'query': str(request.query_params), + 'status_code': response_status + } + } + ) + except Exception as e: + # 日志记录失败不影响主流程 + pass + + # 在响应头中添加请求 ID + try: + response.headers['X-Request-ID'] = request_id + except: + pass + + return response diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/models/deal_info.py b/backend/app/models/deal_info.py new file mode 100644 index 0000000..82e3206 --- /dev/null +++ b/backend/app/models/deal_info.py @@ -0,0 +1,54 @@ +from sqlalchemy import Column, String, Text, Float, Date, Boolean, Integer, DateTime +from sqlalchemy.sql import func +from app.core.database import Base +import uuid + +def generate_uuid(): + return str(uuid.uuid4()) + +class DealInfo(Base): + __tablename__ = "deal_info" + + id = Column(String(36), primary_key=True, default=generate_uuid) + user_id = Column(String(36), nullable=True, index=True) + + # 标题和内容 + title = Column(String(255), nullable=False) + content = Column(Text, nullable=True) + + # 成交信息 + deal_price = Column(Float, nullable=True) # 成交价格 + deal_date = Column(Date, nullable=True) # 成交日期 + deal_no = Column(String(20), nullable=True, index=True) # 行情编号(从A000001开始递增) + + # 包装和分类 + packaging = Column(String(50), nullable=True) # 包装(标百/标十/单张) + category = Column(String(100), nullable=True) # 分类 + + # 评级相关 + is_graded = Column(Boolean, default=False) # 是否评级 + grading_company = Column(String(100), nullable=True) # 评级机构 + grading_score = Column(String(50), nullable=True) # 评级分数 + + # 号码特征 + tail_number = Column(String(10), nullable=True) # 尾号 + size_type = Column(String(20), nullable=True) # 大小号 + + # 版别 + version = Column(String(50), nullable=True) # 版别 + + # 交易信息 + platform = Column(String(50), nullable=True) # 成交平台 + seller = Column(String(100), nullable=True) # 出售者 + buyer = Column(String(100), nullable=True) # 购买者 + + # 状态 + status = Column(String(20), default="active") + + # 统计 + view_count = Column(Integer, default=0) + contact_count = Column(Integer, default=0) + + # 时间 + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) \ No newline at end of file diff --git a/backend/app/models/models.py b/backend/app/models/models.py new file mode 100644 index 0000000..6ea0838 --- /dev/null +++ b/backend/app/models/models.py @@ -0,0 +1,268 @@ +# 数据库模型 - 使用字段编码 +from sqlalchemy import Column, String, Float, Boolean, DateTime, Integer, Text, ForeignKey, Date, UniqueConstraint +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func +from app.core.database import Base +import uuid + + +def generate_uuid(): + """生成 UUID 字符串""" + return str(uuid.uuid4()) + + +class User(Base): + __tablename__ = "users" + + # f99 系统字段 + f99_90_id = Column(String(36), primary_key=True, default=generate_uuid) + user_code = Column(String(10), unique=True, nullable=True, index=True) # 用户编码 + f99_91_user_id = Column(String(36), unique=True, nullable=False, index=True) + f01_01_name = Column(String(255), unique=True, nullable=False, index=True) # username + email = Column(String(255), unique=True, nullable=True, index=True) + phone = Column(String(50), nullable=True) + avatar = Column(String(500), nullable=True) + address = Column(String(500), nullable=True) + bio = Column(Text, nullable=True) + password = Column(String(255), nullable=False) + role = Column(String(50), default="user") + # 时间字段 + f99_92_created_at = Column(DateTime(timezone=True), server_default=func.now()) + f99_93_updated_at = Column(DateTime(timezone=True), onupdate=func.now()) + # 新增字段 + f99_94_level = Column(String(20), default="青铜") # 会员等级 + f99_95_ai_count = Column(Integer, default=0) # ai识别次数 + f99_96_search_count = Column(Integer, default=0) # 寻号使用次数 + f99_97_collection_count = Column(Integer, default=0) # 藏品数量 + f01_06_phone_verified = Column(Boolean, default=False) # 手机号已核验 + f99_98_login_count = Column(Integer, default=0) # 登录次数 + f99_99_last_login = Column(DateTime(timezone=True), nullable=True) # 最后登录时间 + f01_07_gender = Column(String(10), nullable=True) # 性别 + f01_08_birthday = Column(Date, nullable=True) # 生日 + f01_09_region = Column(String(100), nullable=True) # 地区 + f01_10_realname_verified = Column(Boolean, default=False) # 实名认证 + f99_100_points = Column(Integer, default=0) # 积分 + f01_11_balance = Column(Float, default=0) # 余额 + f01_12_total_amount = Column(Float, default=0) # 累计金额 + f01_13_invite_code = Column(String(20), nullable=True) # 邀请码(自己的邀请码) + f99_101_invited_count = Column(Integer, default=0) # 通过自己邀请码注册的用户数量 + + collections = relationship("Collection", back_populates="user", cascade="all, delete-orphan") + operations = relationship("Operation", back_populates="user", cascade="all, delete-orphan") + custom_fields = relationship("CustomField", back_populates="user", cascade="all, delete-orphan") + + +class Collection(Base): + __tablename__ = "collections" + + # f99 系统字段 + f99_90_id = Column(String(36), primary_key=True, default=generate_uuid) + f99_91_user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + f99_92_created_at = Column(DateTime(timezone=True), server_default=func.now(), index=True) + f99_93_updated_at = Column(DateTime(timezone=True), onupdate=func.now()) + + # f01 基本信息 + f01_01_name = Column(String(255), nullable=False) + f01_02_code = Column(String(50), nullable=True, index=True) + f01_03_category = Column(String(100), nullable=False, index=True) + f01_04_status = Column(String(50), default="in_collection", index=True) + f01_05_remark = Column(Text, nullable=True) + + # f02 详细字段 + f02_10_prefix_serial = Column(String(50), nullable=True, index=True) + f02_11_version = Column(String(100), nullable=True, index=True) + f02_12_packaging = Column(String(100), nullable=True, index=True) + f02_13_rarity = Column(String(50), nullable=True, index=True) # 珍惜度 + f02_14_number_category = Column(String(20), nullable=True, index=True) # 号码分类 + + # f03 评级信息 + f03_20_is_graded = Column(Boolean, default=False, index=True) + f03_21_grading_company = Column(String(100), nullable=True, index=True) + f03_22_grading_score = Column(String(20), nullable=True, index=True) + f03_23_three_star = Column(Boolean, default=False, index=True) + + # f04 特殊信息 + f04_30_special_mark = Column(String(200), nullable=True, index=True) + f04_31_serial_feature = Column(String(100), nullable=True, index=True) + f04_32_issuer = Column(String(100), nullable=True, index=True) + f04_33_issue_year = Column(String(20), nullable=True, index=True) + f04_34_material = Column(String(50), nullable=True) + f04_35_denomination = Column(String(20), nullable=True) + f04_36_issue_quantity = Column(String(50), nullable=True) + + # f05 价格信息 + f05_40_cost_price = Column(Float, nullable=True, index=True) + f05_41_target_price = Column(Float, nullable=True, index=True) + f05_42_goal_price = Column(Float, nullable=True) + f05_43_repair_fee = Column(Float, nullable=True) + f05_44_grading_fee = Column(Float, nullable=True) + + # f06 其他信息 + f06_50_purpose = Column(String(100), nullable=True) + + user = relationship("User", back_populates="collections") + images = relationship("CollectionImage", back_populates="collection", cascade="all, delete-orphan") + operations = relationship("Operation", back_populates="collection", cascade="all, delete-orphan") + + +class CollectionImage(Base): + __tablename__ = "collection_images" + + id = Column(String(36), primary_key=True, default=generate_uuid) + collection_id = Column(String(36), ForeignKey("collections.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + filename = Column(String(255), nullable=False) + original_name = Column(String(255), nullable=True) + path = Column(String(500), nullable=True) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + + collection = relationship("Collection", back_populates="images") + + +class Operation(Base): + __tablename__ = "operations" + + f99_90_id = Column(String(36), primary_key=True, default=generate_uuid) + f99_91_user_id = Column(String(36), ForeignKey("collections.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + f99_92_user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + type = Column(String(50), nullable=False, index=True) + price = Column(Float, nullable=True) + note = Column(Text, nullable=True) + f99_93_created_at = Column(DateTime(timezone=True), server_default=func.now(), index=True) + + collection = relationship("Collection", back_populates="operations") + user = relationship("User", back_populates="operations") + + +class CustomField(Base): + __tablename__ = "custom_fields" + + id = Column(String(36), primary_key=True, default=generate_uuid) + user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + name = Column(String(100), nullable=False) + field_type = Column(String(50), default="text") + options = Column(Text, nullable=True) + required = Column(Boolean, default=False) + visible = Column(Boolean, default=True) + sort_order = Column(Integer, default=0) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + + user = relationship("User", back_populates="custom_fields") + + +# 资讯模型 +class Information(Base): + __tablename__ = "information" + + id = Column(String(36), primary_key=True, default=generate_uuid) + user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + + # 信息类型: seek-寻配号, deal-成交数据, publish-发布 + info_type = Column(String(20), nullable=False, index=True) + + # 标题 + title = Column(String(255), nullable=False) + + # 内容描述 + content = Column(Text, nullable=True) + + # 关联藏品ID + collection_id = Column(String(36), ForeignKey("collections.f99_90_id", ondelete="SET NULL"), nullable=True) + + # 期望条件 (寻配号用) + expect_category = Column(String(100), nullable=True) # 期望类别 + expect_version = Column(String(100), nullable=True) # 期望版别 + expect_packaging = Column(String(100), nullable=True) # 期望包装 + expect_number = Column(String(50), nullable=True) # 期望号码 + expect_price_min = Column(Float, nullable=True) # 期望价格区间 + expect_price_max = Column(Float, nullable=True) + + # 成交价格 (成交数据用) + deal_price = Column(Float, nullable=True) + deal_date = Column(Date, nullable=True) + + # 评级相关字段 + packaging = Column(String(50), nullable=True) + is_graded = Column(Boolean, default=False) + grading_company = Column(String(100), nullable=True) + grading_score = Column(String(50), nullable=True) + category = Column(String(100), nullable=True) + + # 行情编号 + deal_no = Column(String(50), nullable=True, index=True) + + # 状态: active-有效, closed-已关闭, expired-已过期 + status = Column(String(20), default="active", index=True) + + # 匹配状态: pending-尚未匹配, matched-已经匹配 + is_matched = Column(String(20), default="pending", index=True) + + # 匹配的用户ID(当用户愿意交换联系方式时) + matched_user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="SET NULL"), nullable=True) + + # 匹配者的联系方式(只有发布者和匹配者可见) + matched_contact = Column(String(100), nullable=True) + + # 浏览/联系次数 + view_count = Column(Integer, default=0) + contact_count = Column(Integer, default=0) + + created_at = Column(DateTime(timezone=True), server_default=func.now(), index=True) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) + + user = relationship("User", foreign_keys=[user_id]) + collection = relationship("Collection") + + +# 资讯评论/留言 +class InformationComment(Base): + __tablename__ = "information_comments" + + id = Column(String(36), primary_key=True, default=generate_uuid) + information_id = Column(String(36), ForeignKey("information.id", ondelete="CASCADE"), nullable=False, index=True) + user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + content = Column(Text, nullable=False) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + + user = relationship("User", foreign_keys=[user_id]) + + +# 资讯联系方式查看记录 +class InformationContactView(Base): + __tablename__ = "information_contact_views" + + id = Column(String(36), primary_key=True, default=generate_uuid) + information_id = Column(String(36), ForeignKey("information.id", ondelete="CASCADE"), nullable=False, index=True) + viewer_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + + viewer = relationship("User", foreign_keys=[viewer_id]) + + +# 资讯关联用户 (收藏/点赞) +class InformationLike(Base): + __tablename__ = "information_likes" + + id = Column(String(36), primary_key=True, default=generate_uuid) + information_id = Column(String(36), ForeignKey("information.id", ondelete="CASCADE"), nullable=False, index=True) + user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + + __table_args__ = ( + UniqueConstraint('information_id', 'user_id', name='uq_information_user'), + ) + + +# 角色常量 +class UserRole: + ADMIN = "admin" # 管理员:全部权限 + EDITOR = "editor" # 信息员:可发布信息、管理资讯 + USER = "user" # 普通用户:基本功能 + + @classmethod + def get_role_name(cls, role): + names = { + cls.ADMIN: "管理员", + cls.EDITOR: "信息员", + cls.USER: "用户" + } + return names.get(role, "用户") diff --git a/backend/app/models/seek_info.py b/backend/app/models/seek_info.py new file mode 100644 index 0000000..eb3fd6c --- /dev/null +++ b/backend/app/models/seek_info.py @@ -0,0 +1,39 @@ +from sqlalchemy import Column, String, Text, Float, Date, Boolean, Integer, DateTime +from sqlalchemy.sql import func +from app.core.database import Base +import uuid + +def generate_uuid(): + return str(uuid.uuid4()) + +class SeekInfo(Base): + __tablename__ = "seek_info" + + id = Column(String(36), primary_key=True, default=generate_uuid) + user_id = Column(String(36), nullable=False, index=True) + + # 标题和内容 + title = Column(String(255), nullable=False) + content = Column(Text, nullable=True) + + # 期望条件(求购条件) + expect_category = Column(String(100), nullable=True) # 期望类别 + expect_version = Column(String(100), nullable=True) # 期望版别 + expect_packaging = Column(String(100), nullable=True) # 期望包装 + expect_number = Column(String(50), nullable=True) # 期望号码 + expect_price_min = Column(Float, nullable=True) # 期望最低价 + expect_price_max = Column(Float, nullable=True) # 期望最高价 + + # 匹配状态 + status = Column(String(20), default="active") # active/closed/expired + is_matched = Column(String(10), default="false") # 是否已匹配 + matched_user_id = Column(String(36), nullable=True) # 匹配的用户ID + matched_contact = Column(String(100), nullable=True) # 匹配的联系方式 + + # 统计 + view_count = Column(Integer, default=0) + contact_count = Column(Integer, default=0) + + # 时间 + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) \ No newline at end of file diff --git a/backend/app/routers/__init__.py b/backend/app/routers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/routers/auth.py b/backend/app/routers/auth.py new file mode 100644 index 0000000..1841872 --- /dev/null +++ b/backend/app/routers/auth.py @@ -0,0 +1,254 @@ +# 认证路由 - 使用字段编码 +from fastapi import APIRouter, Depends, HTTPException, status, Body, Response +from fastapi.security import OAuth2PasswordRequestForm +from sqlalchemy.orm import Session +from app.core.database import get_db +from app.core.auth import verify_password, create_access_token, get_password_hash, get_current_user +from app.models.models import User +from app.schemas.schemas import Token, UserCreate, UserResponse + +router = APIRouter(prefix="/api/auth", tags=["认证"]) + + + + +def generate_user_code(db): + """生成用户编码,从201开始,按自然数顺序递增,跳过已存在的""" + # 查找最大的user_code + max_code = db.query(User.user_code).filter(User.user_code != None).order_by(User.user_code.desc()).first() + if max_code and max_code[0]: + try: + num = int(max_code[0]) + 1 + if num < 201: + num = 201 + # 检查是否已存在,如果存在则继续递增 + while db.query(User).filter(User.user_code == str(num)).first(): + num += 1 + return str(num) + except: + pass + return "201" + +@router.post("/register", response_model=UserResponse) +def register(user_data: UserCreate, db: Session = Depends(get_db)): + """用户注册""" + # 检查用户名是否已存在 + existing_user = db.query(User).filter(User.f01_01_name == user_data.f01_01_name).first() + if existing_user: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="f01_01_name: 用户名已存在" + ) + + # 检查邮箱是否已存在 + + # 检查手机号是否已存在 + if user_data.phone: + existing_phone = db.query(User).filter(User.phone == user_data.phone).first() + if existing_phone: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="E00040:该手机号已被注册,请更换手机号" + ) + if user_data.email: + existing_email = db.query(User).filter(User.email == user_data.email).first() + if existing_email: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="E00041:该邮箱已被注册,请更换邮箱" + ) + + # 处理邀请码 + invited_by_user = None + if user_data.invite_code: + # 查找邀请人 + invited_by_user = db.query(User).filter(User.user_code == user_data.invite_code).first() + if not invited_by_user: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="E00042:邀请码无效" + ) + + # 创建用户 + import uuid + hashed_password = get_password_hash(user_data.password) + generated_code = generate_user_code(db) + user = User( + f99_90_id=str(uuid.uuid4()), + f99_91_user_id=str(uuid.uuid4()), + user_code=generated_code, + f01_01_name=user_data.f01_01_name, + email=user_data.email, + phone=user_data.phone, + avatar=user_data.avatar, + address=user_data.address, + bio=user_data.bio, + password=hashed_password, + role="user" + ) + + db.add(user) + db.flush() # 确保获取user ID + + # 更新邀请人、被邀请人的关联关系 + if invited_by_user: + # 记录是被谁邀请的 + user.f01_13_invite_code = invited_by_user.user_code + # 增加邀请人的邀请计数 + invited_by_user.f99_101_invited_count = (invited_by_user.f99_101_invited_count or 0) + 1 + + # 生成自己的邀请码(用自己的user_code) + user.f01_13_invite_code = generated_code + + db.commit() + db.refresh(user) + + # 返回用户信息(避免Pydantic序列化问题) + return { + "id": user.f99_90_id, + "username": user.f01_01_name, + "user_code": user.user_code, + "email": user.email, + "phone": user.phone, + "avatar": user.avatar, + "role": user.role, + "level": user.f99_94_level, + "aiCount": user.f99_95_ai_count or 0, + "searchCount": user.f99_96_search_count or 0, + "collectionCount": user.f99_97_collection_count or 0 + } + + +@router.post("/login") +def login( + form_data: OAuth2PasswordRequestForm = Depends(), + db: Session = Depends(get_db), + response: Response = None +): + """用户登录 - 支持用户名或用户编码登录,返回Token并设置Cookie""" + # 先尝试用户名登录 + user = db.query(User).filter(User.f01_01_name == form_data.username).first() + # 如果用户名不存在,尝试用户编码登录 + if not user: + user = db.query(User).filter(User.user_code == form_data.username).first() + if not user: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="E00011: 用户名或密码错误", + headers={"WWW-Authenticate": "Bearer"}, + ) + + # 验证密码 + if not verify_password(form_data.password, user.password): + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="E00011: 用户名或密码错误", + headers={"WWW-Authenticate": "Bearer"}, + ) + + # 更新登录次数和最后登录时间 + from datetime import datetime + user.f99_98_login_count = (user.f99_98_login_count or 0) + 1 + user.f99_99_last_login = datetime.now() + db.commit() + + # 生成 token + access_token = create_access_token(data={"sub": user.f99_90_id}) + + # 设置Cookie(有效期7天) + if response: + response.set_cookie( + key="token", + value=access_token, + httponly=False, # 允许JS读取(小程序需要) + max_age=7 * 24 * 60 * 60, # 7天 + samesite="lax", + path="/" + ) + + return { + "access_token": access_token, + "token_type": "bearer" + } + + +@router.get("/me", response_model=UserResponse) +def get_current_user_info( + current_user: User = Depends(lambda: None) +): + """获取当前用户信息""" + raise HTTPException( + status_code=status.HTTP_501_NOT_IMPLEMENTED, + detail="请使用正确的依赖注入" + ) + + +@router.post("/change-password") +def change_password( + old_password: str = Body(...), + new_password: str = Body(...), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """修改当前用户密码""" + from app.core.auth import verify_password, get_password_hash + + # 在当前session中重新查询用户 + user = db.query(User).filter(User.f99_90_id == current_user.f99_90_id).first() + if not user: + raise HTTPException(status_code=404, detail="用户不存在") + + # 验证旧密码 + if not verify_password(old_password, user.password): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="当前密码错误" + ) + + # 更新密码 + user.password = get_password_hash(new_password) + db.commit() + + return {"message": "密码修改成功"} + + +# ============ 短信验证码接口 ============ + +@router.post("/send-verification-code") +def send_verification_code( + phone: str = Body(..., min_length=11, max_length=11), + purpose: str = Body("register") # register | login | reset_password +): + """发送短信验证码""" + from app.services.sms import send_verification_code as send_sms + + # 验证手机号格式 + if not phone.startswith("1") or len(phone) != 11: + return {"success": False, "message": "手机号格式不正确"} + + result = send_sms(phone) + + if result["success"]: + return { + "success": True, + "message": f"验证码已发送到 {phone[:3]}****{phone[7:]}", + "expire": result.get("expire", 300) + } + else: + return result + + +@router.post("/verify-code") +def verify_code( + phone: str = Body(...), + code: str = Body(..., min_length=6, max_length=6) +): + """验证短信验证码(仅验证,不执行后续操作)""" + from app.services.sms import verify_code as check_code + + is_valid = check_code(phone, code) + + if is_valid: + return {"success": True, "message": "验证成功"} + else: + return {"success": False, "message": "验证码错误或已过期"} diff --git a/backend/app/routers/collections.py b/backend/app/routers/collections.py new file mode 100644 index 0000000..7daf3fe --- /dev/null +++ b/backend/app/routers/collections.py @@ -0,0 +1,887 @@ +# 藏品路由 - 使用字段编码 +import os +import uuid +import re +from typing import Optional, List +from fastapi import APIRouter, Depends, HTTPException, status, Query, UploadFile, File +from sqlalchemy import func, text +from sqlalchemy.orm import Session, joinedload +from app.core.database import get_db +from app.core.auth import get_current_user +from app.core.logging_config import logger +from app.models.models import User, Collection, CollectionImage, Operation +from app.schemas.schemas import ( + CollectionCreate, CollectionUpdate, CollectionResponse, + CollectionListResponse, CollectionImageResponse +) +from app.services.oss import upload_to_oss, get_oss_path, delete_from_oss, get_public_url + +router = APIRouter(prefix="/api/collections", tags=["藏品"]) + + +def to_camel_case(data: dict) -> dict: + """将字段编码转换为 camelCase 格式""" + if not data: + return data + + mapping = { + 'f99_90_id': 'id', + 'f99_91_user_id': 'userId', + 'f99_92_created_at': 'createdAt', + 'f99_93_updated_at': 'updatedAt', + 'f01_01_name': 'name', + 'f01_02_code': 'code', + 'f01_03_category': 'category', + 'f01_04_status': 'status', + 'f01_05_remark': 'remark', + 'f02_10_prefix_serial': 'prefixSerial', + 'f02_11_version': 'version', + 'f02_12_packaging': 'packaging', + 'f02_13_rarity': 'rarity', + 'f02_14_number_category': 'numberCategory', + 'f03_20_is_graded': 'isGraded', + 'f03_21_grading_company': 'gradingCompany', + 'f03_22_grading_score': 'gradingScore', + 'f03_23_three_star': 'threeStar', + 'f04_30_special_mark': 'specialMark', + 'f04_31_serial_feature': 'serialFeature', + 'f04_32_issuer': 'issuer', + 'f04_33_issue_year': 'issueYear', + 'f04_34_material': 'material', + 'f04_35_denomination': 'denomination', + 'f04_36_issue_quantity': 'issueQuantity', + 'f05_40_cost_price': 'costPrice', + 'f05_41_target_price': 'targetPrice', + 'f05_42_goal_price': 'goalPrice', + 'f05_43_repair_fee': 'repairFee', + 'f05_44_grading_fee': 'gradingFee', + 'f06_50_purpose': 'purpose', + 'images': 'images', + } + + return {mapping.get(k, k): v for k, v in data.items()} + + +# 编码生成函数 +def generate_code(version: str, user_id: str, db: Session) -> str: + """自动生成藏品编号 - 按用户独立编码""" + import re + + # 查询当前用户的非空编码(不与其他用户混算)- 使用行锁防止并发 + user_codes = db.query(Collection.f01_02_code).filter( + Collection.f01_02_code.isnot(None), + Collection.f99_91_user_id == user_id + ).with_for_update().all() + + max_num = 0 + for (code,) in user_codes: + # 处理纯数字编码(支持4位和5位) + if re.match(r'^\d{4,5}$', code): + try: + num = int(code) + if num > max_num: + max_num = num + except (ValueError, TypeError): + pass + + # 当前用户最大号 +1 + next_num = max_num + 1 + + # 如果超过9999,使用5位;否则使用4位 + if next_num > 9999: + return str(next_num).zfill(5) + else: + return str(next_num).zfill(4) + + +@router.get("/next-code") +def get_next_code( + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取下一个藏品编号""" + next_code = generate_code("2024 龙", current_user.f99_90_id, db) + return {"code": 200, "data": {"nextCode": next_code}} + + +@router.get("") +def get_collections( + id: str = Query(None, description="filter by collection id"), + category: Optional[str] = None, + status: Optional[str] = None, + search: Optional[str] = None, + specialMark: Optional[str] = Query(None, description="special mark filter"), + numberCategory: Optional[str] = Query(None, description="number category filter"), + gradingCompany: Optional[str] = Query(None, description="grading company filter"), + gradingScore: Optional[str] = Query(None, description="grading score filter"), + packaging: Optional[str] = Query(None, description="packaging filter"), + rarity: Optional[str] = Query(None, description="rarity filter"), + version: Optional[str] = Query(None, description="version filter"), + profitLoss: Optional[str] = Query(None, description="profit loss filter: profit or loss"), + page: int = Query(1, ge=1), + limit: int = Query(20, ge=1, le=500), + sortBy: str = Query('createdAt'), + sortOrder: str = Query('desc'), + all_users: bool = Query(False, description="return all users data for admin"), + user_id: str = Query(None, description="filter by user id"), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取藏品列表""" + # admin 用户可以看到所有藏品,普通用户只能看到自己的 + # 如果指定 all_users=true,则返回所有用户藏品 + from sqlalchemy.orm import joinedload + + # 管理员默认查看全库,普通用户只看自己,未登录返回空列表 + if current_user is None or current_user.role != "admin": + # 非管理员或未登录用户只能查看自己的藏品(如果没有登录则返回空) + if current_user is None: + return {"data": [], "total": 0, "page": 1, "limit": 20} + query = db.query(Collection).filter(Collection.f99_91_user_id == current_user.f99_90_id) + else: + # 管理员查看所有藏品 + query = db.query(Collection, User.f01_01_name.label('owner_name')).join( + User, Collection.f99_91_user_id == User.f99_90_id, isouter=True + ) + + # 如果指定了user_id参数,则只返回该用户的藏品 + if user_id: + query = query.filter(Collection.f99_91_user_id == user_id) + + # 按ID精确筛选 + if id: + query = query.filter(Collection.f99_90_id == id) + + if category: + query = query.filter(Collection.f01_03_category == category) + if status: + query = query.filter(Collection.f01_04_status == status) + if specialMark: + query = query.filter(Collection.f04_30_special_mark == specialMark) + if gradingCompany: + query = query.filter(Collection.f03_21_grading_company.contains(gradingCompany)) + if gradingScore: + query = query.filter(Collection.f03_22_grading_score.contains(gradingScore)) + if numberCategory: + query = query.filter(Collection.f02_14_number_category.contains(numberCategory)) + if packaging: + query = query.filter(Collection.f02_12_packaging== packaging) + if rarity: + query = query.filter(Collection.f02_13_rarity.contains(rarity)) + if version: + query = query.filter(Collection.f02_11_version.contains(version)) + + # 盈亏筛选(只对已售藏品有效) + if profitLoss: + if profitLoss == 'profit': + # 盈利:售价 > 成本价 + query = query.filter( + Collection.f01_04_status == 'sold', + Collection.f05_42_goal_price > Collection.f05_40_cost_price + ) + elif profitLoss == 'loss': + # 亏损:售价 <= 成本价 + query = query.filter( + Collection.f01_04_status == 'sold', + Collection.f05_42_goal_price <= Collection.f05_40_cost_price + ) + + if search: + query = query.filter( + (Collection.f01_01_name.contains(search)) | + (Collection.f01_05_remark.contains(search)) + ) + + # 总数(应用筛选条件后的数量) + total = query.count() + + # 使用joinedload预加载图片,避免N+1查询问题 + query = query.options(joinedload(Collection.images)) + + # 分页 + data = query.order_by(Collection.f99_92_created_at.desc()) \ + .offset((page - 1) * limit) \ + .limit(limit) \ + .all() + + # 转换为字典列表并转为 camelCase + data_list = [] + for item in data: + # 处理联表查询结果 + if current_user is not None and current_user.role == "admin": + collection_item, owner_name = item + else: + collection_item = item + owner_name = None + + item_dict = { + 'f99_90_id': collection_item.f99_90_id, + 'f99_91_user_id': collection_item.f99_91_user_id, + 'owner_name': owner_name, # 所属用户名(仅管理员可见) + 'f01_01_name': collection_item.f01_01_name, + 'f01_02_code': collection_item.f01_02_code, + 'f01_03_category': collection_item.f01_03_category, + 'f01_04_status': collection_item.f01_04_status, + 'f01_05_remark': collection_item.f01_05_remark, + 'f02_10_prefix_serial': collection_item.f02_10_prefix_serial, + 'f02_11_version': collection_item.f02_11_version, + 'f02_12_packaging': collection_item.f02_12_packaging, + 'f02_13_rarity': collection_item.f02_13_rarity, + 'f02_14_number_category': collection_item.f02_14_number_category, + 'f03_20_is_graded': collection_item.f03_20_is_graded, + 'f03_21_grading_company': collection_item.f03_21_grading_company, + 'f03_22_grading_score': collection_item.f03_22_grading_score, + 'f03_23_three_star': collection_item.f03_23_three_star, + 'f04_30_special_mark': collection_item.f04_30_special_mark, + 'f04_31_serial_feature': collection_item.f04_31_serial_feature, + 'f04_32_issuer': collection_item.f04_32_issuer, + 'f04_33_issue_year': collection_item.f04_33_issue_year, + 'f04_34_material': collection_item.f04_34_material, + 'f04_35_denomination': collection_item.f04_35_denomination, + 'f04_36_issue_quantity': collection_item.f04_36_issue_quantity, + 'f05_40_cost_price': float(collection_item.f05_40_cost_price) if collection_item.f05_40_cost_price else None, + 'f05_41_target_price': float(collection_item.f05_41_target_price) if collection_item.f05_41_target_price else None, + 'f05_42_goal_price': float(collection_item.f05_42_goal_price) if collection_item.f05_42_goal_price else None, + 'f05_43_repair_fee': float(collection_item.f05_43_repair_fee) if collection_item.f05_43_repair_fee else None, + 'f05_44_grading_fee': float(collection_item.f05_44_grading_fee) if collection_item.f05_44_grading_fee else None, + 'f06_50_purpose': collection_item.f06_50_purpose, + 'f99_92_created_at': collection_item.f99_92_created_at.isoformat() if collection_item.f99_92_created_at else None, + 'images': [] + } + + # 直接使用预加载的图片数据,无需再查询 + for img in collection_item.images: + item_dict['images'].append({ + 'id': img.id, + 'filename': img.filename, + 'original_name': img.original_name, + 'path': img.path, + 'created_at': img.created_at.isoformat() if img.created_at else None + }) + + data_list.append(to_camel_case(item_dict)) + + return { + "data": data_list, + "pagination": { + "page": page, + "limit": limit, + "total": total, + "pages": (total + limit - 1) // limit + } + } + + +@router.get("/stats") +def get_stats( + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取藏品统计 - 使用SQL聚合查询优化性能""" + + # 非管理员或未登录用户只能查看自己的藏品 + if current_user is None: + return { + "totalCount": 0, + "byCategory": [], + "byStatus": [], + "byGrading": [], + "byPackaging": [], + "byRarity": [], + "byVersion": [], + "byGradingCompany": [], + "byGradingScore": [], + "bySpecialMark": [], + "byNumberCategory": [], + "byProfitLoss": [], + "totalCost": 0, + "totalTarget": 0, + "expectedProfit": 0, + "totalRevenue": 0, + "totalProfit": 0 + } + + # 构建基础查询条件 + is_admin = current_user.role == "admin" + + if not is_admin: + base_filter = Collection.f99_91_user_id == current_user.f99_90_id + else: + base_filter = None + + # 总数 - 使用SQL COUNT + total_count = db.query(func.count(Collection.f99_90_id)).filter( + base_filter if base_filter is not True else True + ).scalar() + if base_filter is not True: + total_count = db.query(func.count(Collection.f99_90_id)).filter(base_filter).scalar() + else: + total_count = db.query(func.count(Collection.f99_90_id)).scalar() + + # 按分类统计 - 使用SQL GROUP BY + if base_filter is not True: + by_category = db.query( + Collection.f01_03_category, + func.count(Collection.f99_90_id) + ).filter(base_filter).group_by(Collection.f01_03_category).all() + + by_status = db.query( + Collection.f01_04_status, + func.count(Collection.f99_90_id) + ).filter(base_filter).group_by(Collection.f01_04_status).all() + + by_graded = db.query( + Collection.f03_20_is_graded, + func.count(Collection.f99_90_id) + ).filter(base_filter).group_by(Collection.f03_20_is_graded).all() + + by_packaging = db.query( + Collection.f02_12_packaging, + func.count(Collection.f99_90_id) + ).filter(base_filter, Collection.f02_12_packaging.isnot(None)).group_by(Collection.f02_12_packaging).all() + + by_rarity = db.query( + Collection.f02_13_rarity, + func.count(Collection.f99_90_id) + ).filter(base_filter, Collection.f02_13_rarity.isnot(None)).group_by(Collection.f02_13_rarity).all() + + by_version = db.query( + Collection.f02_11_version, + func.count(Collection.f99_90_id) + ).filter(base_filter, Collection.f02_11_version.isnot(None)).group_by(Collection.f02_11_version).all() + + by_grading_company = db.query( + Collection.f03_21_grading_company, + func.count(Collection.f99_90_id) + ).filter(base_filter, Collection.f03_20_is_graded == True, Collection.f03_21_grading_company.isnot(None)).group_by(Collection.f03_21_grading_company).all() + + by_grading_score = db.query( + Collection.f03_22_grading_score, + func.count(Collection.f99_90_id) + ).filter(base_filter, Collection.f03_20_is_graded == True, Collection.f03_22_grading_score.isnot(None)).group_by(Collection.f03_22_grading_score).all() + + by_special_mark = db.query( + Collection.f04_30_special_mark, + func.count(Collection.f99_90_id) + ).filter(base_filter, Collection.f04_30_special_mark.isnot(None)).group_by(Collection.f04_30_special_mark).all() + + by_number_category = db.query( + Collection.f02_14_number_category, + func.count(Collection.f99_90_id) + ).filter(base_filter, Collection.f02_14_number_category.isnot(None)).group_by(Collection.f02_14_number_category).all() + + # 成本相关统计 - 使用SQL SUM + cost_result = db.query( + func.coalesce(func.sum(Collection.f05_40_cost_price), 0) + + func.coalesce(func.sum(Collection.f05_43_repair_fee), 0) + + func.coalesce(func.sum(Collection.f05_44_grading_fee), 0) + ).filter(base_filter).first() + total_cost = cost_result[0] if cost_result else 0 + + # 预期利润 + expected_profit_result = db.query( + func.coalesce(func.sum(Collection.f05_41_target_price - Collection.f05_40_cost_price), 0) + ).filter(base_filter, Collection.f05_41_target_price.isnot(None), Collection.f05_41_target_price > 0).first() + expected_profit = expected_profit_result[0] if expected_profit_result else 0 + + # 已售藏品统计 + sold_collections = db.query(Collection).filter( + base_filter, + Collection.f01_04_status == 'sold', + Collection.f05_42_goal_price.isnot(None), + Collection.f05_42_goal_price > 0 + ).all() + + else: + # 管理员查看所有数据 + by_category = db.query( + Collection.f01_03_category, + func.count(Collection.f99_90_id) + ).group_by(Collection.f01_03_category).all() + + by_status = db.query( + Collection.f01_04_status, + func.count(Collection.f99_90_id) + ).group_by(Collection.f01_04_status).all() + + by_graded = db.query( + Collection.f03_20_is_graded, + func.count(Collection.f99_90_id) + ).group_by(Collection.f03_20_is_graded).all() + + by_packaging = db.query( + Collection.f02_12_packaging, + func.count(Collection.f99_90_id) + ).filter(Collection.f02_12_packaging.isnot(None)).group_by(Collection.f02_12_packaging).all() + + by_rarity = db.query( + Collection.f02_13_rarity, + func.count(Collection.f99_90_id) + ).filter(Collection.f02_13_rarity.isnot(None)).group_by(Collection.f02_13_rarity).all() + + by_version = db.query( + Collection.f02_11_version, + func.count(Collection.f99_90_id) + ).filter(Collection.f02_11_version.isnot(None)).group_by(Collection.f02_11_version).all() + + by_grading_company = db.query( + Collection.f03_21_grading_company, + func.count(Collection.f99_90_id) + ).filter(Collection.f03_20_is_graded == True, Collection.f03_21_grading_company.isnot(None)).group_by(Collection.f03_21_grading_company).all() + + by_grading_score = db.query( + Collection.f03_22_grading_score, + func.count(Collection.f99_90_id) + ).filter(Collection.f03_20_is_graded == True, Collection.f03_22_grading_score.isnot(None)).group_by(Collection.f03_22_grading_score).all() + + by_special_mark = db.query( + Collection.f04_30_special_mark, + func.count(Collection.f99_90_id) + ).filter(Collection.f04_30_special_mark.isnot(None)).group_by(Collection.f04_30_special_mark).all() + + by_number_category = db.query( + Collection.f02_14_number_category, + func.count(Collection.f99_90_id) + ).filter(Collection.f02_14_number_category.isnot(None)).group_by(Collection.f02_14_number_category).all() + + # 总成本 + cost_result = db.query( + func.coalesce(func.sum(Collection.f05_40_cost_price), 0) + + func.coalesce(func.sum(Collection.f05_43_repair_fee), 0) + + func.coalesce(func.sum(Collection.f05_44_grading_fee), 0) + ).first() + total_cost = cost_result[0] if cost_result else 0 + + # 预期利润 + expected_profit_result = db.query( + func.coalesce(func.sum(Collection.f05_41_target_price - Collection.f05_40_cost_price), 0) + ).filter(Collection.f05_41_target_price.isnot(None), Collection.f05_41_target_price > 0).first() + expected_profit = expected_profit_result[0] if expected_profit_result else 0 + + # 已售藏品 + sold_collections = db.query(Collection).filter( + Collection.f01_04_status == 'sold', + Collection.f05_42_goal_price.isnot(None), + Collection.f05_42_goal_price > 0 + ).all() + + # 总收入和总利润(已售藏品) + total_revenue = sum(c.f05_42_goal_price or 0 for c in sold_collections) + total_profit = sum( + (c.f05_42_goal_price or 0) - (c.f05_40_cost_price or 0) - (c.f05_43_repair_fee or 0) - (c.f05_44_grading_fee or 0) + for c in sold_collections + ) + + # 盈亏统计 + profit_count = sum(1 for c in sold_collections if c.f05_42_goal_price and c.f05_40_cost_price and c.f05_42_goal_price > c.f05_40_cost_price) + loss_count = sum(1 for c in sold_collections if c.f05_42_goal_price and c.f05_40_cost_price and c.f05_42_goal_price <= c.f05_40_cost_price) + + # 目标价格总和 + total_target_result = db.query(func.coalesce(func.sum(Collection.f05_41_target_price), 0)).filter( + base_filter if base_filter is not True else True + ).first() + if base_filter is not True: + total_target_result = db.query(func.coalesce(func.sum(Collection.f05_41_target_price), 0)).filter(base_filter).first() + else: + total_target_result = db.query(func.coalesce(func.sum(Collection.f05_41_target_price), 0)).first() + total_target = total_target_result[0] if total_target_result else 0 + + return { + "totalCount": total_count, + "byCategory": [{"category": c, "count": n} for c, n in by_category], + "byStatus": [{"status": s, "count": n} for s, n in by_status], + "byGrading": [{"isGraded": g, "count": n} for g, n in by_graded], + "byPackaging": [{"packaging": p, "count": n} for p, n in by_packaging], + "byRarity": [{"rarity": r, "count": n} for r, n in by_rarity], + "byVersion": [{"version": v, "count": n} for v, n in by_version], + "byGradingCompany": [{"company": c, "count": n} for c, n in by_grading_company], + "byGradingScore": [{"score": s, "count": n} for s, n in by_grading_score], + "bySpecialMark": [{"mark": m, "count": n} for m, n in by_special_mark], + "byNumberCategory": [{"numberCategory": n, "count": c} for n, c in by_number_category], + "byProfitLoss": [ + {"type": "profit", "label": "盈利", "count": profit_count}, + {"type": "loss", "label": "亏损", "count": loss_count} + ], + "totalCost": total_cost, + "totalTarget": total_target, + "expectedProfit": expected_profit, + "totalRevenue": total_revenue, + "totalProfit": total_profit + } + + +@router.get("/{collection_id}") +def get_collection( + collection_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取单个藏品详情""" + result = db.execute( + text("SELECT * FROM collections WHERE f99_90_id = :id"), + {"id": collection_id} + ).fetchone() + + if not result: + raise HTTPException(status_code=404, detail="E00033: 藏品不存在") + + collection = dict(result._mapping) + + # 非管理员只能查看自己的藏品 + if (current_user is None or current_user.role != "admin") and collection.get('f99_91_user_id') != current_user.f99_90_id: + raise HTTPException(status_code=403, detail="无权访问") + + result_dict = { + 'f99_90_id': collection.get('f99_90_id'), + 'f99_91_user_id': collection.get('f99_91_user_id'), + 'f01_01_name': collection.get('f01_01_name'), + 'f01_02_code': collection.get('f01_02_code'), + 'f01_03_category': collection.get('f01_03_category'), + 'f01_04_status': collection.get('f01_04_status'), + 'f01_05_remark': collection.get('f01_05_remark'), + 'f02_10_prefix_serial': collection.get('f02_10_prefix_serial'), + 'f02_11_version': collection.get('f02_11_version'), + 'f02_12_packaging': collection.get('f02_12_packaging'), + 'f02_13_rarity': collection.get('f02_13_rarity'), + 'f02_14_number_category': collection.get('f02_14_number_category'), + 'f03_20_is_graded': collection.get('f03_20_is_graded'), + 'f03_21_grading_company': collection.get('f03_21_grading_company'), + 'f03_22_grading_score': collection.get('f03_22_grading_score'), + 'f03_23_three_star': collection.get('f03_23_three_star'), + 'f04_30_special_mark': collection.get('f04_30_special_mark'), + 'f04_31_serial_feature': collection.get('f04_31_serial_feature'), + 'f04_32_issuer': collection.get('f04_32_issuer'), + 'f04_33_issue_year': collection.get('f04_33_issue_year'), + 'f04_34_material': collection.get('f04_34_material'), + 'f04_35_denomination': collection.get('f04_35_denomination'), + 'f04_36_issue_quantity': collection.get('f04_36_issue_quantity'), + 'f05_40_cost_price': float(collection.get('f05_40_cost_price')) if collection.get('f05_40_cost_price') else None, + 'f05_41_target_price': float(collection.get('f05_41_target_price')) if collection.get('f05_41_target_price') else None, + 'f05_42_goal_price': float(collection.get('f05_42_goal_price')) if collection.get('f05_42_goal_price') else None, + 'f05_43_repair_fee': float(collection.get('f05_43_repair_fee')) if collection.get('f05_43_repair_fee') else None, + 'f05_44_grading_fee': float(collection.get('f05_44_grading_fee')) if collection.get('f05_44_grading_fee') else None, + 'f06_50_purpose': collection.get('f06_50_purpose'), + 'f99_92_created_at': collection.get('f99_92_created_at').isoformat() if collection.get('f99_92_created_at') else None, + 'images': [] + } + + # 加载图片数据 + images = db.query(CollectionImage).filter( + CollectionImage.collection_id == collection_id + ).all() + + for img in images: + result_dict['images'].append({ + 'id': img.id, + 'filename': img.filename, + 'original_name': img.original_name, + 'path': img.path, + 'created_at': img.created_at.isoformat() if img.created_at else None + }) + + return to_camel_case(result_dict) + + +@router.post("") +def create_collection( + collection_data: CollectionCreate, + force: bool = False, # 是否强制保存(忽略重复警告) + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """创建藏品 - 支持冠字号查重""" + from app.core.logging_config import logger + + # 自动生成编码 + final_code = collection_data.f01_02_code or generate_code( + collection_data.f02_11_version or '2024 龙', + current_user.f99_90_id, + db + ) + + # 编号查重(如果提供了编号且不是强制保存) + if not force and final_code: + existing_code = db.query(Collection).filter( + Collection.f01_02_code == final_code, + Collection.f99_91_user_id == current_user.f99_90_id + ).first() + + if existing_code: + logger.warning(f"发现重复编号:{final_code}, 已存在藏品 ID: {existing_code.f99_90_id}") + return { + "error": { + "code": "DUPLICATE_CODE", + "message": f"藏品编号 {final_code} 已存在,请使用其他编号" + } + } + + # 冠字号查重(如果提供了冠字号且不是强制保存) + if not force and collection_data.f02_10_prefix_serial: + # 查询当前用户是否有相同冠字号的藏品 + existing = db.query(Collection).filter( + Collection.f02_10_prefix_serial == collection_data.f02_10_prefix_serial, + Collection.f99_91_user_id == current_user.f99_90_id + ).first() + + if existing: + logger.warning(f"发现重复冠字号:{collection_data.f02_10_prefix_serial}, 已存在藏品 ID: {existing.f99_90_id}") + # 返回警告信息,让前端询问用户是否继续 + return { + "warning": { + "code": "DUPLICATE_SERIAL", + "message": f"发现重复冠字号:{collection_data.f02_10_prefix_serial}", + "existing_collection": { + "id": existing.f99_90_id, + "name": existing.f01_01_name, + "code": existing.f01_02_code, + "prefix_serial": existing.f02_10_prefix_serial + } + }, + "data": { + "ask_continue": True + } + } + + # 自动分类:如果未提供号码分类,则根据冠字号自动分类 + if not collection_data.f02_14_number_category and collection_data.f02_10_prefix_serial: + from app.utils.number_category import get_number_category + collection_data.f02_14_number_category = get_number_category(collection_data.f02_10_prefix_serial) + + collection = Collection( + f99_91_user_id=current_user.f99_90_id, + f01_01_name=collection_data.f01_01_name, + f01_02_code=final_code, + f01_03_category=collection_data.f01_03_category, + f01_04_status=collection_data.f01_04_status or "in_collection", + f01_05_remark=collection_data.f01_05_remark, + f02_10_prefix_serial=collection_data.f02_10_prefix_serial, + f02_11_version=collection_data.f02_11_version, + f02_12_packaging=collection_data.f02_12_packaging, + f02_13_rarity=collection_data.f02_13_rarity, + f02_14_number_category=collection_data.f02_14_number_category, + f03_20_is_graded=collection_data.f03_20_is_graded or False, + f03_21_grading_company=collection_data.f03_21_grading_company, + f03_22_grading_score=collection_data.f03_22_grading_score, + f03_23_three_star=collection_data.f03_23_three_star or False, + f04_30_special_mark=collection_data.f04_30_special_mark, + f04_31_serial_feature=collection_data.f04_31_serial_feature, + f04_32_issuer=collection_data.f04_32_issuer, + f04_33_issue_year=collection_data.f04_33_issue_year, + f04_34_material=collection_data.f04_34_material, + f04_35_denomination=collection_data.f04_35_denomination, + f04_36_issue_quantity=collection_data.f04_36_issue_quantity, + f05_40_cost_price=collection_data.f05_40_cost_price, + f05_41_target_price=collection_data.f05_41_target_price, + f05_42_goal_price=collection_data.f05_42_goal_price, + f05_43_repair_fee=collection_data.f05_43_repair_fee, + f05_44_grading_fee=collection_data.f05_44_grading_fee, + f06_50_purpose=collection_data.f06_50_purpose + ) + + db.add(collection) + db.commit() + db.refresh(collection) + + return { + 'f99_90_id': collection.f99_90_id, + 'f99_91_user_id': collection.f99_91_user_id, + 'f01_01_name': collection.f01_01_name, + 'f01_02_code': collection.f01_02_code, + 'f01_03_category': collection.f01_03_category, + 'f01_04_status': collection.f01_04_status, + 'f01_05_remark': collection.f01_05_remark, + 'f99_92_created_at': collection.f99_92_created_at.isoformat() if collection.f99_92_created_at else None, + 'message': '创建成功' + } + + +@router.put("/{collection_id}") +def update_collection( + collection_id: str, + collection_data: CollectionUpdate, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新藏品""" + collection = db.query(Collection).filter( + Collection.f99_90_id == collection_id, + Collection.f99_91_user_id == current_user.f99_90_id + ).first() + + if not collection: + raise HTTPException(status_code=404, detail="E00033: 藏品不存在") + + # 更新字段 - 使用 model_fields_set 检查哪些字段被设置 + for field_name in collection_data.model_fields_set: + value = getattr(collection_data, field_name) + if value is not None: + setattr(collection, field_name, value) + + db.commit() + db.refresh(collection) + + return { + "f99_90_id": collection.f99_90_id, + "message": "更新成功" + } + + +@router.delete("/{collection_id}") +def delete_collection( + collection_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除藏品""" + # 验证权限并检查是否存在 + collection = db.query(Collection).filter( + Collection.f99_90_id == collection_id, + Collection.f99_91_user_id == current_user.f99_90_id + ).first() + + if not collection: + raise HTTPException(status_code=404, detail="E00033: 藏品不存在") + + # 使用原生 SQL 删除(避免 ORM 级联查询字段不匹配问题) + from sqlalchemy import text + # 1. 删除关联的 operations(f99_91_user_id 关联到 collections.f99_90_id) + db.execute(text("DELETE FROM operations WHERE f99_91_user_id = :id"), {"id": collection_id}) + # 2. 删除关联的图片 + db.execute(text("DELETE FROM collection_images WHERE collection_id = :id"), {"id": collection_id}) + # 3. 删除藏品本身 + db.execute(text("DELETE FROM collections WHERE f99_90_id = :id"), {"id": collection_id}) + db.commit() + + return {"message": "删除成功"} + + +@router.post("/upload-image") +async def upload_image( + collection_id: str = None, + file: UploadFile = File(...), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """上传藏品图片 - 文件名格式:用户名 - 藏品编号 - 冠字号""" + try: + # 验证藏品是否存在 + collection = db.query(Collection).filter( + Collection.f99_90_id == collection_id + ).first() + + if not collection: + raise HTTPException(status_code=404, detail="E00033: 藏品不存在") + + # 获取用户信息(用于文件名) + owner = db.query(User).filter(User.f99_90_id == collection.f99_91_user_id).first() + username = owner.f01_01_name if owner else "unknown" + + # 获取藏品信息(用于文件名) + code = collection.f01_02_code or "0000" + prefix_serial = collection.f02_10_prefix_serial or "" + + # 检查文件类型 + if not file.content_type.startswith('image/'): + raise HTTPException(status_code=400, detail="E00038: 只能上传图片文件") + + # 检查文件大小(限制 10MB) + file_size = 0 + content = await file.read() + file_size = len(content) + if file_size > 10 * 1024 * 1024: # 10MB + raise HTTPException(status_code=400, detail=f"E00039: 图片大小不能超过 10MB(当前{file_size // 1024 // 1024}MB)") + + # 生成OSS存储路径 + user_id = collection.f99_91_user_id + file_extension = file.filename.split('.')[-1] if '.' in file.filename else 'jpg' + + # 清理特殊字符 + clean_username = re.sub(r'[^\w\u4e00-\u9fff\-]', '', username) + clean_serial = re.sub(r'[^\w\u4e00-\u9fff\-]', '', prefix_serial) + + # 文件名格式:用户名-藏品编号-冠字号.jpg + if clean_serial: + filename = f"{clean_username}-{code}-{clean_serial}.{file_extension}" + else: + filename = f"{clean_username}-{code}.{file_extension}" + + # 生成OSS key + oss_key, unique_name = get_oss_path("collections", user_id=user_id, filename=filename) + + # 上传到OSS + image_url = upload_to_oss(content, oss_key) + + # 创建图片记录(保存OSS URL) + image = CollectionImage( + id=str(uuid.uuid4()), + collection_id=collection_id, + filename=unique_name, + original_name=file.filename, + path=image_url # 保存OSS URL + ) + + db.add(image) + db.commit() + db.refresh(image) + + logger.info(f"图片上传成功:{image_url}, collection_id={collection_id}") + + return { + "message": "上传成功", + "image_id": image.id, + "filename": unique_name, + "url": image_url + } + except HTTPException: + raise + except Exception as e: + logger.error(f"图片上传失败:{str(e)}") + raise HTTPException(status_code=500, detail="上传失败") + + +@router.delete("/images/{image_id}") +async def delete_image( + image_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除藏品图片""" + try: + # 查找图片记录 + image = db.query(CollectionImage).filter( + CollectionImage.id == image_id + ).first() + + if not image: + raise HTTPException(status_code=404, detail="E00033: 图片不存在") + + # 检查权限 + collection = db.query(Collection).filter( + Collection.f99_90_id == image.collection_id + ).first() + + if collection and (current_user is None or current_user.role != "admin") and collection.f99_91_user_id != current_user.f99_90_id: + raise HTTPException(status_code=403, detail="E00014: 无权删除此图片") + + # 删除OSS文件(如果path是OSS URL) + if image.path and image.path.startswith("https://"): + # 从OSS URL提取key + try: + oss_key = image.path.replace("https://jiachenlong-oss.oss-cn-hangzhou.aliyuncs.com/", "") + delete_from_oss(oss_key) + except Exception as e: + logger.warning(f"OSS文件删除失败: {e}") + elif image.path and os.path.exists(image.path): + # 兼容旧的本地上传 + os.remove(image.path) + + # 删除数据库记录 + db.delete(image) + db.commit() + + return {"message": "删除成功"} + except HTTPException: + raise + except Exception as e: + logger.error(f"图片删除失败:{str(e)}") + raise HTTPException(status_code=500, detail="删除失败") diff --git a/backend/app/routers/deal.py b/backend/app/routers/deal.py new file mode 100644 index 0000000..4817aff --- /dev/null +++ b/backend/app/routers/deal.py @@ -0,0 +1,302 @@ +from fastapi import APIRouter, Depends, Query, HTTPException +from sqlalchemy.orm import Session +from pydantic import BaseModel +from typing import Optional +from datetime import datetime, date +from app.core.database import get_db +from app.core.auth import get_current_user +from app.models.deal_info import DealInfo + +router = APIRouter(prefix="/api/deal", tags=["成交行情"]) + +# ============ Schema ============ +class DealInfoCreate(BaseModel): + title: str + content: Optional[str] = None + deal_price: Optional[float] = None + deal_date: Optional[str] = None # YYYY-MM-DD + packaging: Optional[str] = None + category: Optional[str] = None + is_graded: Optional[bool] = False + grading_company: Optional[str] = None + grading_score: Optional[str] = None + tail_number: Optional[str] = None + size_type: Optional[str] = None + version: Optional[str] = None + platform: Optional[str] = None + seller: Optional[str] = None + buyer: Optional[str] = None + +class DealInfoUpdate(BaseModel): + title: Optional[str] = None + content: Optional[str] = None + deal_price: Optional[float] = None + deal_date: Optional[str] = None + packaging: Optional[str] = None + category: Optional[str] = None + is_graded: Optional[bool] = None + grading_company: Optional[str] = None + grading_score: Optional[str] = None + tail_number: Optional[str] = None + size_type: Optional[str] = None + version: Optional[str] = None + platform: Optional[str] = None + seller: Optional[str] = None + buyer: Optional[str] = None + status: Optional[str] = None + +class DealInfoResponse(BaseModel): + id: str + user_id: Optional[str] + title: str + content: Optional[str] + deal_price: Optional[float] + deal_date: Optional[date] + deal_no: Optional[str] + packaging: Optional[str] + category: Optional[str] + is_graded: Optional[bool] + grading_company: Optional[str] + grading_score: Optional[str] + tail_number: Optional[str] + size_type: Optional[str] + version: Optional[str] + platform: Optional[str] + seller: Optional[str] + buyer: Optional[str] + status: str + view_count: int + contact_count: int + created_at: Optional[datetime] + updated_at: Optional[datetime] + + class Config: + from_attributes = True + +# 生成行情编号 +def generate_deal_no(db: Session): + """生成行情编号,从A000001开始递增""" + last = db.query(DealInfo).order_by(DealInfo.deal_no.desc()).first() + if last and last.deal_no: + # 例如 A000001 -> 2 -> A000002 + num = int(last.deal_no[1:]) + 1 + return f"A{num:06d}" + return "A000001" + +# ============ API ============ +@router.get("/list", response_model=list[DealInfoResponse]) +def get_deal_list( + status: str = Query("active"), + deal_date: Optional[str] = Query(None), + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=1000), + user_only: bool = Query(False), # 是否只查看自己的 + current_user: Optional = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取成交行情列表""" + query = db.query(DealInfo).filter(DealInfo.status == status) + + # 我的行情:只查看自己的(管理员也只看自己的) + if user_only and current_user: + query = query.filter(DealInfo.user_id == current_user.f99_90_id) + + # 成交日期过滤 + if deal_date: + query = query.filter(DealInfo.deal_date == deal_date) + + # 排序:优先成交日期倒序,同日按编号倒序 + query = query.order_by(DealInfo.deal_date.desc().nullslast(), DealInfo.deal_no.desc().nullslast()) + + # 分页 + offset = (page - 1) * page_size + items = query.offset(offset).limit(page_size).all() + + return items + +@router.get("/stats") +def get_deal_stats( + db: Session = Depends(get_db) +): + """获取成交行情统计""" + total = db.query(DealInfo).filter(DealInfo.status == "active").count() + + # 按日期统计 + from sqlalchemy import func + date_stats = db.query( + DealInfo.deal_date, + func.count(DealInfo.id).label('count') + ).filter( + DealInfo.status == "active", + DealInfo.deal_date.isnot(None) + ).group_by(DealInfo.deal_date).order_by(DealInfo.deal_date.desc()).limit(10).all() + + return { + "total": total, + "by_date": [{"date": str(d.deal_date), "count": d.count} for d in date_stats] + } + +@router.post("", response_model=DealInfoResponse) +def create_deal( + data: DealInfoCreate, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """创建成交行情""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + # 生成行情编号 + deal_no = generate_deal_no(db) + + # 解析日期 + deal_date = None + if data.deal_date: + try: + deal_date = datetime.strptime(data.deal_date, "%Y-%m-%d").date() + except: + pass + + deal = DealInfo( + user_id=current_user.f99_90_id if current_user else None, + title=data.title, + content=data.content, + deal_price=data.deal_price, + deal_date=deal_date, + deal_no=deal_no, + packaging=data.packaging, + category=data.category, + is_graded=data.is_graded or False, + grading_company=data.grading_company, + grading_score=data.grading_score, + tail_number=data.tail_number, + size_type=data.size_type, + version=data.version, + platform=data.platform, + seller=data.seller, + buyer=data.buyer, + status="active" + ) + db.add(deal) + db.commit() + db.refresh(deal) + return deal + +@router.get("/category-stats") +def get_deal_category_stats( + version: str = Query("龙钞", description="版本筛选:龙钞、马钞、蛇钞、其他"), + db: Session = Depends(get_db) +): + """获取成交行情分类汇总统计数据 - 后端计算优化版""" + from collections import defaultdict + + # 定义版本前缀映射 + version_prefix_map = {"龙钞": "J0", "马钞": "J1", "蛇钞": "J3"} + packagings = ["标百", "标十", "单张"] + category_map = {"通货": "带4号", "无4": "带7号", "永恒": "永恒号", "钻石": "钻石号"} + + # 构建查询 + query = db.query(DealInfo).filter( + DealInfo.status == "active", DealInfo.deal_price.isnot(None), DealInfo.deal_price > 0 + ) + if version != "其他" and version in version_prefix_map: + query = query.filter(DealInfo.title.startswith(version_prefix_map[version])) + + deals = query.all() + stats = defaultdict(lambda: defaultdict(lambda: {"count": 0, "total": 0})) + + for deal in deals: + content = deal.content or "" + packaging = deal.packaging + if not packaging and "包装:" in content: + packaging = content.split("包装:")[1].split("\n")[0].strip() + category = deal.category + if not category and "分类:" in content: + category = content.split("分类:")[1].split("\n")[0].strip() + if category in category_map: + category = category_map[category] + packaging = packaging or "单张" + category = category or "带4号" + stats[packaging][category]["count"] += 1 + stats[packaging][category]["total"] += deal.deal_price + + result = [] + category_order = ['带4号', '带7号', '永恒号', '天马号', '天马王', '金山号', '金山王', '钻石号', '朦胧号', '朦胧王', '金马号', '金马王', '倒置号', '圆圆号'] + for cat in category_order: + row = {"category": cat} + has_data = False + for pkg in packagings: + data = stats[pkg][cat] + if data["count"] > 0: + row[pkg] = {"avg": round(data["total"] / data["count"]), "count": data["count"]} + has_data = True + else: + row[pkg] = None + if has_data: + result.append(row) + return {"version": version, "data": result} + +@router.get("/{deal_id}", response_model=DealInfoResponse) +def get_deal( + deal_id: str, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取成交行情详情""" + deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() + if not deal: + raise HTTPException(status_code=404, detail="成交行情不存在") + + # 增加浏览数 + deal.view_count += 1 + db.commit() + + return deal + +@router.put("/{deal_id}", response_model=DealInfoResponse) +def update_deal( + deal_id: str, + data: DealInfoUpdate, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新成交行情""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() + if not deal: + raise HTTPException(status_code=404, detail="成交行情不存在") + + # 处理日期 + if data.deal_date: + try: + data.deal_date = datetime.strptime(data.deal_date, "%Y-%m-%d").date() + except: + data.deal_date = None + + for key, value in data.model_dump(exclude_unset=True).items(): + setattr(deal, key, value) + + db.commit() + db.refresh(deal) + return deal + +@router.delete("/{deal_id}") +def delete_deal( + deal_id: str, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除成交行情""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() + if not deal: + raise HTTPException(status_code=404, detail="成交行情不存在") + + deal.status = "deleted" + db.commit() + + return {"message": "删除成功"} \ No newline at end of file diff --git a/backend/app/routers/information.py b/backend/app/routers/information.py new file mode 100644 index 0000000..fc65d26 --- /dev/null +++ b/backend/app/routers/information.py @@ -0,0 +1,1066 @@ +# 资讯API路由 +from fastapi import APIRouter, Depends, HTTPException, Query +from sqlalchemy.orm import Session, joinedload +from typing import List, Optional +from pydantic import BaseModel +from datetime import datetime, date + +from app.core.database import get_db +from app.core.auth import get_current_user +from app.core.coolbot_db import coolbot_engine +from sqlalchemy import text +from app.models.models import User, Information, Collection + +router = APIRouter(prefix="/api/information", tags=["资讯"]) + + +# Schema +class InformationCreate(BaseModel): + info_type: str # seek-寻配号, deal-成交数据, publish-发布 + title: str + content: Optional[str] = None + collection_id: Optional[str] = None + expect_category: Optional[str] = None + expect_version: Optional[str] = None + expect_packaging: Optional[str] = None + expect_number: Optional[str] = None + expect_price_min: Optional[float] = None + expect_price_max: Optional[float] = None + deal_price: Optional[float] = None + deal_date: Optional[date] = None + + +class InformationUpdate(BaseModel): + title: Optional[str] = None + content: Optional[str] = None + status: Optional[str] = None + expect_category: Optional[str] = None + expect_version: Optional[str] = None + expect_packaging: Optional[str] = None + expect_number: Optional[str] = None + expect_price_min: Optional[float] = None + expect_price_max: Optional[float] = None + deal_price: Optional[float] = None + deal_date: Optional[date] = None + + +class InformationResponse(BaseModel): + id: str + user_id: str + info_type: str + title: str + content: Optional[str] + collection_id: Optional[str] + expect_category: Optional[str] + expect_version: Optional[str] + expect_packaging: Optional[str] + expect_number: Optional[str] + expect_price_min: Optional[float] + expect_price_max: Optional[float] + deal_price: Optional[float] + deal_date: Optional[date] + status: str + is_matched: Optional[str] = "pending" + matched_user_id: Optional[str] = None + matched_contact: Optional[str] = None + view_count: int + contact_count: int + created_at: datetime + # 用户信息 + user_name: Optional[str] = None + user_avatar: Optional[str] = None + # 关联藏品信息 + collection_name: Optional[str] = None + collection_category: Optional[str] = None + collection_version: Optional[str] = None + collection_number: Optional[str] = None + # 匹配数量(我的藏品中满足条件的数量) + matched_count: Optional[int] = 0 + + class Config: + from_attributes = True + + +# 资讯列表 +@router.get("/list", response_model=List[InformationResponse]) +def get_information_list( + info_type: Optional[str] = Query(None, description="类型: seek/deal/publish"), + status: str = Query("active", description="状态: active/closed/expired"), + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=100), + current_user: Optional[User] = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取资讯列表(公开,无需登录)""" + query = db.query(Information).options( + joinedload(Information.user), + joinedload(Information.collection) + ).filter(Information.status == status) + + if info_type: + query = query.filter(Information.info_type == info_type) + + # 按创建时间倒序 + query = query.order_by(Information.created_at.desc()) + + # 分页 + offset = (page - 1) * page_size + items = query.offset(offset).limit(page_size).all() + + # 转换结果 + result = [] + for item in items: + # 计算匹配数量(仅对seek类型,且用户登录时) + matched_count = 0 + if item.info_type == 'seek' and item.expect_number and current_user: + 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, + )) + + return result + + +def match_collections_count(db: Session, user_id: str, expect_number: str) -> int: + """根据号码特征计算匹配藏品数量""" + 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 '' + # 去掉J0前缀后取前8位 + 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数据库,匹配所有藏品)""" + if not expect_number or len(expect_number) < 4: + return 0 + + # 取后8位或更少进行匹配 + pattern = expect_number[2:] if len(expect_number) > 2 else expect_number + 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) >= 8 + """) + + 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) >= 8: + # 取后8位进行匹配 + col_pattern = crown_code[-8:] + if match_pattern(col_pattern, pattern): + match_count += 1 + return match_count + except Exception as e: + print("Error querying coolbot_data: {}".format(e)) + return 0 + + +def match_collections_list_from_coolbot(expect_number: str, limit: int = 20) -> List[dict]: + """获取匹配的藏品列表(从coolbot_data数据库,匹配所有藏品)""" + if not expect_number or len(expect_number) < 4: + return [] + + # 取后8位或更少进行匹配 + pattern = expect_number[2:] if len(expect_number) > 2 else expect_number + 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) >= 8 + """) + + 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[-8:] + 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": str(row[8]) if row[8] else None + }) + if len(matched) >= limit: + break + return matched + except Exception as e: + print(f"Error querying coolbot_data: {e}") + return [] + + + +def match_pattern(col_number: str, pattern: str) -> bool: + """匹配号码特征模式""" + # X = 任意数字 + # A = 非4 + # B = 非47 + # C = 非347 + # D = 非247 + # E = 非2347 + # F = 非23457 + # G = 非123457 + + # 注意:col_number已经是去掉J0前缀后的8位号码,不需要再处理 + col_num = col_number + + for i, p in enumerate(pattern): + if i >= len(col_num): + return False + + c = col_num[i] + + if p == 'X': + if not c.isdigit(): + return False + elif p == 'A': + if c == '4': + return False + elif p == 'B': + if c in '47': + 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 == 'F': + if c in '23457': + return False + elif p == 'G': + if c in '123457': + return False + else: + # 数字或字母必须完全匹配 + if p != c: + return False + + return True + + +# 获取单条资讯 +@router.get("/{info_id}", response_model=InformationResponse) +def get_information( + info_id: str, + db: Session = Depends(get_db) +): + """获取资讯详情""" + item = db.query(Information).options( + joinedload(Information.user), + joinedload(Information.collection) + ).filter(Information.id == info_id).first() + + if not item: + raise HTTPException(status_code=404, detail="资讯不存在") + + # 增加浏览次数 + item.view_count += 1 + db.commit() + + return 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, + 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, + ) + + +# 发布资讯 +@router.post("/", response_model=InformationResponse) +def create_information( + data: InformationCreate, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """发布资讯""" + info = Information( + user_id=current_user.f99_90_id, + info_type=data.info_type, + title=data.title, + content=data.content, + collection_id=data.collection_id, + expect_category=data.expect_category, + expect_version=data.expect_version, + expect_packaging=data.expect_packaging, + expect_number=data.expect_number, + expect_price_min=data.expect_price_min, + expect_price_max=data.expect_price_max, + deal_price=data.deal_price, + deal_date=data.deal_date, + status="active" + ) + db.add(info) + db.commit() + db.refresh(info) + + return InformationResponse( + id=info.id, + user_id=info.user_id, + info_type=info.info_type, + title=info.title, + content=info.content, + collection_id=info.collection_id, + expect_category=info.expect_category, + expect_version=info.expect_version, + expect_packaging=info.expect_packaging, + expect_number=info.expect_number, + expect_price_min=info.expect_price_min, + expect_price_max=info.expect_price_max, + deal_price=info.deal_price, + deal_date=info.deal_date, + status=info.status, + view_count=info.view_count, + contact_count=info.contact_count, + created_at=info.created_at, + user_name=current_user.f01_01_name, + user_avatar=current_user.avatar, + collection_name=None, + collection_category=None, + collection_version=None, + collection_number=None, + ) + + +# 更新资讯 +@router.put("/{info_id}", response_model=InformationResponse) +def update_information( + info_id: str, + data: InformationUpdate, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新资讯""" + info = db.query(Information).filter( + Information.id == info_id, + Information.user_id == current_user.f99_90_id + ).first() + + if not info: + raise HTTPException(status_code=404, detail="资讯不存在或无权修改") + + # 更新字段 + if data.title is not None: + info.title = data.title + if data.content is not None: + info.content = data.content + if data.status is not None: + info.status = data.status + if data.expect_category is not None: + info.expect_category = data.expect_category + if data.expect_version is not None: + info.expect_version = data.expect_version + if data.expect_packaging is not None: + info.expect_packaging = data.expect_packaging + if data.expect_number is not None: + info.expect_number = data.expect_number + if data.expect_price_min is not None: + info.expect_price_min = data.expect_price_min + if data.expect_price_max is not None: + info.expect_price_max = data.expect_price_max + if data.deal_price is not None: + info.deal_price = data.deal_price + if data.deal_date is not None: + info.deal_date = data.deal_date + + db.commit() + db.refresh(info) + + return InformationResponse( + id=info.id, + user_id=info.user_id, + info_type=info.info_type, + title=info.title, + content=info.content, + collection_id=info.collection_id, + expect_category=info.expect_category, + expect_version=info.expect_version, + expect_packaging=info.expect_packaging, + expect_number=info.expect_number, + expect_price_min=info.expect_price_min, + expect_price_max=info.expect_price_max, + deal_price=info.deal_price, + deal_date=info.deal_date, + status=info.status, + view_count=info.view_count, + contact_count=info.contact_count, + created_at=info.created_at, + user_name=current_user.f01_01_name, + user_avatar=current_user.avatar, + collection_name=info.collection.f01_01_name if info.collection else None, + collection_category=info.collection.f01_03_category if info.collection else None, + collection_version=info.collection.f02_11_version if info.collection else None, + collection_number=info.collection.f02_10_prefix_serial if info.collection else None, + ) + + +# 删除资讯 +@router.delete("/{info_id}") +def delete_information( + info_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除资讯""" + # 允许admin删除任何人的资讯 + if current_user.role == "admin": + info = db.query(Information).filter(Information.id == info_id).first() + else: + info = db.query(Information).filter( + Information.id == info_id, + Information.user_id == current_user.f99_90_id + ).first() + + if not info: + raise HTTPException(status_code=404, detail="资讯不存在或无权删除") + + db.delete(info) + db.commit() + + return {"message": "删除成功"} + + +# 寻配号 - 自动匹配推荐藏品 +@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="请先登录") + + info = db.query(Information).filter( + Information.id == info_id, + Information.info_type == "seek" + ).first() + + if not info: + raise HTTPException(status_code=404, detail="寻配号信息不存在") + + # 更新用户配号(寻号)次数 + current_user.f99_96_search_count = (current_user.f99_96_search_count or 0) + 1 + db.commit() + + # 获取用户所有藏品 + collections = db.query(Collection).filter( + Collection.f99_91_user_id == current_user.f99_90_id, + Collection.f01_04_status == "in_collection" + ).all() + + # 去掉版别筛选,因为藏品分类和发布需求的版别不同 + # if info.expect_category: + # collections = [c for c in collections if c.f01_03_category == info.expect_category] + + # 按号码特征模式匹配 + 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 '' + # 去掉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 + ] + } + + +# 我的寻号列表 +@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: + # 计算匹配数量 + 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, + )) + + return result + + +# 成交数据统计 +@router.get("/deal/stats") +def get_deal_stats( + days: int = Query(7, ge=1, le=90, description="统计天数"), + db: Session = Depends(get_db) +): + """获取成交数据统计""" + from sqlalchemy import func + from datetime import timedelta + + start_date = datetime.now() - timedelta(days=days) + + # 按版别统计 + by_version = db.query( + Information.expect_version, + func.count(Information.id).label("count"), + func.avg(Information.deal_price).label("avg_price"), + func.max(Information.deal_price).label("max_price"), + func.min(Information.deal_price).label("min_price") + ).filter( + Information.info_type == "deal", + Information.status == "active", + Information.created_at >= start_date + ).group_by(Information.expect_version).all() + + # 按包装统计 + by_packaging = db.query( + Information.expect_packaging, + func.count(Information.id).label("count"), + func.avg(Information.deal_price).label("avg_price") + ).filter( + Information.info_type == "deal", + Information.status == "active", + Information.created_at >= start_date + ).group_by(Information.expect_packaging).all() + + # 按号码分类统计 + by_number = db.query( + Information.expect_number, + func.count(Information.id).label("count"), + func.avg(Information.deal_price).label("avg_price") + ).filter( + Information.info_type == "deal", + Information.status == "active", + Information.expect_number.isnot(None), + Information.created_at >= start_date + ).group_by(Information.expect_number).all() + + return { + "days": days, + "by_version": [ + {"version": r[0] or "未知", "count": r[1], "avg_price": float(r[2] or 0), "max_price": float(r[3] or 0), "min_price": float(r[4] or 0)} + for r in by_version if r[0] + ], + "by_packaging": [ + {"packaging": r[0] or "未知", "count": r[1], "avg_price": float(r[2] or 0)} + for r in by_packaging if r[0] + ], + "by_number": [ + {"number": r[0], "count": r[1], "avg_price": float(r[2] or 0)} + for r in by_number + ] + } + + +# 获取我的发布列表 +@router.get("/my/list", response_model=List[InformationResponse]) +def get_my_information_list( + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=100), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取我的发布列表""" + items = db.query(Information).options( + joinedload(Information.collection) + ).filter( + Information.user_id == current_user.f99_90_id + ).order_by(Information.created_at.desc()).offset((page-1)*page_size).limit(page_size).all() + + result = [] + for item in items: + 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=current_user.f01_01_name, + user_avatar=current_user.avatar, + 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, + )) + + return result + +# ============ 获取当前用户发布的列表 ============ +@router.get("/my") +def get_my_information( + page: int = Query(1, ge=1), + limit: int = Query(20, ge=1, le=100), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取当前用户发布的信息列表""" + total = db.query(Information).filter(Information.author == current_user.f01_01_name).count() + infos = db.query(Information).filter( + Information.author == current_user.f01_01_name + ).order_by(Information.created_at.desc()).offset((page-1)*limit).limit(limit).all() + + return { + "total": total, + "list": [{ + "id": i.id, + "title": i.title, + "content": i.content, + "info_type": i.info_type, + "author": i.author, + "created_at": i.created_at.isoformat() if i.created_at else None + } for i in infos] + } + + +# ============ 匹配寻号 ============ +class MatchSeekRequest(BaseModel): + info_id: str + collection_id: Optional[str] = None + 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="寻配号信息不存在") + + # 检查是否已被匹配(一个寻号只能被一个用户匹配) + if info.is_matched == "matched": + 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 "" + # 添加匹配信息:藏品被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"} + + +# ============ 添加留言 ============ +class CommentRequest(BaseModel): + information_id: str + content: str + + +@router.post("/comment") +def add_comment( + request: CommentRequest, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """添加留言""" + info = db.query(Information).filter( + Information.id == request.information_id + ).first() + + if not info: + raise HTTPException(status_code=404, detail="资讯不存在") + + # 创建留言 + from app.models.models import InformationComment + comment = InformationComment( + information_id=request.information_id, + user_id=current_user.f99_90_id, + content=request.content + ) + db.add(comment) + db.commit() + + return { + "message": "留言成功", + "comment": { + "id": comment.id, + "content": comment.content, + "user_name": current_user.f01_01_name, + "user_avatar": current_user.avatar, + "created_at": comment.created_at + } + } + + +# ============ 获取评论列表 ============ +@router.get("/comments/{information_id}") +def get_comments( + information_id: str, + db: Session = Depends(get_db) +): + """获取资讯的评论列表""" + from app.models.models import InformationComment + comments = db.query(InformationComment).filter( + InformationComment.information_id == information_id + ).order_by(InformationComment.created_at.desc()).all() + + return [ + { + "id": c.id, + "content": c.content, + "user_name": c.user.f01_01_name if c.user else '匿名用户', + "user_avatar": c.user.avatar if c.user else None, + "created_at": c.created_at + } + for c in 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="寻配号信息不存在") + + # 只有发布者可以看到匹配者信息 + 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, + "matched_at": info.updated_at.isoformat() if info.updated_at else None + } + + +# ============ 获取发布者信息 ============ +@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="寻配号信息不存在") + + # 只有匹配者可以看到发布者信息 + 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, + "created_at": info.created_at.isoformat() if info.created_at else None + } + + +# 获取网络数据匹配列表 +@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 + } + + +# 获取所有seek列表(包含网络匹配数量) +@router.get("/seek/list") +def get_seek_list_all( + status: str = Query("active"), + user_id: Optional[str] = None, + user_only: bool = Query(False), + current_user: Optional[User] = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取寻配号列表(包含网络匹配数量)""" + query = db.query(Information).filter( + Information.info_type == "seek", + Information.status == status + ) + + if user_only and current_user: + query = query.filter(Information.user_id == current_user.f99_90_id) + + if user_id: + query = query.filter(Information.user_id == user_id) + + items = query.order_by(Information.created_at.desc()).all() + + result = [] + for item in items: + # 计算自有匹配数量 + matched_count = 0 + if item.expect_number: + matched_count = match_collections_count(db, current_user.f99_90_id if current_user else "", item.expect_number) + + # 计算网络匹配数量 + 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, + "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, + "created_at": item.created_at.isoformat() if item.created_at else None, + "user_name": item.user.f01_01_name if item.user else None, + "matched_count": matched_count, + "network_matched_count": network_matched_count + }) + + return result diff --git a/backend/app/routers/information.py.bak b/backend/app/routers/information.py.bak new file mode 100644 index 0000000..46ed3b8 --- /dev/null +++ b/backend/app/routers/information.py.bak @@ -0,0 +1,1065 @@ +# 资讯API路由 +from fastapi import APIRouter, Depends, HTTPException, Query +from sqlalchemy.orm import Session, joinedload +from typing import List, Optional +from pydantic import BaseModel +from datetime import datetime, date + +from app.core.database import get_db +from app.core.auth import get_current_user +from app.core.coolbot_db import coolbot_engine +from sqlalchemy import text +from app.models.models import User, Information, Collection + +router = APIRouter(prefix="/api/information", tags=["资讯"]) + + +# Schema +class InformationCreate(BaseModel): + info_type: str # seek-寻配号, deal-成交数据, publish-发布 + title: str + content: Optional[str] = None + collection_id: Optional[str] = None + expect_category: Optional[str] = None + expect_version: Optional[str] = None + expect_packaging: Optional[str] = None + expect_number: Optional[str] = None + expect_price_min: Optional[float] = None + expect_price_max: Optional[float] = None + deal_price: Optional[float] = None + deal_date: Optional[date] = None + + +class InformationUpdate(BaseModel): + title: Optional[str] = None + content: Optional[str] = None + status: Optional[str] = None + expect_category: Optional[str] = None + expect_version: Optional[str] = None + expect_packaging: Optional[str] = None + expect_number: Optional[str] = None + expect_price_min: Optional[float] = None + expect_price_max: Optional[float] = None + deal_price: Optional[float] = None + deal_date: Optional[date] = None + + +class InformationResponse(BaseModel): + id: str + user_id: str + info_type: str + title: str + content: Optional[str] + collection_id: Optional[str] + expect_category: Optional[str] + expect_version: Optional[str] + expect_packaging: Optional[str] + expect_number: Optional[str] + expect_price_min: Optional[float] + expect_price_max: Optional[float] + deal_price: Optional[float] + deal_date: Optional[date] + status: str + is_matched: Optional[str] = "pending" + matched_user_id: Optional[str] = None + matched_contact: Optional[str] = None + view_count: int + contact_count: int + created_at: datetime + # 用户信息 + user_name: Optional[str] = None + user_avatar: Optional[str] = None + # 关联藏品信息 + collection_name: Optional[str] = None + collection_category: Optional[str] = None + collection_version: Optional[str] = None + collection_number: Optional[str] = None + # 匹配数量(我的藏品中满足条件的数量) + matched_count: Optional[int] = 0 + + class Config: + from_attributes = True + + +# 资讯列表 +@router.get("/list", response_model=List[InformationResponse]) +def get_information_list( + info_type: Optional[str] = Query(None, description="类型: seek/deal/publish"), + status: str = Query("active", description="状态: active/closed/expired"), + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=100), + current_user: Optional[User] = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取资讯列表(公开,无需登录)""" + query = db.query(Information).options( + joinedload(Information.user), + joinedload(Information.collection) + ).filter(Information.status == status) + + if info_type: + query = query.filter(Information.info_type == info_type) + + # 按创建时间倒序 + query = query.order_by(Information.created_at.desc()) + + # 分页 + offset = (page - 1) * page_size + items = query.offset(offset).limit(page_size).all() + + # 转换结果 + result = [] + for item in items: + # 计算匹配数量(仅对seek类型,且用户登录时) + matched_count = 0 + if item.info_type == 'seek' and item.expect_number and current_user: + 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, + )) + + return result + + +def match_collections_count(db: Session, user_id: str, expect_number: str) -> int: + """根据号码特征计算匹配藏品数量""" + 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 '' + # 去掉J0前缀后取前8位 + 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数据库)""" + if not expect_number or len(expect_number) != 10: + return 0 + if not expect_number.startswith('J0'): + return 0 + pattern = expect_number[2:] + 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数据库)""" + if not expect_number or len(expect_number) != 10: + return [] + if not expect_number.startswith('J0'): + return [] + pattern = expect_number[2:] + 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": str(row[8]) if row[8] else None + }) + if len(matched) >= limit: + break + return matched + except Exception as e: + print(f"Error querying coolbot_data: {e}") + return [] + + + +def match_pattern(col_number: str, pattern: str) -> bool: + """匹配号码特征模式""" + # X = 任意数字 + # A = 非4 + # B = 非47 + # C = 非347 + # D = 非247 + # E = 非2347 + # F = 非23457 + # G = 非123457 + + # 注意:col_number已经是去掉J0前缀后的8位号码,不需要再处理 + col_num = col_number + + for i, p in enumerate(pattern): + if i >= len(col_num): + return False + + c = col_num[i] + + if p == 'X': + if not c.isdigit(): + return False + elif p == 'A': + if c == '4': + return False + elif p == 'B': + if c in '47': + 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 == 'F': + if c in '23457': + return False + elif p == 'G': + if c in '123457': + return False + else: + # 数字或字母必须完全匹配 + if p != c: + return False + + return True + + +# 获取单条资讯 +@router.get("/{info_id}", response_model=InformationResponse) +def get_information( + info_id: str, + db: Session = Depends(get_db) +): + """获取资讯详情""" + item = db.query(Information).options( + joinedload(Information.user), + joinedload(Information.collection) + ).filter(Information.id == info_id).first() + + if not item: + raise HTTPException(status_code=404, detail="资讯不存在") + + # 增加浏览次数 + item.view_count += 1 + db.commit() + + return 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, + 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, + ) + + +# 发布资讯 +@router.post("/", response_model=InformationResponse) +def create_information( + data: InformationCreate, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """发布资讯""" + info = Information( + user_id=current_user.f99_90_id, + info_type=data.info_type, + title=data.title, + content=data.content, + collection_id=data.collection_id, + expect_category=data.expect_category, + expect_version=data.expect_version, + expect_packaging=data.expect_packaging, + expect_number=data.expect_number, + expect_price_min=data.expect_price_min, + expect_price_max=data.expect_price_max, + deal_price=data.deal_price, + deal_date=data.deal_date, + status="active" + ) + db.add(info) + db.commit() + db.refresh(info) + + return InformationResponse( + id=info.id, + user_id=info.user_id, + info_type=info.info_type, + title=info.title, + content=info.content, + collection_id=info.collection_id, + expect_category=info.expect_category, + expect_version=info.expect_version, + expect_packaging=info.expect_packaging, + expect_number=info.expect_number, + expect_price_min=info.expect_price_min, + expect_price_max=info.expect_price_max, + deal_price=info.deal_price, + deal_date=info.deal_date, + status=info.status, + view_count=info.view_count, + contact_count=info.contact_count, + created_at=info.created_at, + user_name=current_user.f01_01_name, + user_avatar=current_user.avatar, + collection_name=None, + collection_category=None, + collection_version=None, + collection_number=None, + ) + + +# 更新资讯 +@router.put("/{info_id}", response_model=InformationResponse) +def update_information( + info_id: str, + data: InformationUpdate, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新资讯""" + info = db.query(Information).filter( + Information.id == info_id, + Information.user_id == current_user.f99_90_id + ).first() + + if not info: + raise HTTPException(status_code=404, detail="资讯不存在或无权修改") + + # 更新字段 + if data.title is not None: + info.title = data.title + if data.content is not None: + info.content = data.content + if data.status is not None: + info.status = data.status + if data.expect_category is not None: + info.expect_category = data.expect_category + if data.expect_version is not None: + info.expect_version = data.expect_version + if data.expect_packaging is not None: + info.expect_packaging = data.expect_packaging + if data.expect_number is not None: + info.expect_number = data.expect_number + if data.expect_price_min is not None: + info.expect_price_min = data.expect_price_min + if data.expect_price_max is not None: + info.expect_price_max = data.expect_price_max + if data.deal_price is not None: + info.deal_price = data.deal_price + if data.deal_date is not None: + info.deal_date = data.deal_date + + db.commit() + db.refresh(info) + + return InformationResponse( + id=info.id, + user_id=info.user_id, + info_type=info.info_type, + title=info.title, + content=info.content, + collection_id=info.collection_id, + expect_category=info.expect_category, + expect_version=info.expect_version, + expect_packaging=info.expect_packaging, + expect_number=info.expect_number, + expect_price_min=info.expect_price_min, + expect_price_max=info.expect_price_max, + deal_price=info.deal_price, + deal_date=info.deal_date, + status=info.status, + view_count=info.view_count, + contact_count=info.contact_count, + created_at=info.created_at, + user_name=current_user.f01_01_name, + user_avatar=current_user.avatar, + collection_name=info.collection.f01_01_name if info.collection else None, + collection_category=info.collection.f01_03_category if info.collection else None, + collection_version=info.collection.f02_11_version if info.collection else None, + collection_number=info.collection.f02_10_prefix_serial if info.collection else None, + ) + + +# 删除资讯 +@router.delete("/{info_id}") +def delete_information( + info_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除资讯""" + # 允许admin删除任何人的资讯 + if current_user.role == "admin": + info = db.query(Information).filter(Information.id == info_id).first() + else: + info = db.query(Information).filter( + Information.id == info_id, + Information.user_id == current_user.f99_90_id + ).first() + + if not info: + raise HTTPException(status_code=404, detail="资讯不存在或无权删除") + + db.delete(info) + db.commit() + + return {"message": "删除成功"} + + +# 寻配号 - 自动匹配推荐藏品 +@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="请先登录") + + info = db.query(Information).filter( + Information.id == info_id, + Information.info_type == "seek" + ).first() + + if not info: + raise HTTPException(status_code=404, detail="寻配号信息不存在") + + # 更新用户配号(寻号)次数 + current_user.f99_96_search_count = (current_user.f99_96_search_count or 0) + 1 + db.commit() + + # 获取用户所有藏品 + collections = db.query(Collection).filter( + Collection.f99_91_user_id == current_user.f99_90_id, + Collection.f01_04_status == "in_collection" + ).all() + + # 去掉版别筛选,因为藏品分类和发布需求的版别不同 + # if info.expect_category: + # collections = [c for c in collections if c.f01_03_category == info.expect_category] + + # 按号码特征模式匹配 + 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 '' + # 去掉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 + ] + } + + +# 我的寻号列表 +@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: + # 计算匹配数量 + 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, + )) + + return result + + +# 成交数据统计 +@router.get("/deal/stats") +def get_deal_stats( + days: int = Query(7, ge=1, le=90, description="统计天数"), + db: Session = Depends(get_db) +): + """获取成交数据统计""" + from sqlalchemy import func + from datetime import timedelta + + start_date = datetime.now() - timedelta(days=days) + + # 按版别统计 + by_version = db.query( + Information.expect_version, + func.count(Information.id).label("count"), + func.avg(Information.deal_price).label("avg_price"), + func.max(Information.deal_price).label("max_price"), + func.min(Information.deal_price).label("min_price") + ).filter( + Information.info_type == "deal", + Information.status == "active", + Information.created_at >= start_date + ).group_by(Information.expect_version).all() + + # 按包装统计 + by_packaging = db.query( + Information.expect_packaging, + func.count(Information.id).label("count"), + func.avg(Information.deal_price).label("avg_price") + ).filter( + Information.info_type == "deal", + Information.status == "active", + Information.created_at >= start_date + ).group_by(Information.expect_packaging).all() + + # 按号码分类统计 + by_number = db.query( + Information.expect_number, + func.count(Information.id).label("count"), + func.avg(Information.deal_price).label("avg_price") + ).filter( + Information.info_type == "deal", + Information.status == "active", + Information.expect_number.isnot(None), + Information.created_at >= start_date + ).group_by(Information.expect_number).all() + + return { + "days": days, + "by_version": [ + {"version": r[0] or "未知", "count": r[1], "avg_price": float(r[2] or 0), "max_price": float(r[3] or 0), "min_price": float(r[4] or 0)} + for r in by_version if r[0] + ], + "by_packaging": [ + {"packaging": r[0] or "未知", "count": r[1], "avg_price": float(r[2] or 0)} + for r in by_packaging if r[0] + ], + "by_number": [ + {"number": r[0], "count": r[1], "avg_price": float(r[2] or 0)} + for r in by_number + ] + } + + +# 获取我的发布列表 +@router.get("/my/list", response_model=List[InformationResponse]) +def get_my_information_list( + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=100), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取我的发布列表""" + items = db.query(Information).options( + joinedload(Information.collection) + ).filter( + Information.user_id == current_user.f99_90_id + ).order_by(Information.created_at.desc()).offset((page-1)*page_size).limit(page_size).all() + + result = [] + for item in items: + 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=current_user.f01_01_name, + user_avatar=current_user.avatar, + 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, + )) + + return result + +# ============ 获取当前用户发布的列表 ============ +@router.get("/my") +def get_my_information( + page: int = Query(1, ge=1), + limit: int = Query(20, ge=1, le=100), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取当前用户发布的信息列表""" + total = db.query(Information).filter(Information.author == current_user.f01_01_name).count() + infos = db.query(Information).filter( + Information.author == current_user.f01_01_name + ).order_by(Information.created_at.desc()).offset((page-1)*limit).limit(limit).all() + + return { + "total": total, + "list": [{ + "id": i.id, + "title": i.title, + "content": i.content, + "info_type": i.info_type, + "author": i.author, + "created_at": i.created_at.isoformat() if i.created_at else None + } for i in infos] + } + + +# ============ 匹配寻号 ============ +class MatchSeekRequest(BaseModel): + info_id: str + collection_id: Optional[str] = None + 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="寻配号信息不存在") + + # 检查是否已被匹配(一个寻号只能被一个用户匹配) + if info.is_matched == "matched": + 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 "" + # 添加匹配信息:藏品被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"} + + +# ============ 添加留言 ============ +class CommentRequest(BaseModel): + information_id: str + content: str + + +@router.post("/comment") +def add_comment( + request: CommentRequest, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """添加留言""" + info = db.query(Information).filter( + Information.id == request.information_id + ).first() + + if not info: + raise HTTPException(status_code=404, detail="资讯不存在") + + # 创建留言 + from app.models.models import InformationComment + comment = InformationComment( + information_id=request.information_id, + user_id=current_user.f99_90_id, + content=request.content + ) + db.add(comment) + db.commit() + + return { + "message": "留言成功", + "comment": { + "id": comment.id, + "content": comment.content, + "user_name": current_user.f01_01_name, + "user_avatar": current_user.avatar, + "created_at": comment.created_at + } + } + + +# ============ 获取评论列表 ============ +@router.get("/comments/{information_id}") +def get_comments( + information_id: str, + db: Session = Depends(get_db) +): + """获取资讯的评论列表""" + from app.models.models import InformationComment + comments = db.query(InformationComment).filter( + InformationComment.information_id == information_id + ).order_by(InformationComment.created_at.desc()).all() + + return [ + { + "id": c.id, + "content": c.content, + "user_name": c.user.f01_01_name if c.user else '匿名用户', + "user_avatar": c.user.avatar if c.user else None, + "created_at": c.created_at + } + for c in 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="寻配号信息不存在") + + # 只有发布者可以看到匹配者信息 + 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, + "matched_at": info.updated_at.isoformat() if info.updated_at else None + } + + +# ============ 获取发布者信息 ============ +@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="寻配号信息不存在") + + # 只有匹配者可以看到发布者信息 + 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, + "created_at": info.created_at.isoformat() if info.created_at else None + } + + +# 获取网络数据匹配列表 +@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 + } + + +# 获取所有seek列表(包含网络匹配数量) +@router.get("/seek/list") +def get_seek_list_all( + status: str = Query("active"), + user_id: Optional[str] = None, + user_only: bool = Query(False), + current_user: Optional[User] = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取寻配号列表(包含网络匹配数量)""" + query = db.query(Information).filter( + Information.info_type == "seek", + Information.status == status + ) + + if user_only and current_user: + query = query.filter(Information.user_id == current_user.f99_90_id) + + if user_id: + query = query.filter(Information.user_id == user_id) + + items = query.order_by(Information.created_at.desc()).all() + + result = [] + for item in items: + # 计算自有匹配数量 + matched_count = 0 + if item.expect_number: + matched_count = match_collections_count(db, current_user.f99_90_id if current_user else "", item.expect_number) + + # 计算网络匹配数量 + 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, + "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, + "created_at": item.created_at.isoformat() if item.created_at else None, + "user_name": item.user.f01_01_name if item.user else None, + "matched_count": matched_count, + "network_matched_count": network_matched_count + }) + + return result diff --git a/backend/app/routers/news.py b/backend/app/routers/news.py new file mode 100644 index 0000000..c969522 --- /dev/null +++ b/backend/app/routers/news.py @@ -0,0 +1,128 @@ +from fastapi import APIRouter, Depends, HTTPException, Query +from sqlalchemy import Table, MetaData +from sqlalchemy.orm import Session +from pydantic import BaseModel +from typing import Optional, List +from datetime import datetime, date +from app.core.database import get_db, engine +from app.models.models import User +from app.routers.auth import get_current_user + +router = APIRouter(prefix="/api/news", tags=["资讯"]) +metadata = MetaData() + +# 分类表 +categories_table = Table('news_categories', metadata, autoload_with=engine) +news_table = Table('news', metadata, autoload_with=engine) +user_posts_table = Table('user_posts', metadata, autoload_with=engine) +users_table = Table('users', metadata, autoload_with=engine) +deals_table = Table('deals', metadata, autoload_with=engine) +notifications_table = Table('notifications', metadata, autoload_with=engine) + +# ============ 获取分类 ============ +@router.get("/categories") +def get_categories(db: Session = Depends(get_db)): + results = db.query(categories_table).order_by(categories_table.c.sort_order).all() + return [dict(r._mapping) for r in results] + +# ============ 获取资讯 ============ +@router.get("") +def get_news( + category_id: Optional[int] = None, + page: int = 1, + limit: int = 20, + db: Session = Depends(get_db) +): + query = db.query(news_table) + if category_id: + query = query.filter(news_table.c.category_id == category_id) + offset = (page - 1) * limit + results = query.order_by(news_table.c.created_at.desc()).offset(offset).limit(limit).all() + return [dict(r._mapping) for r in results] + +# ============ 获取用户发布 ============ +@router.get("/posts") +def get_posts( + post_type: Optional[str] = None, + status: str = "active", + page: int = 1, + limit: int = 20, + db: Session = Depends(get_db) +): + query = db.query(user_posts_table).filter(user_posts_table.c.status == status) + if post_type: + query = query.filter(user_posts_table.c.post_type == post_type) + offset = (page - 1) * limit + results = query.order_by(user_posts_table.c.created_at.desc()).offset(offset).limit(limit).all() + return [dict(r._mapping) for r in results] + +# ============ 创建发布 ============ +class PostCreate(BaseModel): + post_type: str + title: str + content: Optional[str] = None + zodiac_type: Optional[str] = None + packaging: Optional[str] = None + +@router.post("/posts") +def create_post( + post: PostCreate, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + result = db.execute(user_posts_table.insert().values( + user_id=current_user.f99_90_id, + post_type=post.post_type, + title=post.title, + content=post.content, + zodiac_type=post.zodiac_type, + packaging=post.packaging, + status="pending" + )) + db.commit() + return {"success": True, "id": result.inserted_primary_key[0]} + +# ============ 成交数据 ============ +@router.get("/deals") +def get_deals( + zodiac_type: Optional[str] = None, + limit: int = 20, + db: Session = Depends(get_db) +): + query = db.query(deals_table) + if zodiac_type: + query = query.filter(deals_table.c.zodiac_type == zodiac_type) + results = query.order_by(deals_table.c.deal_date.desc()).limit(limit).all() + return [dict(r._mapping) for r in results] + +# ============ 通知 ============ +@router.get("/notifications") +def get_notifications(limit: int = 10, db: Session = Depends(get_db)): + results = db.query(notifications_table).filter( + notifications_table.c.is_published == True + ).order_by(notifications_table.c.created_at.desc()).limit(limit).all() + return [dict(r._mapping) for r in results] + +# ============ 首页数据 ============ +@router.get("/home") +def get_home(db: Session = Depends(get_db)): + # 推荐发布 + posts = db.query(user_posts_table).filter( + user_posts_table.c.status == "active" + ).order_by(user_posts_table.c.created_at.desc()).limit(10).all() + + # 成交 + deals = db.query(deals_table).order_by( + deals_table.c.deal_date.desc() + ).limit(10).all() + + # 通知 + notices = db.query(notifications_table).filter( + notifications_table.c.is_published == True + ).order_by(notifications_table.c.created_at.desc()).limit(5).all() + + return { + "posts": [dict(p._mapping) for p in posts], + "deals": [dict(d._mapping) for d in deals], + "notices": [dict(n._mapping) for n in notices] + } diff --git a/backend/app/routers/ocr.py b/backend/app/routers/ocr.py new file mode 100644 index 0000000..e9dffc1 --- /dev/null +++ b/backend/app/routers/ocr.py @@ -0,0 +1,384 @@ +# OCR 识别路由 - 专业人民币生肖纪念钞鉴定 +import os +import uuid +import base64 +import httpx +from fastapi import APIRouter, Depends, HTTPException, UploadFile, File +from sqlalchemy.orm import Session +from app.core.database import get_db +from app.core.auth import get_current_user +from app.models.models import User + +router = APIRouter(prefix="/api/ocr", tags=["OCR 识别"]) + +# 阿里云 DashScope API 配置 +DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY", "sk-9389024a37da4f7bb455ac9a6b28776f") + +# 阿里云 OSS 配置 +OSS_CONFIG = { + "access_key_id": os.getenv("OSS_ACCESS_KEY_ID", "LTAI5t6HUnpFBLEK9194kPVG"), + "access_key_secret": os.getenv("OSS_ACCESS_KEY_SECRET", "LEr4Q8yRxb8D5b24cKfCwlt4MMoke1"), + "bucket_name": "jiachenlong-oss", + "endpoint": "oss-cn-hangzhou.aliyuncs.com", + "public_url": "https://jiachenlong-oss.oss-cn-hangzhou.aliyuncs.com" +} + +# 临时上传目录(用于OCR识别本地备选) +UPLOAD_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "uploads", "temp") +os.makedirs(UPLOAD_DIR, exist_ok=True) + + +def get_oss_path(file_type: str, user_id: str = None, collection_id: str = None, filename: str = None): + """生成OSS路径 - 按年/月/日分类""" + from datetime import datetime + now = datetime.now() + year = now.strftime("%Y") + month = now.strftime("%m") + day = now.strftime("%d") + + if file_type == "temp": + # 临时文件: temp/{year}/{month}/{day}/{uuid}.{ext} + import uuid + unique_id = str(uuid.uuid4()) + ext = filename.split('.')[-1] if filename and '.' in filename else 'jpg' + return f"temp/{year}/{month}/{day}/{unique_id}.{ext}", unique_id + + elif file_type == "collection": + # 藏品文件: collections/{user_id}/{year}/{collection_id}/{filename} + if not user_id or not collection_id: + raise ValueError("user_id and collection_id required for collection") + return f"collections/{user_id}/{year}/{collection_id}/{filename}" + + elif file_type == "avatar": + # 头像: avatars/{user_id}/avatar.{ext} + if not user_id: + raise ValueError("user_id required for avatar") + ext = filename.split('.')[-1] if filename and '.' in filename else 'jpg' + return f"avatars/{user_id}/avatar.{ext}" + + return None + + +# 上传图片到OSS - 使用服务层(带压缩) +from app.services.oss import upload_to_oss as oss_upload + +def upload_to_oss(file_data, oss_key): + """上传文件到阿里云OSS(带自动压缩)""" + return oss_upload(file_data, oss_key) + +# 专业提示词 +PROFESSIONAL_PROMPT = """你是一名专业的人民币生肖纪念钞鉴定专家。请严格按照以下步骤分析这张图片,并提取准确信息。 + +【识别流程】 +1. 判断类型是否评级钞:首先确认是否为裸钞还是评级钞(有封装盒和标签) +2. 验证纪念钞特征:对照生肖纪念钞特征进行确认 +3. 验证评级类型:有'标十'字眼的为标十,有'百连'字眼的为标百,其他为单张 +4. 提取信息:仔细阅读标签上的所有文字内容 + +【版别格式要求】 +只需要:年份 + 属相,例如: +- 2024 龙 +- 2025 蛇 +- 2026 马 + +【输出要求】 +严格按照以下格式输出,每个字段必须填写具体值: +✅ 1 发行机构:中国人民银行 +✅ 2 发行版别:2024 龙 +✅ 3 面额:贰拾圆 +✅ 4 是否评级:是/否 +✅ 5 封装类型:裸钞/单张/标十/标百 +✅ 6 冠字序号:J0xxxxxxxx +✅ 7 评级机构:ACG/PCGS/PMG +✅ 8 评级分数:67/68/69 +✅ 9 是否三星:是/否 +✅ 10 特殊标识:金山标/天马标/红绳版等 +✅ 11 号码特征:金山号 2 张,天马号 3 张等 + +现在请仔细分析提供的图片,按上述格式输出结果。""" + + +@router.post("/recognize") +async def recognize_image( + image: UploadFile = File(...), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """OCR 图片识别 - 识别后自动保存图片到OSS临时目录""" + try: + # 读取图片数据 + image_data = await image.read() + image_base64 = base64.b64encode(image_data).decode('utf-8') + + # 生成OSS临时路径: temp/{year}/{month}/{day}/{uuid}.{ext} + oss_key, temp_id = get_oss_path("temp", filename=image.filename) + + # 初始化temp_path为空 + temp_path = None + + # 上传到OSS + try: + image_url = upload_to_oss(image_data, oss_key) + except Exception as oss_err: + # OSS失败时保存到本地作为备选 + temp_path = os.path.join(UPLOAD_DIR, oss_key.split('/')[-1]) + os.makedirs(os.path.dirname(temp_path), exist_ok=True) + with open(temp_path, 'wb') as f: + f.write(image_data) + image_url = f"/uploads/temp/{oss_key.split('/')[-1]}" + + headers = { + "Authorization": f"Bearer {DASHSCOPE_API_KEY}", + "Content-Type": "application/json" + } + + # 阿里云 DashScope API 格式 (qwen-vl-plus 视觉模型) + payload = { + "model": "qwen-vl-plus", + "input": { + "messages": [{ + "role": "user", + "content": [ + { + "image": f"data:{image.content_type};base64,{image_base64}" + }, + { + "text": PROFESSIONAL_PROMPT + } + ] + }] + }, + "parameters": { + "max_tokens": 1000 + } + } + + async with httpx.AsyncClient(timeout=60.0) as client: + response = await client.post( + "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation", + json=payload, + headers=headers + ) + + if response.status_code != 200: + # 识别失败,删除临时文件 + if temp_path and os.path.exists(temp_path): + os.remove(temp_path) + raise HTTPException(status_code=500, detail=f"OCR API 调用失败:{response.text[:200]}") + + ocr_result = response.json() + text_content = "" + # 新版API返回格式 + if "output" in ocr_result and "choices" in ocr_result["output"]: + choices = ocr_result["output"]["choices"] + if choices and len(choices) > 0: + content = choices[0].get("message", {}).get("content", []) + if content and len(content) > 0: + text_content = content[0].get("text", "") + + fields = extract_fields(text_content) + + # 更新用户AI识别次数 + current_user.f99_95_ai_count = (current_user.f99_95_ai_count or 0) + 1 + db.commit() + + # 返回识别结果和临时图片路径 + return { + "success": True, + "text": text_content, + "fields": fields, + "aiCount": current_user.f99_95_ai_count, + "temp_image": { + "id": temp_id, + "filename": oss_key.split('/')[-1], + "path": image_url, + "original_name": image.filename, + "is_oss": image_url.startswith("https://") + } + } + + except Exception as e: + import traceback + error_detail = f"识别失败:{str(e)}\n{traceback.format_exc()}" + raise HTTPException(status_code=500, detail=error_detail) + + +def extract_fields(text: str) -> dict: + """从 OCR 文本中提取字段 - 直接返回 AI 识别结果""" + import re + fields = {} + + # 解析结构化输出 + patterns = { + 'issuer': r'✅.*?1.*?发行机构.*?[::]\s*(.+?)(?:\n|$)', + 'version': r'✅.*?2.*?发行版别.*?[::]\s*(.+?)(?:\n|$)', + 'denomination': r'✅.*?3.*?面额.*?[::]\s*(.+?)(?:\n|$)', + 'is_graded_text': r'✅.*?4.*?是否评级.*?[::]\s*(.+?)(?:\n|$)', + 'packaging': r'✅.*?5.*?封装类型.*?[::]\s*(.+?)(?:\n|$)', + 'prefix_serial': r'✅.*?6.*?冠字序号.*?[::]\s*(.+?)(?:\n|$)', + 'grading_company': r'✅.*?7.*?评级机构.*?[::]\s*(.+?)(?:\n|$)', + 'grading_score': r'✅.*?8.*?评级分数.*?[::]\s*(.+?)(?:\n|$)', + 'three_star_text': r'✅.*?9.*?是否三星.*?[::]\s*(.+?)(?:\n|$)', + 'special_mark': r'✅.*?10.*?特殊标识.*?[::]\s*(.+?)(?:\n|$)', + 'serial_feature': r'✅.*?11.*?号码特征.*?[::]\s*(.+?)(?:\n|$)' + } + + for field, pattern in patterns.items(): + match = re.search(pattern, text, re.IGNORECASE | re.DOTALL) + if match: + value = match.group(1).strip() + # 保留所有值,包括"无"和"未识别",让前端处理 + fields[field] = value + + # 处理是否评级 + if 'is_graded_text' in fields: + fields['is_graded'] = '是' in fields.pop('is_graded_text') + + # 处理是否三星 + if 'three_star_text' in fields: + fields['three_star'] = '是' in fields.pop('three_star_text') + + # 简化版别字段(2024 龙年贺岁纪念钞(标十) → 2024 龙) + if 'version' in fields: + version = fields['version'] + # 提取年份和生肖 + year_match = re.search(r'(20\d{2})', version) + animal = '' + if '龙' in version: + animal = '龙' + elif '蛇' in version: + animal = '蛇' + elif '马' in version: + animal = '马' + elif '羊' in version: + animal = '羊' + elif '猴' in version: + animal = '猴' + elif '鸡' in version: + animal = '鸡' + elif '狗' in version: + animal = '狗' + elif '猪' in version: + animal = '猪' + elif '鼠' in version: + animal = '鼠' + elif '牛' in version: + animal = '牛' + elif '虎' in version: + animal = '虎' + elif '兔' in version: + animal = '兔' + + if year_match and animal: + fields['version'] = f"{year_match.group(1)}{animal}" + + return fields + + +@router.post("/claim-temp-image") +async def claim_temp_image( + temp_id: str, + collection_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """将临时图片移动到正式藏品目录 - 按用户/年/藏品ID分类""" + from app.models.models import Collection, CollectionImage + from datetime import datetime + + # 验证藏品是否存在 + collection = db.query(Collection).filter( + Collection.f99_90_id == collection_id, + Collection.f99_91_user_id == current_user.f99_90_id + ).first() + + if not collection: + raise HTTPException(status_code=404, detail="藏品不存在") + + # 生成正式文件名和OSS路径: collections/{user_id}/{year}/{collection_id}/{filename} + code = collection.f01_02_code or "0000" + prefix = collection.f02_10_prefix_serial or "" + username = current_user.f01_01_name + import time + final_filename = f"{username}-{code}-{prefix}-{int(time.time())}.jpg" + oss_key = get_oss_path("collection", user_id=current_user.f99_90_id, collection_id=collection_id, filename=final_filename) + + # 尝试从OSS获取临时图片 - 尝试多种扩展名和日期路径 + temp_extensions = ['jpg', 'jpeg', 'png', 'gif', 'JPG', 'JPEG', 'PNG', 'GIF'] + temp_content = None + found_key = None + + # 尝试最近7天的路径 + from datetime import timedelta + for i in range(7): + date = datetime.now() - timedelta(days=i) + year = date.strftime("%Y") + month = date.strftime("%m") + day = date.strftime("%d") + + for ext in temp_extensions: + try: + temp_oss_key = f"temp/{year}/{month}/{day}/{temp_id}.{ext}" + import oss2 + auth = oss2.Auth(OSS_CONFIG["access_key_id"], OSS_CONFIG["access_key_secret"]) + bucket = oss2.Bucket(auth, OSS_CONFIG["endpoint"], OSS_CONFIG["bucket_name"]) + temp_content = bucket.get_object(temp_oss_key).read() + found_key = temp_oss_key + break + except: + continue + if temp_content: + break + + if temp_content: + # 上传到正式目录 + bucket.put_object(oss_key, temp_content) + + # 删除临时图片 + try: + bucket.delete_object(found_key) + except: + pass + + # OSS URL + image_path = f"{OSS_CONFIG['public_url']}/{oss_key}" + + else: + # OSS失败,使用本地文件 + temp_path = None + for ext in temp_extensions: + temp_path = os.path.join(UPLOAD_DIR, f"{temp_id}.{ext}") + if os.path.exists(temp_path): + break + + if not temp_path or not os.path.exists(temp_path): + raise HTTPException(status_code=404, detail="临时图片不存在或已过期") + + # 保存到本地 + collection_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "uploads", "collections") + os.makedirs(collection_dir, exist_ok=True) + + new_path = os.path.join(collection_dir, final_filename) + import shutil + shutil.move(temp_path, new_path) + image_path = f"uploads/collections/{final_filename}" + + # 创建图片记录 + image_record = CollectionImage( + id=str(uuid.uuid4()), + collection_id=collection.f99_90_id, + filename=final_filename, + original_name=temp_id, + path=image_path + ) + db.add(image_record) + db.commit() + + return { + "success": True, + "image": { + "id": image_record.id, + "filename": image_record.filename, + "path": image_record.path + } + } diff --git a/backend/app/routers/operations.py b/backend/app/routers/operations.py new file mode 100644 index 0000000..0881599 --- /dev/null +++ b/backend/app/routers/operations.py @@ -0,0 +1,104 @@ +# 操作路由 +from typing import List, Optional +from fastapi import APIRouter, Depends, HTTPException, status, Query +from sqlalchemy.orm import Session +from app.core.database import get_db +from app.core.auth import get_current_user +from app.models.models import User, Collection, Operation +from app.schemas.schemas import OperationCreate, OperationResponse + +router = APIRouter(prefix="/api", tags=["操作"]) + + +@router.get("/operations", response_model=List[OperationResponse]) +def get_operations( + collection_id: Optional[str] = None, + page: int = Query(1, ge=1), + limit: int = Query(50, ge=1, le=100), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取操作历史""" + query = db.query(Operation).filter(Operation.user_id == current_user.id) + + if collection_id: + query = query.filter(Operation.collection_id == collection_id) + + operations = query.order_by(Operation.created_at.desc()) \ + .offset((page - 1) * limit) \ + .limit(limit) \ + .all() + + return operations + + +@router.get("/operations/history") +def get_operation_history( + collection_id: Optional[str] = None, + type: Optional[str] = None, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + page: int = Query(1, ge=1), + limit: int = Query(50, ge=1, le=100), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取操作历史(带统计)""" + query = db.query(Operation).filter(Operation.user_id == current_user.id) + + if collection_id: + query = query.filter(Operation.collection_id == collection_id) + if type: + query = query.filter(Operation.type == type) + if start_date: + query = query.filter(Operation.created_at >= start_date) + if end_date: + query = query.filter(Operation.created_at <= end_date) + + total = query.count() + + data = query.order_by(Operation.created_at.desc()) \ + .offset((page - 1) * limit) \ + .limit(limit) \ + .all() + + return { + "data": data, + "pagination": { + "page": page, + "limit": limit, + "total": total, + "pages": (total + limit - 1) // limit + } + } + + +@router.post("/operations", response_model=OperationResponse) +def create_operation( + operation_data: OperationCreate, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """创建操作记录""" + # 验证藏品存在 + collection = db.query(Collection).filter( + Collection.id == operation_data.collection_id, + Collection.user_id == current_user.id + ).first() + + if not collection: + raise HTTPException(status_code=404, detail="藏品不存在") + + operation = Operation( + collection_id=operation_data.collection_id, + user_id=current_user.id, + type=operation_data.type, + price=operation_data.price, + note=operation_data.note + ) + + db.add(operation) + db.commit() + db.refresh(operation) + + return operation diff --git a/backend/app/routers/seek.py b/backend/app/routers/seek.py new file mode 100644 index 0000000..76ff298 --- /dev/null +++ b/backend/app/routers/seek.py @@ -0,0 +1,189 @@ +from fastapi import APIRouter, Depends, Query, HTTPException +from sqlalchemy.orm import Session +from pydantic import BaseModel +from typing import Optional +from datetime import datetime +from app.core.database import get_db +from app.core.auth import get_current_user +from app.models.seek_info import SeekInfo + +router = APIRouter(prefix="/api/seek", tags=["寻配号"]) + +# ============ Schema ============ +class SeekInfoCreate(BaseModel): + title: str + content: Optional[str] = None + expect_category: Optional[str] = None + expect_version: Optional[str] = None + expect_packaging: Optional[str] = None + expect_number: Optional[str] = None + expect_price_min: Optional[float] = None + expect_price_max: Optional[float] = None + +class SeekInfoUpdate(BaseModel): + title: Optional[str] = None + content: Optional[str] = None + expect_category: Optional[str] = None + expect_version: Optional[str] = None + expect_packaging: Optional[str] = None + expect_number: Optional[str] = None + expect_price_min: Optional[float] = None + expect_price_max: Optional[float] = None + status: Optional[str] = None + +class SeekInfoResponse(BaseModel): + id: str + user_id: str + title: str + content: Optional[str] + expect_category: Optional[str] + expect_version: Optional[str] + expect_packaging: Optional[str] + expect_number: Optional[str] + expect_price_min: Optional[float] + expect_price_max: Optional[float] + status: str + is_matched: Optional[str] + matched_user_id: Optional[str] + matched_contact: Optional[str] + view_count: int + contact_count: int + created_at: Optional[datetime] + updated_at: Optional[datetime] + + class Config: + from_attributes = True + +# ============ API ============ +@router.get("/list", response_model=list[SeekInfoResponse]) +def get_seek_list( + status: str = Query("active"), + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=1000), + user_only: bool = Query(False), + current_user: Optional = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取寻配号列表""" + query = db.query(SeekInfo).filter(SeekInfo.status == status) + + # 我的寻配号:只查看自己的 + if user_only and current_user: + query = query.filter(SeekInfo.user_id == current_user.f99_90_id) + + # 排序 + query = query.order_by(SeekInfo.created_at.desc()) + + # 分页 + offset = (page - 1) * page_size + items = query.offset(offset).limit(page_size).all() + + return items + +@router.get("/stats") +def get_seek_stats( + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取寻配号统计""" + total = db.query(SeekInfo).filter(SeekInfo.status == "active").count() + matched = db.query(SeekInfo).filter(SeekInfo.is_matched == "true").count() + + return { + "total": total, + "matched": matched, + "unmatched": total - matched + } + +@router.post("", response_model=SeekInfoResponse) +def create_seek( + data: SeekInfoCreate, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """创建寻配号""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + seek = SeekInfo( + user_id=current_user.f99_90_id, + title=data.title, + content=data.content, + expect_category=data.expect_category, + expect_version=data.expect_version, + expect_packaging=data.expect_packaging, + expect_number=data.expect_number, + expect_price_min=data.expect_price_min, + expect_price_max=data.expect_price_max, + status="active" + ) + db.add(seek) + db.commit() + db.refresh(seek) + return seek + +@router.get("/{seek_id}", response_model=SeekInfoResponse) +def get_seek( + seek_id: str, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取寻配号详情""" + seek = db.query(SeekInfo).filter(SeekInfo.id == seek_id).first() + if not seek: + raise HTTPException(status_code=404, detail="寻配号不存在") + + # 增加浏览数 + seek.view_count += 1 + db.commit() + + return seek + +@router.put("/{seek_id}", response_model=SeekInfoResponse) +def update_seek( + seek_id: str, + data: SeekInfoUpdate, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新寻配号""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + seek = db.query(SeekInfo).filter( + SeekInfo.id == seek_id, + SeekInfo.user_id == current_user.f99_90_id + ).first() + + if not seek: + raise HTTPException(status_code=404, detail="寻配号不存在") + + for key, value in data.model_dump(exclude_unset=True).items(): + setattr(seek, key, value) + + db.commit() + db.refresh(seek) + return seek + +@router.delete("/{seek_id}") +def delete_seek( + seek_id: str, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除寻配号""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + seek = db.query(SeekInfo).filter( + SeekInfo.id == seek_id, + SeekInfo.user_id == current_user.f99_90_id + ).first() + + if not seek: + raise HTTPException(status_code=404, detail="寻配号不存在") + + seek.status = "deleted" + db.commit() + + return {"message": "删除成功"} \ No newline at end of file diff --git a/backend/app/routers/users.py b/backend/app/routers/users.py new file mode 100644 index 0000000..c8cf2da --- /dev/null +++ b/backend/app/routers/users.py @@ -0,0 +1,305 @@ +# 用户管理路由 +from typing import Optional +from fastapi import APIRouter, Depends, HTTPException, status, Query, Body +from sqlalchemy.orm import Session +from app.core.database import get_db +from app.core.auth import get_current_user +from app.models.models import User, Collection +from app.schemas.schemas import UserResponse, UserUpdate + +router = APIRouter(prefix="/api", tags=["用户"]) + +# ============ 当前用户接口 ============ + +@router.get("/users/me") # 无 response_model,避免 Pydantic 序列化问题 +def get_current_user_info( + current_user: User = Depends(get_current_user) +): + """获取当前登录用户信息""" + return { + "id": current_user.f99_90_id, + "username": current_user.f01_01_name, + "f99_90_id": current_user.f99_90_id, + "f01_01_name": current_user.f01_01_name, + "email": current_user.email, + "phone": current_user.phone, + "avatar": current_user.avatar, + "address": current_user.address, + "bio": current_user.bio, + "role": current_user.role, + "level": current_user.f99_94_level, + "aiCount": current_user.f99_95_ai_count or 0, + "searchCount": current_user.f99_96_search_count or 0, + "collectionCount": current_user.f99_97_collection_count or 0, + "phoneVerified": current_user.f01_06_phone_verified or False, + "loginCount": current_user.f99_98_login_count or 0, + "lastLogin": current_user.f99_99_last_login.isoformat() if current_user.f99_99_last_login else None, + "gender": current_user.f01_07_gender, + "birthday": current_user.f01_08_birthday.isoformat() if current_user.f01_08_birthday else None, + "region": current_user.f01_09_region, + "realnameVerified": current_user.f01_10_realname_verified or False, + "points": current_user.f99_100_points or 0, + "balance": float(current_user.f01_11_balance) if current_user.f01_11_balance else 0, + "totalAmount": float(current_user.f01_12_total_amount) if current_user.f01_12_total_amount else 0, + "inviteCode": current_user.f01_13_invite_code, + "user_code": current_user.user_code, + "f99_92_created_at": current_user.f99_92_created_at.isoformat() if current_user.f99_92_created_at else None, + "f99_93_updated_at": current_user.f99_93_updated_at.isoformat() if current_user.f99_93_updated_at else None + } + +@router.put("/users/me") # 无 response_model,避免 Pydantic 序列化问题 +def update_current_user( + user_update: UserUpdate, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新当前用户信息""" + import logging + logger = logging.getLogger(__name__) + + # 获取用户ID + user_id = current_user.f99_90_id + logger.info(f"Updating user {user_id}, data={user_update.model_dump()}") + + # 在当前session中重新查询用户 + user = db.query(User).filter(User.f99_90_id == user_id).first() + if not user: + raise HTTPException(status_code=404, detail="用户不存在") + + # 更新字段 + update_data = user_update.model_dump(exclude_unset=True) + for field, value in update_data.items(): + if field == 'f01_01_name': + user.f01_01_name = value + elif field == 'username': + pass # skip, already handled as f01_01_name + elif hasattr(user, field): + setattr(user, field, value) + + # 强制刷新以确保更新被提交 + db.flush() + db.commit() + db.refresh(user) + logger.info(f"After commit, user email={user.email}") + + return user + +# ============ 管理员用户管理 ============ + +admin_router = APIRouter(prefix="/api/admin/users", tags=["用户管理"]) + + +@admin_router.get("") +def get_users( + page: int = Query(1, ge=1), + limit: int = Query(20, ge=1, le=100), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取用户列表(仅管理员)""" + if current_user.role not in ["admin", "editor"]: + raise HTTPException(status_code=403, detail="无权访问") + + total = db.query(User).count() + from sqlalchemy import case + users = db.query(User).order_by( + case( + (User.user_code == None, 1), + else_=0 + ), + User.user_code.asc() + ).offset((page-1)*limit).limit(limit).all() + + user_list = [] + for u in users: + # 统计每个用户的藏品数量 + count = db.query(Collection).filter(Collection.f99_91_user_id == u.f99_90_id).count() + user_list.append({ + "id": u.f99_90_id, + "username": u.f01_01_name, + "email": u.email, + "phone": u.phone, + "role": u.role, + "user_code": u.user_code, + "created_at": u.f99_92_created_at.isoformat() if u.f99_92_created_at else None, + "collectionCount": count, + "level": u.f99_94_level, + "aiCount": u.f99_95_ai_count, + "searchCount": u.f99_96_search_count, + "loginCount": u.f99_98_login_count, + "points": u.f99_100_points, + "balance": float(u.f01_11_balance) if u.f01_11_balance else 0, + "totalAmount": float(u.f01_12_total_amount) if u.f01_12_total_amount else 0, + "phoneVerified": u.f01_06_phone_verified, + }) + + return user_list + + +@admin_router.get("/{user_id}") +def get_user( + user_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取单个用户信息""" + if current_user.role not in ["admin", "editor"]: + raise HTTPException(status_code=403, detail="无权访问") + + user = db.query(User).filter(User.id == user_id).first() + if not user: + raise HTTPException(status_code=404, detail="用户不存在") + + return { + "id": user.id, + "username": user.username, + "email": user.email, + "phone": user.phone, + "role": user.role, + "created_at": user.created_at.isoformat() if user.created_at else None + } + + +@admin_router.get("/{user_id}/collections") +def get_user_collections( + user_id: str, + limit: int = Query(100, ge=1, le=100), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取指定用户的藏品列表""" + if current_user.role not in ["admin", "editor"]: + raise HTTPException(status_code=403, detail="无权访问") + + collections = db.query(Collection).filter( + Collection.user_id == user_id + ).limit(limit).all() + + return [c.code for c in collections] + + +@admin_router.get("/{user_id}/count") +def get_user_collection_count( + user_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取指定用户的藏品数量""" + if current_user.role not in ["admin", "editor"]: + raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问") + + count = db.query(Collection).filter(Collection.user_id == user_id).count() + return {"count": count} + + +@admin_router.put("/{user_id}") +def update_user( + user_id: str, + username: Optional[str] = Body(None), + email: Optional[str] = Body(None), + role: Optional[str] = Body(None), + password: Optional[str] = Body(None), + user_code: Optional[str] = Body(None), + level: Optional[str] = Body(None), + points: Optional[int] = Body(None), + balance: Optional[float] = Body(None), + totalAmount: Optional[float] = Body(None), + aiCount: Optional[int] = Body(None), + searchCount: Optional[int] = Body(None), + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新用户信息(仅管理员)""" + if current_user.role not in ["admin", "editor"]: + raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问") + + user = db.query(User).filter(User.f99_90_id == user_id).first() + if not user: + raise HTTPException(status_code=404, detail="E00051: 用户不存在") + + # 更新基本信息 + if username: + user.f01_01_name = username + if email: + user.email = email + if role is not None: + user.role = role + + # 更新会员等级 + if level is not None: + user.f99_94_level = level + + # 更新积分 + if points is not None: + user.f99_100_points = points + + # 更新余额 + if balance is not None: + user.f01_11_balance = balance + + # 更新累计金额 + if totalAmount is not None: + user.f01_12_total_amount = totalAmount + + # 更新AI识别次数 + if aiCount is not None: + user.f99_95_ai_count = aiCount + + # 更新寻号次数 + if searchCount is not None: + user.f99_96_search_count = searchCount + + # 更新用户编码 + if user_code is not None: + # 只有非空字符串才检查唯一性 + user_code_str = user_code.strip() if user_code else '' + if user_code_str: + existing = db.query(User).filter( + User.user_code == user_code_str, + User.f99_90_id != user_id + ).first() + if existing: + raise HTTPException(status_code=400, detail="E00052: 该用户编码已被其他用户使用") + user.user_code = user_code_str + else: + user.user_code = None + + # 更新密码 + if password and password.strip(): + from app.core.auth import get_password_hash + user.password = get_password_hash(password) + + db.commit() + db.refresh(user) + + return { + "id": user.f99_90_id, + "username": user.f01_01_name, + "email": user.email, + "role": user.role, + "message": "更新成功" + } + + +@admin_router.delete("/{user_id}") +def delete_user( + user_id: str, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除用户(仅管理员)""" + if current_user.role not in ["admin", "editor"]: + raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问") + + # 不能删除自己 + if user_id == str(current_user.f99_90_id): + raise HTTPException(status_code=400, detail="E00052: 不能删除自己") + + user = db.query(User).filter(User.f99_90_id == user_id).first() + if not user: + raise HTTPException(status_code=404, detail="E00051: 用户不存在") + + db.delete(user) + db.commit() + + return {"message": "删除成功"} diff --git a/backend/app/routers/yichens.py b/backend/app/routers/yichens.py new file mode 100644 index 0000000..de8e152 --- /dev/null +++ b/backend/app/routers/yichens.py @@ -0,0 +1,377 @@ +from fastapi import APIRouter, Depends, Query +from sqlalchemy import func, text +from sqlalchemy.orm import Session +from pydantic import BaseModel +from typing import Optional, List +from datetime import datetime, date +from app.core.coolbot_db import get_coolbot_db + +router = APIRouter(prefix="/api/yichens", tags=["一尘看板"]) + +# ============ 数据模型 ============ +class YichensPostStats(BaseModel): + total_posts: int + total_deals: int # 出售 + total_wants: int # 求购 + total_replies: int + total_views: int + avg_price: Optional[float] + +class CategoryStat(BaseModel): + category: str + count: int + +class PostItem(BaseModel): + post_id: str + title: str + category: Optional[str] + post_type: str + price: Optional[float] + author_username: str + post_time: str + reply_count: int + view_count: int + url: Optional[str] + content: Optional[str] + +class UserStat(BaseModel): + total_users: int + new_users_today: int + sellers: int + +class UserItem(BaseModel): + user_id: str + username: str + avatar_url: Optional[str] + content: Optional[str] + credit_level: Optional[str] + credit_score: Optional[int] + post_count: int + is_seller: bool + registration_date: Optional[str] + +# ============ 统计接口 ============ +@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)): + """获取帖子统计""" + result = db.execute(text(""" + SELECT + COUNT(*) as total_posts, + COUNT(*) FILTER (WHERE post_type = 'deal') as total_deals, + COUNT(*) FILTER (WHERE post_type = 'want') as total_wants, + COALESCE(SUM(reply_count), 0) as total_replies, + COALESCE(SUM(view_count), 0) as total_views, + AVG(price) as avg_price + FROM yichens_posts + WHERE post_time >= NOW() - INTERVAL '1 day' * :days + """), {"days": days}).fetchone() + + return YichensPostStats( + total_posts=result[0] or 0, + total_deals=result[1] or 0, + total_wants=result[2] or 0, + total_replies=result[3] or 0, + total_views=result[4] or 0, + avg_price=float(result[5]) if result[5] else None + ) + +@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)): + """按分类统计帖子数量""" + results = db.execute(text(""" + SELECT category, COUNT(*) as count + FROM yichens_posts + WHERE post_time >= NOW() - INTERVAL '1 day' * :days + GROUP BY category + ORDER BY count DESC + """), {"days": days}).fetchall() + + return [CategoryStat(category=r[0] or "未知", count=r[1]) for r in results] + +@router.get("/stats/users", response_model=UserStat) +def get_user_stats(db: Session = Depends(get_coolbot_db)): + """获取用户统计""" + result = db.execute(text(""" + SELECT + COUNT(*) as total_users, + COUNT(*) FILTER (WHERE created_at::date = CURRENT_DATE) as new_users_today, + COUNT(*) FILTER (WHERE is_seller = true) as sellers + FROM yichens_users + """)).fetchone() + + return UserStat( + total_users=result[0] or 0, + new_users_today=result[1] or 0, + sellers=result[2] or 0 + ) + +@router.get("/posts") +def get_posts( + limit: int = Query(20, ge=1, le=500), + offset: int = Query(0, ge=0), + category: Optional[str] = None, + post_type: Optional[str] = None, + keyword: Optional[str] = None, + db: Session = Depends(get_coolbot_db) +): + """获取帖子列表 - 支持全局搜索,返回总数和分页信息""" + # 构建WHERE条件 + where_clauses = ["1=1"] + params = {"limit": limit, "offset": offset} + + if category: + where_clauses.append("category = :category") + params["category"] = category + + if post_type: + where_clauses.append("post_type = :post_type") + params["post_type"] = post_type + + # 全局搜索 + if keyword: + where_clauses.append("(title ILIKE :keyword OR content ILIKE :keyword OR category ILIKE :keyword OR author_username ILIKE :keyword)") + params["keyword"] = f"%{keyword}%" + + where_sql = " AND ".join(where_clauses) + + # 查询总数 + 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 + + # 查询数据 + data_query = f""" + SELECT post_id, title, content, category, post_type, price, + author_username, post_time, reply_count, view_count, url + FROM yichens_posts + WHERE {where_sql} + ORDER BY post_time DESC LIMIT :limit OFFSET :offset + """ + results = db.execute(text(data_query), params).fetchall() + + posts = [PostItem( + post_id=r[0], + title=r[1] or "", + content=r[2] or "", + category=r[3], + post_type=r[4] or "", + price=float(r[5]) if r[5] else None, + author_username=r[6] or "", + post_time=str(r[7]) if r[7] else "", + reply_count=r[8] or 0, + view_count=r[9] or 0, + url=r[10] + ) for r in results] + + return { + "posts": posts, + "total": total_count, + "page": offset // limit + 1, + "page_size": limit + } + +@router.get("/users", response_model=List[UserItem]) +def get_users( + limit: int = Query(20, ge=1, le=500), + offset: int = Query(0, ge=0), + is_seller: Optional[bool] = None, + db: Session = Depends(get_coolbot_db) +): + """获取用户列表""" + query = """ + SELECT user_id, username, avatar_url, credit_level, credit_score, + post_count, is_seller, registration_date + FROM yichens_users + WHERE 1=1 + """ + params = {"limit": limit, "offset": offset} + + if is_seller is not None: + query += " AND is_seller = :is_seller" + params["is_seller"] = is_seller + + query += " ORDER BY post_count DESC LIMIT :limit OFFSET :offset" + + results = db.execute(text(query), params).fetchall() + + return [UserItem( + user_id=r[0], + username=r[1] or "", + avatar_url=r[2], + credit_level=r[3], + credit_score=r[4], + post_count=r[5] or 0, + is_seller=r[6] or False, + registration_date=str(r[7]) if r[7] else None + ) for r in results] + + +@router.get("/stats/today") +async def get_today_stats(db: Session = Depends(get_coolbot_db)): + """获取今日新增帖子统计""" + query = """ + SELECT + COUNT(*) as total, + 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 = '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 horses, + 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 + FROM yichens_posts + WHERE post_time >= CURRENT_DATE + """ + result = db.execute(text(query)).fetchone() + return { + "total": result[0] or 0, + "deals": result[1] or 0, + "wants": result[2] or 0, + "others": result[3] or 0, + "dragons": result[4] or 0, + "horses": result[5] or 0, + "snakes": result[6] or 0, + "tianma": result[7] or 0 + } + +@router.get("/stats/hour") +async def get_hour_stats(db: Session = Depends(get_coolbot_db)): + """获取近一个小时新增帖子统计""" + query = """ + SELECT + COUNT(*) as total, + 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 = '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 horses, + SUM(CASE WHEN category LIKE '%蛇%' THEN 1 ELSE 0 END) as snakes + FROM yichens_posts + WHERE post_time >= NOW() - INTERVAL '1 hour' + """ + result = db.execute(text(query)).fetchone() + return { + "total": result[0] or 0, + "deals": result[1] or 0, + "wants": result[2] or 0, + "others": result[3] or 0, + "dragons": result[3] or 0, + "horses": result[4] or 0, + "snakes": result[5] or 0 + } + +@router.get("/stats/today-category") +async def get_today_category_stats(db: Session = Depends(get_coolbot_db)): + """获取今日帖子分类统计""" + query = """ + SELECT category, COUNT(*) as count + FROM yichens_posts + WHERE post_time >= CURRENT_DATE + GROUP BY category + ORDER BY count DESC + """ + results = db.execute(text(query)).fetchall() + return [{"category": r[0] or "未分类", "count": r[1]} for r in results] + + +@router.get("/stats/dragons-today") +def get_dragons_stats_today( + db: Session = Depends(get_coolbot_db) +): + """获取今日龙钞详细统计数据(按号码分类)- 就高不就低""" + from sqlalchemy import text + + # 1. 带4:包含"带4"、"带四"、"通货" + dai4 = db.execute(text(""" + SELECT + COUNT(*) as total, + 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 + FROM yichens_posts + WHERE post_time >= CURRENT_DATE + AND category LIKE '%龙%' + AND ( + content LIKE '%带4%' OR title LIKE '%带4%' + OR content LIKE '%带四%' OR title LIKE '%带四%' + OR content LIKE '%通货%' OR title LIKE '%通货%' + ) + """)).fetchone() + + # 2. 无4:包含"无4"、"无四",排除"无47"、"无247"、"无四七"、"永恒" + wu4 = db.execute(text(""" + SELECT + COUNT(*) as total, + 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 + FROM yichens_posts + WHERE post_time >= CURRENT_DATE + AND category LIKE '%龙%' + AND ( + content LIKE '%无4%' OR title LIKE '%无4%' + OR content LIKE '%无四%' OR title LIKE '%无四%' + ) + AND content NOT LIKE '%无47%' AND title NOT LIKE '%无47%' + 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 '%无四七%' + """)).fetchone() + + # 3. 无47:包含"无47"、"永恒"、"无四七",排除"无247" + wu47 = db.execute(text(""" + SELECT + COUNT(*) as total, + 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 + FROM yichens_posts + WHERE post_time >= CURRENT_DATE + AND category LIKE '%龙%' + AND ( + content LIKE '%无47%' OR title LIKE '%无47%' + OR content LIKE '%永恒%' OR title LIKE '%永恒%' + OR content LIKE '%无四七%' OR title LIKE '%无四七%' + ) + AND content NOT LIKE '%无247%' AND title NOT LIKE '%无247%' + """)).fetchone() + + # 4. 无247:包含"无247"、"天马"、"金山",排除"无347" + wu247 = db.execute(text(""" + SELECT + COUNT(*) as total, + 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 + FROM yichens_posts + WHERE post_time >= CURRENT_DATE + AND category LIKE '%龙%' + AND ( + content LIKE '%无247%' OR title LIKE '%无247%' + OR content LIKE '%天马%' OR title LIKE '%天马%' + OR content LIKE '%金山%' OR title LIKE '%金山%' + ) + AND content NOT LIKE '%无347%' AND title NOT LIKE '%无347%' + """)).fetchone() + + # 5. 无347:包含"无347"、"钻石"、"金马"、"魅力"、"朦胧" + wu347 = db.execute(text(""" + SELECT + COUNT(*) as total, + 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 + FROM yichens_posts + WHERE post_time >= CURRENT_DATE + AND category LIKE '%龙%' + AND ( + 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 '%朦胧%' + ) + """)).fetchone() + + return { + "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}, + "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}, + "wu347": {"total": wu347[0] or 0, "deals": wu347[1] or 0, "wants": wu347[2] or 0} + } + diff --git a/backend/app/schemas/__init__.py b/backend/app/schemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/app/schemas/schemas.py b/backend/app/schemas/schemas.py new file mode 100644 index 0000000..a8497b5 --- /dev/null +++ b/backend/app/schemas/schemas.py @@ -0,0 +1,231 @@ +# Pydantic Schema - 使用字段编码并支持 camelCase +from typing import Optional, List +from pydantic import BaseModel, EmailStr, Field, ConfigDict +from datetime import datetime + + +# ============ 用户相关 ============ + +class UserBase(BaseModel): + f01_01_name: str = Field(..., min_length=3, max_length=255, alias="username") + email: Optional[EmailStr] = None + phone: Optional[str] = None + avatar: Optional[str] = None + address: Optional[str] = None + bio: Optional[str] = None + + model_config = ConfigDict(from_attributes=True, populate_by_name=True) + + +class UserCreate(UserBase): + password: str = Field(..., min_length=6) + invite_code: Optional[str] = Field(None, alias="inviteCode") # 填写的邀请码(选填) + + +class UserUpdate(BaseModel): + f01_01_name: Optional[str] = Field(None, alias="username") + email: Optional[EmailStr] = None + phone: Optional[str] = None + avatar: Optional[str] = None + address: Optional[str] = None + bio: Optional[str] = None + password: Optional[str] = None + + model_config = ConfigDict(from_attributes=True, populate_by_name=True) + + +class UserResponse(UserBase): + # 新增字段 + f99_94_level: Optional[str] = Field(None, alias="level") + f99_95_ai_count: Optional[int] = Field(0, alias="aiCount") + f99_96_search_count: Optional[int] = Field(0, alias="searchCount") + f99_97_collection_count: Optional[int] = Field(0, alias="collectionCount") + f01_06_phone_verified: Optional[bool] = Field(False, alias="phoneVerified") + f99_98_login_count: Optional[int] = Field(0, alias="loginCount") + f99_99_last_login: Optional[datetime] = Field(None, alias="lastLogin") + f01_07_gender: Optional[str] = Field(None, alias="gender") + f01_08_birthday: Optional[datetime] = Field(None, alias="birthday") + f01_09_region: Optional[str] = Field(None, alias="region") + f01_10_realname_verified: Optional[bool] = Field(False, alias="realnameVerified") + f99_100_points: Optional[int] = Field(0, alias="points") + f01_11_balance: Optional[float] = Field(0, alias="balance") + f01_12_total_amount: Optional[float] = Field(0, alias="totalAmount") + f01_13_invite_code: Optional[str] = Field(None, alias="inviteCode") + f99_101_invited_count: Optional[int] = Field(0, alias="invitedCount") + f99_90_id: str = Field(..., alias="id") + f01_01_name: str = Field(..., alias="username") + role: str + user_code: Optional[str] = None + f99_92_created_at: Optional[datetime] = Field(None, alias="created_at") + f99_93_updated_at: Optional[datetime] = Field(None, alias="updated_at") + + model_config = ConfigDict(from_attributes=True, populate_by_name=True) + + +# ============ 藏品相关 ============ + +class CollectionBase(BaseModel): + # f01 基本信息 + f01_01_name: str = Field(..., min_length=2, max_length=255, alias="name") + f01_02_code: Optional[str] = Field(None, max_length=50, alias="code") + f01_03_category: str = Field(..., max_length=100, alias="category") + f01_04_status: Optional[str] = Field("in_collection", alias="status") + f01_05_remark: Optional[str] = Field(None, alias="remark") + + # f02 详细字段 + f02_10_prefix_serial: Optional[str] = Field(None, alias="prefixSerial") + f02_11_version: Optional[str] = Field(None, alias="version") + f02_12_packaging: Optional[str] = Field(None, alias="packaging") + f02_13_rarity: Optional[str] = Field(None, alias="rarity") + f02_14_number_category: Optional[str] = Field(None, alias="numberCategory") + + # f03 评级信息 + f03_20_is_graded: Optional[bool] = Field(False, alias="isGraded") + f03_21_grading_company: Optional[str] = Field(None, alias="gradingCompany") + f03_22_grading_score: Optional[str] = Field(None, alias="gradingScore") + f03_23_three_star: Optional[bool] = Field(False, alias="threeStar") + + # f04 特殊信息 + f04_30_special_mark: Optional[str] = Field(None, alias="specialMark") + f04_31_serial_feature: Optional[str] = Field(None, alias="serialFeature") + f04_32_issuer: Optional[str] = Field(None, alias="issuer") + f04_33_issue_year: Optional[str] = Field(None, alias="issueYear") + f04_34_material: Optional[str] = Field(None, alias="material") + f04_35_denomination: Optional[str] = Field(None, alias="denomination") + f04_36_issue_quantity: Optional[str] = Field(None, alias="issueQuantity") + + # f05 价格信息 + f05_40_cost_price: Optional[float] = Field(None, ge=0, alias="costPrice") + f05_41_target_price: Optional[float] = Field(None, ge=0, alias="targetPrice") + f05_42_goal_price: Optional[float] = Field(None, ge=0, alias="goalPrice") + f05_43_repair_fee: Optional[float] = Field(None, ge=0, alias="repairFee") + f05_44_grading_fee: Optional[float] = Field(None, ge=0, alias="gradingFee") + + # f06 其他信息 + f06_50_purpose: Optional[str] = Field(None, alias="purpose") + + model_config = ConfigDict(from_attributes=True, populate_by_name=True) + + +class CollectionCreate(CollectionBase): + pass + + +class CollectionUpdate(BaseModel): + # f01 基本信息 + f01_01_name: Optional[str] = Field(None, alias="name") + f01_02_code: Optional[str] = Field(None, alias="code") + f01_03_category: Optional[str] = Field(None, alias="category") + f01_04_status: Optional[str] = Field(None, alias="status") + f01_05_remark: Optional[str] = Field(None, alias="remark") + + # f02 详细字段 + f02_10_prefix_serial: Optional[str] = Field(None, alias="prefixSerial") + f02_11_version: Optional[str] = Field(None, alias="version") + f02_12_packaging: Optional[str] = Field(None, alias="packaging") + f02_13_rarity: Optional[str] = Field(None, alias="rarity") + f02_14_number_category: Optional[str] = Field(None, alias="numberCategory") + + # f03 评级信息 + f03_20_is_graded: Optional[bool] = Field(None, alias="isGraded") + f03_21_grading_company: Optional[str] = Field(None, alias="gradingCompany") + f03_22_grading_score: Optional[str] = Field(None, alias="gradingScore") + f03_23_three_star: Optional[bool] = Field(None, alias="threeStar") + + # f04 特殊信息 + f04_30_special_mark: Optional[str] = Field(None, alias="specialMark") + f04_31_serial_feature: Optional[str] = Field(None, alias="serialFeature") + f04_32_issuer: Optional[str] = Field(None, alias="issuer") + f04_33_issue_year: Optional[str] = Field(None, alias="issueYear") + f04_34_material: Optional[str] = Field(None, alias="material") + f04_35_denomination: Optional[str] = Field(None, alias="denomination") + f04_36_issue_quantity: Optional[str] = Field(None, alias="issueQuantity") + + # f05 价格信息 + f05_40_cost_price: Optional[float] = Field(None, ge=0, alias="costPrice") + f05_41_target_price: Optional[float] = Field(None, ge=0, alias="targetPrice") + f05_42_goal_price: Optional[float] = Field(None, ge=0, alias="goalPrice") + f05_43_repair_fee: Optional[float] = Field(None, ge=0, alias="repairFee") + f05_44_grading_fee: Optional[float] = Field(None, ge=0, alias="gradingFee") + + # f06 其他信息 + f06_50_purpose: Optional[str] = Field(None, alias="purpose") + + model_config = ConfigDict(from_attributes=True, populate_by_name=True) + + +class CollectionImageResponse(BaseModel): + f99_90_id: str + filename: str + original_name: Optional[str] = None + path: Optional[str] = None + f99_92_created_at: Optional[datetime] = None + + model_config = ConfigDict(from_attributes=True) + + +class CollectionResponse(CollectionBase): + f99_90_id: str = Field(..., alias="id") + f99_91_user_id: str = Field(..., alias="userId") + f99_92_created_at: Optional[datetime] = Field(None, alias="createdAt") + f99_93_updated_at: Optional[datetime] = Field(None, alias="updatedAt") + images: List[CollectionImageResponse] = [] + + model_config = ConfigDict(from_attributes=True, populate_by_name=True) + + +class CollectionListResponse(BaseModel): + data: List[CollectionResponse] + pagination: dict + + +# ============ 操作日志相关 ============ + +class OperationBase(BaseModel): + type: str = Field(..., max_length=50) + price: Optional[float] = None + note: Optional[str] = None + + +class OperationCreate(OperationBase): + f99_91_user_id: str + + +class OperationResponse(OperationBase): + f99_90_id: str + f99_91_user_id: str + f99_93_created_at: Optional[datetime] = None + + model_config = ConfigDict(from_attributes=True) + + +# ============ OCR 相关 ============ + +class OCRRequest(BaseModel): + image: str + ocr_provider: Optional[str] = "aliyun" + + +class OCRResponse(BaseModel): + text: str + confidence: float + fields: Optional[dict] = None + + +# ============ 通用响应 ============ + +class Token(BaseModel): + access_token: str + token_type: str = "bearer" + + +class TokenData(BaseModel): + f99_90_user_id: Optional[str] = None + + +class MessageResponse(BaseModel): + message: str + + +class ErrorResponse(BaseModel): + detail: str diff --git a/backend/app/services/oss.py b/backend/app/services/oss.py new file mode 100644 index 0000000..6c52c87 --- /dev/null +++ b/backend/app/services/oss.py @@ -0,0 +1,126 @@ +# 阿里云OSS服务 +import os +import uuid +import datetime +from typing import Optional +import oss2 +from PIL import Image +import io + +# OSS配置 +OSS_CONFIG = { + "access_key_id": os.getenv("OSS_ACCESS_KEY_ID", "LTAI5t6HUnpFBLEK9194kPVG"), + "access_key_secret": os.getenv("OSS_ACCESS_KEY_SECRET", "LEr4Q8yRxb8D5b24cKfCwlt4MMoke1"), + "bucket_name": "jiachenlong-oss", + "endpoint": "oss-cn-hangzhou.aliyuncs.com", + "public_url": "https://jiachenlong-oss.oss-cn-hangzhou.aliyuncs.com" +} + +# 图片压缩配置 +IMAGE_CONFIG = { + "max_size": 1024 * 1024, # 1MB + "max_width": 2048, + "max_height": 2048, + "quality": 85, + "format": "JPEG" +} + +# 初始化OSS +auth = oss2.Auth(OSS_CONFIG["access_key_id"], OSS_CONFIG["access_key_secret"]) +bucket = oss2.Bucket(auth, OSS_CONFIG["endpoint"], OSS_CONFIG["bucket_name"]) + + +def get_oss_path(prefix: str, user_id: str = None, filename: str = None) -> str: + """生成OSS存储路径""" + now = datetime.datetime.now() + year = now.strftime("%Y") + month = now.strftime("%m") + day = now.strftime("%d") + + if filename: + ext = filename.split('.')[-1] if '.' in filename else 'jpg' + unique_name = f"{uuid.uuid4().hex}.{ext}" + else: + unique_name = f"{uuid.uuid4().hex}.jpg" + + if user_id: + path = f"{prefix}/{user_id}/{year}/{month}/{unique_name}" + else: + path = f"{prefix}/{year}/{month}/{day}/{unique_name}" + + return path, unique_name + + +def upload_to_oss(file_data: bytes, oss_key: str, compress: bool = True) -> str: + """上传文件到OSS,返回公网URL""" + try: + # 如果是图片,进行压缩 + if compress and any(oss_key.lower().endswith(ext) for ext in ['.jpg', '.jpeg', '.png', '.webp']): + file_data = compress_image(file_data) + + # 上传文件 + result = bucket.put_object(oss_key, file_data) + + if result.status == 200: + # 返回公网URL + return f"{OSS_CONFIG['public_url']}/{oss_key}" + else: + raise Exception(f"OSS上传失败: {result.status}") + + except Exception as e: + raise Exception(f"OSS上传失败: {str(e)}") + + +def delete_from_oss(oss_key: str) -> bool: + """从OSS删除文件""" + try: + result = bucket.delete_object(oss_key) + return result.status == 204 + except Exception as e: + print(f"OSS删除失败: {str(e)}") + return False + + +def get_public_url(oss_key: str) -> str: + """获取公网URL""" + return f"{OSS_CONFIG['public_url']}/{oss_key}" + + +def compress_image(image_data: bytes, max_size: int = None) -> bytes: + """压缩图片到指定大小以内""" + if max_size is None: + max_size = IMAGE_CONFIG["max_size"] + + # 如果已经小于限制,直接返回 + if len(image_data) <= max_size: + return image_data + + # 打开图片 + img = Image.open(io.BytesIO(image_data)) + + # 如果是PNG且有透明通道,转换为RGB + if img.mode in ('RGBA', 'P'): + img = img.convert('RGB') + + # 逐步降低质量直到达到目标大小 + quality = 95 + compressed_data = image_data + + while quality > 30 and len(compressed_data) > max_size: + output = io.BytesIO() + img.save(output, format=IMAGE_CONFIG["format"], quality=quality, optimize=True) + compressed_data = output.getvalue() + quality -= 10 + + # 如果还是太大,缩小尺寸 + if len(compressed_data) > max_size: + width, height = img.size + while len(compressed_data) > max_size and width > 400: + width = int(width * 0.8) + height = int(height * 0.8) + img_resized = img.resize((width, height), Image.Resampling.LANCZOS) + output = io.BytesIO() + img_resized.save(output, format=IMAGE_CONFIG["format"], quality=80, optimize=True) + compressed_data = output.getvalue() + + return compressed_data diff --git a/backend/app/services/sms.py b/backend/app/services/sms.py new file mode 100644 index 0000000..f067142 --- /dev/null +++ b/backend/app/services/sms.py @@ -0,0 +1,106 @@ +# 阿里云短信服务 +import os +import random +import string +import time +from datetime import datetime, timedelta +from typing import Optional + +# 阿里云短信配置 +SMS_CONFIG = { + "access_key_id": os.getenv("SMS_ACCESS_KEY_ID", "LTAI5tQAx5niD7JQVqGE5acE"), + "access_key_secret": os.getenv("SMS_ACCESS_KEY_SECRET", "QsQFAEKBkaNynIoKyvdIi3BUyWVZu1"), + "sign_name": os.getenv("SMS_SIGN_NAME", "苏州算力"), + "template_code": os.getenv("SMS_TEMPLATE_CODE", "SMS_501590956"), +} + +# 验证码缓存(生产环境建议用Redis) +# 格式: { phone: { code: "123456", expire: 1234567890 } } +VERIFICATION_CODES = {} + + +def generate_code(length: int = 6) -> str: + """生成6位数字验证码""" + return ''.join(random.choices(string.digits, k=length)) + + +def send_verification_code(phone: str) -> dict: + """发送短信验证码""" + from alibabacloud_dysmsapi20170525 import models + from alibabacloud_dysmsapi20170525.client import Client + from alibabacloud_tea_openapi import models as open_models + + try: + # 生成验证码 + code = generate_code(6) + + # 配置客户端 + config = open_models.Config( + access_key_id=SMS_CONFIG["access_key_id"], + access_key_secret=SMS_CONFIG["access_key_secret"], + ) + config.endpoint = "dysmsapi.aliyuncs.com" + config.region_id = "cn-hangzhou" + + client = Client(config) + + # 构造请求 + request = models.SendSmsRequest( + phone_numbers=phone, + sign_name=SMS_CONFIG["sign_name"], + template_code=SMS_CONFIG["template_code"], + template_param=f'{{"code":"{code}"}}' + ) + + # 发送 + response = client.send_sms(request) + + # 检查结果 + if response.body.code == "OK": + # 保存验证码 + VERIFICATION_CODES[phone] = { + "code": code, + "expire": int(time.time()) + 300 # 5分钟有效 + } + return { + "success": True, + "message": "验证码已发送", + "expire": 300 + } + else: + return { + "success": False, + "message": f"发送失败: {response.body.message}" + } + + except Exception as e: + return { + "success": False, + "message": f"发送失败: {str(e)}" + } + + +def verify_code(phone: str, code: str) -> bool: + """验证验证码""" + if phone not in VERIFICATION_CODES: + return False + + stored = VERIFICATION_CODES[phone] + + # 检查是否过期 + if int(time.time()) > stored["expire"]: + del VERIFICATION_CODES[phone] + return False + + # 验证码匹配 + if stored["code"] == code: + # 验证成功,删除验证码 + del VERIFICATION_CODES[phone] + return True + + return False + + +def check_code_exists(phone: str) -> bool: + """检查是否已发送过验证码""" + return phone in VERIFICATION_CODES diff --git a/backend/app/utils/number_category.py b/backend/app/utils/number_category.py new file mode 100644 index 0000000..340e9f2 --- /dev/null +++ b/backend/app/utils/number_category.py @@ -0,0 +1,132 @@ +# 号码分类工具 +# 按MEMORY.md最新规则 (2026-04-02) +# 优先级:数字越小越有价值 + +CATEGORIES = [ + # 1. 圆圆号:无.123457,只能用0689 + {"name": "圆圆号", "cannot_use": ".123457", "must_have": ""}, + # 2. 倒置号:无23457,可用01689必须有1 + {"name": "倒置号", "cannot_use": "23457", "must_have": "1"}, + # 3. 金马王:无12347,可用05689必须有5 + {"name": "金马王", "cannot_use": "12347", "must_have": "5"}, + # 4. 金马号:无2347,可用015689必须有1和5 + {"name": "金马号", "cannot_use": "2347", "must_have": "15"}, + # 5. 金山王:无12457,可用03689必须有3 + {"name": "金山王", "cannot_use": "12457", "must_have": "3"}, + # 6. 天马王:无1247,可用035689必须有3和5 + {"name": "天马王", "cannot_use": "1247", "must_have": "35"}, + # 7. 金山号:无2457,可用013689必须有1和3 + {"name": "金山号", "cannot_use": "2457", "must_have": "13"}, + # 8. 天马号:无247,可用0135689必须有1、3和5 + {"name": "天马号", "cannot_use": "247", "must_have": "135"}, + # 9. 朦胧王:无13457 + {"name": "朦胧王", "cannot_use": "13457", "must_have": ""}, + # 10. 朦胧号:无3457 + {"name": "朦胧号", "cannot_use": "3457", "must_have": ""}, + # 11. 如意号:无1347 + {"name": "如意号", "cannot_use": "1347", "must_have": ""}, + # 12. 钻石号:无347 + {"name": "钻石号", "cannot_use": "347", "must_have": ""}, + # 13. 永恒号:无47 + {"name": "永恒号", "cannot_use": "47", "must_have": ""}, + # 14. 无4号:不包含4 + {"name": "无4号", "cannot_use": "4", "must_have": ""}, + # 15. 通货:含4 + {"name": "通货", "cannot_use": "", "must_have": "4"}, +] + + +def extract_digits(serial: str) -> dict: + """提取冠字号中的数字部分""" + if not serial: + return {"digits": "", "type": "single"} + + nums = serial.replace("J", "").replace(",", "").replace(".", "").strip() + nums = "".join(c for c in nums if c.isdigit()) + + if nums.endswith("01"): + return {"digits": nums[:-2], "type": "hundred"} + elif nums.endswith("1"): + return {"digits": nums[:-1], "type": "ten"} + else: + return {"digits": nums, "type": "single"} + + +def matches_category(digits: str, category: dict) -> bool: + cannot_use = category.get("cannot_use", "") + must_have = category.get("must_have", "") + + # 检查不能用的数字 + for n in cannot_use: + if n in digits: + return False + + # 检查必须有的数字 + if must_have: + for n in must_have: + if n not in digits: + return False + + return True + + +def get_number_category(serial: str) -> str: + """号码分类函数""" + if not serial: + return "" + + # 提取数字 + info = extract_digits(serial) + digits = info["digits"] + + if not digits: + return "" + + # 根据类型取对应位数 + digits_type = info["type"] + if digits_type == "hundred": + # 标百看后6位 + check_digits = digits[-6:] if len(digits) >= 6 else digits + elif digits_type == "ten": + # 标十看后7位 + check_digits = digits[-7:] if len(digits) >= 7 else digits + else: + # 散钞看全部 + check_digits = digits + + # 按优先级匹配分类 + for category in CATEGORIES: + if matches_category(check_digits, category): + return category["name"] + + return "通货" + + +def get_number_category_color(category: str) -> str: + """获取分类颜色""" + colors = { + "圆圆号": "#ef4444", # 红 + "倒置号": "#f97316", # 橙 + "金马王": "#eab308", # 黄 + "金马号": "#84cc16", # 绿 + "金山王": "#22c55e", # 深绿 + "天马王": "#14b8a6", # 青 + "金山号": "#06b6d4", # 蓝 + "天马号": "#0ea5e9", # 浅蓝 + "朦胧王": "#6366f1", # 靛蓝 + "朦胧号": "#8b5cf6", # 紫 + "如意号": "#a855f7", # 深紫 + "钻石号": "#d946ef", # 品红 + "永恒号": "#ec4899", # 粉红 + "无4号": "#64748b", # 灰 + "通货": "#9ca3af", # 浅灰 + } + return colors.get(category, "#9ca3af") + + +def get_category_priority(category: str) -> int: + """获取分类优先级(数字越小越高级)""" + for i, cat in enumerate(CATEGORIES, 1): + if cat["name"] == category: + return i + return 999 \ No newline at end of file diff --git a/backend/logs/app.log b/backend/logs/app.log new file mode 100644 index 0000000..f254449 --- /dev/null +++ b/backend/logs/app.log @@ -0,0 +1,47 @@ +{"timestamp": "2026-04-15T04:06:34.997704Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "979705e7-6942-4347-af1b-886297594d66", "user_id": null, "request_id": "857409fa-6f64-424a-9cbd-8c2c7cb4cd15", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:07:02.330013Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "4cec75a0-0ae3-4a30-86fe-b2a3bca6943e", "user_id": null, "request_id": "c96d816b-309a-447e-9241-fe005a769d31", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:07:33.485146Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "f3762a9d-0c17-4bc7-be60-70c1b7b579d2", "user_id": null, "request_id": "799e1335-ab10-4aa4-aeaa-b6f77a6c7eb2", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:07:55.082694Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: type object 'Information' has no attribute 'deal_no'", "trace_id": "aa0f7d18-0428-47f0-92d3-13698ad6f8ce", "user_id": null, "request_id": "c68777ae-fd05-4192-bb5f-c105ba038bfc", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:07:55.086656Z", "level": "ERROR", "logger": "root", "message": "API 请求异常:GET /api/information/list", "trace_id": "2895acdc-f404-415b-b8bb-65cc76367aab", "user_id": null, "request_id": "ada08c80-2231-445b-b4f3-0c67239a1f8e", "ip_address": "127.0.0.1", "duration_ms": 21.480321884155273, "data": {"method": "GET", "path": "/api/information/list", "query": "info_type=yichen&page=1&page_size=2", "error": "type object 'Information' has no attribute 'deal_no'"}, "exception": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 159, in call_next\n message = await recv_stream.receive()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/streams/memory.py\", line 132, in receive\n raise EndOfStream from None\nanyio.EndOfStream\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 135, in get_information_list\n query = query.order_by(Information.deal_date.desc().nullslast(), Information.deal_no.desc().nullslast())\n ^^^^^^^^^^^^^^^^^^^\nAttributeError: type object 'Information' has no attribute 'deal_no'"} +{"timestamp": "2026-04-15T04:07:55.093581Z", "level": "ERROR", "logger": "root", "message": "未捕获异常:type object 'Information' has no attribute 'deal_no'\n + Exception Group Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 85, in collapse_excgroups\n | yield\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 190, in __call__\n | async with anyio.create_task_group() as task_group:\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 783, in __aexit__\n | raise BaseExceptionGroup(\n | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)\n +-+---------------- 1 ----------------\n | Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n | await self.app(scope, receive, _send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n | with collapse_excgroups():\n | File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n | self.gen.throw(value)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n | response = await self.dispatch_func(request, call_next)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n | response = await call_next(request)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n | raise app_exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n | await self.app(scope, receive_or_disconnect, send_no_error)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n | await self.middleware_stack(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n | await route.handle(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n | await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n | response = await func(request)\n | ^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n | raise e\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n | raw_response = await run_endpoint_function(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n | return await run_in_threadpool(dependant.call, **values)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n | return await anyio.to_thread.run_sync(func, *args)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n | return await get_async_backend().run_sync_in_worker_thread(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n | return await future\n | ^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n | result = context.run(func, *args)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 135, in get_information_list\n | query = query.order_by(Information.deal_date.desc().nullslast(), Information.deal_no.desc().nullslast())\n | ^^^^^^^^^^^^^^^^^^^\n | AttributeError: type object 'Information' has no attribute 'deal_no'\n +------------------------------------\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n await self.app(scope, receive, _send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n with collapse_excgroups():\n File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n self.gen.throw(value)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n response = await self.dispatch_func(request, call_next)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 135, in get_information_list\n query = query.order_by(Information.deal_date.desc().nullslast(), Information.deal_no.desc().nullslast())\n ^^^^^^^^^^^^^^^^^^^\nAttributeError: type object 'Information' has no attribute 'deal_no'\n", "trace_id": "18a49976-49f4-45a5-a927-190bcb2f4b86", "user_id": null, "request_id": "0eb02dbe-30c6-4693-a456-36e9aa54abbe", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:09:13.628237Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "ba877311-e544-42b4-8b25-aa7058128c64", "user_id": null, "request_id": "33a35503-64c1-4359-8ed0-151527e274cb", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:09:17.533102Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: (psycopg2.errors.UndefinedColumn) column users_1.f99_101_invited_count does not exist\nLINE 1: ...f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f9...\n ^\n\n[SQL: SELECT information.id AS information_id, information.user_id AS information_user_id, information.info_type AS information_info_type, information.title AS information_title, information.content AS information_content, information.collection_id AS information_collection_id, information.expect_category AS information_expect_category, information.expect_version AS information_expect_version, information.expect_packaging AS information_expect_packaging, information.expect_number AS information_expect_number, information.expect_price_min AS information_expect_price_min, information.expect_price_max AS information_expect_price_max, information.deal_price AS information_deal_price, information.deal_date AS information_deal_date, information.status AS information_status, information.is_matched AS information_is_matched, information.matched_user_id AS information_matched_user_id, information.matched_contact AS information_matched_contact, information.view_count AS information_view_count, information.contact_count AS information_contact_count, information.created_at AS information_created_at, information.updated_at AS information_updated_at, information.author AS information_author, users_1.f99_90_id AS users_1_f99_90_id, users_1.user_code AS users_1_user_code, users_1.f99_91_user_id AS users_1_f99_91_user_id, users_1.f01_01_name AS users_1_f01_01_name, users_1.email AS users_1_email, users_1.phone AS users_1_phone, users_1.avatar AS users_1_avatar, users_1.address AS users_1_address, users_1.bio AS users_1_bio, users_1.password AS users_1_password, users_1.role AS users_1_role, users_1.f99_92_created_at AS users_1_f99_92_created_at, users_1.f99_93_updated_at AS users_1_f99_93_updated_at, users_1.f99_94_level AS users_1_f99_94_level, users_1.f99_95_ai_count AS users_1_f99_95_ai_count, users_1.f99_96_search_count AS users_1_f99_96_search_count, users_1.f99_97_collection_count AS users_1_f99_97_collection_count, users_1.f01_06_phone_verified AS users_1_f01_06_phone_verified, users_1.f99_98_login_count AS users_1_f99_98_login_count, users_1.f99_99_last_login AS users_1_f99_99_last_login, users_1.f01_07_gender AS users_1_f01_07_gender, users_1.f01_08_birthday AS users_1_f01_08_birthday, users_1.f01_09_region AS users_1_f01_09_region, users_1.f01_10_realname_verified AS users_1_f01_10_realname_verified, users_1.f99_100_points AS users_1_f99_100_points, users_1.f01_11_balance AS users_1_f01_11_balance, users_1.f01_12_total_amount AS users_1_f01_12_total_amount, users_1.f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f99_101_invited_count AS users_1_f99_101_invited_count, users_1.f99_101_information_count AS users_1_f99_101_information_count, collections_1.f99_90_id AS collections_1_f99_90_id, collections_1.f99_91_user_id AS collections_1_f99_91_user_id, collections_1.f99_92_created_at AS collections_1_f99_92_created_at, collections_1.f99_93_updated_at AS collections_1_f99_93_updated_at, collections_1.f01_01_name AS collections_1_f01_01_name, collections_1.f01_02_code AS collections_1_f01_02_code, collections_1.f01_03_category AS collections_1_f01_03_category, collections_1.f01_04_status AS collections_1_f01_04_status, collections_1.f01_05_remark AS collections_1_f01_05_remark, collections_1.f02_10_prefix_serial AS collections_1_f02_10_prefix_serial, collections_1.f02_11_version AS collections_1_f02_11_version, collections_1.f02_12_packaging AS collections_1_f02_12_packaging, collections_1.f02_13_rarity AS collections_1_f02_13_rarity, collections_1.f02_14_number_category AS collections_1_f02_14_number_category, collections_1.f03_20_is_graded AS collections_1_f03_20_is_graded, collections_1.f03_21_grading_company AS collections_1_f03_21_grading_company, collections_1.f03_22_grading_score AS collections_1_f03_22_grading_score, collections_1.f03_23_three_star AS collections_1_f03_23_three_star, collections_1.f04_30_special_mark AS collections_1_f04_30_special_mark, collections_1.f04_31_serial_feature AS collections_1_f04_31_serial_feature, collections_1.f04_32_issuer AS collections_1_f04_32_issuer, collections_1.f04_33_issue_year AS collections_1_f04_33_issue_year, collections_1.f04_34_material AS collections_1_f04_34_material, collections_1.f04_35_denomination AS collections_1_f04_35_denomination, collections_1.f04_36_issue_quantity AS collections_1_f04_36_issue_quantity, collections_1.f05_40_cost_price AS collections_1_f05_40_cost_price, collections_1.f05_41_target_price AS collections_1_f05_41_target_price, collections_1.f05_42_goal_price AS collections_1_f05_42_goal_price, collections_1.f05_43_repair_fee AS collections_1_f05_43_repair_fee, collections_1.f05_44_grading_fee AS collections_1_f05_44_grading_fee, collections_1.f06_50_purpose AS collections_1_f06_50_purpose \nFROM information LEFT OUTER JOIN users AS users_1 ON users_1.f99_90_id = information.user_id LEFT OUTER JOIN collections AS collections_1 ON collections_1.f99_90_id = information.collection_id \nWHERE information.status = %(status_1)s AND information.info_type = %(info_type_1)s ORDER BY information.deal_date DESC NULLS LAST \n LIMIT %(param_1)s OFFSET %(param_2)s]\n[parameters: {'status_1': 'active', 'info_type_1': 'yichen', 'param_1': 2, 'param_2': 0}]\n(Background on this error at: https://sqlalche.me/e/20/f405)", "trace_id": "1527cf36-195d-49ae-aa16-0487f464ad72", "user_id": null, "request_id": "b5f2c384-c275-4339-9155-ec8dfdb7b482", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:09:17.539802Z", "level": "ERROR", "logger": "root", "message": "API 请求异常:GET /api/information/list", "trace_id": "f24c915b-4e68-45a0-b01c-1f887ed5a8f9", "user_id": null, "request_id": "ab15af30-5ddb-464f-96de-56c91b85e0a1", "ip_address": "127.0.0.1", "duration_ms": 32.13644027709961, "data": {"method": "GET", "path": "/api/information/list", "query": "info_type=yichen&page=1&page_size=2", "error": "(psycopg2.errors.UndefinedColumn) column users_1.f99_101_invited_count does not exist\nLINE 1: ...f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f9...\n ^\n\n[SQL: SELECT information.id AS information_id, information.user_id AS information_user_id, information.info_type AS information_info_type, information.title AS information_title, information.content AS information_content, information.collection_id AS information_collection_id, information.expect_category AS information_expect_category, information.expect_version AS information_expect_version, information.expect_packaging AS information_expect_packaging, information.expect_number AS information_expect_number, information.expect_price_min AS information_expect_price_min, information.expect_price_max AS information_expect_price_max, information.deal_price AS information_deal_price, information.deal_date AS information_deal_date, information.status AS information_status, information.is_matched AS information_is_matched, information.matched_user_id AS information_matched_user_id, information.matched_contact AS information_matched_contact, information.view_count AS information_view_count, information.contact_count AS information_contact_count, information.created_at AS information_created_at, information.updated_at AS information_updated_at, information.author AS information_author, users_1.f99_90_id AS users_1_f99_90_id, users_1.user_code AS users_1_user_code, users_1.f99_91_user_id AS users_1_f99_91_user_id, users_1.f01_01_name AS users_1_f01_01_name, users_1.email AS users_1_email, users_1.phone AS users_1_phone, users_1.avatar AS users_1_avatar, users_1.address AS users_1_address, users_1.bio AS users_1_bio, users_1.password AS users_1_password, users_1.role AS users_1_role, users_1.f99_92_created_at AS users_1_f99_92_created_at, users_1.f99_93_updated_at AS users_1_f99_93_updated_at, users_1.f99_94_level AS users_1_f99_94_level, users_1.f99_95_ai_count AS users_1_f99_95_ai_count, users_1.f99_96_search_count AS users_1_f99_96_search_count, users_1.f99_97_collection_count AS users_1_f99_97_collection_count, users_1.f01_06_phone_verified AS users_1_f01_06_phone_verified, users_1.f99_98_login_count AS users_1_f99_98_login_count, users_1.f99_99_last_login AS users_1_f99_99_last_login, users_1.f01_07_gender AS users_1_f01_07_gender, users_1.f01_08_birthday AS users_1_f01_08_birthday, users_1.f01_09_region AS users_1_f01_09_region, users_1.f01_10_realname_verified AS users_1_f01_10_realname_verified, users_1.f99_100_points AS users_1_f99_100_points, users_1.f01_11_balance AS users_1_f01_11_balance, users_1.f01_12_total_amount AS users_1_f01_12_total_amount, users_1.f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f99_101_invited_count AS users_1_f99_101_invited_count, users_1.f99_101_information_count AS users_1_f99_101_information_count, collections_1.f99_90_id AS collections_1_f99_90_id, collections_1.f99_91_user_id AS collections_1_f99_91_user_id, collections_1.f99_92_created_at AS collections_1_f99_92_created_at, collections_1.f99_93_updated_at AS collections_1_f99_93_updated_at, collections_1.f01_01_name AS collections_1_f01_01_name, collections_1.f01_02_code AS collections_1_f01_02_code, collections_1.f01_03_category AS collections_1_f01_03_category, collections_1.f01_04_status AS collections_1_f01_04_status, collections_1.f01_05_remark AS collections_1_f01_05_remark, collections_1.f02_10_prefix_serial AS collections_1_f02_10_prefix_serial, collections_1.f02_11_version AS collections_1_f02_11_version, collections_1.f02_12_packaging AS collections_1_f02_12_packaging, collections_1.f02_13_rarity AS collections_1_f02_13_rarity, collections_1.f02_14_number_category AS collections_1_f02_14_number_category, collections_1.f03_20_is_graded AS collections_1_f03_20_is_graded, collections_1.f03_21_grading_company AS collections_1_f03_21_grading_company, collections_1.f03_22_grading_score AS collections_1_f03_22_grading_score, collections_1.f03_23_three_star AS collections_1_f03_23_three_star, collections_1.f04_30_special_mark AS collections_1_f04_30_special_mark, collections_1.f04_31_serial_feature AS collections_1_f04_31_serial_feature, collections_1.f04_32_issuer AS collections_1_f04_32_issuer, collections_1.f04_33_issue_year AS collections_1_f04_33_issue_year, collections_1.f04_34_material AS collections_1_f04_34_material, collections_1.f04_35_denomination AS collections_1_f04_35_denomination, collections_1.f04_36_issue_quantity AS collections_1_f04_36_issue_quantity, collections_1.f05_40_cost_price AS collections_1_f05_40_cost_price, collections_1.f05_41_target_price AS collections_1_f05_41_target_price, collections_1.f05_42_goal_price AS collections_1_f05_42_goal_price, collections_1.f05_43_repair_fee AS collections_1_f05_43_repair_fee, collections_1.f05_44_grading_fee AS collections_1_f05_44_grading_fee, collections_1.f06_50_purpose AS collections_1_f06_50_purpose \nFROM information LEFT OUTER JOIN users AS users_1 ON users_1.f99_90_id = information.user_id LEFT OUTER JOIN collections AS collections_1 ON collections_1.f99_90_id = information.collection_id \nWHERE information.status = %(status_1)s AND information.info_type = %(info_type_1)s ORDER BY information.deal_date DESC NULLS LAST \n LIMIT %(param_1)s OFFSET %(param_2)s]\n[parameters: {'status_1': 'active', 'info_type_1': 'yichen', 'param_1': 2, 'param_2': 0}]\n(Background on this error at: https://sqlalche.me/e/20/f405)"}, "exception": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1969, in _exec_single_context\n self.dialect.do_execute(\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/default.py\", line 922, in do_execute\n cursor.execute(statement, parameters)\npsycopg2.errors.UndefinedColumn: column users_1.f99_101_invited_count does not exist\nLINE 1: ...f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f9...\n ^\n\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 129, in get_information_list\n items = query.offset(offset).limit(page_size).all()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/query.py\", line 2693, in all\n return self._iter().all() # type: ignore\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/query.py\", line 2847, in _iter\n result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/session.py\", line 2308, in execute\n return self._execute_internal(\n ^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/session.py\", line 2190, in _execute_internal\n result: Result[Any] = compile_state_cls.orm_execute_statement(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/context.py\", line 293, in orm_execute_statement\n result = conn.execute(\n ^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1416, in execute\n return meth(\n ^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/sql/elements.py\", line 517, in _execute_on_connection\n return connection._execute_clauseelement(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1639, in _execute_clauseelement\n ret = self._execute_context(\n ^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1848, in _execute_context\n return self._exec_single_context(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1988, in _exec_single_context\n self._handle_dbapi_exception(\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 2344, in _handle_dbapi_exception\n raise sqlalchemy_exception.with_traceback(exc_info[2]) from e\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1969, in _exec_single_context\n self.dialect.do_execute(\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/default.py\", line 922, in do_execute\n cursor.execute(statement, parameters)\nsqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedColumn) column users_1.f99_101_invited_count does not exist\nLINE 1: ...f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f9...\n ^\n\n[SQL: SELECT information.id AS information_id, information.user_id AS information_user_id, information.info_type AS information_info_type, information.title AS information_title, information.content AS information_content, information.collection_id AS information_collection_id, information.expect_category AS information_expect_category, information.expect_version AS information_expect_version, information.expect_packaging AS information_expect_packaging, information.expect_number AS information_expect_number, information.expect_price_min AS information_expect_price_min, information.expect_price_max AS information_expect_price_max, information.deal_price AS information_deal_price, information.deal_date AS information_deal_date, information.status AS information_status, information.is_matched AS information_is_matched, information.matched_user_id AS information_matched_user_id, information.matched_contact AS information_matched_contact, information.view_count AS information_view_count, information.contact_count AS information_contact_count, information.created_at AS information_created_at, information.updated_at AS information_updated_at, information.author AS information_author, users_1.f99_90_id AS users_1_f99_90_id, users_1.user_code AS users_1_user_code, users_1.f99_91_user_id AS users_1_f99_91_user_id, users_1.f01_01_name AS users_1_f01_01_name, users_1.email AS users_1_email, users_1.phone AS users_1_phone, users_1.avatar AS users_1_avatar, users_1.address AS users_1_address, users_1.bio AS users_1_bio, users_1.password AS users_1_password, users_1.role AS users_1_role, users_1.f99_92_created_at AS users_1_f99_92_created_at, users_1.f99_93_updated_at AS users_1_f99_93_updated_at, users_1.f99_94_level AS users_1_f99_94_level, users_1.f99_95_ai_count AS users_1_f99_95_ai_count, users_1.f99_96_search_count AS users_1_f99_96_search_count, users_1.f99_97_collection_count AS users_1_f99_97_collection_count, users_1.f01_06_phone_verified AS users_1_f01_06_phone_verified, users_1.f99_98_login_count AS users_1_f99_98_login_count, users_1.f99_99_last_login AS users_1_f99_99_last_login, users_1.f01_07_gender AS users_1_f01_07_gender, users_1.f01_08_birthday AS users_1_f01_08_birthday, users_1.f01_09_region AS users_1_f01_09_region, users_1.f01_10_realname_verified AS users_1_f01_10_realname_verified, users_1.f99_100_points AS users_1_f99_100_points, users_1.f01_11_balance AS users_1_f01_11_balance, users_1.f01_12_total_amount AS users_1_f01_12_total_amount, users_1.f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f99_101_invited_count AS users_1_f99_101_invited_count, users_1.f99_101_information_count AS users_1_f99_101_information_count, collections_1.f99_90_id AS collections_1_f99_90_id, collections_1.f99_91_user_id AS collections_1_f99_91_user_id, collections_1.f99_92_created_at AS collections_1_f99_92_created_at, collections_1.f99_93_updated_at AS collections_1_f99_93_updated_at, collections_1.f01_01_name AS collections_1_f01_01_name, collections_1.f01_02_code AS collections_1_f01_02_code, collections_1.f01_03_category AS collections_1_f01_03_category, collections_1.f01_04_status AS collections_1_f01_04_status, collections_1.f01_05_remark AS collections_1_f01_05_remark, collections_1.f02_10_prefix_serial AS collections_1_f02_10_prefix_serial, collections_1.f02_11_version AS collections_1_f02_11_version, collections_1.f02_12_packaging AS collections_1_f02_12_packaging, collections_1.f02_13_rarity AS collections_1_f02_13_rarity, collections_1.f02_14_number_category AS collections_1_f02_14_number_category, collections_1.f03_20_is_graded AS collections_1_f03_20_is_graded, collections_1.f03_21_grading_company AS collections_1_f03_21_grading_company, collections_1.f03_22_grading_score AS collections_1_f03_22_grading_score, collections_1.f03_23_three_star AS collections_1_f03_23_three_star, collections_1.f04_30_special_mark AS collections_1_f04_30_special_mark, collections_1.f04_31_serial_feature AS collections_1_f04_31_serial_feature, collections_1.f04_32_issuer AS collections_1_f04_32_issuer, collections_1.f04_33_issue_year AS collections_1_f04_33_issue_year, collections_1.f04_34_material AS collections_1_f04_34_material, collections_1.f04_35_denomination AS collections_1_f04_35_denomination, collections_1.f04_36_issue_quantity AS collections_1_f04_36_issue_quantity, collections_1.f05_40_cost_price AS collections_1_f05_40_cost_price, collections_1.f05_41_target_price AS collections_1_f05_41_target_price, collections_1.f05_42_goal_price AS collections_1_f05_42_goal_price, collections_1.f05_43_repair_fee AS collections_1_f05_43_repair_fee, collections_1.f05_44_grading_fee AS collections_1_f05_44_grading_fee, collections_1.f06_50_purpose AS collections_1_f06_50_purpose \nFROM information LEFT OUTER JOIN users AS users_1 ON users_1.f99_90_id = information.user_id LEFT OUTER JOIN collections AS collections_1 ON collections_1.f99_90_id = information.collection_id \nWHERE information.status = %(status_1)s AND information.info_type = %(info_type_1)s ORDER BY information.deal_date DESC NULLS LAST \n LIMIT %(param_1)s OFFSET %(param_2)s]\n[parameters: {'status_1': 'active', 'info_type_1': 'yichen', 'param_1': 2, 'param_2': 0}]\n(Background on this error at: https://sqlalche.me/e/20/f405)"} +{"timestamp": "2026-04-15T04:09:17.545679Z", "level": "ERROR", "logger": "root", "message": "未捕获异常:(psycopg2.errors.UndefinedColumn) column users_1.f99_101_invited_count does not exist\nLINE 1: ...f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f9...\n ^\n\n[SQL: SELECT information.id AS information_id, information.user_id AS information_user_id, information.info_type AS information_info_type, information.title AS information_title, information.content AS information_content, information.collection_id AS information_collection_id, information.expect_category AS information_expect_category, information.expect_version AS information_expect_version, information.expect_packaging AS information_expect_packaging, information.expect_number AS information_expect_number, information.expect_price_min AS information_expect_price_min, information.expect_price_max AS information_expect_price_max, information.deal_price AS information_deal_price, information.deal_date AS information_deal_date, information.status AS information_status, information.is_matched AS information_is_matched, information.matched_user_id AS information_matched_user_id, information.matched_contact AS information_matched_contact, information.view_count AS information_view_count, information.contact_count AS information_contact_count, information.created_at AS information_created_at, information.updated_at AS information_updated_at, information.author AS information_author, users_1.f99_90_id AS users_1_f99_90_id, users_1.user_code AS users_1_user_code, users_1.f99_91_user_id AS users_1_f99_91_user_id, users_1.f01_01_name AS users_1_f01_01_name, users_1.email AS users_1_email, users_1.phone AS users_1_phone, users_1.avatar AS users_1_avatar, users_1.address AS users_1_address, users_1.bio AS users_1_bio, users_1.password AS users_1_password, users_1.role AS users_1_role, users_1.f99_92_created_at AS users_1_f99_92_created_at, users_1.f99_93_updated_at AS users_1_f99_93_updated_at, users_1.f99_94_level AS users_1_f99_94_level, users_1.f99_95_ai_count AS users_1_f99_95_ai_count, users_1.f99_96_search_count AS users_1_f99_96_search_count, users_1.f99_97_collection_count AS users_1_f99_97_collection_count, users_1.f01_06_phone_verified AS users_1_f01_06_phone_verified, users_1.f99_98_login_count AS users_1_f99_98_login_count, users_1.f99_99_last_login AS users_1_f99_99_last_login, users_1.f01_07_gender AS users_1_f01_07_gender, users_1.f01_08_birthday AS users_1_f01_08_birthday, users_1.f01_09_region AS users_1_f01_09_region, users_1.f01_10_realname_verified AS users_1_f01_10_realname_verified, users_1.f99_100_points AS users_1_f99_100_points, users_1.f01_11_balance AS users_1_f01_11_balance, users_1.f01_12_total_amount AS users_1_f01_12_total_amount, users_1.f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f99_101_invited_count AS users_1_f99_101_invited_count, users_1.f99_101_information_count AS users_1_f99_101_information_count, collections_1.f99_90_id AS collections_1_f99_90_id, collections_1.f99_91_user_id AS collections_1_f99_91_user_id, collections_1.f99_92_created_at AS collections_1_f99_92_created_at, collections_1.f99_93_updated_at AS collections_1_f99_93_updated_at, collections_1.f01_01_name AS collections_1_f01_01_name, collections_1.f01_02_code AS collections_1_f01_02_code, collections_1.f01_03_category AS collections_1_f01_03_category, collections_1.f01_04_status AS collections_1_f01_04_status, collections_1.f01_05_remark AS collections_1_f01_05_remark, collections_1.f02_10_prefix_serial AS collections_1_f02_10_prefix_serial, collections_1.f02_11_version AS collections_1_f02_11_version, collections_1.f02_12_packaging AS collections_1_f02_12_packaging, collections_1.f02_13_rarity AS collections_1_f02_13_rarity, collections_1.f02_14_number_category AS collections_1_f02_14_number_category, collections_1.f03_20_is_graded AS collections_1_f03_20_is_graded, collections_1.f03_21_grading_company AS collections_1_f03_21_grading_company, collections_1.f03_22_grading_score AS collections_1_f03_22_grading_score, collections_1.f03_23_three_star AS collections_1_f03_23_three_star, collections_1.f04_30_special_mark AS collections_1_f04_30_special_mark, collections_1.f04_31_serial_feature AS collections_1_f04_31_serial_feature, collections_1.f04_32_issuer AS collections_1_f04_32_issuer, collections_1.f04_33_issue_year AS collections_1_f04_33_issue_year, collections_1.f04_34_material AS collections_1_f04_34_material, collections_1.f04_35_denomination AS collections_1_f04_35_denomination, collections_1.f04_36_issue_quantity AS collections_1_f04_36_issue_quantity, collections_1.f05_40_cost_price AS collections_1_f05_40_cost_price, collections_1.f05_41_target_price AS collections_1_f05_41_target_price, collections_1.f05_42_goal_price AS collections_1_f05_42_goal_price, collections_1.f05_43_repair_fee AS collections_1_f05_43_repair_fee, collections_1.f05_44_grading_fee AS collections_1_f05_44_grading_fee, collections_1.f06_50_purpose AS collections_1_f06_50_purpose \nFROM information LEFT OUTER JOIN users AS users_1 ON users_1.f99_90_id = information.user_id LEFT OUTER JOIN collections AS collections_1 ON collections_1.f99_90_id = information.collection_id \nWHERE information.status = %(status_1)s AND information.info_type = %(info_type_1)s ORDER BY information.deal_date DESC NULLS LAST \n LIMIT %(param_1)s OFFSET %(param_2)s]\n[parameters: {'status_1': 'active', 'info_type_1': 'yichen', 'param_1': 2, 'param_2': 0}]\n(Background on this error at: https://sqlalche.me/e/20/f405)\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1969, in _exec_single_context\n self.dialect.do_execute(\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/default.py\", line 922, in do_execute\n cursor.execute(statement, parameters)\npsycopg2.errors.UndefinedColumn: column users_1.f99_101_invited_count does not exist\nLINE 1: ...f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f9...\n ^\n\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n await self.app(scope, receive, _send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n with collapse_excgroups():\n File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n self.gen.throw(value)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n response = await self.dispatch_func(request, call_next)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 129, in get_information_list\n items = query.offset(offset).limit(page_size).all()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/query.py\", line 2693, in all\n return self._iter().all() # type: ignore\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/query.py\", line 2847, in _iter\n result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/session.py\", line 2308, in execute\n return self._execute_internal(\n ^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/session.py\", line 2190, in _execute_internal\n result: Result[Any] = compile_state_cls.orm_execute_statement(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/orm/context.py\", line 293, in orm_execute_statement\n result = conn.execute(\n ^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1416, in execute\n return meth(\n ^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/sql/elements.py\", line 517, in _execute_on_connection\n return connection._execute_clauseelement(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1639, in _execute_clauseelement\n ret = self._execute_context(\n ^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1848, in _execute_context\n return self._exec_single_context(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1988, in _exec_single_context\n self._handle_dbapi_exception(\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 2344, in _handle_dbapi_exception\n raise sqlalchemy_exception.with_traceback(exc_info[2]) from e\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/base.py\", line 1969, in _exec_single_context\n self.dialect.do_execute(\n File \"/usr/local/lib/python3.12/dist-packages/sqlalchemy/engine/default.py\", line 922, in do_execute\n cursor.execute(statement, parameters)\nsqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedColumn) column users_1.f99_101_invited_count does not exist\nLINE 1: ...f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f9...\n ^\n\n[SQL: SELECT information.id AS information_id, information.user_id AS information_user_id, information.info_type AS information_info_type, information.title AS information_title, information.content AS information_content, information.collection_id AS information_collection_id, information.expect_category AS information_expect_category, information.expect_version AS information_expect_version, information.expect_packaging AS information_expect_packaging, information.expect_number AS information_expect_number, information.expect_price_min AS information_expect_price_min, information.expect_price_max AS information_expect_price_max, information.deal_price AS information_deal_price, information.deal_date AS information_deal_date, information.status AS information_status, information.is_matched AS information_is_matched, information.matched_user_id AS information_matched_user_id, information.matched_contact AS information_matched_contact, information.view_count AS information_view_count, information.contact_count AS information_contact_count, information.created_at AS information_created_at, information.updated_at AS information_updated_at, information.author AS information_author, users_1.f99_90_id AS users_1_f99_90_id, users_1.user_code AS users_1_user_code, users_1.f99_91_user_id AS users_1_f99_91_user_id, users_1.f01_01_name AS users_1_f01_01_name, users_1.email AS users_1_email, users_1.phone AS users_1_phone, users_1.avatar AS users_1_avatar, users_1.address AS users_1_address, users_1.bio AS users_1_bio, users_1.password AS users_1_password, users_1.role AS users_1_role, users_1.f99_92_created_at AS users_1_f99_92_created_at, users_1.f99_93_updated_at AS users_1_f99_93_updated_at, users_1.f99_94_level AS users_1_f99_94_level, users_1.f99_95_ai_count AS users_1_f99_95_ai_count, users_1.f99_96_search_count AS users_1_f99_96_search_count, users_1.f99_97_collection_count AS users_1_f99_97_collection_count, users_1.f01_06_phone_verified AS users_1_f01_06_phone_verified, users_1.f99_98_login_count AS users_1_f99_98_login_count, users_1.f99_99_last_login AS users_1_f99_99_last_login, users_1.f01_07_gender AS users_1_f01_07_gender, users_1.f01_08_birthday AS users_1_f01_08_birthday, users_1.f01_09_region AS users_1_f01_09_region, users_1.f01_10_realname_verified AS users_1_f01_10_realname_verified, users_1.f99_100_points AS users_1_f99_100_points, users_1.f01_11_balance AS users_1_f01_11_balance, users_1.f01_12_total_amount AS users_1_f01_12_total_amount, users_1.f01_13_invite_code AS users_1_f01_13_invite_code, users_1.f99_101_invited_count AS users_1_f99_101_invited_count, users_1.f99_101_information_count AS users_1_f99_101_information_count, collections_1.f99_90_id AS collections_1_f99_90_id, collections_1.f99_91_user_id AS collections_1_f99_91_user_id, collections_1.f99_92_created_at AS collections_1_f99_92_created_at, collections_1.f99_93_updated_at AS collections_1_f99_93_updated_at, collections_1.f01_01_name AS collections_1_f01_01_name, collections_1.f01_02_code AS collections_1_f01_02_code, collections_1.f01_03_category AS collections_1_f01_03_category, collections_1.f01_04_status AS collections_1_f01_04_status, collections_1.f01_05_remark AS collections_1_f01_05_remark, collections_1.f02_10_prefix_serial AS collections_1_f02_10_prefix_serial, collections_1.f02_11_version AS collections_1_f02_11_version, collections_1.f02_12_packaging AS collections_1_f02_12_packaging, collections_1.f02_13_rarity AS collections_1_f02_13_rarity, collections_1.f02_14_number_category AS collections_1_f02_14_number_category, collections_1.f03_20_is_graded AS collections_1_f03_20_is_graded, collections_1.f03_21_grading_company AS collections_1_f03_21_grading_company, collections_1.f03_22_grading_score AS collections_1_f03_22_grading_score, collections_1.f03_23_three_star AS collections_1_f03_23_three_star, collections_1.f04_30_special_mark AS collections_1_f04_30_special_mark, collections_1.f04_31_serial_feature AS collections_1_f04_31_serial_feature, collections_1.f04_32_issuer AS collections_1_f04_32_issuer, collections_1.f04_33_issue_year AS collections_1_f04_33_issue_year, collections_1.f04_34_material AS collections_1_f04_34_material, collections_1.f04_35_denomination AS collections_1_f04_35_denomination, collections_1.f04_36_issue_quantity AS collections_1_f04_36_issue_quantity, collections_1.f05_40_cost_price AS collections_1_f05_40_cost_price, collections_1.f05_41_target_price AS collections_1_f05_41_target_price, collections_1.f05_42_goal_price AS collections_1_f05_42_goal_price, collections_1.f05_43_repair_fee AS collections_1_f05_43_repair_fee, collections_1.f05_44_grading_fee AS collections_1_f05_44_grading_fee, collections_1.f06_50_purpose AS collections_1_f06_50_purpose \nFROM information LEFT OUTER JOIN users AS users_1 ON users_1.f99_90_id = information.user_id LEFT OUTER JOIN collections AS collections_1 ON collections_1.f99_90_id = information.collection_id \nWHERE information.status = %(status_1)s AND information.info_type = %(info_type_1)s ORDER BY information.deal_date DESC NULLS LAST \n LIMIT %(param_1)s OFFSET %(param_2)s]\n[parameters: {'status_1': 'active', 'info_type_1': 'yichen', 'param_1': 2, 'param_2': 0}]\n(Background on this error at: https://sqlalche.me/e/20/f405)\n", "trace_id": "fd653117-7066-4645-b23d-4395e1453cb5", "user_id": null, "request_id": "b36fd8b6-3f0f-4291-95e6-903b48b96e0a", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:10:21.921961Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "c0c8c9fb-02ac-4f1c-8d97-caa806e6d54a", "user_id": null, "request_id": "64d0ed38-3b51-4a50-9161-2a9750d4479c", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:10:55.614704Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "994f8d7d-61fb-496b-8204-441cb9ead315", "user_id": null, "request_id": "72434856-457c-422d-8881-d12aac04a97a", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:11:54.743982Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "bfd9d19c-30aa-4863-8fdd-65552e601a53", "user_id": null, "request_id": "60c1dfe9-dce6-4fd6-ac45-5890871cbb61", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:12:18.350083Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "c27c03bb-e733-4967-80ab-bbc1c75221a5", "user_id": null, "request_id": "e1b1ce77-1bc9-469b-8e89-62dfcc6da361", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:32:54.455912Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 401: E00011: 用户名或密码错误", "trace_id": "bee519b9-6cfc-41bb-ab79-63e9bcdb7ca0", "user_id": null, "request_id": "07418ddc-394d-447f-8c9f-3b988827e210", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:33:46.727754Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type", "trace_id": "4d9f265f-dd65-404f-a352-4209a53da3e2", "user_id": null, "request_id": "50d8f2a6-f3e9-40d9-8c69-ab18965f534a", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:33:46.731371Z", "level": "ERROR", "logger": "root", "message": "API 请求异常:POST /api/information/", "trace_id": "0b8b5cbf-e872-4d30-8447-588447273e4a", "user_id": "authenticated", "request_id": "19f0ce46-1030-4724-97b6-e198883564a1", "ip_address": "127.0.0.1", "duration_ms": 19.598007202148438, "data": {"method": "POST", "path": "/api/information/", "query": "", "error": "1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type"}, "exception": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 159, in call_next\n message = await recv_stream.receive()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/streams/memory.py\", line 132, in receive\n raise EndOfStream from None\nanyio.EndOfStream\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 470, in create_information\n return InformationResponse(\n ^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\npydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type"} +{"timestamp": "2026-04-15T04:33:46.736348Z", "level": "ERROR", "logger": "root", "message": "未捕获异常:1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n + Exception Group Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 85, in collapse_excgroups\n | yield\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 190, in __call__\n | async with anyio.create_task_group() as task_group:\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 783, in __aexit__\n | raise BaseExceptionGroup(\n | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)\n +-+---------------- 1 ----------------\n | Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n | await self.app(scope, receive, _send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n | with collapse_excgroups():\n | File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n | self.gen.throw(value)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n | response = await self.dispatch_func(request, call_next)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n | response = await call_next(request)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n | raise app_exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n | await self.app(scope, receive_or_disconnect, send_no_error)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n | await self.middleware_stack(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n | await route.handle(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n | await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n | response = await func(request)\n | ^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n | raise e\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n | raw_response = await run_endpoint_function(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n | return await run_in_threadpool(dependant.call, **values)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n | return await anyio.to_thread.run_sync(func, *args)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n | return await get_async_backend().run_sync_in_worker_thread(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n | return await future\n | ^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n | result = context.run(func, *args)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 470, in create_information\n | return InformationResponse(\n | ^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n | __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\n | pydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\n | created_at\n | Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n | For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n +------------------------------------\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n await self.app(scope, receive, _send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n with collapse_excgroups():\n File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n self.gen.throw(value)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n response = await self.dispatch_func(request, call_next)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 470, in create_information\n return InformationResponse(\n ^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\npydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n", "trace_id": "918c81da-4a49-4bf6-a5c4-6af79b9126c7", "user_id": null, "request_id": "05ea208b-2aca-41c5-b06c-dd32372aaefa", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:35:27.776534Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 404: 资讯不存在", "trace_id": "fe5e3bf9-3864-45c2-b44c-ad150aa45fc4", "user_id": null, "request_id": "b4558b5a-0685-4ed9-85de-cc62f04d6599", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:39:37.783033Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "88e5f2ea-5660-431f-8a1e-3b9764f559aa", "user_id": null, "request_id": "6d2c816a-e153-484c-8dd6-43f74fd9d8f4", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:39:42.958240Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 404: 资讯不存在", "trace_id": "1b25d3fd-3a7e-47ed-81bd-62aeecb62fa1", "user_id": null, "request_id": "c9993123-65b4-4891-9271-3641d0cedd2d", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:41:51.486935Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type", "trace_id": "40594474-d1ba-4548-9d2f-3cf318e77363", "user_id": null, "request_id": "de7d80e8-aa27-484a-aa4e-50d31c589482", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:41:51.490603Z", "level": "ERROR", "logger": "root", "message": "API 请求异常:GET /api/information/list", "trace_id": "5710b554-8725-4d24-9d6a-c720970694e9", "user_id": "authenticated", "request_id": "f9a6185c-a73b-46cb-bd33-9ceb05d1b198", "ip_address": "127.0.0.1", "duration_ms": 21.33631706237793, "data": {"method": "GET", "path": "/api/information/list", "query": "info_type=seek", "error": "1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type"}, "exception": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 159, in call_next\n message = await recv_stream.receive()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/streams/memory.py\", line 132, in receive\n raise EndOfStream from None\nanyio.EndOfStream\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 148, in get_information_list\n result.append(InformationResponse(\n ^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\npydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type"} +{"timestamp": "2026-04-15T04:41:51.495550Z", "level": "ERROR", "logger": "root", "message": "未捕获异常:1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n + Exception Group Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 85, in collapse_excgroups\n | yield\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 190, in __call__\n | async with anyio.create_task_group() as task_group:\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 783, in __aexit__\n | raise BaseExceptionGroup(\n | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)\n +-+---------------- 1 ----------------\n | Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n | await self.app(scope, receive, _send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n | with collapse_excgroups():\n | File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n | self.gen.throw(value)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n | response = await self.dispatch_func(request, call_next)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n | response = await call_next(request)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n | raise app_exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n | await self.app(scope, receive_or_disconnect, send_no_error)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n | await self.middleware_stack(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n | await route.handle(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n | await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n | response = await func(request)\n | ^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n | raise e\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n | raw_response = await run_endpoint_function(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n | return await run_in_threadpool(dependant.call, **values)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n | return await anyio.to_thread.run_sync(func, *args)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n | return await get_async_backend().run_sync_in_worker_thread(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n | return await future\n | ^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n | result = context.run(func, *args)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 148, in get_information_list\n | result.append(InformationResponse(\n | ^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n | __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\n | pydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\n | created_at\n | Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n | For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n +------------------------------------\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n await self.app(scope, receive, _send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n with collapse_excgroups():\n File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n self.gen.throw(value)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n response = await self.dispatch_func(request, call_next)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 148, in get_information_list\n result.append(InformationResponse(\n ^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\npydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n", "trace_id": "9086b2b8-98df-41fe-bacf-3ba62a92f0b5", "user_id": null, "request_id": "f4c8cc51-606e-4ac4-93e5-fcaf50d570d1", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:42:58.846192Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type", "trace_id": "26b91125-790c-4d3f-9b4d-6b416b5b2c33", "user_id": null, "request_id": "d51b4b7a-78f6-4db8-9339-7698778b05a6", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:42:58.848163Z", "level": "ERROR", "logger": "root", "message": "API 请求异常:GET /api/information/my/list", "trace_id": "1f653a8b-0aa4-4103-bce0-fa46d6a2264a", "user_id": "authenticated", "request_id": "b82e34b3-50d1-463f-aebe-d8b884b501ef", "ip_address": "127.0.0.1", "duration_ms": 18.507719039916992, "data": {"method": "GET", "path": "/api/information/my/list", "query": "", "error": "1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type"}, "exception": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 159, in call_next\n message = await recv_stream.receive()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/streams/memory.py\", line 132, in receive\n raise EndOfStream from None\nanyio.EndOfStream\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 865, in get_my_information_list\n result.append(InformationResponse(\n ^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\npydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type"} +{"timestamp": "2026-04-15T04:42:58.853579Z", "level": "ERROR", "logger": "root", "message": "未捕获异常:1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n + Exception Group Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 85, in collapse_excgroups\n | yield\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 190, in __call__\n | async with anyio.create_task_group() as task_group:\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 783, in __aexit__\n | raise BaseExceptionGroup(\n | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)\n +-+---------------- 1 ----------------\n | Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n | await self.app(scope, receive, _send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n | with collapse_excgroups():\n | File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n | self.gen.throw(value)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n | response = await self.dispatch_func(request, call_next)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n | response = await call_next(request)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n | raise app_exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n | await self.app(scope, receive_or_disconnect, send_no_error)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n | await self.middleware_stack(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n | await route.handle(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n | await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n | response = await func(request)\n | ^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n | raise e\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n | raw_response = await run_endpoint_function(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n | return await run_in_threadpool(dependant.call, **values)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n | return await anyio.to_thread.run_sync(func, *args)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n | return await get_async_backend().run_sync_in_worker_thread(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n | return await future\n | ^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n | result = context.run(func, *args)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 865, in get_my_information_list\n | result.append(InformationResponse(\n | ^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n | __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\n | pydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\n | created_at\n | Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n | For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n +------------------------------------\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n await self.app(scope, receive, _send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n with collapse_excgroups():\n File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n self.gen.throw(value)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n response = await self.dispatch_func(request, call_next)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 299, in app\n raise e\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 294, in app\n raw_response = await run_endpoint_function(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 193, in run_endpoint_function\n return await run_in_threadpool(dependant.call, **values)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/concurrency.py\", line 40, in run_in_threadpool\n return await anyio.to_thread.run_sync(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/to_thread.py\", line 63, in run_sync\n return await get_async_backend().run_sync_in_worker_thread(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 2502, in run_sync_in_worker_thread\n return await future\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 986, in run\n result = context.run(func, *args)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/routers/information.py\", line 865, in get_my_information_list\n result.append(InformationResponse(\n ^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/pydantic/main.py\", line 164, in __init__\n __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)\npydantic_core._pydantic_core.ValidationError: 1 validation error for InformationResponse\ncreated_at\n Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType]\n For further information visit https://errors.pydantic.dev/2.5/v/datetime_type\n", "trace_id": "9ad0efb7-00bf-4486-9a8b-fb92580ff08a", "user_id": null, "request_id": "b36c422b-8d83-4c07-8eb1-1b364a4d84e8", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:48:07.281241Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "6f6cd185-cd65-4400-ba50-4a875a3752b9", "user_id": null, "request_id": "59082f37-bf42-445b-a989-3ec7a8f32405", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:48:34.642478Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n", "trace_id": "5a24478f-193a-41ff-8f03-278094ed2e83", "user_id": null, "request_id": "f5593d8a-f8df-4b6e-8b0a-91ef7a1a0917", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:48:34.644427Z", "level": "ERROR", "logger": "root", "message": "API 请求异常:GET /api/deal/list", "trace_id": "2c627391-bde1-47de-b4ff-5731a023c409", "user_id": "authenticated", "request_id": "b8c85965-fb12-4dad-bfae-065cf67484bc", "ip_address": "127.0.0.1", "duration_ms": 5.033731460571289, "data": {"method": "GET", "path": "/api/deal/list", "query": "", "error": "2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n"}, "exception": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 159, in call_next\n message = await recv_stream.receive()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/streams/memory.py\", line 132, in receive\n raise EndOfStream from None\nanyio.EndOfStream\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n content = await serialize_response(\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n raise ResponseValidationError(\nfastapi.exceptions.ResponseValidationError: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n"} +{"timestamp": "2026-04-15T04:48:34.647748Z", "level": "ERROR", "logger": "root", "message": "未捕获异常:2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n\n + Exception Group Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 85, in collapse_excgroups\n | yield\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 190, in __call__\n | async with anyio.create_task_group() as task_group:\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 783, in __aexit__\n | raise BaseExceptionGroup(\n | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)\n +-+---------------- 1 ----------------\n | Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n | await self.app(scope, receive, _send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n | with collapse_excgroups():\n | File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n | self.gen.throw(value)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n | response = await self.dispatch_func(request, call_next)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n | response = await call_next(request)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n | raise app_exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n | await self.app(scope, receive_or_disconnect, send_no_error)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n | await self.middleware_stack(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n | await route.handle(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n | await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n | response = await func(request)\n | ^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n | content = await serialize_response(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n | raise ResponseValidationError(\n | fastapi.exceptions.ResponseValidationError: 2 validation errors:\n | {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n | {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n | \n +------------------------------------\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n await self.app(scope, receive, _send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n with collapse_excgroups():\n File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n self.gen.throw(value)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n response = await self.dispatch_func(request, call_next)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n content = await serialize_response(\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n raise ResponseValidationError(\nfastapi.exceptions.ResponseValidationError: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n\n", "trace_id": "bec50163-3a4c-4acd-afce-89ae53cc9ada", "user_id": null, "request_id": "7aec923e-dcdb-4fc2-9925-6c58522eca2a", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:49:16.266011Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "48a1e525-2343-48eb-808f-0251c0412ca7", "user_id": null, "request_id": "10a19f52-44e1-40b0-a106-921ffe00f6fd", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:49:58.006677Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "1caf2b84-32e8-4666-91a0-777cba8cd10f", "user_id": null, "request_id": "6ec3b15d-c285-4fca-96ad-446fdef4ce7f", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:51:32.869462Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "4ed7e61c-82f3-4b62-8736-79da1aaa7e6f", "user_id": null, "request_id": "436515bb-30db-4ddf-9a73-cda22ada49ce", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:52:07.316981Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "56d0f6a9-e671-4e09-a1bd-e6b78660e77a", "user_id": null, "request_id": "b4abaa99-f024-4542-b7c4-01b34734e7e9", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:52:44.266934Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "e5116cd9-26d7-47d7-b739-f35b5977e43a", "user_id": null, "request_id": "9f22ae8c-098e-4533-ada6-83ee6c9b9788", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:53:55.198568Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "6ed5bb9a-f6e7-4b05-94c5-b862ba5636f4", "user_id": null, "request_id": "9b554653-6013-45b6-a122-d6a8f22e26e8", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:55:00.396074Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "a0c907b0-5b4b-4108-a5a0-ef02d52a6a0d", "user_id": null, "request_id": "748da3dc-2349-4d3b-bb4d-07ce2f8b2619", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:55:42.128833Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n", "trace_id": "718e585c-9383-44c8-913c-5e2e3027c3fb", "user_id": null, "request_id": "5eb46231-5418-4929-ab6b-792319cdffb7", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:55:42.131315Z", "level": "ERROR", "logger": "root", "message": "API 请求异常:GET /api/deal/list", "trace_id": "929f3ffd-19cf-4348-baf3-ad9fa80379a6", "user_id": "authenticated", "request_id": "06f3d2cd-1662-46cb-95c6-72f960a5fe21", "ip_address": "127.0.0.1", "duration_ms": 14.678478240966797, "data": {"method": "GET", "path": "/api/deal/list", "query": "", "error": "2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n"}, "exception": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 159, in call_next\n message = await recv_stream.receive()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/streams/memory.py\", line 132, in receive\n raise EndOfStream from None\nanyio.EndOfStream\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n content = await serialize_response(\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n raise ResponseValidationError(\nfastapi.exceptions.ResponseValidationError: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n"} +{"timestamp": "2026-04-15T04:55:42.135299Z", "level": "ERROR", "logger": "root", "message": "未捕获异常:2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n\n + Exception Group Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 85, in collapse_excgroups\n | yield\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 190, in __call__\n | async with anyio.create_task_group() as task_group:\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 783, in __aexit__\n | raise BaseExceptionGroup(\n | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)\n +-+---------------- 1 ----------------\n | Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n | await self.app(scope, receive, _send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n | with collapse_excgroups():\n | File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n | self.gen.throw(value)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n | response = await self.dispatch_func(request, call_next)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n | response = await call_next(request)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n | raise app_exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n | await self.app(scope, receive_or_disconnect, send_no_error)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n | await self.middleware_stack(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n | await route.handle(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n | await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n | response = await func(request)\n | ^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n | content = await serialize_response(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n | raise ResponseValidationError(\n | fastapi.exceptions.ResponseValidationError: 2 validation errors:\n | {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n | {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n | \n +------------------------------------\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n await self.app(scope, receive, _send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n with collapse_excgroups():\n File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n self.gen.throw(value)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n response = await self.dispatch_func(request, call_next)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n content = await serialize_response(\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n raise ResponseValidationError(\nfastapi.exceptions.ResponseValidationError: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n\n", "trace_id": "1717aeb9-909f-4141-b400-f21f2da118ee", "user_id": null, "request_id": "9380897d-def5-48d7-9d8d-7af62fd23ca8", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:56:32.065975Z", "level": "ERROR", "logger": "app.core.database", "message": "数据库会话错误: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n", "trace_id": "82ffeeac-0f40-4dff-b5d4-a1234d9ff83a", "user_id": null, "request_id": "af57ea21-9ea3-48c0-adb3-ba3e1db499ec", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:56:32.067664Z", "level": "ERROR", "logger": "root", "message": "API 请求异常:GET /api/deal/list", "trace_id": "5ec0a5fa-31f7-4a1a-a16c-2edc58264970", "user_id": "authenticated", "request_id": "21cbfdcd-d11b-4d31-a5de-b1d521abab09", "ip_address": "127.0.0.1", "duration_ms": 14.132261276245117, "data": {"method": "GET", "path": "/api/deal/list", "query": "", "error": "2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n"}, "exception": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 159, in call_next\n message = await recv_stream.receive()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/anyio/streams/memory.py\", line 132, in receive\n raise EndOfStream from None\nanyio.EndOfStream\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n content = await serialize_response(\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n raise ResponseValidationError(\nfastapi.exceptions.ResponseValidationError: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n"} +{"timestamp": "2026-04-15T04:56:32.071101Z", "level": "ERROR", "logger": "root", "message": "未捕获异常:2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n\n + Exception Group Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 85, in collapse_excgroups\n | yield\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 190, in __call__\n | async with anyio.create_task_group() as task_group:\n | File \"/usr/local/lib/python3.12/dist-packages/anyio/_backends/_asyncio.py\", line 783, in __aexit__\n | raise BaseExceptionGroup(\n | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)\n +-+---------------- 1 ----------------\n | Traceback (most recent call last):\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n | await self.app(scope, receive, _send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n | with collapse_excgroups():\n | File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n | self.gen.throw(value)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n | response = await self.dispatch_func(request, call_next)\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n | response = await call_next(request)\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n | raise app_exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n | await self.app(scope, receive_or_disconnect, send_no_error)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n | await self.middleware_stack(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n | await route.handle(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n | await self.app(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n | await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n | raise exc\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n | await app(scope, receive, sender)\n | File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n | response = await func(request)\n | ^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n | content = await serialize_response(\n | ^^^^^^^^^^^^^^^^^^^^^^^^^\n | File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n | raise ResponseValidationError(\n | fastapi.exceptions.ResponseValidationError: 2 validation errors:\n | {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n | {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n | \n +------------------------------------\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/errors.py\", line 164, in __call__\n await self.app(scope, receive, _send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 189, in __call__\n with collapse_excgroups():\n File \"/usr/lib/python3.12/contextlib.py\", line 158, in __exit__\n self.gen.throw(value)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_utils.py\", line 91, in collapse_excgroups\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 191, in __call__\n response = await self.dispatch_func(request, call_next)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/root/.openclaw/workspace/jiachenlong/backend/app/middleware/logging.py\", line 28, in logging_middleware\n response = await call_next(request)\n ^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 165, in call_next\n raise app_exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/base.py\", line 151, in coro\n await self.app(scope, receive_or_disconnect, send_no_error)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/cors.py\", line 83, in __call__\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 762, in __call__\n await self.middleware_stack(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 782, in app\n await route.handle(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 297, in handle\n await self.app(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 77, in app\n await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n raise exc\n File \"/usr/local/lib/python3.12/dist-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n await app(scope, receive, sender)\n File \"/usr/local/lib/python3.12/dist-packages/starlette/routing.py\", line 72, in app\n response = await func(request)\n ^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 315, in app\n content = await serialize_response(\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/fastapi/routing.py\", line 155, in serialize_response\n raise ResponseValidationError(\nfastapi.exceptions.ResponseValidationError: 2 validation errors:\n {'type': 'int_type', 'loc': ('response', 0, 'view_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n {'type': 'int_type', 'loc': ('response', 0, 'contact_count'), 'msg': 'Input should be a valid integer', 'input': None, 'url': 'https://errors.pydantic.dev/2.5/v/int_type'}\n\n", "trace_id": "a05bdaf9-6aab-417a-84ef-83d1f80ae150", "user_id": null, "request_id": "292b0d05-6ef3-4df3-ae75-45702b48f1fb", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:57:52.248276Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "171b9f58-06d4-46b9-8739-77aaa801e177", "user_id": null, "request_id": "ff662c1c-a1ed-4432-bfc1-2e91f1a066df", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:59:01.357100Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "f1f16bce-a725-4684-afe8-bfd5fccb0588", "user_id": null, "request_id": "59bbc981-3c1a-4cd6-b553-5db880c79a75", "ip_address": null, "duration_ms": null} +{"timestamp": "2026-04-15T04:59:50.412138Z", "level": "INFO", "logger": "root", "message": "甲辰收藏系统 FastAPI 后端 v0.0.0 启动成功", "trace_id": "d884e124-b403-485a-8ba8-8d961ec357aa", "user_id": null, "request_id": "ca3cbcf1-034c-42f9-8727-d919fb26a1e3", "ip_address": null, "duration_ms": null} diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..bda1a26 --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,13 @@ +# 甲辰藏品管理系统后端 - Python 依赖 +# 版本:v1.0.0 + +fastapi==0.109.0 +uvicorn[standard]==0.27.0 +sqlalchemy==2.0.25 +psycopg2-binary==2.9.9 +pydantic==2.5.3 +python-jose[cryptography]==3.3.0 +bcrypt==4.1.2 +python-multipart==0.0.6 +pillow==10.2.0 +dashscope==1.14.1 diff --git a/backend/uploads/.gitkeep b/backend/uploads/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..2fe6c95 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,47 @@ +# 前端 - React + Vite + +## 启动方式 + +### 开发环境 + +```bash +# 安装依赖 +npm install + +# 开发模式(热重载) +npm run dev + +# 访问 http://localhost:5173 +``` + +### 生产构建 + +```bash +# 构建 +npm run build + +# 部署 dist/ 目录到服务器 +``` + +## 目录结构 + +``` +frontend/ +├── src/ +│ ├── pages/ # 页面组件 +│ ├── utils/ # 工具函数 +│ └── config/ # 配置文件 +├── public/ # 静态资源 +└── dist/ # 构建产物 +``` + +## 页面列表 + +- `/` - 首页 +- `/login` - 登录 +- `/stats` - 统计 +- `/list` - 藏品列表 +- `/add` - 添加藏品 +- `/detail` - 藏品详情 +- `/edit` - 编辑藏品 +- `/admin` - 用户管理(仅管理员) diff --git a/frontend/VERSION b/frontend/VERSION new file mode 100644 index 0000000..ce6248b --- /dev/null +++ b/frontend/VERSION @@ -0,0 +1 @@ +VERSION=1.2.97 diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..72cb774 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,31 @@ + + + + + + + 甲辰收藏 v=1.2.97 + + + + + + + +
+ + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..f22a1fc --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,2132 @@ +{ + "name": "jiachenlong-frontend", + "version": "1.2.82", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "jiachenlong-frontend", + "version": "1.2.82", + "dependencies": { + "axios": "^1.7.9", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^7.1.0" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.3.4", + "vite": "^6.4.2" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.8", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", + "integrity": "sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001779", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001779.tgz", + "integrity": "sha512-U5og2PN7V4DMgF50YPNtnZJGWVLFjjsN3zb6uMT5VGYIewieDj1upwfuVNXf4Kor+89c3iCRJnSzMD5LmTvsfA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.313", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz", + "integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==", + "dev": true, + "license": "ISC" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz", + "integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.1.tgz", + "integrity": "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==", + "license": "MIT", + "dependencies": { + "react-router": "7.13.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "6.4.2", + "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..1826e55 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,21 @@ +{ + "name": "jiachenlong-frontend", + "version": "1.2.82", + "private": true, + "description": "甲辰藏品管理系统 - 移动端前端", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "axios": "^1.7.9", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^7.1.0" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.3.4", + "vite": "^6.4.2" + } +} diff --git a/frontend/package.txt b/frontend/package.txt new file mode 100644 index 0000000..1d01bc1 --- /dev/null +++ b/frontend/package.txt @@ -0,0 +1 @@ +v=1.2.80 diff --git a/frontend/postbuild.js b/frontend/postbuild.js new file mode 100644 index 0000000..0962aea --- /dev/null +++ b/frontend/postbuild.js @@ -0,0 +1,20 @@ +const fs = require('fs'); +const path = require('path'); + +const src = path.join(__dirname, 'static', 'images'); +const dst = path.join(__dirname, 'dist', 'static', 'images'); + +if (!fs.existsSync(dst)) { + fs.mkdirSync(dst, { recursive: true }); +} + +if (fs.existsSync(src)) { + fs.readdirSync(src).forEach(f => { + const srcFile = path.join(src, f); + const dstFile = path.join(dst, f); + fs.copyFileSync(srcFile, dstFile); + console.log('Copied:', f); + }); +} + +console.log('Logo复制完成'); \ No newline at end of file diff --git a/frontend/public/images/jiachenlong-logo.png b/frontend/public/images/jiachenlong-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..247598e711dcbe9bb403c9ee65d1e293d3b0c510 GIT binary patch literal 136602 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 z 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 + + + + + + + + + + + + + + + + + + + + + 甲辰收藏 + + + 生肖纪念钞管理系统 + diff --git a/frontend/public/static/icons/apple-touch-icon.png b/frontend/public/static/icons/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..247598e711dcbe9bb403c9ee65d1e293d3b0c510 GIT binary patch literal 136602 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 z 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 z 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 z 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 + + + + + 用户协议 - 甲辰收藏 + + + +
+

甲辰收藏平台用户协议

+
版本生效日期:自注册之日起
+ +

特别提示:本协议涉及您的重大权利义务,加粗条款请您重点阅读。您完成注册、登录或继续使用本平台服务,即视为已充分阅读、理解并同意本协议全部内容。本协议适用《中华人民共和国民法典》《网络安全法》《个人信息保护法》《电子商务法》等法律法规。

+ +

一、协议主体与适用范围

+
    +
  1. 本协议由您与甲辰收藏平台运营主体(以下简称"平台")签订,约束您使用平台藏品管理,信息展示,数据存储,社区互动等全部服务。
  2. +
  3. 平台发布的隐私政策、藏品发布规则、交易规范等均为本协议组成部分,与本协议具有同等法律效力。
  4. +
  5. 您承诺为具备完全民事行为能力的自然人/法人;未成年人使用需监护人同意并陪同。
  6. +
+ +

二、个人信息收集与使用

+

(一)收集原则

+

平台遵循合法、正当、必要、诚信、最小必要原则收集信息,仅为实现服务功能所必需,不强制收集非必要信息。

+ +

(二)收集范围与目的

+
    +
  1. 注册与身份信息:用户名、手机号、邮箱(用于账号创建,安全验证、客服联系)。
  2. +
  3. 藏品与行为信息:藏品上传内容、收藏记录、浏览操作、发布评论、交易数据(用于藏品管理,服务优化、风控核验)。
  4. +
  5. 设备与网络信息:设备型号、系统版本、IP 地址、日志信息(用于安全防护、故障排查,防作弊)。
  6. +
  7. 位置信息:仅在您主动开启定位权限时收集,用于同城展示等可选功能,关闭不影响基础服务。
  8. +
+ +

(三)信息使用规则

+
    +
  1. 平台仅在您授权范围内使用信息,不超出约定目的、范围与期限处理。
  2. +
  3. 向第三方共享信息时,将单独告知并取得您明确同意,法律法规要求除外。
  4. +
  5. 您有权查阅、更正、删除个人信息,申请注销账号,平台在核验身份后依法处理。
  6. +
  7. 平台采取加密、去标识化、权限管控等措施保护信息安全,制定安全事件应急预案。
  8. +
+ +

三、公开信息使用与免责条款

+
    +
  1. 公开信息定义:您通过平台主动发布、设置为公开可见的藏品资料、图文、评论、动态等内容,均属于您自行公开的信息。
  2. +
  3. 授权使用:您同意平台可在合理范围内使用您的公开信息,用于藏品展示、平台运营、合规审核、服务推广等,不侵犯您合法权益。
  4. +
  5. 法定免责依据:根据《个人信息保护法》第二十七条,平台处理您自行合法公开的信息,在无明确拒绝且不对您权益造成重大影响的情形下,无需另行取得单独同意。
  6. +
  7. 第三方行为免责: +
      +
    • 公开信息可被其他用户浏览、复制、存储、转发,平台无法完全控制第三方使用行为。
    • +
    • 因第三方擅自使用、转载、篡改您公开信息引发的纠纷、损失,平台不承担责任。
    • +
    +
  8. +
  9. 内容责任自负: +
      +
    • 您对公开信息的真实性、合法性、原创性承担全部责任,不得侵犯第三方知识产权、肖像权、名誉权等。
    • +
    • 如因您发布违法、侵权内容导致平台受损,您应承担全部赔偿责任。
    • +
    +
  10. +
  11. 平台管理边界:平台仅依据法律法规与平台规则进行内容审核,对用户自主发布的公开信息不做修改、篡改,不承担真实性担保责任。
  12. +
+ +

四、用户权利与义务

+
    +
  1. 您有权使用平台基础服务,对账号与密码安全负责,不得转借、出售账号。
  2. +
  3. 不得发布违法违规、侵权、虚假、低俗等违反法律法规与公序良俗的内容。
  4. +
  5. 不得利用平台从事洗钱、诈骗、非法交易等违法活动。
  6. +
  7. 您对自行上传的藏品素材、文字等享有知识产权,授权平台在服务范围内非独占使用。
  8. +
+ +

五、知识产权条款

+
    +
  1. 平台所有文字、图标、界面设计、软件代码等知识产权归平台所有,受法律保护。
  2. +
  3. 您上传的原创内容知识产权归您所有;您授权平台为提供服务之目的,使用、存储、展示、传播该内容。
  4. +
  5. 未经权利人书面许可,任何主体不得复制、改编、传播、商用平台内容或用户原创内容。
  6. +
+ +

六、服务变更、中断与终止

+
    +
  1. 平台因维护、升级、政策调整需变更或暂停服务的,将提前公示;因不可抗力、监管要求、第三方故障导致服务中断的,平台不承担违约责任。
  2. +
  3. 平台有权对违规账号采取警示、限流、删帖、封禁等处理措施。
  4. +
  5. 您可随时停止使用服务;账号注销后,平台按法律法规留存相关数据,逾期依法删除。
  6. +
+ +

七、免责声明(法律允许范围内)

+
    +
  1. 平台按"现状"提供服务,对服务及时性、安全性、稳定性不作绝对担保。
  2. +
  3. 平台不对藏品真伪、价值、权属作明示或暗示保证,藏品鉴定与价值判断由您自行负责。
  4. +
  5. 法律允许的最大范围内,平台不对间接损失、利润损失、数据丢失等承担赔偿责任;因平台故意或重大过失导致的损失除外。
  6. +
  7. 因您自身操作不当、账号保管不善、第三方侵权等导致的损失,由您自行承担。
  8. +
+ +

八、协议修改与争议解决

+
    +
  1. 平台修改协议将提前7日公示,您继续使用视为接受修订;如不同意,可停止使用并注销账号。
  2. +
  3. 因本协议产生争议,双方协商解决;协商不成,提交平台运营主体所在地有管辖权的人民法院诉讼解决。
  4. +
  5. 本协议适用中华人民共和国大陆地区法律(不含港澳台法律)。
  6. +
+ +

九、联系与通知

+

平台联系方式:aicoolbot@163.com;您可通过客服渠道咨询协议、隐私、投诉等相关事宜。

+
+ + diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx new file mode 100644 index 0000000..34e17ce --- /dev/null +++ b/frontend/src/App.jsx @@ -0,0 +1,115 @@ +import React, { useState, useEffect } from 'react' +import Home from './pages/Home' +import Settings from './pages/Settings' +import List from './pages/List' +import Add from './pages/Add' +import Stats from './pages/Stats' +import News from './pages/News' +import Login from './pages/Login' +import Detail from './pages/Detail' +import Edit from './pages/Edit' +import Admin from './pages/Admin' + +export default function App() { + const [path, setPath] = useState(window.location.hash.slice(1) || '/') + + useEffect(() => { + const handleHashChange = () => { + setPath(window.location.hash.slice(1) || '/') + } + window.addEventListener('hashchange', handleHashChange) + return () => window.removeEventListener('hashchange', handleHashChange) + }, []) + + const handleNavigate = (newPath) => { + window.location.hash = '#' + newPath + setPath(newPath) + } + + const getComponent = () => { + const basePath = path.split('?')[0] + if (basePath === '/') return + if (basePath === '/news') return + if (basePath === '/stats') return + if (basePath === '/list') return + if (basePath === '/add') return + if (basePath === '/login') return + if (basePath === '/settings') return + if (basePath === '/admin') return + if (basePath.startsWith('/edit')) return + if (basePath.startsWith('/detail')) return + return + } + + const token = localStorage.getItem('token') + const userStr = localStorage.getItem('user') + let user = null + try { + user = userStr ? JSON.parse(userStr) : null + } catch (e) { + console.error('Parse user error:', e) + } + const isAdmin = user && user.role === 'admin' + const isEditor = user && user.role === 'editor' + + // 登录页面独立渲染,不显示底部导航 + if (!token) { + // 强制刷新页面,确保状态同步 + if (path !== '/login') { + window.location.hash = '#/login' + } + return + } + + // 如果已登录且在登录页,强制跳转到首页 + if (path === '/login') { + // 使用 href 强制刷新页面 + window.location.href = window.location.origin + window.location.pathname + '#/' + return null + } + + return ( +
+ {getComponent()} + +
+ {[ + { path: '/', icon: '🏠', label: '首页' }, + { path: '/news', icon: '📰', label: '行情' }, + { path: '/stats', icon: '📊', label: '统计' }, + { path: '/list', icon: '📚', label: '我的' }, + { path: '/add', icon: '🎯', label: '录入' }, + ...(isAdmin ? [{ path: '/admin', icon: '⚙️', label: '管理' }] : []) + ].map(tab => ( +
handleNavigate(tab.path)} + style={{ + flex: 1, + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + color: path === tab.path ? '#fbbf24' : '#94a3b8', + cursor: 'pointer' + }} + > +
{tab.icon}
+
{tab.label}
+
+ ))} +
+
+ ) +} +// Fri Apr 10 03:44:24 PM CST 2026 diff --git a/frontend/src/config/version.js b/frontend/src/config/version.js new file mode 100644 index 0000000..4810618 --- /dev/null +++ b/frontend/src/config/version.js @@ -0,0 +1 @@ +VERSION=1.2.100 diff --git a/frontend/src/index.css b/frontend/src/index.css new file mode 100644 index 0000000..5c1e0df --- /dev/null +++ b/frontend/src/index.css @@ -0,0 +1 @@ +/* 全局样式 */ diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx new file mode 100644 index 0000000..ef33be1 --- /dev/null +++ b/frontend/src/main.jsx @@ -0,0 +1,23 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import { HashRouter } from 'react-router-dom' +import App from './App' +import './index.css' + +// 渲染应用 +const root = document.getElementById('root') +try { + ReactDOM.createRoot(root).render( + + + + + + ) + console.log('App rendered successfully') +} catch (e) { + console.error('Render error:', e) + root.innerHTML = '
Error: ' + e.message + '
' +} +// v2.7.2 build +// Force rebuild v2.7.2 - 1773392274 diff --git a/frontend/src/pages/Add.jsx b/frontend/src/pages/Add.jsx new file mode 100644 index 0000000..09a9208 --- /dev/null +++ b/frontend/src/pages/Add.jsx @@ -0,0 +1,1083 @@ +// 添加藏品页面 - 支持 AI 识别/手工录入 +import React, { useState, useRef } from 'react' +import { APP_VERSION } from '../config/version' +const API_BASE = localStorage.getItem('API_BASE') || '' +const numberCategoryOptions = [{value:'无2347',label:'无2347'},{value:'无347',label:'无347'},{value:'无247',label:'无247'},{value:'无47',label:'无47'},{value:'带7号',label:'带7号'},{value:'带4号',label:'带4号'},{value:'其他',label:'其他'}]; + +// 字段转换函数 +const convertField = (obj) => { + const map = { + id: 'f99_90_id', userId: 'f99_91_user_id', + name: 'f01_01_name', code: 'f01_02_code', category: 'f01_03_category', + status: 'f01_04_status', remark: 'f01_05_remark', + prefixSerial: 'f02_10_prefix_serial', version: 'f02_11_version', + packaging: 'f02_12_packaging', rarity: 'f02_13_rarity', + isGraded: 'f03_20_is_graded', gradingCompany: 'f03_21_grading_company', + gradingScore: 'f03_22_grading_score', threeStar: 'f03_23_three_star', + specialMark: 'f04_30_special_mark', serialFeature: 'f04_31_serial_feature', numberCategory: 'f02_14_number_category', + issuer: 'f04_32_issuer', issueYear: 'f04_33_issue_year', + material: 'f04_34_material', denomination: 'f04_35_denomination', + issueQuantity: 'f04_36_issue_quantity', + costPrice: 'f05_40_cost_price', targetPrice: 'f05_41_target_price', + goalPrice: 'f05_42_goal_price', repairFee: 'f05_43_repair_fee', + gradingFee: 'f05_44_grading_fee', purpose: 'f06_50_purpose' + } + const result = {} + const numberFields = ['costPrice', 'targetPrice', 'goalPrice', 'repairFee', 'gradingFee'] + for (const key in obj) { + let value = obj[key] + if (value === '' || value === null) value = null + else if (numberFields.includes(key)) { + value = parseFloat(value) + if (isNaN(value)) value = null + } + result[map[key] || key] = value + } + return result +} + +// 通用 Input 组件 +const Input = ({ form, handleChange, label, field, type = 'text', options = null }) => { + const onChange = (e) => { + const value = e.target.value + if (type === 'number' && value !== '') { + const num = parseFloat(value) + handleChange(field, isNaN(num) ? '' : num) + } else handleChange(field, value) + } + return ( +
+
{label}
+ {options ? ( + + ) : ( + + )} +
+ ) +} + +const getDefaultForm = () => ({ + name: '藏品', code: '', category: '自持', rarity: '通货', prefixSerial: '', + version: '2024 龙', denomination: '', status: 'in_collection', packaging: '单张', + material: '塑料钞', issueQuantity: '1 亿', purpose: '收藏', isGraded: false, + gradingCompany: '爱藏', gradingScore: '67+', threeStar: false, specialMark: '', + serialFeature: '', numberCategory: '', issuer: '中国人民银行', issueYear: '2024', + costPrice: '', targetPrice: '', goalPrice: '', repairFee: '', gradingFee: '', remark: '' +}) + +export default function Add() { + // 行情录入表单 + const [dealForm, setDealForm] = useState({ + serial: '', + category: '', + packaging: '标十', + price: '', + platform: '抖音', + seller: '', + buyer: '', + date: new Date().toISOString().split('T')[0], + isGraded: false, + gradingCompany: '爱藏', + gradingScore: '67+' + }) + const [batchDefaultPackaging, setBatchDefaultPackaging] = useState('') + const [batchDefaultDate, setBatchDefaultDate] = useState('') + const [batchDefaultPlatform, setBatchDefaultPlatform] = useState('抖音') + const [dealMode, setDealMode] = useState('single') // single-单条录入, batch-批量录入 + const [batchText, setBatchText] = useState('') + const [batchResult, setBatchResult] = useState([]) + const [parsing, setParsing] = useState(false) + const [savingDeal, setSavingDeal] = useState(false) + + // 号码分类函数 + const autoCategory = (serial) => { + const digits = serial.replace('J', '').replace(/[^0-9]/g, '').slice(0, 9) + if (!digits) return '' + const d = digits + if (!d.includes('1') && !d.includes('2') && !d.includes('3') && !d.includes('4') && !d.includes('5') && !d.includes('7')) return '圆圆号' + if (!d.includes('2') && !d.includes('3') && !d.includes('4') && !d.includes('5') && !d.includes('7')) return '倒置号' + if (!d.includes('1') && !d.includes('2') && !d.includes('3') && !d.includes('4') && !d.includes('7')) return '金马王' + if (!d.includes('2') && !d.includes('3') && !d.includes('4') && !d.includes('7')) return '金马号' + if (!d.includes('1') && !d.includes('2') && !d.includes('4') && !d.includes('5') && !d.includes('7')) return '金山王' + if (!d.includes('1') && !d.includes('2') && !d.includes('4') && !d.includes('7')) return '天马王' + if (!d.includes('2') && !d.includes('4') && !d.includes('5') && !d.includes('7')) return '金山号' + if (!d.includes('2') && !d.includes('4') && !d.includes('7')) return '天马号' + if (!d.includes('1') && !d.includes('3') && !d.includes('4') && !d.includes('5') && !d.includes('7')) return '朦胧王' + if (!d.includes('3') && !d.includes('4') && !d.includes('5') && !d.includes('7')) return '朦胧号' + if (!d.includes('1') && !d.includes('3') && !d.includes('4') && !d.includes('7')) return '如意号' + if (!d.includes('3') && !d.includes('4') && !d.includes('7')) return '钻石号' + if (!d.includes('4') && !d.includes('7')) return '永恒号' + if (!d.includes('4')) return '带7号' + return '带4号' + } + + // 根据 URL 参数确定默认标签 + const params = new URLSearchParams(window.location.hash.split('?')[1] || '') + const modeParam = params.get('mode') + const defaultTab = modeParam === 'manual' ? 'manual' : 'ai' + + const [activeTab, setActiveTab] = useState(defaultTab) // ai, manual, deal + const [form, setForm] = useState(getDefaultForm()) + const [saving, setSaving] = useState(false) + const [error, setError] = useState('') + const [recognizing, setRecognizing] = useState(false) + const [selectedImage, setSelectedImage] = useState(null) + const [imagePreview, setImagePreview] = useState(null) + const [recognizedImage, setRecognizedImage] = useState(null) + const fileInputRef = useRef(null) + const imageFileInputRef = useRef(null) + const [uploadImages, setUploadImages] = useState([]) + const [tempImage, setTempImage] = useState(null) // OCR识别后的临时图片 + const maxImages = 1 + + const handleUploadImage = (e) => { + const files = Array.from(e.target.files) + if (files.length === 0) return + if (files.length + uploadImages.length > maxImages) { + alert(`最多只能上传${maxImages}张图片`) + return + } + const newImages = files.map(file => ({ + file, + preview: URL.createObjectURL(file), + name: file.name, + size: file.size + })) + setUploadImages([...uploadImages, ...newImages]) + } + + const statusOptions = [ + { value: 'in_collection', label: '收藏中' }, + { value: 'selling', label: '出售中' }, + { value: 'sold', label: '已售' }, + { value: 'grading', label: '送评中' }, + { value: 'repairing', label: '修复中' }, + { value: 'transit', label: '在途中' }, + { value: 'seeking', label: '寻号中' }, + { value: 'other', label: '其他' } + ] + + const categoryOptions = [ + { value: '自持', label: '自持' }, + { value: '寄存', label: '寄存' }, + { value: '寄售', label: '寄售' }, + { value: '共有', label: '共有' }, + { value: '其他', label: '其他' } + ] + + const rarityOptions = [ + { value: '通货', label: '通货' }, + { value: '特色', label: '特色' }, + { value: '少见', label: '少见' }, + { value: '稀有', label: '稀有' }, + { value: '珍品', label: '珍品' }, + { value: '孤品', label: '孤品' } + ] + + const packagingOptions = [ + { value: '标十', label: '标十' }, + { value: '标百', label: '标百' }, + { value: '单张', label: '单张' }, + { value: '裸钞', label: '裸钞' } + ] + + const handleChange = (key, value) => { + setForm({ ...form, [key]: value }) + // 只有设置了出售价(goalPrice)才自动设置为"已售" + if (key === 'goalPrice' && value) { + setForm(prev => ({ ...prev, status: 'sold' })) + } + // 冠字号变化时自动分类 + if (key === 'prefixSerial') { + const serial = value + let cat = '' + const match = serial.match(/J(\d{9})/) + const digits = match ? match[1] : serial.replace(/\D/g, '').slice(0, 9) + if (digits) { + if (!digits.includes('2') && !digits.includes('3') && !digits.includes('4') && !digits.includes('7')) cat = '无2347' + else if (!digits.includes('3') && !digits.includes('4') && !digits.includes('7')) cat = '无347' + else if (!digits.includes('2') && !digits.includes('4') && !digits.includes('7')) cat = '无247' + else if (!digits.includes('4') && !digits.includes('7') && digits.includes('2') && digits.includes('3')) cat = '无47' + else if (digits.includes('7') && !digits.includes('4')) cat = '带7号' + else if (digits.includes('4')) cat = '带4号' + else cat = '其他' + } + setForm(prev => ({ ...prev, numberCategory: cat })) + } + // 版别变化时同步发行年份 + if (key === 'version') { + const yearMatch = value.match(/(20\d{2})/) + if (yearMatch) { + setForm(prev => ({ ...prev, issueYear: yearMatch[1] })) + } + } + } + + const handleSelectImage = (e) => { + const file = e.target.files[0] + if (!file) return + setSelectedImage(file) + const reader = new FileReader() + reader.onload = (e) => setImagePreview(e.target.result) + reader.readAsDataURL(file) + } + + const handleRecognize = async () => { + if (!selectedImage) { setError('请先选择图片'); return } + setRecognizing(true) + setError('') + const token = localStorage.getItem('token') + const formData = new FormData() + formData.append('image', selectedImage) + + // 使用 XMLHttpRequest 替代 fetch + const data = await new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest() + xhr.open('POST', '/api/ocr/recognize') + xhr.setRequestHeader('Authorization', 'Bearer ' + token) + + xhr.onload = function() { + if (xhr.status >= 200 && xhr.status < 300) { + try { + const data = JSON.parse(xhr.responseText) + resolve(data) + } catch (e) { + reject(new Error('JSON解析失败: ' + xhr.responseText.substring(0, 100))) + } + } else { + try { + const data = JSON.parse(xhr.responseText) + reject(new Error(data.error?.message || data.detail || '识别失败')) + } catch (e) { + reject(new Error('请求失败: ' + xhr.status)) + } + } + } + + xhr.onerror = function() { + reject(new Error('网络错误')) + } + + xhr.send(formData) + }) + try { + if (data.fields) { + const recognizedForm = { ...getDefaultForm() } + // 直接对应 AI 返回的字段,不需要二次解析 + if (data.fields.issuer) recognizedForm.issuer = data.fields.issuer + if (data.fields.version) recognizedForm.version = data.fields.version + if (data.fields.denomination) recognizedForm.denomination = data.fields.denomination + if (data.fields.prefix_serial) recognizedForm.prefixSerial = data.fields.prefix_serial + if (data.fields.packaging) recognizedForm.packaging = data.fields.packaging + if (data.fields.grading_company) recognizedForm.gradingCompany = data.fields.grading_company + if (data.fields.grading_score) recognizedForm.gradingScore = data.fields.grading_score + if (data.fields.special_mark && data.fields.special_mark !== '无') recognizedForm.specialMark = data.fields.special_mark + if (data.fields.serial_feature && data.fields.serial_feature !== '无') recognizedForm.serialFeature = data.fields.serial_feature + // 布尔字段 + if (data.fields.is_graded !== undefined) recognizedForm.isGraded = data.fields.is_graded + if (data.fields.three_star !== undefined) recognizedForm.threeStar = data.fields.three_star + + // 保存识别的图片信息(包含服务器临时路径) + const newImage = { + file: selectedImage, + preview: URL.createObjectURL(selectedImage), + name: selectedImage.name, + size: selectedImage.size, + temp_image: data.temp_image // 保存临时图片信息 + } + setUploadImages([newImage]) + setTempImage(data.temp_image) // 保存临时图片信息 + + setForm(recognizedForm) + setActiveTab('manual') + console.log('AI 识别结果:', recognizedForm) + console.log('识别图片:', newImage) + } else setError('识别结果为空') + } catch (e) { setError('识别失败:' + e.message) } + finally { setRecognizing(false) } + } + + const handleSave = async () => { + if (!form.name || !form.version) { setError('名称和版别为必填项'); return } + setSaving(true) + setError('') + const token = localStorage.getItem('token') + // 保存前自动根据冠字号设置号码分类 + const formWithCategory = { ...form } + if (formWithCategory.prefixSerial && !formWithCategory.numberCategory) { + const serial = formWithCategory.prefixSerial + const match = serial.match(/J(\d{9})/) + const digits = match ? match[1] : serial.replace(/\D/g, '').slice(0, 9) + if (digits) { + let cat = '' + if (!digits.includes('2') && !digits.includes('3') && !digits.includes('4') && !digits.includes('7')) cat = '无2347' + else if (!digits.includes('3') && !digits.includes('4') && !digits.includes('7')) cat = '无347' + else if (!digits.includes('2') && !digits.includes('4') && !digits.includes('7')) cat = '无247' + else if (!digits.includes('4') && !digits.includes('7') && digits.includes('2') && digits.includes('3')) cat = '无47' + else if (digits.includes('7') && !digits.includes('4')) cat = '带7号' + else if (digits.includes('4')) cat = '带4号' + else cat = '其他' + formWithCategory.numberCategory = cat + } + } + + const formData = convertField(formWithCategory) + try { + // 1. 保存藏品信息(先检查是否重复) + const res = await fetch('/api/collections', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, + body: JSON.stringify(formData) + }) + if (!res.ok) { + const data = await res.json() + throw new Error(data.error?.message || data.detail || '保存失败') + } + const result = await res.json() + let collectionId = result.f99_90_id || result.id + + // 检查是否有错误(重复编号等) + if (result.error) { + throw new Error(result.error.message || '保存失败') + } + + // 检查是否有重复警告 + if (result.warning && result.warning.code === 'DUPLICATE_SERIAL') { + const { warning } = result + const confirmed = window.confirm( + `⚠️ 发现重复冠字号!\n\n` + + `冠字号:${warning.existing_collection.prefix_serial}\n` + + `已存在于:${warning.existing_collection.name} (编号:${warning.existing_collection.code})\n\n` + + `是否继续保存?` + ) + + if (!confirmed) { + setSaving(false) + return + } + + // 用户确认继续,再次调用 API(添加 force=true 参数) + const forceRes = await fetch('/api/collections?force=true', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, + body: JSON.stringify(formData) + }) + + if (!forceRes.ok) { + const forceData = await forceRes.json() + throw new Error(forceData.error?.message || '保存失败') + } + + const forceResult = await forceRes.json() + collectionId = forceResult.f99_90_id || forceResult.id + console.log('藏品保存成功(确认重复),ID:', collectionId) + } else if (collectionId) { + console.log('藏品保存成功,ID:', collectionId) + } else { + throw new Error('保存失败:未返回藏品 ID') + } + + // 上传图片(无论是否重复都执行) + let totalUploadCount = 0 + + // 2. 处理识别的图片(如果有临时图片,直接认领;否则上传) + if (uploadImages.length > 0 && collectionId) { + console.log('处理图片,数量:', uploadImages.length) + + for (const img of uploadImages) { + // 检查是否有临时图片(OCR识别后保存的) + if (img.temp_image && img.temp_image.id) { + // 认领临时图片 + try { + const claimRes = await fetch(`/api/ocr/claim-temp-image?temp_id=${img.temp_image.id}&collection_id=${collectionId}`, { + method: 'POST', + headers: { 'Authorization': 'Bearer ' + token } + }) + if (claimRes.ok) { + totalUploadCount++ + console.log('✅ 临时图片认领成功') + } else { + console.error('临时图片认领失败:', await claimRes.text()) + } + } catch (claimErr) { + console.error('临时图片认领异常:', claimErr) + } + } else { + // 普通上传 + const imgFormData = new FormData() + imgFormData.append('file', img.file) + try { + const uploadRes = await fetch(`/api/collections/upload-image?collection_id=${collectionId}`, { + method: 'POST', + headers: { 'Authorization': 'Bearer ' + token }, + body: imgFormData + }) + if (uploadRes.ok) { + totalUploadCount++ + console.log(`图片上传成功`) + } else { + console.error('图片上传失败:', await uploadRes.text()) + } + } catch (uploadErr) { + console.error('图片上传异常:', uploadErr) + } + } + } + + console.log(`✅ 共处理 ${totalUploadCount} 张图片`) + } + + alert('保存成功!' + (totalUploadCount > 0 ? `已上传${totalUploadCount}张图片` : '')) + window.location.hash = '#/list' + window.refreshList?.() + window.refreshHome?.() + } catch (e) { + console.error('保存失败:', e) + alert('保存失败:' + e.message) + } + finally { setSaving(false) } + } + + return ( +
+ {/* 顶部标签切换 */} +
+
+ + + +
+
+ + {error && ( +
⚠️ {error}
+ )} + + {/* AI 识别模式 */} + {activeTab === 'ai' && ( +
+
+ + {imagePreview ? ( +
+ 已选择图片 +
+ + +
+
+ ) : ( +
+
{ fileInputRef.current.setAttribute('capture', 'environment'); fileInputRef.current.click(); }} + style={{ padding: '24px', background: 'rgba(59, 130, 246, 0.1)', border: '2px dashed rgba(59, 130, 246, 0.5)', borderRadius: '12px', cursor: 'pointer', marginBottom: '16px', textAlign: 'center' }}> +
📷
+
拍照识别
+
使用相机拍照并识别
+
+
{ fileInputRef.current.removeAttribute('capture'); fileInputRef.current.click(); }} + style={{ padding: '24px', background: 'rgba(34, 197, 94, 0.1)', border: '2px dashed rgba(34, 197, 94, 0.5)', borderRadius: '12px', cursor: 'pointer', textAlign: 'center' }}> +
🖼️
+
从相册选择
+
从相册选择已有图片
+
+
+ )} +
+
+
💡 识别说明
+
    +
  • 支持拍照或从相册选择图片
  • +
  • 自动识别名称、版别、冠字序号等字段
  • +
  • 识别结果可手动修改完善
  • +
  • 建议拍摄清晰、光线充足的正面照片
  • +
+
+
+ )} + + {/* 手工录入模式 - 完整表单 */} + {activeTab === 'manual' && ( +
+ {/* 图片上传区域 */} +
+
+
藏品图片 ({uploadImages.length}/1)
+
+ + + {uploadImages.length > 0 ? ( +
+ {uploadImages.map((img, index) => ( +
+ {img.name} +
{img.name}
+ +
{index + 1}/{uploadImages.length}
+
+ ))} + {uploadImages.length < 1 && ( +
imageFileInputRef.current?.click()} style={{ + aspectRatio: '1.5', + background: 'rgba(255,255,255,0.05)', + border: '2px dashed rgba(255,255,255,0.3)', + borderRadius: '12px', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + cursor: 'pointer', + color: '#94a3b8', + fontSize: '13px' + }}> +
📷
+
添加图片
+
最多可上传 1 张
+
+ )} +
+ ) : ( +
imageFileInputRef.current?.click()} style={{ + aspectRatio: '1.5', + background: 'rgba(255,255,255,0.05)', + border: '2px dashed #fbbf24', + borderRadius: '12px', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + cursor: 'pointer', + color: '#fbbf24', + fontSize: '13px' + }}> +
📷
+
点击上传图片
+
最多可上传 1 张
+
+ )} +
+ + {/* 基本信息 */} +
+
基本信息
+
+ + + + + + + + + +
+
+ + {/* 评级信息 */} +
+
评级信息
+
+
+ handleChange('isGraded', e.target.checked)} + style={{ width: '18px', height: '18px', cursor: 'pointer', accentColor: '#22c55e' }} /> + +
+
+ handleChange('threeStar', e.target.checked)} + style={{ width: '18px', height: '18px', cursor: 'pointer', accentColor: '#22c55e' }} /> + +
+
+
+ + +
+
+ + {/* 特殊信息 */} +
+
特殊信息
+
+ + + + + + + +
+
+ + {/* 价格信息 */} +
+
价格信息
+
+ + + + + + +
+
+ + {/* 备注 */} +
+
备注
+