Files
gao 423b9ab55e STDIN
1 fix: 修复Vue模板语法错误和优化项目配置
   2
   3 - 修复MainDashboard.vue中多余的template结束标签导致的Vue编译错误
   4 - 更新项目文档QWEN.md,完善项目说明和部署指南
   5 - 优化create_admin.py脚本,从main.py导入统一配置
   6 - 增强PDF解析器错误处理和兼容性
   7 - 改进登录页面UI设计和用户体验
   8
   9 🤖 Generated with [Claude Code](https://claude.com/claude-code)
  10
  11 Co-Authored-By: Claude <[email protected]>
2025-11-02 22:44:18 +08:00

487 lines
16 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 统一启动脚本 - 一键启动前后端应用(优化版)
# 作者: Qwen Assistant
# 功能: 自动设置环境、启动后端和前端、管理进程、处理依赖和端口冲突
set -e # 遇到错误立即退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 打印带颜色的消息
print_message() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
# 日志记录函数
log_message() {
local level=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "startup.log"
}
# 检查端口是否被占用
check_port() {
local port=$1
if lsof -i :$port > /dev/null 2>&1; then
return 0 # 端口被占用
else
return 1 # 端口未被占用
fi
}
# 生成随机可用端口
get_available_port() {
local start_port=$1
local max_attempts=50
local port=$start_port
local attempts=0
while check_port $port && [ $attempts -lt $max_attempts ]; do
port=$((port + 1))
attempts=$((attempts + 1))
done
if [ $attempts -eq $max_attempts ]; then
print_message $RED "❌ 无法找到可用端口,请手动释放相关端口"
exit 1
fi
echo $port
}
# 检查依赖安装状态
check_dependencies() {
local missing_deps=()
# 检查 Python 依赖
if ! command -v python3 &> /dev/null; then
missing_deps+=("python3")
else
if ! python3 -c "import fastapi, uvicorn, sqlalchemy, pydantic, jwt, bcrypt, pandas, fitz, dotenv" > /dev/null 2>&1; then
missing_deps+=("python_backend_deps")
fi
fi
# 检查 Node.js 依赖
if ! command -v node &> /dev/null; then
missing_deps+=("nodejs")
fi
if ! command -v npm &> /dev/null; then
missing_deps+=("npm")
fi
# 检查前端依赖
if [ -f "frontend/package.json" ] && [ ! -d "frontend/node_modules" ]; then
missing_deps+=("frontend_deps")
fi
if [ ${#missing_deps[@]} -ne 0 ]; then
print_message $YELLOW "⚠️ 检测到以下依赖缺失或未安装:"
for dep in "${missing_deps[@]}"; do
echo " - $dep"
done
return 1
fi
return 0
}
# 检查系统资源
check_system_resources() {
print_message $BLUE "📊 系统资源检查:"
if command -v free &> /dev/null; then
# Linux system
mem_available=$(free -m | awk 'NR==2{printf "%.1f", $7/1024}')
disk_available=$(df . | awk 'NR==2{printf "%d", $4/1024}')
print_message $CYAN " 可用内存: ${mem_available}GB"
print_message $CYAN " 可用磁盘: ${disk_available}MB"
if (( $(echo "$mem_available < 0.5" | bc -l 2>/dev/null || echo "0") )); then
print_message $YELLOW "⚠️ 可用内存较少,可能影响启动性能"
fi
if [ $disk_available -lt 500 ]; then
print_message $YELLOW "⚠️ 可用磁盘空间较少,可能影响应用运行"
fi
else
# macOS system - use vm_stat for memory and df for disk
# Memory check for macOS using vm_stat
page_size=$(vm_stat | grep "page size" | awk '{print $6}' | sed 's/bytes//')
free_pages=$(vm_stat | grep free | awk '{print $3}' | sed 's/\.//')
inactive_pages=$(vm_stat | grep inactive | awk '{print $3}' | sed 's/\.//')
free_memory=$(( (free_pages + inactive_pages) * page_size / 1024 / 1024 / 1024 ))
# Disk space check for macOS
disk_available=$(df . | awk 'NR==2{printf "%d", $4/1024}') # Convert to MB
print_message $CYAN " 可用内存估算: ${free_memory}GB"
print_message $CYAN " 可用磁盘: ${disk_available}MB"
if [ $free_memory -lt 1 ]; then
print_message $YELLOW "⚠️ 可用内存较少,可能影响启动性能"
fi
if [ $disk_available -lt 500 ]; then
print_message $YELLOW "⚠️ 可用磁盘空间较少,可能影响应用运行"
fi
fi
}
print_message $BLUE "🚀 开始启动 WordMaster Pro 系统 (优化版)..."
# 记录启动过程
log_message "INFO" "开始启动 WordMaster Pro 系统"
# 获取脚本目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 检查系统资源
check_system_resources
# 检查必要命令
print_message $BLUE "🔍 检查系统环境..."
if ! command -v python3 &> /dev/null; then
log_message "ERROR" "Python3 未安装,请先安装 Python 3.8+"
print_message $RED "❌ Python3 未安装,请先安装 Python 3.8+"
exit 1
fi
if ! command -v node &> /dev/null; then
log_message "ERROR" "Node.js 未安装,请先安装 Node.js 16+"
print_message $RED "❌ Node.js 未安装,请先安装 Node.js 16+"
exit 1
fi
if ! command -v npm &> /dev/null; then
log_message "ERROR" "npm 未安装,请先安装 Node.js 16+ (包含npm)"
print_message $RED "❌ npm 未安装,请先安装 Node.js 16+ (包含npm)"
exit 1
fi
if ! command -v lsof &> /dev/null; then
log_message "ERROR" "lsof 未安装,无法检查端口占用"
print_message $RED "❌ lsof 未安装,无法检查端口占用"
exit 1
fi
print_message $GREEN "✅ 系统环境检查通过"
# 加载环境变量
ENV_FILE=".env"
if [ -f "$ENV_FILE" ]; then
print_message $BLUE "🔧 加载环境变量配置..."
export $(grep -v '^#' "$ENV_FILE" | xargs)
BACKEND_PORT=${BACKEND_PORT:-8888}
FRONTEND_PORT=${FRONTEND_PORT:-3008}
DATABASE_URL=${DATABASE_URL:-"sqlite:///./wordmaster.db"}
else
print_message $YELLOW "⚠️ 未找到 $ENV_FILE 文件,使用默认配置"
BACKEND_PORT=8888
FRONTEND_PORT=3008
DATABASE_URL="sqlite:///./wordmaster.db"
fi
print_message $BLUE "🔧 使用配置信息:"
print_message $GREEN " 后端端口: $BACKEND_PORT"
print_message $GREEN " 前端端口: $FRONTEND_PORT"
print_message $GREEN " 数据库: $DATABASE_URL"
# 检查并清理之前的进程
print_message $BLUE "🧹 检查并清理之前的进程..."
if [ -f ".backend.pid" ]; then
OLD_BACKEND_PID=$(cat .backend.pid)
if ps -p $OLD_BACKEND_PID > /dev/null 2>&1; then
print_message $YELLOW "⚠️ 发现已存在的后端进程 $OLD_BACKEND_PID,正在停止..."
kill $OLD_BACKEND_PID 2>/dev/null || true
sleep 2
# 等待进程终止
attempts=0
while ps -p $OLD_BACKEND_PID > /dev/null 2>&1 && [ $attempts -lt 10 ]; do
sleep 1
attempts=$((attempts + 1))
done
# 如果仍未终止,强制杀死
if ps -p $OLD_BACKEND_PID > /dev/null 2>&1; then
print_message $YELLOW "⏳ 强制终止后端进程..."
kill -9 $OLD_BACKEND_PID 2>/dev/null || true
fi
fi
rm -f .backend.pid
fi
if [ -f ".frontend.pid" ]; then
OLD_FRONTEND_PID=$(cat .frontend.pid)
if ps -p $OLD_FRONTEND_PID > /dev/null 2>&1; then
print_message $YELLOW "⚠️ 发现已存在的前端进程 $OLD_FRONTEND_PID,正在停止..."
kill $OLD_FRONTEND_PID 2>/dev/null || true
sleep 2
# 等待进程终止
attempts=0
while ps -p $OLD_FRONTEND_PID > /dev/null 2>&1 && [ $attempts -lt 10 ]; do
sleep 1
attempts=$((attempts + 1))
done
# 如果仍未终止,强制杀死
if ps -p $OLD_FRONTEND_PID > /dev/null 2>&1; then
print_message $YELLOW "⏳ 强制终止前端进程..."
kill -9 $OLD_FRONTEND_PID 2>/dev/null || true
fi
fi
rm -f .frontend.pid
fi
# 检查端口占用情况
print_message $BLUE "🔍 检查端口占用情况..."
if check_port $BACKEND_PORT; then
print_message $YELLOW "⚠️ 后端端口 $BACKEND_PORT 被占用,寻找可用端口..."
BACKEND_PORT=$(get_available_port 8888)
print_message $GREEN "ℹ️ 使用后端端口: $BACKEND_PORT"
fi
if check_port $FRONTEND_PORT; then
print_message $YELLOW "⚠️ 前端端口 $FRONTEND_PORT 被占用,寻找可用端口..."
FRONTEND_PORT=$(get_available_port 3008)
print_message $GREEN "ℹ️ 使用前端端口: $FRONTEND_PORT"
fi
# 检查依赖状态
print_message $BLUE "🔍 检查依赖安装状态..."
if ! check_dependencies; then
print_message $YELLOW "⚠️ 检测到依赖缺失,正在尝试自动安装..."
# 检查并创建后端虚拟环境
if [ ! -d "backend/venv" ]; then
print_message $BLUE "🔧 创建后端虚拟环境..."
python3 -m venv backend/venv
print_message $GREEN "✅ 虚拟环境创建成功"
fi
# 激活虚拟环境
source backend/venv/bin/activate
# 检查并安装后端依赖
if ! python -c "import fastapi, uvicorn, sqlalchemy, pydantic, jwt, bcrypt, pandas, fitz, dotenv" > /dev/null 2>&1; then
print_message $BLUE "🔧 安装后端依赖..."
cd backend
if [ ! -f "requirements.txt" ]; then
print_message $RED "❌ requirements.txt 不存在"
exit 1
fi
pip install --upgrade pip
if ! pip install -r requirements.txt; then
print_message $RED "❌ 后端依赖安装失败"
exit 1
fi
cd ..
print_message $GREEN "✅ 后端依赖安装完成"
fi
# 检查并安装前端依赖
if [ -f "frontend/package.json" ] && [ ! -d "frontend/node_modules" ]; then
print_message $BLUE "🔧 安装前端依赖..."
cd frontend
if ! npm install; then
print_message $RED "❌ 前端依赖安装失败"
exit 1
fi
cd ..
print_message $GREEN "✅ 前端依赖安装完成"
fi
else
print_message $GREEN "✅ 依赖检查通过"
fi
# 激活后端虚拟环境
print_message $BLUE "🔧 激活后端虚拟环境..."
source backend/venv/bin/activate
# 启动后端
print_message $BLUE "📡 启动后端服务 (端口: $BACKEND_PORT)..."
cd backend
# 清理旧日志文件(保留最近的)
if [ -f "backend.log" ]; then
mv backend.log backend.log.prev 2>/dev/null || true
fi
# 启动后端服务
nohup uvicorn main:app --host 0.0.0.0 --port $BACKEND_PORT --log-level info > backend.log 2>&1 &
BACKEND_PID=$!
echo $BACKEND_PID > ../.backend.pid
print_message $GREEN "✅ 后端已启动 (PID: $BACKEND_PID, 端口: $BACKEND_PORT)"
log_message "INFO" "后端服务启动成功 (PID: $BACKEND_PID, 端口: $BACKEND_PORT)"
# 等待后端启动并验证
print_message $BLUE "⏳ 验证后端服务启动状态..."
backend_attempts=0
backend_ready=false
while [ $backend_attempts -lt 30 ]; do # 最多等待30秒
if kill -0 $BACKEND_PID 2>/dev/null; then
if curl -s --max-time 5 "http://localhost:$BACKEND_PORT/docs" > /dev/null; then
print_message $GREEN "✅ 后端API服务运行正常"
backend_ready=true
break
else
print_message $CYAN "⏳ 等待后端服务完全启动... ($backend_attempts/30)"
fi
else
print_message $RED "❌ 后端进程已终止"
break
fi
sleep 1
backend_attempts=$((backend_attempts + 1))
done
if [ "$backend_ready" = false ]; then
print_message $RED "❌ 后端服务启动超时或无法访问"
log_message "ERROR" "后端服务启动失败"
# 检查后端日志
if [ -f "backend.log" ]; then
print_message $RED "📋 后端错误日志最后10行:"
tail -10 backend.log
fi
exit 1
fi
# 启动前端
print_message $BLUE "🎨 启动前端服务 (端口: $FRONTEND_PORT)..."
cd ../frontend
# 清理旧日志文件(保留最近的)
if [ -f "frontend.log" ]; then
mv frontend.log frontend.log.prev 2>/dev/null || true
fi
# 确保环境变量文件包含正确的端口
if [ -f ".env.development" ]; then
# 更新 .env.development with the correct backend port
sed -i.bak "s|VITE_BACKEND_PORT=.*|VITE_BACKEND_PORT=$BACKEND_PORT|" .env.development 2>/dev/null || true
sed -i.bak "s|VITE_SERVER_PORT=.*|VITE_SERVER_PORT=$FRONTEND_PORT|" .env.development 2>/dev/null || true
else
# Create .env.development if it doesn't exist
cat > .env.development << EOF
# 开发环境配置
NODE_ENV=development
VITE_MODE=development
# API配置 - 开发环境使用代理
VITE_API_BASE_URL=/api
VITE_FILE_BASE_URL=/api
VITE_WS_BASE_URL=ws://localhost:$BACKEND_PORT/ws
# 后端服务地址 (仅用于代理配置)
VITE_BACKEND_HOST=localhost
VITE_BACKEND_PORT=$BACKEND_PORT
# 调试配置
VITE_DEBUG=true
VITE_LOG_LEVEL=info
VITE_SERVER_PORT=$FRONTEND_PORT
EOF
print_message $GREEN "✅ 创建了前端环境配置文件"
fi
# 启动前端 - 使用指定端口
if command -v timeout >/dev/null 2>&1; then
# timeout 命令可用
timeout 60s npm run dev -- --port $FRONTEND_PORT > ../frontend.log 2>&1 &
else
# timeout 命令不可用,直接启动
npm run dev -- --port $FRONTEND_PORT > ../frontend.log 2>&1 &
fi
FRONTEND_PID=$!
echo $FRONTEND_PID > ../.frontend.pid
print_message $GREEN "✅ 前端已启动 (PID: $FRONTEND_PID, 端口: $FRONTEND_PORT)"
log_message "INFO" "前端服务启动成功 (PID: $FRONTEND_PID, 端口: $FRONTEND_PORT)"
# 等待前端启动并验证
print_message $BLUE "⏳ 验证前端服务启动状态..."
frontend_attempts=0
frontend_ready=false
while [ $frontend_attempts -lt 45 ]; do # 最多等待45秒,因为前端启动通常需要更多时间
if kill -0 $FRONTEND_PID 2>/dev/null; then
# 尝试访问前端服务
if curl -s --max-time 5 "http://localhost:$FRONTEND_PORT" > /dev/null; then
print_message $GREEN "✅ 前端服务运行正常"
frontend_ready=true
break
else
print_message $CYAN "⏳ 等待前端服务完全启动... ($frontend_attempts/45)"
fi
else
print_message $YELLOW "⚠️ 前端进程可能已重启或仍在启动中... ($frontend_attempts/45)"
fi
sleep 1
frontend_attempts=$((frontend_attempts + 1))
done
if [ "$frontend_ready" = false ]; then
print_message $YELLOW "⚠️ 前端服务可能需要更多时间启动(后台继续运行)"
log_message "WARNING" "前端服务启动时间较长"
else
log_message "INFO" "前端服务启动完成"
fi
# 显示启动完成信息
print_message $GREEN ""
print_message $GREEN "🎉 WordMaster Pro 系统启动成功!"
print_message $GREEN ""
echo ""
print_message $BLUE "📝 访问地址:"
print_message $GREEN "📖 前端访问地址: http://localhost:$FRONTEND_PORT"
print_message $GREEN "🔧 后端 API 地址: http://localhost:$BACKEND_PORT"
print_message $GREEN "📚 API 文档: http://localhost:$BACKEND_PORT/docs"
print_message $GREEN "🌐 支持远程访问 (通过服务器IP:端口访问)"
echo ""
print_message $BLUE "📋 进程信息:"
print_message $GREEN "📡 后端进程 PID: $(cat .backend.pid)"
print_message $GREEN "🎨 前端进程 PID: $(cat .frontend.pid)"
echo ""
print_message $BLUE "📁 日志文件:"
print_message $CYAN " 后端日志: $(pwd)/backend/backend.log"
print_message $CYAN " 前端日志: $(pwd)/frontend/frontend.log"
print_message $CYAN " 启动日志: $(pwd)/startup.log"
echo ""
print_message $YELLOW "💡 提示:"
print_message $YELLOW " - 使用 ./stop_app.sh 停止应用程序"
print_message $YELLOW " - 使用 ./status_app.sh 检查应用程序状态"
print_message $YELLOW " - 实时查看后端日志: tail -f backend/backend.log"
print_message $YELLOW " - 实时查看前端日志: tail -f frontend/frontend.log"
print_message $YELLOW " - 如遇问题,请查看日志并重新启动"
echo ""
print_message $GREEN "📋 要实时监控日志,可使用以下命令:"
print_message $CYAN " 后端实时日志: tail -f backend/backend.log"
print_message $CYAN " 前端实时日志: tail -f frontend/frontend.log"
print_message $CYAN " 同时查看: tail -f backend/backend.log frontend/frontend.log"
log_message "INFO" "WordMaster Pro 系统启动完成"
print_message $GREEN "✅ 应用程序已在后台稳定运行!"