# FTB 智能项目管理系统 — 初始化实现计划 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 初始化 monorepo 项目代码结构,包含前后端骨架、数据库 Schema、共享类型包,使项目可以运行并进入功能开发阶段。 **Architecture:** Turborepo monorepo,apps/web (Next.js 14 App Router) + apps/server (NestJS),packages/shared 共享类型。PostgreSQL + Prisma ORM,pnpm workspace 管理依赖。 **Tech Stack:** Next.js 14, Shadcn/ui, Tailwind CSS, Zustand, NestJS, Prisma, PostgreSQL, TypeScript --- ## Task 1: 初始化 Monorepo 根目录 **Files:** - Create: `package.json` - Create: `pnpm-workspace.yaml` - Create: `turbo.json` - Create: `.gitignore` - Create: `.nvmrc` - [ ] **Step 1: 初始化 git 仓库** ```bash git init ``` - [ ] **Step 2: 创建根 package.json** ```json { "name": "ftb-project-management", "private": true, "scripts": { "dev": "turbo dev", "build": "turbo build", "lint": "turbo lint", "type-check": "turbo type-check", "test": "turbo test", "db:migrate": "pnpm --filter=server db:migrate", "db:seed": "pnpm --filter=server db:seed", "db:studio": "pnpm --filter=server db:studio" }, "devDependencies": { "turbo": "^2.0.0", "typescript": "^5.5.0" }, "packageManager": "pnpm@9.4.0" } ``` - [ ] **Step 3: 创建 pnpm-workspace.yaml** ```yaml packages: - "apps/*" - "packages/*" ``` - [ ] **Step 4: 创建 turbo.json** ```json { "$schema": "https://turbo.build/schema.json", "tasks": { "dev": { "cache": false, "persistent": true }, "build": { "dependsOn": ["^build"], "outputs": [".next/**", "dist/**"] }, "lint": { "dependsOn": ["^build"] }, "type-check": { "dependsOn": ["^build"] }, "test": { "dependsOn": ["^build"] } } } ``` - [ ] **Step 5: 创建 .gitignore** ``` node_modules/ dist/ .next/ .env .env.local .env.production *.log .turbo/ coverage/ .DS_Store ``` - [ ] **Step 6: 创建 .nvmrc** ``` 20 ``` - [ ] **Step 7: 安装根依赖并验证** ```bash pnpm install ``` - [ ] **Step 8: Commit** ```bash git add package.json pnpm-workspace.yaml turbo.json .gitignore .nvmrc git commit -m "chore: 初始化 monorepo 根目录配置" ``` --- ## Task 2: 初始化 packages/shared 共享类型包 **Files:** - Create: `packages/shared/package.json` - Create: `packages/shared/tsconfig.json` - Create: `packages/shared/src/index.ts` - Create: `packages/shared/src/enums.ts` - Create: `packages/shared/src/types.ts` - [ ] **Step 1: 创建 packages/shared/package.json** ```json { "name": "@ftb/shared", "version": "0.0.1", "private": true, "main": "./src/index.ts", "types": "./src/index.ts", "scripts": { "type-check": "tsc --noEmit", "lint": "eslint src/" }, "devDependencies": { "typescript": "^5.5.0" } } ``` - [ ] **Step 2: 创建 packages/shared/tsconfig.json** ```json { "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "declaration": true, "outDir": "./dist" }, "include": ["src"] } ``` - [ ] **Step 3: 创建 packages/shared/src/enums.ts** ```typescript export enum TaskStatus { TODO = 'todo', IN_PROGRESS = 'in_progress', IN_REVIEW = 'in_review', DONE = 'done', CLOSED = 'closed', } export enum ProjectRole { OWNER = 'owner', ADMIN = 'admin', MEMBER = 'member', VIEWER = 'viewer', } export enum RequirementStatus { DRAFT = 'draft', REVIEWING = 'reviewing', APPROVED = 'approved', REJECTED = 'rejected', DELIVERED = 'delivered', } ``` - [ ] **Step 4: 创建 packages/shared/src/types.ts** ```typescript import { TaskStatus, ProjectRole, RequirementStatus } from './enums'; export interface Product { id: string; name: string; description: string; createdAt: Date; updatedAt: Date; } export interface Project { id: string; productId: string; name: string; description: string; createdAt: Date; updatedAt: Date; } export interface Task { id: string; projectId: string; sprintId: string | null; versionId: string | null; parentId: string | null; title: string; description: string; status: TaskStatus; assigneeId: string | null; creatorId: string; priority: number; startDate: Date | null; dueDate: Date | null; createdAt: Date; updatedAt: Date; } export interface Requirement { id: string; productId: string; title: string; description: string; status: RequirementStatus; priority: number; creatorId: string; createdAt: Date; updatedAt: Date; } export interface Version { id: string; productId: string; name: string; description: string; releaseDate: Date | null; createdAt: Date; updatedAt: Date; } export interface Sprint { id: string; projectId: string; name: string; startDate: Date; endDate: Date; createdAt: Date; updatedAt: Date; } ``` - [ ] **Step 5: 创建 packages/shared/src/index.ts** ```typescript export * from './enums'; export * from './types'; ``` - [ ] **Step 6: Commit** ```bash git add packages/shared/ git commit -m "feat(shared): 初始化共享类型包,定义核心枚举和实体类型" ``` --- ## Task 3: 初始化 NestJS 后端 (apps/server) **Files:** - Create: `apps/server/package.json` - Create: `apps/server/tsconfig.json` - Create: `apps/server/nest-cli.json` - Create: `apps/server/src/main.ts` - Create: `apps/server/src/app.module.ts` - [ ] **Step 1: 创建 apps/server/package.json** ```json { "name": "server", "version": "0.0.1", "private": true, "scripts": { "dev": "nest start --watch", "build": "nest build", "start": "nest start", "start:prod": "node dist/main", "lint": "eslint \"src/**/*.ts\"", "type-check": "tsc --noEmit", "test": "jest", "test:watch": "jest --watch", "db:migrate": "prisma migrate dev", "db:seed": "ts-node prisma/seed.ts", "db:studio": "prisma studio" }, "dependencies": { "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@prisma/client": "^5.15.0", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.0", "@ftb/shared": "workspace:*" }, "devDependencies": { "@nestjs/cli": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.0", "@types/jest": "^29.5.0", "@types/node": "^20.0.0", "jest": "^29.7.0", "prisma": "^5.15.0", "ts-jest": "^29.1.0", "ts-node": "^10.9.0", "typescript": "^5.5.0" } } ``` - [ ] **Step 2: 创建 apps/server/tsconfig.json** ```json { "compilerOptions": { "module": "commonjs", "declaration": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "ES2021", "sourceMap": true, "outDir": "./dist", "baseUrl": "./", "strict": true, "skipLibCheck": true, "paths": { "@/*": ["src/*"] } }, "include": ["src"] } ``` - [ ] **Step 3: 创建 apps/server/nest-cli.json** ```json { "$schema": "https://json.schemastore.org/nest-cli", "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { "deleteOutDir": true } } ``` - [ ] **Step 4: 创建 apps/server/src/app.module.ts** ```typescript import { Module } from '@nestjs/common'; @Module({ imports: [], controllers: [], providers: [], }) export class AppModule {} ``` - [ ] **Step 5: 创建 apps/server/src/main.ts** ```typescript import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.setGlobalPrefix('api/v1'); app.useGlobalPipes(new ValidationPipe({ whitelist: true })); app.enableCors(); await app.listen(3001); } bootstrap(); ``` - [ ] **Step 6: Commit** ```bash git add apps/server/ git commit -m "feat(server): 初始化 NestJS 后端骨架" ``` --- ## Task 4: 配置 Prisma Schema **Files:** - Create: `apps/server/prisma/schema.prisma` - [ ] **Step 1: 创建 Prisma Schema 文件** ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) email String @unique name String avatar String? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") createdTasks Task[] @relation("TaskCreator") assignedTasks Task[] @relation("TaskAssignee") projectMembers ProjectMember[] requirements Requirement[] watchedTasks TaskWatcher[] @@map("users") } model Product { id String @id @default(cuid()) name String description String @default("") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") projects Project[] requirements Requirement[] versions Version[] @@map("products") } model Project { id String @id @default(cuid()) productId String @map("product_id") name String description String @default("") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") product Product @relation(fields: [productId], references: [id]) sprints Sprint[] tasks Task[] members ProjectMember[] @@map("projects") } ``` - [ ] **Step 2: 继续添加剩余模型到 schema.prisma** 在上面的文件末尾追加: ```prisma model Sprint { id String @id @default(cuid()) projectId String @map("project_id") name String startDate DateTime @map("start_date") endDate DateTime @map("end_date") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") project Project @relation(fields: [projectId], references: [id]) tasks Task[] @@map("sprints") } model Version { id String @id @default(cuid()) productId String @map("product_id") name String description String @default("") releaseDate DateTime? @map("release_date") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") product Product @relation(fields: [productId], references: [id]) tasks Task[] @@map("versions") } model Requirement { id String @id @default(cuid()) productId String @map("product_id") title String description String @default("") status String @default("draft") priority Int @default(0) creatorId String @map("creator_id") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") product Product @relation(fields: [productId], references: [id]) creator User @relation(fields: [creatorId], references: [id]) @@map("requirements") } model Task { id String @id @default(cuid()) projectId String @map("project_id") sprintId String? @map("sprint_id") versionId String? @map("version_id") parentId String? @map("parent_id") title String description String @default("") status String @default("todo") priority Int @default(0) assigneeId String? @map("assignee_id") creatorId String @map("creator_id") startDate DateTime? @map("start_date") dueDate DateTime? @map("due_date") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") project Project @relation(fields: [projectId], references: [id]) sprint Sprint? @relation(fields: [sprintId], references: [id]) version Version? @relation(fields: [versionId], references: [id]) parent Task? @relation("TaskChildren", fields: [parentId], references: [id]) children Task[] @relation("TaskChildren") assignee User? @relation("TaskAssignee", fields: [assigneeId], references: [id]) creator User @relation("TaskCreator", fields: [creatorId], references: [id]) watchers TaskWatcher[] comments Comment[] @@map("tasks") } model TaskWatcher { id String @id @default(cuid()) taskId String @map("task_id") userId String @map("user_id") task Task @relation(fields: [taskId], references: [id]) user User @relation(fields: [userId], references: [id]) @@unique([taskId, userId]) @@map("task_watchers") } model Comment { id String @id @default(cuid()) taskId String @map("task_id") authorId String @map("author_id") content String createdAt DateTime @default(now()) @map("created_at") task Task @relation(fields: [taskId], references: [id]) @@map("comments") } model ProjectMember { id String @id @default(cuid()) projectId String @map("project_id") userId String @map("user_id") role String @default("member") project Project @relation(fields: [projectId], references: [id]) user User @relation(fields: [userId], references: [id]) @@unique([projectId, userId]) @@map("project_members") } ``` - [ ] **Step 3: Commit** ```bash git add apps/server/prisma/ git commit -m "feat(server): 添加 Prisma Schema,定义全部核心数据模型" ``` --- ## Task 5: 初始化 Next.js 前端 (apps/web) **Files:** - Create: `apps/web/package.json` - Create: `apps/web/tsconfig.json` - Create: `apps/web/next.config.js` - Create: `apps/web/tailwind.config.ts` - Create: `apps/web/postcss.config.js` - Create: `apps/web/app/layout.tsx` - Create: `apps/web/app/page.tsx` - Create: `apps/web/app/globals.css` - [ ] **Step 1: 创建 apps/web/package.json** ```json { "name": "web", "version": "0.0.1", "private": true, "scripts": { "dev": "next dev --port 3000", "build": "next build", "start": "next start", "lint": "next lint", "type-check": "tsc --noEmit" }, "dependencies": { "next": "^14.2.0", "react": "^18.3.0", "react-dom": "^18.3.0", "zustand": "^4.5.0", "@ftb/shared": "workspace:*" }, "devDependencies": { "@types/node": "^20.0.0", "@types/react": "^18.3.0", "@types/react-dom": "^18.3.0", "autoprefixer": "^10.4.0", "postcss": "^8.4.0", "tailwindcss": "^3.4.0", "typescript": "^5.5.0" } } ``` - [ ] **Step 2: 创建 apps/web/tsconfig.json** ```json { "compilerOptions": { "target": "ES2017", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "plugins": [{ "name": "next" }], "paths": { "@/*": ["./*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] } ``` - [ ] **Step 3: 创建 apps/web/next.config.js** ```javascript /** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ['@ftb/shared'], }; module.exports = nextConfig; ``` - [ ] **Step 4: 创建 apps/web/tailwind.config.ts** ```typescript import type { Config } from 'tailwindcss'; const config: Config = { content: ['./app/**/*.{ts,tsx}', './components/**/*.{ts,tsx}'], theme: { extend: {} }, plugins: [], }; export default config; ``` - [ ] **Step 5: 创建 apps/web/postcss.config.js** ```javascript module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, }; ``` - [ ] **Step 6: 创建 apps/web/app/globals.css** ```css @tailwind base; @tailwind components; @tailwind utilities; ``` - [ ] **Step 7: 创建 apps/web/app/layout.tsx** ```tsx import './globals.css'; import type { Metadata } from 'next'; export const metadata: Metadata = { title: 'FTB 项目管理', description: '智能项目管理系统', }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children} ); } ``` - [ ] **Step 8: 创建 apps/web/app/page.tsx** ```tsx export default function HomePage() { return (

FTB 项目管理系统

); } ``` - [ ] **Step 9: 创建前端页面目录占位** ```bash mkdir -p apps/web/app/workspace mkdir -p apps/web/app/products/[id]/requirements mkdir -p apps/web/app/products/[id]/versions mkdir -p apps/web/app/projects/[id]/board mkdir -p apps/web/app/projects/[id]/gantt mkdir -p apps/web/app/projects/[id]/sprints mkdir -p apps/web/app/projects/[id]/settings mkdir -p apps/web/app/admin/members mkdir -p apps/web/components/ui mkdir -p apps/web/components/board mkdir -p apps/web/components/gantt mkdir -p apps/web/components/shared mkdir -p apps/web/hooks mkdir -p apps/web/stores mkdir -p apps/web/lib ``` - [ ] **Step 10: Commit** ```bash git add apps/web/ git commit -m "feat(web): 初始化 Next.js 前端骨架,配置 Tailwind CSS" ``` --- ## Task 6: Docker + 环境配置 **Files:** - Create: `docker-compose.yml` - Create: `.env.example` - Create: `apps/server/.env.example` - [ ] **Step 1: 创建 docker-compose.yml** ```yaml version: '3.8' services: postgres: image: postgres:16-alpine ports: - '5432:5432' environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: ftb_pm volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine ports: - '6379:6379' volumes: postgres_data: ``` - [ ] **Step 2: 创建 .env.example** ```bash # 数据库 DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm # 认证 NEXTAUTH_SECRET=change-me-to-random-secret NEXTAUTH_URL=http://localhost:3000 # AI ANTHROPIC_API_KEY=sk-ant-xxx # Redis REDIS_URL=redis://localhost:6379 # 邮件通知(可选) SMTP_HOST=smtp.example.com SMTP_PORT=465 SMTP_USER=noreply@example.com SMTP_PASS=your-smtp-password ``` - [ ] **Step 3: 创建 apps/server/.env.example** ```bash DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm ANTHROPIC_API_KEY=sk-ant-xxx REDIS_URL=redis://localhost:6379 ``` - [ ] **Step 4: Commit** ```bash git add docker-compose.yml .env.example apps/server/.env.example git commit -m "chore: 添加 Docker Compose 和环境变量示例配置" ``` --- ## Task 7: 验证整体项目结构 - [ ] **Step 1: 安装全部依赖** ```bash pnpm install ``` - [ ] **Step 2: 启动数据库** ```bash docker-compose up -d ``` - [ ] **Step 3: 运行 Prisma 迁移** ```bash cd apps/server && pnpm db:migrate ``` - [ ] **Step 4: 验证后端启动** ```bash pnpm dev --filter=server ``` 预期:控制台输出 `Nest application successfully started`,监听 3001 端口。 - [ ] **Step 5: 验证前端启动** ```bash pnpm dev --filter=web ``` 预期:控制台输出 `ready started server on 0.0.0.0:3000`,浏览器打开看到 "FTB 项目管理系统"。 - [ ] **Step 6: 类型检查通过** ```bash pnpm type-check ``` 预期:无错误输出。