# 第一周开发指南(Day 1-7) > **目标:** 搭建完整的开发环境,实现第一个功能(用户认证) > **时间:** 7天 > **状态:** 🚀 准备就绪! --- ## ✅ 已完成准备工作 - [x] Docker Desktop 安装完毕 - [x] DeepSeek API Key 已申请 - [x] Qwen API Key 已申请 --- ## 📅 本周计划 | 天数 | 任务 | 预计时间 | |------|------|---------| | Day 1 | 验证环境 + 创建项目结构 | 2小时 | | Day 2 | 启动基础服务(Docker) | 1小时 | | Day 3 | 搭建后端框架 | 3小时 | | Day 4 | 搭建前端框架 | 3小时 | | Day 5 | 实现用户认证(后端) | 4小时 | | Day 6 | 实现登录界面(前端) | 4小时 | | Day 7 | 测试联调 | 2小时 | --- ## 🎯 Day 1: 验证环境 + 创建项目结构 ### 步骤1:验证 Docker 安装 打开终端(Windows用PowerShell或CMD,macOS用Terminal),执行: ```bash # 检查 Docker 版本 docker --version # 应输出类似:Docker version 24.0.x # 检查 Docker Compose 版本 docker-compose --version # 应输出类似:Docker Compose version v2.x.x # 检查 Docker 是否运行 docker ps # 应输出表头(即使没有容器运行) ``` **如果遇到错误:** - Windows: 确保 Docker Desktop 已启动(系统托盘有Docker图标) - macOS: 确保 Docker Desktop 已启动 --- ### 步骤2:创建项目目录结构 ```bash # 选择一个工作目录(比如 D:\Projects 或 ~/Projects) cd D:\Projects # Windows # 或 cd ~/Projects # macOS/Linux # 创建项目根目录 mkdir ai-clinical-research cd ai-clinical-research # 创建子目录 mkdir backend frontend config docs # 验证目录结构 tree -L 1 # 或 Windows: dir ``` **预期结构:** ``` ai-clinical-research/ ├── backend/ # 后端代码 ├── frontend/ # 前端代码 ├── config/ # 配置文件 └── docs/ # 文档 ``` --- ### 步骤3:创建 docker-compose.yml 在项目根目录创建 `docker-compose.yml`: ```yaml version: '3.8' services: # PostgreSQL 数据库 postgres: image: postgres:15-alpine container_name: acr-postgres environment: POSTGRES_DB: ai_clinical_research POSTGRES_USER: dev_user POSTGRES_PASSWORD: dev_pass_2024 ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U dev_user -d ai_clinical_research"] interval: 10s timeout: 5s retries: 5 # Redis 缓存 redis: image: redis:7-alpine container_name: acr-redis ports: - "6379:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 5 # Dify Sandbox(沙箱环境,Dify依赖) dify-sandbox: image: langgenius/dify-sandbox:latest container_name: acr-dify-sandbox restart: unless-stopped # Dify API dify-api: image: langgenius/dify-api:latest container_name: acr-dify-api environment: # 数据库配置 DB_USERNAME: dify DB_PASSWORD: dify_pass_2024 DB_HOST: dify-postgres DB_PORT: 5432 DB_DATABASE: dify # Redis配置 REDIS_HOST: dify-redis REDIS_PORT: 6379 REDIS_DB: 0 # 应用配置 MODE: api SECRET_KEY: sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U CONSOLE_WEB_URL: http://localhost CONSOLE_API_URL: http://localhost:5001 SERVICE_API_URL: http://localhost:5001 APP_WEB_URL: http://localhost # 文件存储(本地) STORAGE_TYPE: local STORAGE_LOCAL_PATH: /app/storage # Vector Store(向量数据库) VECTOR_STORE: qdrant QDRANT_URL: http://dify-qdrant:6333 QDRANT_API_KEY: dify-qdrant-key # Celery(异步任务) CELERY_BROKER_URL: redis://dify-redis:6379/1 # 模型配置(可选,可在Web界面配置) # OPENAI_API_KEY: your-key-here ports: - "5001:5001" volumes: - dify_app_storage:/app/storage depends_on: - dify-postgres - dify-redis - dify-qdrant - dify-sandbox restart: unless-stopped # Dify Worker(后台任务处理) dify-worker: image: langgenius/dify-api:latest container_name: acr-dify-worker environment: MODE: worker DB_USERNAME: dify DB_PASSWORD: dify_pass_2024 DB_HOST: dify-postgres DB_PORT: 5432 DB_DATABASE: dify REDIS_HOST: dify-redis REDIS_PORT: 6379 REDIS_DB: 0 CELERY_BROKER_URL: redis://dify-redis:6379/1 SECRET_KEY: sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U STORAGE_TYPE: local STORAGE_LOCAL_PATH: /app/storage VECTOR_STORE: qdrant QDRANT_URL: http://dify-qdrant:6333 QDRANT_API_KEY: dify-qdrant-key volumes: - dify_app_storage:/app/storage depends_on: - dify-postgres - dify-redis - dify-qdrant restart: unless-stopped # Dify PostgreSQL dify-postgres: image: postgres:15-alpine container_name: acr-dify-postgres environment: POSTGRES_DB: dify POSTGRES_USER: dify POSTGRES_PASSWORD: dify_pass_2024 PGDATA: /var/lib/postgresql/data/pgdata volumes: - dify_postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U dify -d dify"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # Dify Redis dify-redis: image: redis:7-alpine container_name: acr-dify-redis volumes: - dify_redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 5 restart: unless-stopped # Qdrant 向量数据库 dify-qdrant: image: qdrant/qdrant:latest container_name: acr-dify-qdrant environment: QDRANT__SERVICE__API_KEY: dify-qdrant-key ports: - "6333:6333" volumes: - dify_qdrant_data:/qdrant/storage restart: unless-stopped # Dify Web界面 dify-web: image: langgenius/dify-web:latest container_name: acr-dify-web environment: CONSOLE_API_URL: http://localhost:5001 APP_API_URL: http://localhost:5001 ports: - "3000:3000" depends_on: - dify-api restart: unless-stopped volumes: postgres_data: redis_data: dify_postgres_data: dify_redis_data: dify_qdrant_data: dify_app_storage: networks: default: name: acr-network ``` **保存文件:** `ai-clinical-research/docker-compose.yml` --- ### 步骤4:创建 .gitignore 在项目根目录创建 `.gitignore`: ```gitignore # Node modules node_modules/ */node_modules/ # Environment variables .env .env.local .env.*.local *.env # IDE .vscode/ .idea/ *.swp *.swo *~ # OS .DS_Store Thumbs.db # Build outputs dist/ build/ *.log # Database *.sqlite *.db # API Keys(重要!) **/config/api-keys.json backend/config/api-keys.json ``` --- ### 步骤5:创建 README.md 在项目根目录创建 `README.md`: ```markdown # AI科研助手 ## 快速启动 ### 启动所有服务 \`\`\`bash docker-compose up -d \`\`\` ### 查看服务状态 \`\`\`bash docker-compose ps \`\`\` ### 查看日志 \`\`\`bash docker-compose logs -f \`\`\` ### 停止所有服务 \`\`\`bash docker-compose down \`\`\` ## 访问地址 - 前端开发服务器: http://localhost:5173 - 后端API: http://localhost:3001 - Dify Web管理界面: http://localhost:3000 - Dify API: http://localhost:5001 - PostgreSQL: localhost:5432 - Redis: localhost:6379 ## 开发文档 详见 `docs/` 目录 ``` --- **✅ Day 1 完成检查清单:** - [ ] Docker 命令验证通过 - [ ] 项目目录创建完成 - [ ] docker-compose.yml 创建完成 - [ ] .gitignore 创建完成 - [ ] README.md 创建完成 --- ## 🎯 Day 2: 启动基础服务 ### 步骤1:启动 Docker 服务 ```bash # 确保在项目根目录 cd ai-clinical-research # 启动所有服务(首次启动会下载镜像,需要5-10分钟) docker-compose up -d # 查看启动日志 docker-compose logs -f # 等待所有服务启动完成(约2-3分钟) # 看到类似信息表示成功: # acr-dify-api | INFO: Application startup complete. # acr-dify-web | ready - started server on 0.0.0.0:3000 ``` **注意:** 首次启动会下载Docker镜像(约2GB),请耐心等待。 --- ### 步骤2:验证服务状态 ```bash # 查看所有容器状态 docker-compose ps # 应该看到所有服务都是 "Up" 状态 # NAME STATUS # acr-postgres Up (healthy) # acr-redis Up (healthy) # acr-dify-postgres Up (healthy) # acr-dify-redis Up (healthy) # acr-dify-qdrant Up # acr-dify-api Up # acr-dify-worker Up # acr-dify-web Up ``` --- ### 步骤3:访问 Dify Web 界面 1. 打开浏览器访问:http://localhost:3000 2. 首次访问会要求创建管理员账号 3. 填写信息: - 邮箱:admin@example.com - 密码:Admin123!(自己设置一个) - 确认密码:Admin123! 4. 点击"创建账号" **成功标志:** 进入Dify管理后台 --- ### 步骤4:获取 Dify API Key 1. 在Dify管理后台,点击左侧 "设置" → "API密钥" 2. 点击 "创建密钥" 3. 复制生成的API Key(类似:`app-xxx...`) 4. 保存到安全的地方(后面会用到) --- ### 步骤5:测试数据库连接 ```bash # 测试 PostgreSQL(业务数据库) docker exec -it acr-postgres psql -U dev_user -d ai_clinical_research -c "SELECT version();" # 应输出 PostgreSQL 版本信息 # 测试 Redis docker exec -it acr-redis redis-cli ping # 应输出: PONG # 测试 Dify API curl http://localhost:5001/health # 应输出: {"status":"ok"} ``` --- **✅ Day 2 完成检查清单:** - [ ] 所有Docker容器启动成功 - [ ] Dify Web界面可访问 - [ ] Dify管理员账号创建完成 - [ ] Dify API Key获取完成 - [ ] 数据库连接测试通过 --- ## 🎯 Day 3: 搭建后端框架 ### 步骤1:初始化后端项目 ```bash # 进入后端目录 cd backend # 初始化 Node.js 项目 npm init -y # 安装依赖 npm install fastify@4.26.0 \ @fastify/cors@9.0.0 \ @fastify/jwt@7.2.0 \ @prisma/client@5.10.0 \ bcryptjs@2.4.3 \ dotenv@16.4.0 \ ioredis@5.3.0 \ axios@1.6.0 # 安装开发依赖 npm install -D \ prisma@5.10.0 \ typescript@5.3.0 \ @types/node@20.11.0 \ @types/bcryptjs@2.4.6 \ tsx@4.7.0 \ nodemon@3.0.0 ``` --- ### 步骤2:配置 TypeScript 创建 `backend/tsconfig.json`: ```json { "compilerOptions": { "target": "ES2022", "module": "commonjs", "lib": ["ES2022"], "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "moduleResolution": "node" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } ``` --- ### 步骤3:配置环境变量 创建 `backend/.env`: ```bash # 数据库配置 DATABASE_URL="postgresql://dev_user:dev_pass_2024@localhost:5432/ai_clinical_research" # Redis配置 REDIS_URL="redis://localhost:6379" # JWT配置 JWT_SECRET="your-super-secret-jwt-key-change-this-in-production-2024" JWT_EXPIRES_IN="7d" # LLM API Keys DEEPSEEK_API_KEY="你的DeepSeek API Key" DASHSCOPE_API_KEY="你的Qwen API Key" # Dify配置 DIFY_API_URL="http://localhost:5001" DIFY_API_KEY="你在Day2获取的Dify API Key" # 应用配置 NODE_ENV="development" PORT=3001 ``` **注意:** 把"你的XXX API Key"替换成你实际申请的Key --- ### 步骤4:初始化 Prisma ```bash # 初始化 Prisma npx prisma init # 这会创建 prisma/schema.prisma 文件 ``` 编辑 `backend/prisma/schema.prisma`: ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // 用户表 model User { id String @id @default(uuid()) email String @unique password String name String? role String @default("user") // user, admin status String @default("active") // active, inactive createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // 关联 projects Project[] knowledgeBases KnowledgeBase[] @@map("users") } // 项目/课题表 model Project { id String @id @default(uuid()) userId String name String description String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // 关联 user User @relation(fields: [userId], references: [id], onDelete: Cascade) conversations Conversation[] @@map("projects") } // 对话表 model Conversation { id String @id @default(uuid()) projectId String? userId String agentId String title String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // 关联 project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade) messages Message[] @@map("conversations") } // 消息表 model Message { id String @id @default(uuid()) conversationId String role String // user, assistant content String @db.Text createdAt DateTime @default(now()) // 关联 conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade) @@map("messages") } // 知识库表 model KnowledgeBase { id String @id @default(uuid()) userId String name String description String? difyDatasetId String // Dify中的知识库ID fileCount Int @default(0) totalSizeBytes BigInt @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // 关联 user User @relation(fields: [userId], references: [id], onDelete: Cascade) documents Document[] @@map("knowledge_bases") } // 文档表 model Document { id String @id @default(uuid()) kbId String userId String filename String fileType String fileSizeBytes BigInt fileUrl String difyDocumentId String status String @default("uploading") // uploading, processing, completed, failed progress Int @default(0) errorMessage String? segmentsCount Int? tokensCount Int? uploadedAt DateTime @default(now()) processedAt DateTime? // 关联 knowledgeBase KnowledgeBase @relation(fields: [kbId], references: [id], onDelete: Cascade) @@map("documents") } ``` --- ### 步骤5:创建数据库表 ```bash # 生成 Prisma Client npx prisma generate # 创建数据库迁移 npx prisma migrate dev --name init # 看到类似输出表示成功: # ✔ Generated Prisma Client # ✔ Your database is now in sync with your schema. ``` --- ### 步骤6:创建基础目录结构 ```bash # 在 backend 目录下创建 mkdir -p src/routes src/services src/config src/utils src/types ``` --- ### 步骤7:创建服务器入口文件 创建 `backend/src/server.ts`: ```typescript import Fastify from 'fastify'; import cors from '@fastify/cors'; import dotenv from 'dotenv'; // 加载环境变量 dotenv.config(); const server = Fastify({ logger: true }); // 注册CORS server.register(cors, { origin: true // 开发环境允许所有来源 }); // 健康检查端点 server.get('/health', async (request, reply) => { return { status: 'ok', timestamp: new Date().toISOString() }; }); // 测试端点 server.get('/api/test', async (request, reply) => { return { message: 'AI科研助手后端服务运行正常!', env: process.env.NODE_ENV, timestamp: new Date().toISOString() }; }); // 启动服务器 const start = async () => { try { const port = parseInt(process.env.PORT || '3001'); await server.listen({ port, host: '0.0.0.0' }); console.log(`🚀 服务器启动成功!`); console.log(`📝 API地址: http://localhost:${port}`); console.log(`🏥 健康检查: http://localhost:${port}/health`); } catch (err) { server.log.error(err); process.exit(1); } }; start(); ``` --- ### 步骤8:配置 package.json scripts 编辑 `backend/package.json`,添加 scripts: ```json { "scripts": { "dev": "tsx watch src/server.ts", "build": "tsc", "start": "node dist/server.js", "prisma:generate": "prisma generate", "prisma:migrate": "prisma migrate dev", "prisma:studio": "prisma studio" } } ``` --- ### 步骤9:启动后端服务 ```bash # 启动开发服务器 npm run dev # 看到类似输出表示成功: # 🚀 服务器启动成功! # 📝 API地址: http://localhost:3001 # 🏥 健康检查: http://localhost:3001/health ``` --- ### 步骤10:测试后端API 打开新的终端窗口: ```bash # 测试健康检查 curl http://localhost:3001/health # 测试API curl http://localhost:3001/api/test ``` --- **✅ Day 3 完成检查清单:** - [ ] 后端项目初始化完成 - [ ] 依赖安装完成 - [ ] TypeScript配置完成 - [ ] 环境变量配置完成 - [ ] Prisma数据库模型创建完成 - [ ] 数据库迁移成功 - [ ] 后端服务启动成功 - [ ] API测试通过 --- ## 🎯 Day 4-7: 继续开发... (后续天数的详细步骤将在您完成Day 1-3后提供) --- ## 📊 当前进度 ``` ✅ 环境准备: 100% ⏳ Day 1: 待开始 ⏳ Day 2: 待开始 ⏳ Day 3: 待开始 ``` --- ## 🆘 常见问题 ### Q1: Docker 容器启动失败 ```bash # 查看日志 docker-compose logs [服务名] # 重启服务 docker-compose restart [服务名] # 完全重置 docker-compose down -v docker-compose up -d ``` ### Q2: 端口被占用 ```bash # Windows 查找占用端口的进程 netstat -ano | findstr :3001 # macOS/Linux lsof -i :3001 # 修改端口(在 .env 中) PORT=3002 ``` ### Q3: npm install 太慢 ```bash # 使用国内镜像 npm config set registry https://registry.npmmirror.com ``` --- ## 🎉 准备开始! **现在就开始 Day 1 吧!** 执行第一个命令: ```bash docker --version ``` 有任何问题随时告诉我!🚀