# 用户反馈系统 - 数据模型文档

> **版本**: v1.0.3  
> **最后更新**: 2026-01-07  
> **维护者**: 后端团队

---

## 📋 概述

### Schema 信息

- **Schema 名称**: `platform_feedback`
- **业务域**: 用户反馈收集与处理
- **核心表数量**: 1 个（`feedbacks`）

### 设计原则

- 反馈记录采用软删除，保留历史
- region 从用户 metadata.region 继承，不允许手工修改（服务层写入，数据库提供默认值兜底）
- 状态流转受限于状态机规则

---

## 🗄️ 表结构设计

### 表 1: feedbacks（主表）

#### 基本信息

- **表名**: `platform_feedback.feedbacks`
- **说明**: 用户反馈主表
- **主键**: `id`
- **外键**: `user_id` → `platform_iam.users.id`，`assignee_id` → `platform_iam.users.id`

#### 表结构

```sql
CREATE TABLE platform_feedback.feedbacks (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

  -- 反馈内容
  type VARCHAR(20) NOT NULL,
  title VARCHAR(200) NOT NULL,
  content TEXT NOT NULL,
  attachments TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],

  -- 上下文信息
  page_url VARCHAR(500),
  user_agent VARCHAR(500),

  -- 状态管理
  status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
  priority VARCHAR(20),

  -- 管理员处理
  admin_note TEXT,
  admin_reply TEXT,
  assignee_id UUID,
  resolved_at TIMESTAMPTZ,

  -- 用户信息
  user_id UUID NOT NULL,

  -- 多区域
  region VARCHAR(10) NOT NULL DEFAULT 'CN',

  -- 审计字段
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  deleted_at TIMESTAMPTZ,

  CONSTRAINT fk_feedback_user FOREIGN KEY (user_id) REFERENCES platform_iam.users(id),
  CONSTRAINT fk_feedback_assignee FOREIGN KEY (assignee_id) REFERENCES platform_iam.users(id),
  CONSTRAINT check_feedback_type CHECK (type IN ('BUG', 'FEATURE', 'IMPROVEMENT', 'OTHER')),
  CONSTRAINT check_feedback_status CHECK (status IN ('PENDING', 'IN_PROGRESS', 'RESOLVED', 'CLOSED')),
  CONSTRAINT check_feedback_priority CHECK (priority IN ('LOW', 'MEDIUM', 'HIGH', 'URGENT'))
);
```

#### 字段详细说明

| 字段名 | 类型 | 必需 | 默认值 | 说明 |
|--------|------|------|--------|------|
| `id` | UUID | 是 | gen_random_uuid() | 主键 |
| `type` | VARCHAR(20) | 是 | - | 反馈类型 |
| `title` | VARCHAR(200) | 是 | - | 标题 |
| `content` | TEXT | 是 | - | 内容 |
| `attachments` | TEXT[] | 是 | 空数组 | 附件 URL 数组 |
| `page_url` | VARCHAR(500) | 否 | NULL | 页面地址 |
| `user_agent` | VARCHAR(500) | 否 | NULL | 浏览器信息 |
| `status` | VARCHAR(20) | 是 | PENDING | 处理状态 |
| `priority` | VARCHAR(20) | 否 | NULL | 优先级 |
| `admin_note` | TEXT | 否 | NULL | 管理员内部备注 |
| `admin_reply` | TEXT | 否 | NULL | 管理员回复 |
| `assignee_id` | UUID | 否 | NULL | 指派处理人 |
| `resolved_at` | TIMESTAMPTZ | 否 | NULL | 解决时间 |
| `user_id` | UUID | 是 | - | 提交用户 |
| `region` | VARCHAR(10) | 是 | 'CN' | 区域（CN/US/EU/APAC） |
| `created_at` | TIMESTAMPTZ | 是 | NOW() | 创建时间 |
| `updated_at` | TIMESTAMPTZ | 是 | NOW() | 更新时间 |
| `deleted_at` | TIMESTAMPTZ | 否 | NULL | 软删除时间 |

#### 枚举值定义

##### type（反馈类型）

| 值 | 说明 | 中文名 |
|----|------|--------|
| `BUG` | 问题反馈 | 问题反馈 |
| `FEATURE` | 功能建议 | 功能建议 |
| `IMPROVEMENT` | 改进建议 | 改进建议 |
| `OTHER` | 其他 | 其他 |

##### status（处理状态）

| 值 | 说明 | 中文名 |
|----|------|--------|
| `PENDING` | 待处理 | 待处理 |
| `IN_PROGRESS` | 处理中 | 处理中 |
| `RESOLVED` | 已解决 | 已解决 |
| `CLOSED` | 已关闭 | 已关闭 |

##### priority（优先级）

| 值 | 说明 | 中文名 |
|----|------|--------|
| `LOW` | 低 | 低 |
| `MEDIUM` | 中 | 中 |
| `HIGH` | 高 | 高 |
| `URGENT` | 紧急 | 紧急 |

#### 索引

```sql
CREATE INDEX idx_feedbacks_user_id ON platform_feedback.feedbacks(user_id);
CREATE INDEX idx_feedbacks_assignee_id ON platform_feedback.feedbacks(assignee_id);
CREATE INDEX idx_feedbacks_status ON platform_feedback.feedbacks(status);
CREATE INDEX idx_feedbacks_type ON platform_feedback.feedbacks(type);
CREATE INDEX idx_feedbacks_region ON platform_feedback.feedbacks(region);
CREATE INDEX idx_feedbacks_created_at ON platform_feedback.feedbacks(created_at);
CREATE INDEX idx_feedbacks_region_status ON platform_feedback.feedbacks(region, status);
```

#### 业务约束

1. region 继承自用户 metadata.region，不允许手动修改（默认值为 CN）
2. 状态流转必须符合状态机规则
3. 软删除记录不参与默认查询

---

## 📊 表关系图

### ER 图

```mermaid
erDiagram
    platform_iam_users ||--o{ feedbacks : creates
    platform_iam_users ||--o{ feedbacks : assigned

    platform_iam_users {
        UUID id PK
        string displayName
        string email
        string region
    }

    feedbacks {
        UUID id PK
        UUID user_id FK
        UUID assignee_id FK
        string type
        string status
        string region
    }
```

### 关系说明

| 主表 | 关系 | 从表 | 说明 |
|------|------|------|------|
| `platform_iam.users` | 1:N | `platform_feedback.feedbacks` | 用户可提交多条反馈 |
| `platform_iam.users` | 1:N | `platform_feedback.feedbacks` | 管理员可被指派多条反馈 |

---

## 🔧 Prisma Schema

```prisma
// prisma/schema/platform_feedback.prisma

model Feedback {
  id              String            @id @default(uuid()) @db.Uuid

  // 反馈内容
  type            FeedbackType
  title           String            @db.VarChar(200)
  content         String            @db.Text
  attachments     String[]          @default([])

  // 上下文信息
  pageUrl         String?           @map("page_url") @db.VarChar(500)
  userAgent       String?           @map("user_agent") @db.VarChar(500)

  // 状态管理
  status          FeedbackStatus    @default(PENDING)
  priority        FeedbackPriority?

  // 管理员处理
  adminNote       String?           @map("admin_note") @db.Text
  adminReply      String?           @map("admin_reply") @db.Text
  assigneeId      String?           @map("assignee_id") @db.Uuid
  resolvedAt      DateTime?         @map("resolved_at")

  // 用户信息
  userId          String            @map("user_id") @db.Uuid

  // 多区域支持
  region          String            @db.VarChar(10)

  // 审计
  createdAt       DateTime          @default(now()) @map("created_at")
  updatedAt       DateTime          @updatedAt @map("updated_at")
  deletedAt       DateTime?         @map("deleted_at")

  // 关联
  user            User              @relation("FeedbackUser", fields: [userId], references: [id])
  assignee        User?             @relation("FeedbackAssignee", fields: [assigneeId], references: [id])

  @@index([userId])
  @@index([assigneeId])
  @@index([status])
  @@index([type])
  @@index([region])
  @@index([createdAt])
  @@index([region, status])
  @@map("feedbacks")
  @@schema("platform_feedback")
}

enum FeedbackType {
  BUG
  FEATURE
  IMPROVEMENT
  OTHER

  @@schema("platform_feedback")
}

enum FeedbackStatus {
  PENDING
  IN_PROGRESS
  RESOLVED
  CLOSED

  @@schema("platform_feedback")
}

enum FeedbackPriority {
  LOW
  MEDIUM
  HIGH
  URGENT

  @@schema("platform_feedback")
}
```

---

## 📈 数据量预估

### 容量规划

> 说明：以下为基于用户场景频率的初步估算，需与实际用户规模确认。

| 表名 | 初期数据量 | 1年后 | 3年后 | 增长率 |
|------|-----------|-------|-------|--------|
| `feedbacks` | 1,000 - 5,000 | 30,000 - 80,000 | 100,000 - 250,000 | 中等 |

### 估算假设

- 日均反馈提交 50-200 条（参考用户场景频率）
- 软删除不做物理清理

---

## 🔄 迁移策略

- 新增字段需走 Prisma 迁移
- 禁止修改已合并迁移
- 遵循增量式变更流程（先加列、回填、再加约束）

---

## ⚠️ 注意事项

### 数据完整性

1. 软删除使用 `deleted_at`
2. 外键约束确保用户关联一致性
3. 附件数量在请求校验层校验（DTO 校验）

### 安全考虑

1. `admin_note` 仅管理员可见
2. `page_url` 与 `user_agent` 仅管理员可见

---

## 🔗 相关文档

- [架构设计](./03-architecture.md)
- [API 文档](./07-api.md)
- [状态机](./04-state-machine.md)

---

**最后更新**: 2026-01-06  
**版本**: v1.0.2  
**维护者**: 后端团队
