refactor: 后端分层调整(集成层独立、crud 改名) + 本地启动脚本

- core 拆分: 极光/美团/短信三个外部集成从 core/ 迁出到新建的 integrations/,
  core/ 仅保留 config/security/logging 等基础设施
- crud/ 改名 repositories/; auth.py 中模块别名 crud_user -> user_repo
- 同步更新 app/api/v1/{auth,meituan}.py 的 import 路径
- 新增 run.sh: 本地开发启动脚本(校验 .env、alembic upgrade 建表、uvicorn 监听 0.0.0.0:8770)
- .gitignore 忽略 *.log, 避免 run.sh 运行日志入库

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 11:04:51 +08:00
parent 9cf24ccecd
commit 8303a4fac2
10 changed files with 28 additions and 7 deletions
+3
View File
@@ -34,3 +34,6 @@ secrets/*
.idea/
.vscode/
*.swp
# 运行日志(run.sh 输出, 不入库)
*.log
+6 -6
View File
@@ -15,10 +15,10 @@ import logging
from fastapi import APIRouter, HTTPException, status
from app.api.deps import CurrentUser, DbSession
from app.core.jiguang import JiguangError, mask_phone, verify_and_get_phone
from app.core.security import TokenError, decode_token, issue_token_pair
from app.core.sms import SmsError, send_code, verify_code
from app.crud import user as crud_user
from app.integrations.jiguang import JiguangError, mask_phone, verify_and_get_phone
from app.integrations.sms import SmsError, send_code, verify_code
from app.repositories import user as user_repo
from app.schemas.auth import (
JverifyLoginRequest,
LogoutResponse,
@@ -61,7 +61,7 @@ def jverify_login(req: JverifyLoginRequest, db: DbSession) -> TokenWithUser:
logger.error("[JG] verify+decrypt failed: %s", e, exc_info=True)
raise HTTPException(status_code=502, detail=f"jiguang verify failed: {e}") from e
user = crud_user.upsert_user_for_login(db, phone=phone, register_channel="jverify")
user = user_repo.upsert_user_for_login(db, phone=phone, register_channel="jverify")
if user.status != "active":
raise HTTPException(status_code=403, detail="account disabled")
@@ -88,7 +88,7 @@ def sms_login(req: SmsLoginRequest, db: DbSession) -> TokenWithUser:
if not verify_code(req.phone, req.code):
raise HTTPException(status_code=400, detail="invalid sms code")
user = crud_user.upsert_user_for_login(db, phone=req.phone, register_channel="sms")
user = user_repo.upsert_user_for_login(db, phone=req.phone, register_channel="sms")
if user.status != "active":
raise HTTPException(status_code=403, detail="account disabled")
@@ -106,7 +106,7 @@ def refresh(req: RefreshRequest, db: DbSession) -> TokenPair:
raise HTTPException(status_code=401, detail=str(e)) from e
user_id = int(payload["sub"])
user = crud_user.get_user_by_id(db, user_id)
user = user_repo.get_user_by_id(db, user_id)
if user is None or user.status != "active":
raise HTTPException(status_code=401, detail="user not found or disabled")
+1 -1
View File
@@ -9,7 +9,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
from fastapi import APIRouter, HTTPException
from app.core.meituan import MeituanCpsError, get_referral_link, query_coupon
from app.integrations.meituan import MeituanCpsError, get_referral_link, query_coupon
from app.schemas.meituan import (
CouponCard,
CouponListRequest,
View File
Executable
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# 本地开发启动脚本:监听 0.0.0.0(真机局域网 / adb reverse 都能连),改代码自动重启。
#
# 前置(首次):先激活装好依赖的环境,例如:
# conda activate price && pip install -e .
# 真机联调流程见前台 local.properties 的 debug.api.host。
set -e
cd "$(dirname "$0")"
if [ ! -f .env ]; then
echo "❌ 缺 .env:先 cp .env.example .env 并填值(至少 JWT_SECRET_KEY;测美团再填 MT_CPS_*"
exit 1
fi
mkdir -p data # sqlite 文件所在目录
alembic upgrade head # 确保表已建(幂等,已是最新则 no-op)
exec uvicorn app.main:app --host 0.0.0.0 --port 8770 --reload