# Schema隔离架构设计（10个Schema）

> **文档版本：** V1.0  
> **制定日期：** 2025-11-09  
> **实施策略：** 3个详细迁移 + 7个空Schema预留  
> **架构原则：** Just-in-time设计，聚焦当前需求，架构预留扩展

---

## 📋 目录

1. [架构概述](#架构概述)
2. [10个Schema全景](#10个schema全景)
3. [Schema依赖关系](#schema依赖关系)
4. [详细设计：3个迁移Schema](#详细设计3个迁移schema)
5. [预留：7个空Schema](#预留7个空schema)
6. [迁移策略](#迁移策略)
7. [现有表分配方案](#现有表分配方案)
8. [外键和跨Schema引用](#外键和跨schema引用)
9. [Prisma配置策略](#prisma配置策略)

---

## 架构概述

### 设计目标

1. **模块化隔离** - 每个业务模块独立Schema，支持独立部署
2. **数据安全** - Schema级别的权限控制
3. **扩展性强** - 新模块快速接入，只需创建新Schema
4. **渐进式实施** - 优先迁移核心3个Schema，其余按需扩展

### 实施策略：3详细+7空 ⭐

```
Week 1重点：
┌─────────────────────────────────────────────┐
│  3个详细Schema（完整设计+数据迁移）         │
│  ✅ platform_schema  - 1个表（users）       │
│  ✅ aia_schema       - 5个表（对话相关）    │
│  ✅ pkb_schema       - 5个表（知识库相关）  │
├─────────────────────────────────────────────┤
│  7个空Schema（只创建命名空间）             │
│  📋 asl_schema       - Week 3再设计表       │
│  📋 common_schema    - 需要时再创建表       │
│  📋 dc_schema        - 数据清洗模块         │
│  📋 rvw_schema       - 审稿系统（含现有表） │
│  📋 admin_schema     - 运营管理（含现有表） │
│  📋 ssa_schema       - 智能统计分析         │
│  📋 st_schema        - 统计分析工具         │
└─────────────────────────────────────────────┘
```

### 核心原则

- ✅ **聚焦当前** - 只详细设计和迁移现在需要的（Platform/AIA/PKB）
- ✅ **架构预留** - 创建7个空Schema，命名空间占位
- ✅ **Just-in-time** - ASL等模块在开发前再详细设计（避免过度设计）
- ✅ **降低风险** - Week 1工作量从2天降到1.5天

---

## 10个Schema全景

| # | Schema名称 | 中文名称 | 状态 | 用途 | Week 1任务 |
|---|-----------|---------|------|------|-----------|
| 1 | `platform_schema` | 平台基础层 | ✅ 详细设计 | 用户、权限、认证 | 迁移1个表 |
| 2 | `aia_schema` | AI智能问答 | ✅ 详细设计 | 对话、项目管理 | 迁移5个表 |
| 3 | `pkb_schema` | 个人知识库 | ✅ 详细设计 | 知识库、文档、批处理 | 迁移5个表 |
| 4 | `asl_schema` | AI智能文献 | 📋 空Schema | 文献筛选 | 只创建Schema |
| 5 | `common_schema` | 通用能力层 | 📋 空Schema | LLM使用记录、Feature Flags | 只创建Schema |
| 6 | `dc_schema` | 数据清洗 | 📋 空Schema | 数据清洗工具 | 只创建Schema |
| 7 | `rvw_schema` | 审稿系统 | 📋 空Schema | 稿件审查 | 只创建Schema+迁移1表 |
| 8 | `admin_schema` | 运营管理 | 📋 空Schema | 管理后台、日志 | 只创建Schema+迁移1表 |
| 9 | `ssa_schema` | 智能统计分析 | 📋 空Schema | 智能数据分析 | 只创建Schema |
| 10 | `st_schema` | 统计分析工具 | 📋 空Schema | 统计工具集 | 只创建Schema |

---

## Schema依赖关系

### 层级结构 ⭐

```
┌─────────────────────────────────────────────────────────────┐
│  L3: 业务模块层                                              │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌────────┐│
│  │   AIA   │ │   PKB   │ │   ASL   │ │   RVW   │ │ ADMIN  ││
│  └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬───┘│
│       │           │           │           │           │     │
│       └───────────┴───────────┴───────────┴───────────┘     │
│                             ↓                                │
├─────────────────────────────────────────────────────────────┤
│  L2: 通用能力层                                              │
│  ┌──────────────┐  ┌──────────────┐                        │
│  │   Common     │  │   DC/SSA/ST  │                        │
│  │  (通用数据)   │  │  (通用工具)   │                        │
│  └──────┬───────┘  └──────────────┘                        │
│         │                                                   │
│         └───────────────────────────────────────────────────│
│                             ↓                                │
├─────────────────────────────────────────────────────────────┤
│  L1: 平台基础层                                              │
│  ┌──────────────────────────────────────────────────────┐  │
│  │   Platform Schema                                    │  │
│  │   - 用户管理 (users)                                  │  │
│  │   - 权限控制 (RBAC)                                   │  │
│  │   - 认证服务 (JWT/Session)                           │  │
│  └──────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
```

### 引用关系说明

**核心规则：单向依赖，向下引用**

1. **所有业务模块 → platform_schema.users**
   - 所有表的 `user_id` 字段引用 `platform_schema.users(id)`
   - 跨Schema外键（PostgreSQL支持）

2. **业务模块内部表之间**
   - 同Schema内的表可以相互引用（如aia_schema.conversations → aia_schema.projects）

3. **禁止反向依赖**
   - platform_schema **不能**引用业务模块Schema
   - 业务模块之间**不应**相互引用（保持独立性）

---

## 详细设计：3个迁移Schema

### 1️⃣ platform_schema（平台基础层）⭐

**用途：** 用户管理、权限控制、认证服务

**迁移表：** 1个
- `users` - 从 `public.users` 迁移

#### 表结构：users

| 字段名 | 类型 | 说明 | 索引 |
|-------|------|------|------|
| `id` | UUID | 主键 | PK |
| `email` | VARCHAR(255) | 邮箱（唯一） | UNIQUE, INDEX |
| `password` | VARCHAR(255) | 密码哈希 | - |
| `name` | VARCHAR(255) | 用户名 | - |
| `avatar_url` | VARCHAR(500) | 头像URL | - |
| `role` | VARCHAR(50) | 角色（user/admin） | INDEX |
| `status` | VARCHAR(50) | 状态（active/inactive） | INDEX |
| `kb_quota` | INT | 知识库配额 | - |
| `kb_used` | INT | 已使用配额 | - |
| `trial_ends_at` | TIMESTAMP | 试用结束时间 | - |
| `is_trial` | BOOLEAN | 是否试用 | - |
| `last_login_at` | TIMESTAMP | 最后登录时间 | - |
| `created_at` | TIMESTAMP | 创建时间 | INDEX |
| `updated_at` | TIMESTAMP | 更新时间 | - |

**SQL DDL：**
```sql
CREATE SCHEMA IF NOT EXISTS platform_schema;

CREATE TABLE platform_schema.users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    name VARCHAR(255),
    avatar_url VARCHAR(500),
    role VARCHAR(50) NOT NULL DEFAULT 'user',
    status VARCHAR(50) DEFAULT 'active',
    kb_quota INT DEFAULT 3,
    kb_used INT DEFAULT 0,
    trial_ends_at TIMESTAMP,
    is_trial BOOLEAN DEFAULT true,
    last_login_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 索引
CREATE INDEX idx_users_email ON platform_schema.users(email);
CREATE INDEX idx_users_role ON platform_schema.users(role);
CREATE INDEX idx_users_status ON platform_schema.users(status);
CREATE INDEX idx_users_created_at ON platform_schema.users(created_at);
```

---

### 2️⃣ aia_schema（AI智能问答）⭐

**用途：** AI对话、项目管理、通用对话

**迁移表：** 5个
- `projects` - 从 `public.projects` 迁移
- `conversations` - 从 `public.conversations` 迁移
- `messages` - 从 `public.messages` 迁移
- `general_conversations` - 从 `public.general_conversations` 迁移
- `general_messages` - 从 `public.general_messages` 迁移

#### 表结构概览

**1. projects（项目表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `user_id` | UUID | 用户ID | → `platform_schema.users(id)` |
| `name` | VARCHAR(255) | 项目名称 | - |
| `background` | TEXT | 研究背景 | - |
| `research_type` | VARCHAR(50) | 研究类型 | - |
| `conversation_count` | INT | 对话数 | - |
| `created_at` | TIMESTAMP | 创建时间 | - |
| `updated_at` | TIMESTAMP | 更新时间 | - |
| `deleted_at` | TIMESTAMP | 删除时间（软删除） | - |

**2. conversations（对话表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `user_id` | UUID | 用户ID | → `platform_schema.users(id)` |
| `project_id` | UUID | 项目ID | → `aia_schema.projects(id)` |
| `agent_id` | VARCHAR(100) | 智能体ID | - |
| `title` | VARCHAR(255) | 对话标题 | - |
| `model_name` | VARCHAR(50) | 模型名称 | - |
| `message_count` | INT | 消息数 | - |
| `total_tokens` | INT | 总Token数 | - |
| `metadata` | JSONB | 元数据 | - |
| `created_at` | TIMESTAMP | 创建时间 | - |
| `updated_at` | TIMESTAMP | 更新时间 | - |
| `deleted_at` | TIMESTAMP | 删除时间 | - |

**3. messages（消息表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `conversation_id` | UUID | 对话ID | → `aia_schema.conversations(id)` |
| `role` | VARCHAR(20) | 角色（user/assistant） | - |
| `content` | TEXT | 消息内容 | - |
| `model` | VARCHAR(50) | 使用的模型 | - |
| `metadata` | JSONB | 元数据 | - |
| `tokens` | INT | Token数 | - |
| `is_pinned` | BOOLEAN | 是否置顶 | - |
| `created_at` | TIMESTAMP | 创建时间 | - |

**4. general_conversations（通用对话表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `user_id` | UUID | 用户ID | → `platform_schema.users(id)` |
| `title` | VARCHAR(255) | 对话标题 | - |
| `model_name` | VARCHAR(50) | 模型名称 | - |
| `created_at` | TIMESTAMP | 创建时间 | - |
| `updated_at` | TIMESTAMP | 更新时间 | - |
| `deleted_at` | TIMESTAMP | 删除时间 | - |

**5. general_messages（通用消息表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `conversation_id` | UUID | 对话ID | → `aia_schema.general_conversations(id)` |
| `role` | VARCHAR(20) | 角色 | - |
| `content` | TEXT | 消息内容 | - |
| `model` | VARCHAR(50) | 使用的模型 | - |
| `metadata` | JSONB | 元数据 | - |
| `tokens` | INT | Token数 | - |
| `created_at` | TIMESTAMP | 创建时间 | - |

**SQL DDL：**
```sql
CREATE SCHEMA IF NOT EXISTS aia_schema;

-- 1. projects
CREATE TABLE aia_schema.projects (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL, -- 引用platform_schema.users
    name VARCHAR(255) NOT NULL,
    background TEXT DEFAULT '',
    research_type VARCHAR(50) DEFAULT 'observational',
    conversation_count INT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,
    
    FOREIGN KEY (user_id) REFERENCES platform_schema.users(id) ON DELETE CASCADE
);

-- 2. conversations
CREATE TABLE aia_schema.conversations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    project_id UUID,
    agent_id VARCHAR(100) NOT NULL,
    title VARCHAR(255) NOT NULL,
    model_name VARCHAR(50) DEFAULT 'deepseek-v3',
    message_count INT DEFAULT 0,
    total_tokens INT DEFAULT 0,
    metadata JSONB,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,
    
    FOREIGN KEY (user_id) REFERENCES platform_schema.users(id) ON DELETE CASCADE,
    FOREIGN KEY (project_id) REFERENCES aia_schema.projects(id) ON DELETE CASCADE
);

-- 3. messages
CREATE TABLE aia_schema.messages (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    conversation_id UUID NOT NULL,
    role VARCHAR(20) NOT NULL,
    content TEXT NOT NULL,
    model VARCHAR(50),
    metadata JSONB,
    tokens INT,
    is_pinned BOOLEAN DEFAULT false,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (conversation_id) REFERENCES aia_schema.conversations(id) ON DELETE CASCADE
);

-- 4. general_conversations
CREATE TABLE aia_schema.general_conversations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    title VARCHAR(255) NOT NULL,
    model_name VARCHAR(50),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,
    
    FOREIGN KEY (user_id) REFERENCES platform_schema.users(id) ON DELETE CASCADE
);

-- 5. general_messages
CREATE TABLE aia_schema.general_messages (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    conversation_id UUID NOT NULL,
    role VARCHAR(20) NOT NULL,
    content TEXT NOT NULL,
    model VARCHAR(50),
    metadata JSONB,
    tokens INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (conversation_id) REFERENCES aia_schema.general_conversations(id) ON DELETE CASCADE
);

-- 索引
CREATE INDEX idx_aia_projects_user_id ON aia_schema.projects(user_id);
CREATE INDEX idx_aia_projects_created_at ON aia_schema.projects(created_at);
CREATE INDEX idx_aia_conversations_user_id ON aia_schema.conversations(user_id);
CREATE INDEX idx_aia_conversations_project_id ON aia_schema.conversations(project_id);
CREATE INDEX idx_aia_messages_conversation_id ON aia_schema.messages(conversation_id);
CREATE INDEX idx_aia_general_conversations_user_id ON aia_schema.general_conversations(user_id);
CREATE INDEX idx_aia_general_messages_conversation_id ON aia_schema.general_messages(conversation_id);
```

---

### 3️⃣ pkb_schema（个人知识库）⭐

**用途：** 知识库管理、文档管理、批处理任务

**迁移表：** 5个
- `knowledge_bases` - 从 `public.knowledge_bases` 迁移
- `documents` - 从 `public.documents` 迁移
- `batch_tasks` - 从 `public.batch_tasks` 迁移
- `batch_results` - 从 `public.batch_results` 迁移
- `task_templates` - 从 `public.task_templates` 迁移

#### 表结构概览

**1. knowledge_bases（知识库表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `user_id` | UUID | 用户ID | → `platform_schema.users(id)` |
| `name` | VARCHAR(255) | 知识库名称 | - |
| `description` | TEXT | 描述 | - |
| `dify_dataset_id` | VARCHAR(255) | Dify知识库ID | - |
| `file_count` | INT | 文件数 | - |
| `total_size_bytes` | BIGINT | 总大小（字节） | - |
| `created_at` | TIMESTAMP | 创建时间 | - |
| `updated_at` | TIMESTAMP | 更新时间 | - |

**2. documents（文档表）** ⭐ 包含Phase 2全文阅读字段

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `kb_id` | UUID | 知识库ID | → `pkb_schema.knowledge_bases(id)` |
| `user_id` | UUID | 用户ID | → `platform_schema.users(id)` |
| `filename` | VARCHAR(255) | 文件名 | - |
| `file_type` | VARCHAR(50) | 文件类型 | - |
| `file_size_bytes` | BIGINT | 文件大小 | - |
| `file_url` | TEXT | 文件URL | - |
| `dify_document_id` | VARCHAR(255) | Dify文档ID | - |
| `status` | VARCHAR(50) | 状态 | - |
| `progress` | INT | 进度（0-100） | - |
| `error_message` | TEXT | 错误信息 | - |
| `segments_count` | INT | 分段数 | - |
| `tokens_count` | INT | Token数 | - |
| **Phase 2字段：** | | | |
| `extraction_method` | VARCHAR(50) | 提取方法（pymupdf/nougat/mammoth/direct） | - |
| `extraction_quality` | FLOAT | 提取质量（0-1） | - |
| `char_count` | INT | 字符数 | - |
| `language` | VARCHAR(20) | 语言（chinese/english） | - |
| `extracted_text` | TEXT | 提取的文本 | - |
| `uploaded_at` | TIMESTAMP | 上传时间 | - |
| `processed_at` | TIMESTAMP | 处理完成时间 | - |

**3. batch_tasks（批处理任务表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `user_id` | UUID | 用户ID | → `platform_schema.users(id)` |
| `kb_id` | UUID | 知识库ID | → `pkb_schema.knowledge_bases(id)` |
| `name` | VARCHAR(255) | 任务名称 | - |
| `template_type` | VARCHAR(50) | 模板类型 | - |
| `template_id` | VARCHAR(100) | 模板ID | - |
| `prompt` | TEXT | 提示词 | - |
| `status` | VARCHAR(50) | 状态 | - |
| `total_documents` | INT | 总文档数 | - |
| `completed_count` | INT | 完成数 | - |
| `failed_count` | INT | 失败数 | - |
| `model_type` | VARCHAR(50) | 模型类型 | - |
| `concurrency` | INT | 并发数 | - |
| `started_at` | TIMESTAMP | 开始时间 | - |
| `completed_at` | TIMESTAMP | 完成时间 | - |
| `duration_seconds` | INT | 执行时长（秒） | - |
| `created_at` | TIMESTAMP | 创建时间 | - |
| `updated_at` | TIMESTAMP | 更新时间 | - |

**4. batch_results（批处理结果表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `task_id` | UUID | 任务ID | → `pkb_schema.batch_tasks(id)` |
| `document_id` | UUID | 文档ID | → `pkb_schema.documents(id)` |
| `status` | VARCHAR(50) | 状态 | - |
| `data` | JSONB | 结构化数据 | - |
| `raw_output` | TEXT | 原始输出 | - |
| `error_message` | TEXT | 错误信息 | - |
| `processing_time_ms` | INT | 处理时长（毫秒） | - |
| `tokens_used` | INT | Token使用量 | - |
| `created_at` | TIMESTAMP | 创建时间 | - |

**5. task_templates（任务模板表）**

| 字段名 | 类型 | 说明 | 外键 |
|-------|------|------|------|
| `id` | UUID | 主键 | - |
| `user_id` | UUID | 用户ID | → `platform_schema.users(id)` |
| `name` | VARCHAR(255) | 模板名称 | - |
| `description` | TEXT | 描述 | - |
| `prompt` | TEXT | 提示词 | - |
| `output_fields` | JSONB | 输出字段定义 | - |
| `is_public` | BOOLEAN | 是否公开 | - |
| `created_at` | TIMESTAMP | 创建时间 | - |
| `updated_at` | TIMESTAMP | 更新时间 | - |

**SQL DDL：**
```sql
CREATE SCHEMA IF NOT EXISTS pkb_schema;

-- 1. knowledge_bases
CREATE TABLE pkb_schema.knowledge_bases (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    dify_dataset_id VARCHAR(255) NOT NULL,
    file_count INT DEFAULT 0,
    total_size_bytes BIGINT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (user_id) REFERENCES platform_schema.users(id) ON DELETE CASCADE
);

-- 2. documents (包含Phase 2字段)
CREATE TABLE pkb_schema.documents (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    kb_id UUID NOT NULL,
    user_id UUID NOT NULL,
    filename VARCHAR(255) NOT NULL,
    file_type VARCHAR(50) NOT NULL,
    file_size_bytes BIGINT NOT NULL,
    file_url TEXT NOT NULL,
    dify_document_id VARCHAR(255) NOT NULL,
    status VARCHAR(50) DEFAULT 'uploading',
    progress INT DEFAULT 0,
    error_message TEXT,
    segments_count INT,
    tokens_count INT,
    -- Phase 2字段
    extraction_method VARCHAR(50),
    extraction_quality FLOAT,
    char_count INT,
    language VARCHAR(20),
    extracted_text TEXT,
    uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    processed_at TIMESTAMP,
    
    FOREIGN KEY (kb_id) REFERENCES pkb_schema.knowledge_bases(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES platform_schema.users(id) ON DELETE CASCADE
);

-- 3. batch_tasks
CREATE TABLE pkb_schema.batch_tasks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    kb_id UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    template_type VARCHAR(50) NOT NULL,
    template_id VARCHAR(100),
    prompt TEXT NOT NULL,
    status VARCHAR(50) NOT NULL,
    total_documents INT NOT NULL,
    completed_count INT DEFAULT 0,
    failed_count INT DEFAULT 0,
    model_type VARCHAR(50) NOT NULL,
    concurrency INT DEFAULT 3,
    started_at TIMESTAMP,
    completed_at TIMESTAMP,
    duration_seconds INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (user_id) REFERENCES platform_schema.users(id) ON DELETE CASCADE,
    FOREIGN KEY (kb_id) REFERENCES pkb_schema.knowledge_bases(id) ON DELETE CASCADE
);

-- 4. batch_results
CREATE TABLE pkb_schema.batch_results (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    task_id UUID NOT NULL,
    document_id UUID NOT NULL,
    status VARCHAR(50) NOT NULL,
    data JSONB,
    raw_output TEXT,
    error_message TEXT,
    processing_time_ms INT,
    tokens_used INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (task_id) REFERENCES pkb_schema.batch_tasks(id) ON DELETE CASCADE,
    FOREIGN KEY (document_id) REFERENCES pkb_schema.documents(id) ON DELETE CASCADE
);

-- 5. task_templates
CREATE TABLE pkb_schema.task_templates (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    prompt TEXT NOT NULL,
    output_fields JSONB NOT NULL,
    is_public BOOLEAN DEFAULT false,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (user_id) REFERENCES platform_schema.users(id) ON DELETE CASCADE
);

-- 索引
CREATE INDEX idx_pkb_knowledge_bases_user_id ON pkb_schema.knowledge_bases(user_id);
CREATE INDEX idx_pkb_documents_kb_id ON pkb_schema.documents(kb_id);
CREATE INDEX idx_pkb_documents_user_id ON pkb_schema.documents(user_id);
CREATE INDEX idx_pkb_documents_status ON pkb_schema.documents(status);
CREATE INDEX idx_pkb_batch_tasks_user_id ON pkb_schema.batch_tasks(user_id);
CREATE INDEX idx_pkb_batch_tasks_kb_id ON pkb_schema.batch_tasks(kb_id);
CREATE INDEX idx_pkb_batch_results_task_id ON pkb_schema.batch_results(task_id);
CREATE INDEX idx_pkb_task_templates_user_id ON pkb_schema.task_templates(user_id);
```

---

## 预留：7个空Schema

### 创建策略 ⭐

**只执行 `CREATE SCHEMA`，不创建表结构**

```sql
-- 4. AI智能文献（Week 3再详细设计）
CREATE SCHEMA IF NOT EXISTS asl_schema;
COMMENT ON SCHEMA asl_schema IS 'AI智能文献筛选模块 - Week 3开发前再设计表结构';

-- 5. 通用能力层（需要时再创建表）
CREATE SCHEMA IF NOT EXISTS common_schema;
COMMENT ON SCHEMA common_schema IS '通用能力层 - LLM使用记录、Feature Flags等';

-- 6. 数据清洗模块
CREATE SCHEMA IF NOT EXISTS dc_schema;
COMMENT ON SCHEMA dc_schema IS '数据清洗工具模块';

-- 7. 审稿系统（包含现有review_tasks表）
CREATE SCHEMA IF NOT EXISTS rvw_schema;
COMMENT ON SCHEMA rvw_schema IS '稿件审查系统模块';

-- 8. 运营管理（包含现有admin_logs表）
CREATE SCHEMA IF NOT EXISTS admin_schema;
COMMENT ON SCHEMA admin_schema IS '运营管理后台模块';

-- 9. 智能统计分析
CREATE SCHEMA IF NOT EXISTS ssa_schema;
COMMENT ON SCHEMA ssa_schema IS '智能统计分析模块';

-- 10. 统计分析工具
CREATE SCHEMA IF NOT EXISTS st_schema;
COMMENT ON SCHEMA st_schema IS '统计分析工具集模块';
```

### 各空Schema的用途

| Schema | 用途说明 | 何时设计表结构 |
|--------|---------|--------------|
| `asl_schema` | AI智能文献筛选 | **Week 3 Day 1** - ASL开发前详细设计 |
| `common_schema` | 通用能力（LLM使用记录、Feature Flags） | 需要时再设计 |
| `dc_schema` | 数据清洗工具 | Week 5+或按需 |
| `rvw_schema` | 稿件审查系统 | Week 1迁移review_tasks，其他表按需 |
| `admin_schema` | 运营管理后台 | Week 1迁移admin_logs，其他表按需 |
| `ssa_schema` | 智能统计分析 | Week 5+或按需 |
| `st_schema` | 统计分析工具集 | Week 5+或按需 |

---

## 迁移策略

### 迁移优先级

| 优先级 | Schema | 表数量 | 数据量估算 | 迁移时间 |
|-------|--------|--------|-----------|---------|
| **P0** | platform_schema | 1 | ~10条 | 15分钟 |
| **P0** | aia_schema | 5 | ~500条 | 30分钟 |
| **P0** | pkb_schema | 5 | ~100条 | 30分钟 |
| **P1** | rvw_schema | 1（review_tasks） | ~20条 | 10分钟 |
| **P1** | admin_schema | 1（admin_logs） | ~50条 | 10分钟 |

### 迁移步骤（4步法）

**Step 1：创建10个Schema（5分钟）**
```sql
-- 执行脚本：001-create-all-10-schemas.sql
-- 创建10个Schema（3详细+7空）
```

**Step 2：创建表结构（30分钟）**
```sql
-- 执行脚本：
-- 002-migrate-platform.sql  - 创建platform_schema.users
-- 003-migrate-aia.sql       - 创建aia_schema的5个表
-- 004-migrate-pkb.sql       - 创建pkb_schema的5个表
```

**Step 3：迁移数据（30分钟）**
```sql
-- 使用 INSERT INTO ... SELECT FROM 方式
-- 保持ID不变，确保引用关系不变
```

**Step 4：验证（30分钟）**
```sql
-- 执行脚本：005-validate-all.sql
-- 验证数据完整性、外键约束
```

### 数据迁移示例

**platform_schema.users：**
```sql
INSERT INTO platform_schema.users 
SELECT * FROM public.users;
```

**aia_schema.projects：**
```sql
INSERT INTO aia_schema.projects 
SELECT * FROM public.projects;
```

**验证：**
```sql
-- 验证数据量
SELECT 'users' AS table_name, COUNT(*) FROM platform_schema.users
UNION ALL
SELECT 'projects', COUNT(*) FROM aia_schema.projects
UNION ALL
SELECT 'conversations', COUNT(*) FROM aia_schema.conversations;
```

---

## 现有表分配方案

### 当前public schema中的13个表

| # | 表名 | 目标Schema | 迁移时机 | 说明 |
|---|------|-----------|---------|------|
| 1 | `users` | `platform_schema` | Week 1 | ✅ P0核心表 |
| 2 | `projects` | `aia_schema` | Week 1 | ✅ P0核心表 |
| 3 | `conversations` | `aia_schema` | Week 1 | ✅ P0核心表 |
| 4 | `messages` | `aia_schema` | Week 1 | ✅ P0核心表 |
| 5 | `general_conversations` | `aia_schema` | Week 1 | ✅ P0核心表 |
| 6 | `general_messages` | `aia_schema` | Week 1 | ✅ P0核心表 |
| 7 | `knowledge_bases` | `pkb_schema` | Week 1 | ✅ P0核心表 |
| 8 | `documents` | `pkb_schema` | Week 1 | ✅ P0核心表 |
| 9 | `batch_tasks` | `pkb_schema` | Week 1 | ✅ P0核心表 |
| 10 | `batch_results` | `pkb_schema` | Week 1 | ✅ P0核心表 |
| 11 | `task_templates` | `pkb_schema` | Week 1 | ✅ P0核心表 |
| 12 | `review_tasks` | `rvw_schema` | Week 1或保留 | 📋 P1可选 |
| 13 | `admin_logs` | `admin_schema` | Week 1或保留 | 📋 P1可选 |

**说明：**
- **优先迁移11个表**到3个详细Schema（Platform/AIA/PKB）
- **review_tasks和admin_logs**可以：
  - 选项A：Week 1一并迁移到对应的空Schema（简单）
  - 选项B：暂时保留在public，需要时再迁移（务实）
  - **建议选项A**：一次性迁移完成，避免残留

---

## 外键和跨Schema引用

### PostgreSQL跨Schema外键支持 ✅

PostgreSQL **完全支持**跨Schema的外键约束：

```sql
-- 示例：aia_schema.projects 引用 platform_schema.users
CREATE TABLE aia_schema.projects (
    id UUID PRIMARY KEY,
    user_id UUID NOT NULL,
    name VARCHAR(255),
    
    FOREIGN KEY (user_id) 
        REFERENCES platform_schema.users(id) 
        ON DELETE CASCADE
);
```

### 引用规则

**✅ 允许的引用：**
- 业务模块Schema → `platform_schema.users(id)`
- 同Schema内的表相互引用

**❌ 禁止的引用：**
- `platform_schema` → 业务模块Schema（反向依赖）
- 业务模块Schema之间相互引用（保持独立性）

### 数据一致性保证

1. **CASCADE删除** - 用户删除时，关联数据自动删除
2. **外键索引** - 所有外键字段创建索引
3. **事务保护** - 迁移在事务中执行，全成功或全失败

---

## Prisma配置策略

### Week 1的Prisma配置

**在schema.prisma中：**

1. **启用multiSchema预览特性**
```prisma
generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["multiSchema"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
  schemas  = [
    "platform_schema",
    "aia_schema",
    "pkb_schema",
    "asl_schema",      // 空Schema，预留
    "common_schema",   // 空Schema，预留
    "dc_schema",       // 空Schema，预留
    "rvw_schema",      // 空Schema，预留
    "admin_schema",    // 空Schema，预留
    "ssa_schema",      // 空Schema，预留
    "st_schema"        // 空Schema，预留
  ]
}
```

2. **只为3个详细Schema定义模型**
```prisma
// Platform Schema
model User {
  // ...
  @@map("users")
  @@schema("platform_schema")
}

// AIA Schema
model Project {
  // ...
  @@map("projects")
  @@schema("aia_schema")
}

// PKB Schema
model KnowledgeBase {
  // ...
  @@map("knowledge_bases")
  @@schema("pkb_schema")
}
```

3. **7个空Schema不定义模型**
   - 只在schemas列表中声明
   - Week 3再为asl_schema添加模型
   - 其他按需添加

**详细Prisma配置参考：**
- 见V2.2完整版文档的 Day 4 Prisma配置示例

---

## 📊 工作量估算

| 任务 | 预计时间 | 说明 |
|------|---------|------|
| **Day 1-2上午：架构规划与设计** | 8小时 | 本文档 + 3个Schema SQL |
| **Day 2下午：编写迁移脚本** | 1.5小时 | 5个SQL脚本 |
| **Day 3上午：执行迁移** | 2-3小时 | 备份 + 迁移 + 验证 |
| **Day 3下午：功能测试** | 2小时 | 测试现有功能 |
| **Day 4：Prisma配置** | 3小时 | 更新schema.prisma |
| **总计** | **约16-17小时（2天）** | ✅ |

---

## 🎯 成功标准

Week 1结束时，应达到：

- [ ] ✅ 10个Schema全部创建成功
- [ ] ✅ 3个详细Schema的11个表数据100%迁移
- [ ] ✅ 所有外键约束正确建立
- [ ] ✅ 现有功能（AIA、PKB）正常运行
- [ ] ✅ Prisma Client生成成功
- [ ] ✅ 7个空Schema验证通过（可查询、可创建表）

---

## 📝 后续步骤

### Week 2
- 前端统一架构
- 后端代码分层
- 适配新的Schema结构

### Week 3
- **详细设计asl_schema** ⭐
- 为asl_schema创建表结构
- 开发ASL核心功能

### Week 5+
- 按需为其他空Schema设计表结构
- LLM网关统一
- 其他模块开发

---

**文档制定：** AI助手  
**审核：** 待审核  
**最后更新：** 2025-11-09  

**核心策略：聚焦当前 + 架构预留 + Just-in-time设计** ⭐⭐⭐







