chore: initialize tuhui repository

This commit is contained in:
Codex
2026-03-08 19:28:32 +08:00
commit ee10c46aae
189 changed files with 17754 additions and 0 deletions

View File

@@ -0,0 +1 @@
"""核心模块"""

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,51 @@
from pydantic_settings import BaseSettings
from typing import List
class Settings(BaseSettings):
# 项目信息
PROJECT_NAME: str = "爱设计 API"
VERSION: str = "1.0.0"
API_PREFIX: str = "/api"
# 数据库配置
DATABASE_URL: str = "sqlite:///./test.db" # 使用SQLite进行测试
# DATABASE_URL: str = "mysql+pymysql://root:password@localhost:3306/aishej" # MySQL配置
# JWT 配置
SECRET_KEY: str = "your-secret-key-change-this"
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 1440 # 24小时
# 文件配置
UPLOAD_DIR: str = "./uploads"
MAX_FILE_SIZE: int = 52428800 # 50MB
# 水印配置
WATERMARK_TEXT: str = "爱设计 AiSheji.com"
WATERMARK_OPACITY: int = 128
# 缩略图配置
THUMBNAIL_SIZE: int = 400
THUMBNAIL_QUALITY: int = 85
# CORS 配置(生产环境配置为具体域名)
ALLOWED_ORIGINS: List[str] = [
"https://backend.huijie168.uk",
"https://app.huijie168.uk",
"https://run.huijie168.uk",
"https://huijie168.uk",
"https://www.huijie168.uk"
]
# 易收米支付配置
YSM_APPID: str = "YSMcd16b45d"
YSM_APPSECRET: str = "899850e778e8d2b53e4c4a4e88695688"
YSM_NOTIFY_URL: str = "https://backend.huijie168.uk/api/payment/notify" # 支付回调地址
YSM_CALLBACK_URL: str = "https://run.huijie168.uk/payment/success" # 支付成功跳转地址
YSM_NOPAY_URL: str = "https://run.huijie168.uk/payment/cancel" # 未支付跳转地址
class Config:
env_file = ".env"
case_sensitive = True
settings = Settings()

View File

@@ -0,0 +1,26 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from .config import settings
# 创建数据库引擎
engine = create_engine(
settings.DATABASE_URL,
pool_pre_ping=True,
pool_recycle=3600,
echo=True # 开发环境打印 SQL
)
# 创建 Session 工厂
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# 创建基类
Base = declarative_base()
# 依赖注入:获取数据库会话
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

View File

@@ -0,0 +1,54 @@
from datetime import datetime, timedelta
from typing import Optional
from jose import JWTError, jwt
from passlib.context import CryptContext
from .config import settings
import hashlib
# 密码加密上下文 - 禁用bcrypt的wrap bug检测以避免72字节限制错误
pwd_context = CryptContext(
schemes=["bcrypt"],
deprecated="auto",
bcrypt__ident="2b", # 使用2b版本跳过wrap bug检测
)
def _truncate_password(password: str) -> str:
"""
截断密码以适应bcrypt的72字节限制
对于超长密码使用SHA256哈希确保唯一性
"""
password_bytes = password.encode('utf-8')
if len(password_bytes) <= 72:
return password
# 对超长密码进行hash确保唯一性且在72字节以内
return hashlib.sha256(password_bytes).hexdigest()
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""验证密码"""
safe_password = _truncate_password(plain_password)
return pwd_context.verify(safe_password, hashed_password)
def get_password_hash(password: str) -> str:
"""加密密码bcrypt限制最多72字节"""
safe_password = _truncate_password(password)
return pwd_context.hash(safe_password)
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
"""创建 JWT Token"""
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
return encoded_jwt
def decode_access_token(token: str) -> Optional[dict]:
"""解析 JWT Token"""
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
return payload
except JWTError:
return None