#!/bin/bash # 项目模板创建脚本 # 用法: ./create-from-template.sh [目标目录] set -e # 遇到错误立即退出 # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 打印带颜色的消息 print_success() { echo -e "${GREEN}✓ $1${NC}" } print_info() { echo -e "${BLUE}ℹ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠ $1${NC}" } print_error() { echo -e "${RED}✗ $1${NC}" } print_header() { echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${BLUE} $1${NC}" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" } # 获取当前模板目录 TEMPLATE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # 欢迎信息 clear print_header "FastAPI + Vue 3 项目模板生成器" echo "" print_info "此脚本将基于当前模板创建一个新项目" echo "" # 获取目标目录 if [ -n "$1" ]; then TARGET_DIR="$1" else read -p "$(echo -e ${BLUE}请输入新项目目录 [默认: ../my-new-project]: ${NC})" TARGET_DIR TARGET_DIR=${TARGET_DIR:-../my-new-project} fi # 转换为绝对路径 TARGET_DIR=$(cd "$(dirname "$TARGET_DIR")" 2>/dev/null && pwd)/$(basename "$TARGET_DIR") || TARGET_DIR="$TARGET_DIR" # 检查目标目录是否已存在 if [ -d "$TARGET_DIR" ]; then print_warning "目录 $TARGET_DIR 已存在" read -p "$(echo -e ${YELLOW}是否覆盖? [y/N]: ${NC})" OVERWRITE if [[ ! $OVERWRITE =~ ^[Yy]$ ]]; then print_info "已取消" exit 0 fi rm -rf "$TARGET_DIR" fi echo "" print_header "项目配置" echo "" # 收集项目信息 read -p "$(echo -e ${BLUE}项目名称 (小写,用连字符) [my-app]: ${NC})" PROJECT_NAME PROJECT_NAME=${PROJECT_NAME:-my-app} read -p "$(echo -e ${BLUE}项目显示名称 [My Application]: ${NC})" PROJECT_DISPLAY_NAME PROJECT_DISPLAY_NAME=${PROJECT_DISPLAY_NAME:-My Application} read -p "$(echo -e ${BLUE}数据库名称 [${PROJECT_NAME//-/_}_db]: ${NC})" DATABASE_NAME DATABASE_NAME=${DATABASE_NAME:-${PROJECT_NAME//-/_}_db} read -p "$(echo -e ${BLUE}后端 API 端口 [8888]: ${NC})" API_PORT API_PORT=${API_PORT:-8888} read -p "$(echo -e ${BLUE}前端开发端口 [3000]: ${NC})" FRONTEND_PORT FRONTEND_PORT=${FRONTEND_PORT:-3000} read -p "$(echo -e ${BLUE}域名 (可选,按回车跳过): ${NC})" DOMAIN_NAME # 数据库类型 echo "" echo -e "${BLUE}选择数据库类型:${NC}" echo " 1) SQLite (默认,适合开发)" echo " 2) PostgreSQL (推荐生产环境)" read -p "$(echo -e ${BLUE}请选择 [1]: ${NC})" DB_TYPE DB_TYPE=${DB_TYPE:-1} if [ "$DB_TYPE" = "2" ]; then read -p "$(echo -e ${BLUE}PostgreSQL 主机 [localhost]: ${NC})" PG_HOST PG_HOST=${PG_HOST:-localhost} read -p "$(echo -e ${BLUE}PostgreSQL 端口 [5432]: ${NC})" PG_PORT PG_PORT=${PG_PORT:-5432} read -p "$(echo -e ${BLUE}PostgreSQL 用户名 [postgres]: ${NC})" PG_USER PG_USER=${PG_USER:-postgres} read -s -p "$(echo -e ${BLUE}PostgreSQL 密码: ${NC})" PG_PASSWORD echo "" DATABASE_URL="postgresql://${PG_USER}:${PG_PASSWORD}@${PG_HOST}:${PG_PORT}/${DATABASE_NAME}" else DATABASE_URL="sqlite:///./${DATABASE_NAME}.db" fi # 生成随机 SECRET_KEY SECRET_KEY=$(openssl rand -base64 32 2>/dev/null || python3 -c "import secrets; print(secrets.token_urlsafe(32))") # 确认信息 echo "" print_header "配置确认" echo "" echo -e "${BLUE}项目名称:${NC} $PROJECT_NAME" echo -e "${BLUE}显示名称:${NC} $PROJECT_DISPLAY_NAME" echo -e "${BLUE}数据库名称:${NC} $DATABASE_NAME" echo -e "${BLUE}数据库 URL:${NC} $DATABASE_URL" echo -e "${BLUE}API 端口:${NC} $API_PORT" echo -e "${BLUE}前端端口:${NC} $FRONTEND_PORT" echo -e "${BLUE}域名:${NC} ${DOMAIN_NAME:-未设置}" echo -e "${BLUE}目标目录:${NC} $TARGET_DIR" echo "" read -p "$(echo -e ${BLUE}确认创建项目? [Y/n]: ${NC})" CONFIRM if [[ $CONFIRM =~ ^[Nn]$ ]]; then print_info "已取消" exit 0 fi # 开始创建项目 echo "" print_header "创建项目" echo "" # 1. 创建目标目录 print_info "创建目录: $TARGET_DIR" mkdir -p "$TARGET_DIR" # 2. 复制文件 print_info "复制项目文件..." rsync -a --progress "$TEMPLATE_DIR/" "$TARGET_DIR/" \ --exclude='.git' \ --exclude='node_modules' \ --exclude='__pycache__' \ --exclude='*.pyc' \ --exclude='dist' \ --exclude='backend/wordmaster.db' \ --exclude='backend/uploads/*' \ --exclude='frontend/.env.local' \ --exclude='.DS_Store' print_success "文件复制完成" # 3. 替换配置 print_info "更新配置文件..." cd "$TARGET_DIR" # 替换后端配置 if [ -f "backend/main.py" ]; then # macOS 和 Linux 兼容的 sed if [[ "$OSTYPE" == "darwin"* ]]; then sed -i '' "s/wordmaster/$DATABASE_NAME/g" backend/main.py sed -i '' "s/学习助手 Pro/$PROJECT_DISPLAY_NAME/g" backend/main.py else sed -i "s/wordmaster/$DATABASE_NAME/g" backend/main.py sed -i "s/学习助手 Pro/$PROJECT_DISPLAY_NAME/g" backend/main.py fi fi # 创建 .env 文件 cat > backend/.env << EOF # Database Configuration DATABASE_URL=$DATABASE_URL # JWT Configuration SECRET_KEY=$SECRET_KEY ALGORITHM=HS256 ACCESS_TOKEN_EXPIRE_MINUTES=30 # OpenRouter AI Configuration (for Claude Sonnet 4.5 access) # Get your API key from: https://openrouter.ai/keys OPENROUTER_API_KEY=your-openrouter-api-key-here # AI Model Selection # Available models: # - anthropic/claude-sonnet-4.5 (默认,通用能力强) # - google/gemini-3-pro-preview (数学能力强,推荐数学试卷使用) # - openai/gpt-4o # - openai/gpt-4-turbo AI_MODEL=anthropic/claude-sonnet-4.5 # Parser Configuration USE_CLAUDE_PARSER=true EOF print_success "后端配置已更新" # 替换前端配置 if [ -f "frontend/package.json" ]; then if [[ "$OSTYPE" == "darwin"* ]]; then sed -i '' "s/\"name\": \"wordmaster-frontend\"/\"name\": \"$PROJECT_NAME-frontend\"/g" frontend/package.json else sed -i "s/\"name\": \"wordmaster-frontend\"/\"name\": \"$PROJECT_NAME-frontend\"/g" frontend/package.json fi fi if [ -f "frontend/index.html" ]; then if [[ "$OSTYPE" == "darwin"* ]]; then sed -i '' "s/