File size: 7,684 Bytes
551658a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5c86d0a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from routers import auth, company, categories, products, product_certifications, product_media, product_packaging, membership, operation_log, contact, template, customer_relationship, member_level, r2_config, media, statistics
from database import engine, Base, get_db
from sqlalchemy.orm import Session
import json
import os
from pathlib import Path
from dotenv import load_dotenv
from datetime import datetime, timedelta

# 导入中间件
from middleware.trace import TraceMiddleware

# 导入日志模块
from utils.logger import logger

# 加载 .env 文件
load_dotenv()

# 导入模板配置
from config.templates import DEFAULT_TEMPLATES
# 导入会员等级配置
from config.member_levels import DEFAULT_MEMBER_LEVELS
# 导入默认公司和用户配置
from config.default_companies import DEFAULT_COMPANIES, DEFAULT_USERS

# 导入所有模型,确保它们被注册到Base
from models.user import User
from models.company import Company
from models.category import Category
from models.product import Product
from models.membership import Membership
from models.operation_log import OperationLog
from models.contact import Contact
from models.template import Template
from models.customer_relationship import CustomerRelationship
from models.member_level import MemberLevel
from models.company_r2_config import CompanyR2Config
from models.media import Media, MediaTag, MediaTagMapping, MediaDirectory
from models.site_visit import SiteVisit
from utils.auth import get_password_hash

# 数据库表创建已在database.py中处理

app = FastAPI(
    title="外贸独立站 API",
    description="用于外贸独立站的后端 API",
    version="1.0.0"
)

# 配置 CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 在生产环境中应该设置具体的前端域名
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 添加 TraceMiddleware 中间件
app.add_middleware(TraceMiddleware)

# 挂载静态文件目录(用于访问上传的图片)
BASE_DIR = Path(__file__).parent
IMAGES_DIR = BASE_DIR / "images"
if IMAGES_DIR.exists():
    app.mount("/images", StaticFiles(directory=str(IMAGES_DIR)), name="images")

# 注册路由
# 注意:更具体的路由(如 /{product_number}/media)必须在较不具体的路由(如 /{product_number})之前注册
app.include_router(auth.router, prefix="/api/auth", tags=["认证"])
app.include_router(product_media.router, prefix="/api/products", tags=["产品媒体"])
app.include_router(product_certifications.router, prefix="/api/products", tags=["产品认证"])
app.include_router(product_packaging.router, prefix="/api/products", tags=["产品包装"])
app.include_router(products.router, prefix="/api/products", tags=["产品"])
app.include_router(company.router, prefix="/api/company", tags=["公司信息"])
app.include_router(categories.router, prefix="/api/categories", tags=["类目"])
app.include_router(membership.router, prefix="/api/membership", tags=["会员充值"])
app.include_router(operation_log.router, prefix="/api/operation-logs", tags=["操作日志"])
app.include_router(contact.router, prefix="/api/contact", tags=["联系信息管理"])
app.include_router(template.router, prefix="/api/templates", tags=["模板管理"])
app.include_router(customer_relationship.router, prefix="/api/customer-relationships", tags=["客户关系管理"])
app.include_router(member_level.router, prefix="/api/member-levels", tags=["会员等级管理"])
app.include_router(r2_config.router, prefix="/api/r2-config", tags=["R2 配置管理"])
app.include_router(media.router, prefix="/api/media", tags=["媒体素材管理"])
app.include_router(statistics.router, prefix="/api/statistics", tags=["统计指标"])

# 初始化超级管理员用户和默认类目
@app.on_event("startup")
def startup_event():
    try:
        db = next(get_db())
        # 检查是否已有超级管理员
        superadmin = db.query(User).filter(User.is_superadmin == True).first()
        if not superadmin:
            # 创建超级管理员
            superadmin = User(
                username="admin",
                email="admin@mail.yomaton.com",
                password=get_password_hash("admin00"),
                is_superadmin=True,
                company_code="0000"
            )
            db.add(superadmin)
            db.commit()
            logger.info("超级管理员已创建: username=admin, password=admin00")
        
        
        # 创建默认模板
        for template_data in DEFAULT_TEMPLATES:
            # 转换features和regions列表为JSON字符串
            template_data["features"] = json.dumps(template_data["features"], ensure_ascii=False)
            template_data["regions"] = json.dumps(template_data["regions"], ensure_ascii=False)
            
            existing_template = db.query(Template).filter(Template.key == template_data["key"]).first()
            if not existing_template:
                new_template = Template(**template_data)
                db.add(new_template)
        db.commit()
        logger.info("默认模板已创建")
        
        # 创建默认会员等级
        for level_data in DEFAULT_MEMBER_LEVELS:
            existing_level = db.query(MemberLevel).filter(MemberLevel.level == level_data["level"]).first()
            if not existing_level:
                new_level = MemberLevel(**level_data)
                db.add(new_level)
        db.commit()
        logger.info("默认会员等级已创建")
        
        # 创建默认公司
        for company_data in DEFAULT_COMPANIES:
            existing_company = db.query(Company).filter(Company.company_code == company_data["company_code"]).first()
            if not existing_company:
                new_company = Company(**company_data)
                db.add(new_company)
        db.commit()
        logger.info("默认公司已创建")
        
        # 创建默认用户和会员信息
        for user_data in DEFAULT_USERS:
            existing_user = db.query(User).filter(User.username == user_data["username"]).first()
            if not existing_user:
                user_data_copy = user_data.copy()
                user_data_copy["password"] = get_password_hash(user_data_copy["password"])
                new_user = User(**user_data_copy)
                db.add(new_user)
                db.flush()
                
                # 为用户创建默认会员信息
                existing_membership = db.query(Membership).filter(Membership.company_code == user_data["company_code"]).first()
                if not existing_membership:
                    new_membership = Membership(
                        company_code = user_data["company_code"],
                        level = 0,  # 默认普通会员
                        start_date = datetime.now(),
                        end_date = datetime.now() + timedelta(days=365)
                    )
                    db.add(new_membership)
        db.commit()
        logger.info("默认用户和会员信息已创建")
    except Exception as e:
        logger.error(f"初始化数据时出错: {e}")

@app.get("/")
def read_root():
    logger.info("访问根路径")
    return {"message": "欢迎使用外贸独立站 API"}

@app.get("/health")
def health_check():
    logger.info("健康检查")
    return {"status": "healthy"}

if __name__ == "__main__":
    import uvicorn
    logger.info("启动应用服务器")
    uvicorn.run(app, host="0.0.0.0", port=7860)