chore: project initialization - Day 4 environment setup

This commit is contained in:
AI Clinical Dev Team
2025-10-10 15:14:54 +08:00
commit bdc7de8043
22 changed files with 12276 additions and 0 deletions

900
第一周开发指南.md Normal file
View File

@@ -0,0 +1,900 @@
# 第一周开发指南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或CMDmacOS用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
```
有任何问题随时告诉我!🚀