18 KiB
18 KiB
第一周开发指南(Day 1-7)
目标: 搭建完整的开发环境,实现第一个功能(用户认证)
时间: 7天
状态: 🚀 准备就绪!
✅ 已完成准备工作
- Docker Desktop 安装完毕
- DeepSeek API Key 已申请
- 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),执行:
# 检查 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:创建项目目录结构
# 选择一个工作目录(比如 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:
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:
# 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:
# 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 服务
# 确保在项目根目录
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:验证服务状态
# 查看所有容器状态
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 界面
- 打开浏览器访问:http://localhost:3000
- 首次访问会要求创建管理员账号
- 填写信息:
- 邮箱:admin@example.com
- 密码:Admin123!(自己设置一个)
- 确认密码:Admin123!
- 点击"创建账号"
成功标志: 进入Dify管理后台
步骤4:获取 Dify API Key
- 在Dify管理后台,点击左侧 "设置" → "API密钥"
- 点击 "创建密钥"
- 复制生成的API Key(类似:
app-xxx...) - 保存到安全的地方(后面会用到)
步骤5:测试数据库连接
# 测试 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:初始化后端项目
# 进入后端目录
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:
{
"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:
# 数据库配置
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
# 初始化 Prisma
npx prisma init
# 这会创建 prisma/schema.prisma 文件
编辑 backend/prisma/schema.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:创建数据库表
# 生成 Prisma Client
npx prisma generate
# 创建数据库迁移
npx prisma migrate dev --name init
# 看到类似输出表示成功:
# ✔ Generated Prisma Client
# ✔ Your database is now in sync with your schema.
步骤6:创建基础目录结构
# 在 backend 目录下创建
mkdir -p src/routes src/services src/config src/utils src/types
步骤7:创建服务器入口文件
创建 backend/src/server.ts:
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:
{
"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:启动后端服务
# 启动开发服务器
npm run dev
# 看到类似输出表示成功:
# 🚀 服务器启动成功!
# 📝 API地址: http://localhost:3001
# 🏥 健康检查: http://localhost:3001/health
步骤10:测试后端API
打开新的终端窗口:
# 测试健康检查
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 容器启动失败
# 查看日志
docker-compose logs [服务名]
# 重启服务
docker-compose restart [服务名]
# 完全重置
docker-compose down -v
docker-compose up -d
Q2: 端口被占用
# Windows 查找占用端口的进程
netstat -ano | findstr :3001
# macOS/Linux
lsof -i :3001
# 修改端口(在 .env 中)
PORT=3002
Q3: npm install 太慢
# 使用国内镜像
npm config set registry https://registry.npmmirror.com
🎉 准备开始!
现在就开始 Day 1 吧!
执行第一个命令:
docker --version
有任何问题随时告诉我!🚀