# ✅ 必须修改清单(上线前) ## 🎯 修改目标 解决 5 个架构问题: 1. ✅ CORS 支持 CEP 环境(`Origin: null`) 2. ✅ 生产环境 API 地址配置 3. ✅ 静态文件由 Caddy 处理(性能优化) 4. ✅ Token 通过 Header 传递(已经正确,确认即可) 5. ✅ 使用 Caddy 自动 HTTPS --- ## 📝 需要修改的文件 ### 1. 后端 CORS 配置 ⭐ 重要 **文件**: `Server/app/main.py` **修改前** (第 16-28 行): ```python # CORS configuration origins = [ "http://localhost:5173", # Vite default "http://localhost:3000", "*" # For development convenience ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) ``` **修改后**: ```python # ========== CORS 配置 ========== import os IS_DEV = os.getenv("ENV", "development") == "development" if IS_DEV: # 开发环境:保持宽松 app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) else: # 生产环境:严格配置 allowed_origins = os.getenv("ALLOWED_ORIGINS", "").split(",") app.add_middleware( CORSMiddleware, allow_origins=allowed_origins, allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_headers=["*"], ) # ✅ CEP 环境特殊处理 @app.middleware("http") async def cep_cors_middleware(request: Request, call_next): origin = request.headers.get("origin") # CEP 的 Origin 是 null 或 cep:// if origin in ["null", None] or (origin and origin.startswith("cep://")): response = await call_next(request) response.headers["Access-Control-Allow-Origin"] = "*" response.headers["Access-Control-Allow-Credentials"] = "true" response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS" response.headers["Access-Control-Allow-Headers"] = "*" return response return await call_next(request) ``` **还需要在文件开头添加导入**: ```python from fastapi import FastAPI, Request # ← 添加 Request ``` --- ### 2. 删除 FastAPI 静态文件挂载 ⭐ 重要 **文件**: `Server/app/main.py` **修改前** (第 36-55 行): ```python # Mount archives directory for download app.mount("/download", StaticFiles(directory="archives"), name="download") # Mount Shell directory (登录页面) shell_dir = Path(__file__).parent.parent / "Designer" if shell_dir.exists(): app.mount("/shell", StaticFiles(directory=str(shell_dir), html=True), name="shell") print(f"✓ Shell 已挂载: {shell_dir}") else: print(f"⚠️ Shell 目录不存在: {shell_dir}") print(" 请先运行: cd Designer && npm run build:shell") # Mount DesignerCache directory to serve Core application files designer_cache = Path.home() / "AppData" / "Roaming" / "DesignerCache" if designer_cache.exists(): app.mount("/core", StaticFiles(directory=str(designer_cache), html=True), name="core") else: # Create directory if it doesn't exist designer_cache.mkdir(parents=True, exist_ok=True) app.mount("/core", StaticFiles(directory=str(designer_cache), html=True), name="core") ``` **修改后**: ```python # ❌ 删除所有静态文件挂载(交给 Caddy 处理) # 生产环境不需要 FastAPI 处理静态文件 # 可以添加健康检查接口 @app.get("/health") def health_check(): return {"status": "healthy", "timestamp": datetime.now().isoformat()} ``` --- ### 3. 后端环境变量配置 **文件**: `Server/.env` **新建或修改**: ```bash # 环境配置 ENV=production # 项目配置 PROJECT_NAME=DesignerCEP API_V1_STR=/api/v1 # 安全配置 SECRET_KEY=your-secret-key-here-change-this-in-production # 数据库配置 DATABASE_URL=mysql://username:password@localhost:3306/designer_cep # CORS 允许的来源(生产环境) ALLOWED_ORIGINS=https://your-domain.com,https://www.your-domain.com # 管理员配置 ADMIN_TOKEN=your-admin-token-here ``` **⚠️ 重要**:将 `your-domain.com` 替换为你的实际域名! --- ### 4. 前端 API 地址配置 **文件**: `Designer/src/config/index.ts` **修改前** (第 14-16 行): ```typescript apiServer: isDev ? 'http://127.0.0.1:8000' : 'http://127.0.0.1:8000', // ❌ 生产环境还是 localhost ``` **修改后**: ```typescript apiServer: isDev ? 'http://127.0.0.1:8000' : 'https://your-domain.com', // ✅ 生产环境用线上地址 ``` **或者使用环境变量** (推荐): **新建文件**: `Designer/.env.production` ```bash VITE_API_SERVER=https://your-domain.com ``` **修改**: `Designer/src/config/index.ts` ```typescript const isDev = import.meta.env.DEV; const PROD_API_SERVER = import.meta.env.VITE_API_SERVER || 'http://127.0.0.1:8000'; export const config = { apiServer: isDev ? 'http://127.0.0.1:8000' : PROD_API_SERVER, // ✅ 从环境变量读取 apiPrefix: '/api/v1', shellLoginUrl: isDev ? 'http://localhost:5173/#/login' : 'https://your-domain.com/shell/#/login', // ✅ 生产环境登录页 get apiBaseUrl() { return `${this.apiServer}${this.apiPrefix}`; }, getDownloadUrl(path: string): string { if (path.startsWith('/')) { return `${this.apiServer}${path}`; } return path; }, getCoreUrl(version: string): string { if (isDev) { return `http://localhost:5173/`; } return `${this.apiServer}/core/${version}/index.html`; // ✅ 线上加载 } }; ``` --- ### 5. 确认 Token 传递方式(已经正确)✅ **文件**: `Designer/src/utils/request.ts` **检查** (第 16-18 行): ```typescript const token = localStorage.getItem('token'); if (token) { config.headers['Authorization'] = `Bearer ${token}`; // ✅ 已经正确 } ``` **这个不需要改,已经是对的!** --- ## 🚀 部署步骤 ### 步骤 1: 修改代码 ```bash # 1. 后端修改 # - Server/app/main.py(CORS + 删除静态挂载) # - Server/.env(环境变量) # 2. 前端修改 # - Designer/.env.production(API 地址) # - Designer/src/config/index.ts(可选) ``` ### 步骤 2: 本地测试 ```bash # 1. 测试后端 cd Server ENV=development python -m uvicorn app.main:app --reload # 访问 http://localhost:8000/health # 2. 测试前端 cd Designer npm run dev # 访问 http://localhost:5173 # 登录测试,检查 Network 标签 ``` ### 步骤 3: 构建生产版本 ```bash cd Designer npm run build # 检查生成的文件 ls -la dist/Shell/ ls -la dist/Designer/ ``` ### 步骤 4: 部署到服务器 ```bash # 方法 A: 自动化部署(推荐) cd AdminTool python auto_deploy_core.py --version 1.0.6 --deploy --update-db # 方法 B: 手动部署 scp -r dist/Shell/* user@server:/var/www/DesignerCEP/Server/static/shell/ scp -r dist/Designer/* user@server:/var/www/DesignerCEP/Server/static/core/1.0.6/ ``` ### 步骤 5: 配置 Caddy 参考 `Caddy部署指南.md` 的完整配置。 **关键配置**: ```caddy your-domain.com { # API → FastAPI handle /api/* { reverse_proxy localhost:8000 } # Shell 静态文件 handle /shell/* { root * /var/www/DesignerCEP/Server/static/shell file_server } # Core 静态文件 handle /core/* { root * /var/www/DesignerCEP/Server/static/core file_server } # 下载文件 handle /downloads/* { root * /var/www/DesignerCEP/Server/static/downloads file_server } } ``` ### 步骤 6: 启动服务 ```bash # 1. 启动 FastAPI sudo systemctl restart designer-cep # 2. 启动 Caddy sudo systemctl restart caddy # 3. 检查状态 sudo systemctl status designer-cep sudo systemctl status caddy ``` ### 步骤 7: 测试上线 ```bash # 1. 测试 API curl https://your-domain.com/api/v1/health # 2. 测试 CEP CORS curl -X OPTIONS https://your-domain.com/api/v1/client/login \ -H "Origin: null" \ -H "Access-Control-Request-Method: POST" \ -v # 3. 浏览器测试 # 打开 https://your-domain.com/shell/ # 登录并检查功能 ``` --- ## 📊 修改影响评估 | 修改项 | 风险 | 是否必须 | 回滚难度 | |--------|------|---------|---------| | CORS CEP 支持 | ⭐ 低 | 是 | 容易 | | 删除静态挂载 | ⭐⭐ 中 | 是 | 中等 | | 环境变量配置 | ⭐ 低 | 是 | 容易 | | 前端 API 地址 | ⭐⭐ 中 | 是 | 容易 | | Token 方式确认 | ⭐ 无 | 否(已正确) | - | --- ## 🔍 常见问题 ### Q: 改完后本地开发会受影响吗? **A**: 不会!代码中有环境判断: - 开发环境(`ENV=development`):保持原样,CORS 宽松 - 生产环境(`ENV=production`):严格 CORS + CEP 支持 ### Q: 如果改错了怎么办? **A**: 1. Git 回滚:`git checkout Server/app/main.py` 2. 或保留 FastAPI 静态挂载(性能差一点,但能用) 3. 环境变量改回 `ENV=development` ### Q: 必须用 Caddy 吗? **A**: 不必须,但强烈推荐: - ✅ Caddy:配置简单,自动 HTTPS - ⚠️ Nginx:配置复杂,需要手动申请证书 - 二选一即可 --- ## ✅ 完成后检查 - [ ] 本地开发环境测试通过 - [ ] 生产构建无错误 - [ ] API 请求正常(200) - [ ] CORS 无错误 - [ ] CEP 扩展能登录 - [ ] 浏览器能访问 - [ ] Token 在 Header 里 - [ ] 静态文件正常加载 - [ ] HTTPS 证书有效 --- ## 📞 如需帮助 1. 查看日志:`sudo journalctl -u designer-cep -f` 2. 查看 Caddy 日志:`sudo journalctl -u caddy -f` 3. 测试 API:`curl -v https://your-domain.com/api/v1/health` --- **总结**:改动不大,主要是添加环境判断和 CEP CORS 支持,风险可控!