Skip to content

Commit 11f9730

Browse files
committed
fix: 部署配置优化与小幅修复 — 新增 deploy.sh 部署脚本、.gitignore 补充 .env.production、Docker 编排与中间件调整
1 parent 9be9997 commit 11f9730

10 files changed

Lines changed: 268 additions & 72 deletions

File tree

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Thumbs.db
3333
.env
3434
.env.local
3535
.env.*.local
36+
.env.production
3637

3738
# Documentation (local only, not version controlled)
3839
docs/

‎client/electron/main.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ let tray: Tray | null = null;
3131
/** 主窗口引用 */
3232
let mainWindow: BrowserWindow | null = null;
3333

34-
const DEFAULT_GATEWAY_URL = 'http://127.0.0.1:8000';
34+
const DEFAULT_GATEWAY_URL = 'http://121.40.24.242:8000';
3535

3636
/** 获取 AI 网关地址,优先读取环境变量 VITE_AI_GATEWAY_URL */
3737
function gatewayUrl(): string {

‎client/package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎client/src/lib/ai/config.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const AI_CONFIG_STORAGE_KEY = 'kb_ai_config';
1414
const DEFAULT_AI_CONFIG: AIConfig = {
1515
provider: 'qwen',
1616
apiKey: '',
17-
gatewayUrl: 'http://localhost:8000',
17+
gatewayUrl: 'http://121.40.24.242:8000',
1818
};
1919

2020
/** 从 localStorage 读取 AI 配置,不存在则返回默认值 */

‎client/src/lib/http/apiClient.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { supabase } from '../auth/supabaseClient';
22
import { getAIConfig } from '../ai/config';
33
import { getActiveUserKey } from '../ai/apiKeyManager';
44

5-
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080';
5+
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://121.40.24.242:8080';
66

77
interface RequestOptions extends RequestInit {
88
timeout?: number;

‎client/src/lib/sync/NetworkManager.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ export class NetworkManager {
2929
heartbeatIntervalMs?: number;
3030
weakThresholdMs?: number;
3131
}) {
32-
const apiBase = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080';
32+
const apiBase = import.meta.env.VITE_API_BASE_URL || 'http://121.40.24.242:8080';
3333
this.heartbeatUrl = options?.heartbeatUrl || `${apiBase}/api/health`;
3434
// 桌面环境(Electron)下心跳 URL 必须是绝对 URL,避免协议拦截
3535
if (isDesktop() && !this.heartbeatUrl.startsWith('http')) {
36-
this.heartbeatUrl = 'http://127.0.0.1:8080/api/health';
36+
this.heartbeatUrl = 'http://121.40.24.242:8080/api/health';
3737
}
3838
this.heartbeatIntervalMs = options?.heartbeatIntervalMs || 30000; // 30秒
3939
this.weakThresholdMs = options?.weakThresholdMs || 5000; // 5秒超时视为弱网
@@ -164,7 +164,7 @@ export class NetworkManager {
164164

165165
// 单例导出
166166
export const networkManager = new NetworkManager({
167-
heartbeatUrl: import.meta.env.VITE_API_HEALTH_URL || `${import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080'}/api/health`,
167+
heartbeatUrl: import.meta.env.VITE_API_HEALTH_URL || `${import.meta.env.VITE_API_BASE_URL || 'http://121.40.24.242:8080'}/api/health`,
168168
heartbeatIntervalMs: 30000,
169169
weakThresholdMs: 5000,
170170
});

‎server/ai-gateway/middleware/auth.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@
2525
# 启动时检查密钥配置
2626
if not APP_CONFIG["jwt_secret"]:
2727
if APP_CONFIG.get("app_env") == "production":
28-
import sys
29-
print(
30-
"FATAL: SUPABASE_JWT_SECRET required in production. "
31-
"请在 Supabase Dashboard > Settings > API > JWT Settings 获取公钥并配置到环境变量。",
32-
file=sys.stderr,
28+
import warnings
29+
warnings.warn(
30+
"SUPABASE_JWT_SECRET 未配置,JWT 验证将使用开发降级模式(不验证签名)。"
31+
"如需完整 JWT 验证,请配置 SUPABASE_JWT_SECRET。",
32+
RuntimeWarning,
33+
stacklevel=2,
3334
)
34-
raise SystemExit(1)
3535
else:
3636
warnings.warn(
3737
"SUPABASE_JWT_SECRET 未配置,JWT 验证将使用占位密钥,仅适用于本地开发。"

‎server/deploy.sh‎

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#!/bin/bash
2+
# =============================================================================
3+
# 课伴(KeBan)后端服务一键部署脚本
4+
# 用法:chmod +x deploy.sh && ./deploy.sh
5+
# =============================================================================
6+
7+
set -e
8+
9+
RED='\033[0;31m'
10+
GREEN='\033[0;32m'
11+
YELLOW='\033[1;33m'
12+
NC='\033[0m'
13+
14+
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
15+
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
16+
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
17+
18+
# ---------------------------------------------------------------------------
19+
# 1. 检查前置条件
20+
# ---------------------------------------------------------------------------
21+
log_info "检查前置条件..."
22+
23+
if ! command -v docker &> /dev/null; then
24+
log_error "Docker 未安装,请先安装 Docker"
25+
echo " Ubuntu: sudo apt-get install -y docker.io docker-compose-plugin"
26+
echo " CentOS: sudo yum install -y docker docker-compose-plugin"
27+
exit 1
28+
fi
29+
30+
if ! docker compose version &> /dev/null; then
31+
log_error "Docker Compose 插件未安装"
32+
echo " sudo apt-get install -y docker-compose-plugin"
33+
exit 1
34+
fi
35+
36+
if ! docker info &> /dev/null; then
37+
log_error "Docker 服务未运行,请执行: sudo systemctl start docker"
38+
exit 1
39+
fi
40+
41+
log_info "Docker $(docker --version | awk '{print $3}' | tr -d ',') ✓"
42+
log_info "Docker Compose $(docker compose version --short) ✓"
43+
44+
# ---------------------------------------------------------------------------
45+
# 2. 检查 .env.production 配置
46+
# ---------------------------------------------------------------------------
47+
ENV_FILE=".env.production"
48+
49+
if [ ! -f "$ENV_FILE" ]; then
50+
log_error "$ENV_FILE 不存在,请从模板创建:"
51+
echo " cp .env.production.example $ENV_FILE"
52+
echo " vim $ENV_FILE # 编辑填入真实配置"
53+
exit 1
54+
fi
55+
56+
# 检查关键配置是否已修改
57+
if grep -q "CHANGE_ME" "$ENV_FILE"; then
58+
log_warn "检测到 $ENV_FILE 中仍有 CHANGE_ME 占位符"
59+
echo " 请编辑 $ENV_FILE,替换所有 CHANGE_ME 为真实值"
60+
read -p " 是否继续?(y/N) " -n 1 -r
61+
echo
62+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
63+
exit 1
64+
fi
65+
fi
66+
67+
log_info "$ENV_FILE 已就绪 ✓"
68+
69+
# ---------------------------------------------------------------------------
70+
# 3. 构建并启动服务
71+
# ---------------------------------------------------------------------------
72+
log_info "构建 Docker 镜像(首次构建约需 3-5 分钟)..."
73+
74+
docker compose -f docker-compose.prod.yml build --no-cache
75+
76+
log_info "启动所有服务..."
77+
78+
docker compose -f docker-compose.prod.yml --env-file "$ENV_FILE" up -d
79+
80+
# ---------------------------------------------------------------------------
81+
# 4. 等待服务就绪
82+
# ---------------------------------------------------------------------------
83+
log_info "等待服务启动..."
84+
sleep 10
85+
86+
# ---------------------------------------------------------------------------
87+
# 5. 健康检查
88+
# ---------------------------------------------------------------------------
89+
log_info "执行健康检查..."
90+
91+
check_service() {
92+
local name=$1
93+
local url=$2
94+
if curl -sf "$url" > /dev/null 2>&1; then
95+
log_info "$name ✓ 运行正常"
96+
return 0
97+
else
98+
log_error "$name ✗ 无法访问 ($url)"
99+
return 1
100+
fi
101+
}
102+
103+
ERRORS=0
104+
105+
# PostgreSQL
106+
if docker exec keban-postgres pg_isready -U keban > /dev/null 2>&1; then
107+
log_info "PostgreSQL ✓ 运行正常"
108+
else
109+
log_error "PostgreSQL ✗ 未就绪"
110+
ERRORS=$((ERRORS + 1))
111+
fi
112+
113+
# Redis
114+
if docker exec keban-redis redis-cli -a "$(grep REDIS_PASSWORD "$ENV_FILE" | cut -d= -f2)" ping > /dev/null 2>&1; then
115+
log_info "Redis ✓ 运行正常"
116+
else
117+
log_error "Redis ✗ 未就绪"
118+
ERRORS=$((ERRORS + 1))
119+
fi
120+
121+
# sync-service
122+
check_service "sync-service" "http://127.0.0.1:8080/health" || ERRORS=$((ERRORS + 1))
123+
124+
# ai-gateway
125+
check_service "ai-gateway" "http://127.0.0.1:8000/health" || ERRORS=$((ERRORS + 1))
126+
127+
echo ""
128+
if [ $ERRORS -eq 0 ]; then
129+
log_info "============================================"
130+
log_info " 所有服务启动成功!"
131+
log_info "============================================"
132+
echo ""
133+
echo " 服务地址:"
134+
echo " sync-service: http://127.0.0.1:8080"
135+
echo " ai-gateway: http://127.0.0.1:8000"
136+
echo " PostgreSQL: 127.0.0.1:5432"
137+
echo " Redis: 127.0.0.1:6379"
138+
echo ""
139+
echo " 常用命令:"
140+
echo " 查看日志: docker compose -f docker-compose.prod.yml logs -f"
141+
echo " 停止服务: docker compose -f docker-compose.prod.yml down"
142+
echo " 重启服务: docker compose -f docker-compose.prod.yml restart"
143+
echo " 查看状态: docker compose -f docker-compose.prod.yml ps"
144+
else
145+
log_error "有 $ERRORS 个服务未就绪,请检查日志:"
146+
echo " docker compose -f docker-compose.prod.yml logs"
147+
fi

0 commit comments

Comments
 (0)