# 工单系统 PRD

> 产品需求文档 - 定义工单系统的功能需求和验收标准
>
> **版本**: v1.3  
> **模块标识**: `platform_tickets`  
> **创建日期**: 2025-12-11  
> **更新日期**: 2025-12-11

---

## 🚀 MVP 范围定义

> ⚠️ **重要**: 本系统功能完整但落地需分阶段，以下为 MVP（Phase 1-2）必须实现的最小可行范围。

### MVP 必须包含 ✅

| 功能 | 说明 |
|------|------|
| 工单创建 | 分类选择、优先级、标题描述、附件上传 |
| 工单列表 | 我的工单、待处理工单、基本筛选排序 |
| 状态流转 | OPEN → ASSIGNED → IN_PROGRESS → RESOLVED → CLOSED |
| 手动分配 | 管理员/组长手动分配工单 |
| 简单自动分配 | 按分类 → 默认处理组 → 轮询分配 |
| 评论/附件 | 工单评论、附件上传下载 |
| 邮件通知 | 工单创建、分配、状态变更通知 |
| 基本 SLA 显示 | 显示响应/解决时间，不做复杂升级规则 |
| 基础统计 | 工单量、状态分布、分类分布 |
| 满意度评价 | 基本评分功能 |

### MVP 不包含（Phase 3+ 实现）❌

| 功能 | 所属阶段 | 说明 |
|------|----------|------|
| 技能匹配分配 (F4.5) | Phase 3 | 基于技能标签智能匹配 |
| 负载均衡分配 (F4.4) | Phase 3 | 基于工作量动态分配 |
| 智能升级 (F6.6) | Phase 4 | 超时自动升级处理人 |
| 复杂 SLA 规则 | Phase 4 | 升级策略、多级预警 |
| 人员绩效统计 (F7.6) | Phase 5 | 处理人绩效分析 |
| 匿名评价 (F10.4) | Phase 5 | 匿名满意度评价 |
| 跨区域协作 (F9.3) | Phase 6 | 跨区域工单转派 |
| 知识库集成 | Phase 6 | 解决方案推荐 |
| 批量操作 | Phase 6 | 批量分配、状态更新 |

### MVP 开发周期

| 阶段 | 内容 | 周期 | 累计 |
|------|------|------|------|
| Phase 1 | 基础工单 CRUD + 状态流转 | 2 周 | 2 周 |
| Phase 2 | 分配 + 评论 + 通知 | 1.5 周 | 3.5 周 |
| **MVP 完成** | 可上线使用 | - | **3.5 周** |

---

## 📋 背景与目标

### 背景

1. **现有问题**
   - 企业内各类服务请求（IT 支持、行政服务、设备维修等）缺少统一的管理入口
   - 服务请求通过邮件、即时通讯等方式提交，难以追踪和管理
   - 服务团队缺少工作量统计和效率分析工具
   - 用户无法了解请求的处理进度

2. **业务场景**
   - **IT 支持**: 电脑故障、软件安装、网络问题、账号问题
   - **行政服务**: 办公用品申请、会议室预订问题、访客接待
   - **设备维修**: 办公设备报修、设施维护
   - **HR 服务**: 证明开具、信息变更、咨询答疑
   - **财务服务**: 报销咨询、发票申请、账务查询

### 目标

构建一个通用工单系统，实现：

1. **统一入口** - 所有服务请求通过工单系统提交
2. **智能分配** - 基于工单类型、技能匹配、工作负载自动分配
3. **状态追踪** - 完整的工单生命周期可视化
4. **协作沟通** - 支持评论、附件、@提醒，实现高效沟通
5. **数据驱动** - 工单效率、质量、满意度分析
6. **SLA 管理** - 服务等级协议和升级机制
7. **AI 联动** - 与[企业智能助手](../../../ai-assistant/docs/PRD.md)协同，支持 AI 对话一键升级工单，保留对话上下文，减少重复沟通

### ⚠️ 边界声明

> **工单系统负责「服务请求管理」，不负责具体业务审批。**
>
> - ✅ 管理工单的创建、分配、状态、沟通
> - ✅ 工单可关联审批流程（如需要审批的采购请求）
> - ❌ 不处理具体业务逻辑（如采购流程、请假流程）
> - ❌ 不替代审批引擎的职能
>
> 工单系统与审批引擎的关系：工单是「请求」，审批是「决策」。

---

## 🏗️ 核心概念

### 系统架构

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                              用户端                                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │
│  │  创建工单   │  │  我的工单   │  │  工单详情   │  │  满意度评价  │        │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘        │
│         │                │                │                │               │
├─────────┴────────────────┴────────────────┴────────────────┴───────────────┤
│                              工单服务层                                       │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                        Ticket Service                                │   │
│  │  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐        │   │
│  │  │ 工单管理  │  │ 自动分配  │  │ SLA 监控  │  │ 统计分析  │        │   │
│  │  └───────────┘  └───────────┘  └───────────┘  └───────────┘        │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                              │                                              │
├──────────────────────────────┼──────────────────────────────────────────────┤
│                              ▼                                              │
│                           处理端                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │
│  │  工单队列   │  │  工单处理   │  │  工单转派   │  │  工单关闭   │        │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘        │
│                                                                              │
├──────────────────────────────────────────────────────────────────────────────┤
│                           管理端                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │
│  │  分类管理   │  │  分配规则   │  │  SLA 配置   │  │  报表分析   │        │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘        │
└──────────────────────────────────────────────────────────────────────────────┘
```

### 核心实体

#### Ticket（工单）

```typescript
interface Ticket {
  id: UUID;                           // 全局唯一标识
  ticketNo: string;                   // 工单编号 (如: TK-20251211-0001)
  
  // 基本信息
  title: string;                      // 工单标题
  description: string;                // 详细描述（支持富文本）
  
  // 分类与优先级
  categoryId: UUID;                   // 工单分类
  priority: TicketPriority;           // 优先级
  tags?: string[];                    // 标签
  
  // 状态
  status: TicketStatus;               // 工单状态
  
  // 人员
  creatorId: UUID;                    // 创建人
  assigneeId?: UUID;                  // 当前处理人
  assigneeGroupId?: UUID;             // 处理组
  watcherIds?: UUID[];                // 关注人
  
  // 时间
  createdAt: Date;                    // 创建时间
  updatedAt: Date;                    // 更新时间
  firstResponseAt?: Date;             // 首次响应时间
  resolvedAt?: Date;                  // 解决时间
  closedAt?: Date;                    // 关闭时间
  dueAt?: Date;                       // 截止时间（SLA）
  
  // SLA
  slaId?: UUID;                       // 关联的 SLA 策略
  slaBreached: boolean;               // 是否超时
  
  // 满意度
  satisfactionRating?: number;        // 满意度评分 (1-5)
  satisfactionComment?: string;       // 满意度评价
  
  // 关联
  relatedTicketIds?: UUID[];          // 关联工单
  parentTicketId?: UUID;              // 父工单（子工单场景）
  
  // 来源
  source: TicketSource;               // 工单来源
  externalId?: string;                // 外部系统 ID
  channelMetadata?: JSON;             // 🆕 来源渠道元数据
                                      //    邮件: { messageId, subject, from }
                                      //    AI Chat: { conversationId, sessionId }
                                      //    API: { clientId, requestId }
  
  // 解决方案
  resolution?: string;                // 解决方案
  rootCause?: string;                 // 根本原因
  
  // 多区域/多租户
  region: string;                     // 地域标识 (CN/US/EU/APAC)
  tenantId?: UUID;                    // 🆕 租户 ID（多公司场景）
  language?: string;                  // 🆕 工单语言 (zh-CN/en-US)
  
  // 合规与软删除
  complianceFlag: boolean;            // 🆕 合规标记（true 时不可物理删除）
  deletedAt?: Date;
}
```

#### TicketCategory（工单分类）

```typescript
interface TicketCategory {
  id: UUID;
  name: string;                       // 分类名称
  code: string;                       // 分类编码 (如: IT_SUPPORT)
  description?: string;               // 描述
  parentId?: UUID;                    // 父分类（支持多级）
  icon?: string;                      // 图标
  
  // 配置
  defaultPriority: TicketPriority;    // 默认优先级
  defaultAssigneeGroupId?: UUID;      // 默认处理组
  slaId?: UUID;                       // 默认 SLA
  formTemplateId?: UUID;              // 自定义表单模板
  
  // 状态
  isActive: boolean;
  sortOrder: number;
  
  // 可见性
  allowedDepartmentIds?: UUID[];      // 允许使用的部门
  allowedRoleIds?: UUID[];            // 允许使用的角色
  
  // 审计
  createdAt: Date;
  updatedAt: Date;
}
```

#### TicketComment（工单评论）

```typescript
interface TicketComment {
  id: UUID;
  ticketId: UUID;
  
  // 内容
  content: string;                    // 评论内容（支持富文本）
  attachments?: Attachment[];         // 附件
  
  // 类型
  type: CommentType;                  // 评论类型
  isInternal: boolean;                // 是否内部评论（用户不可见）
  visibilityScope?: VisibilityScope;  // 🆕 可见范围（更细粒度控制）
  
  // 作者
  authorId: UUID;
  
  // @提醒
  mentionedUserIds?: UUID[];
  
  // 审计
  createdAt: Date;
  updatedAt: Date;
  deletedAt?: Date;
}

enum CommentType {
  COMMENT = 'COMMENT',                // 普通评论
  STATUS_CHANGE = 'STATUS_CHANGE',    // 状态变更
  ASSIGNMENT = 'ASSIGNMENT',          // 分配变更
  SYSTEM = 'SYSTEM',                  // 系统消息
  AI_CONTEXT = 'AI_CONTEXT',          // 🆕 AI 对话上下文（来自智能助手升级）
}

// 🆕 可见范围枚举
enum VisibilityScope {
  ALL = 'ALL',                        // 所有人可见（默认）
  AGENT_ONLY = 'AGENT_ONLY',          // 仅处理人可见
  GROUP_ONLY = 'GROUP_ONLY',          // 仅处理组可见
  INTERNAL = 'INTERNAL',              // 内部可见（等同 isInternal=true）
}
```

#### TicketSLA（服务等级协议）

```typescript
interface TicketSLA {
  id: UUID;
  name: string;                       // SLA 名称
  description?: string;
  
  // 响应时间（分钟）
  firstResponseTime: {
    low: number;                      // 低优先级（如 480 = 8小时）
    medium: number;                   // 中优先级（如 240 = 4小时）
    high: number;                     // 高优先级（如 60 = 1小时）
    urgent: number;                   // 紧急（如 30 = 30分钟）
  };
  
  // 解决时间（分钟）
  resolutionTime: {
    low: number;                      // 如 2880 = 48小时
    medium: number;                   // 如 1440 = 24小时
    high: number;                     // 如 480 = 8小时
    urgent: number;                   // 如 240 = 4小时
  };
  
  // 工作时间
  businessHours: BusinessHours;       // 工作时间配置
  excludeHolidays: boolean;           // 排除节假日
  
  // 升级策略
  escalationRules?: EscalationRule[];
  
  // 状态
  isActive: boolean;
  isDefault: boolean;
  
  // 审计
  createdAt: Date;
  updatedAt: Date;
}

interface EscalationRule {
  level: number;                      // 升级级别
  triggerType: 'RESPONSE' | 'RESOLUTION';
  triggerPercentage: number;          // 触发百分比 (如 80% 时提醒)
  actions: EscalationAction[];        // 升级动作
}

interface EscalationAction {
  type: 'NOTIFY' | 'REASSIGN' | 'ESCALATE_TO_MANAGER';
  targetUserIds?: UUID[];
  targetRoleIds?: UUID[];
  notificationChannels?: string[];
}
```

#### AssignmentGroup（处理组）

```typescript
interface AssignmentGroup {
  id: UUID;
  name: string;                       // 组名称
  code: string;                       // 组编码
  description?: string;
  
  // 成员
  memberIds: UUID[];                  // 组成员
  managerId?: UUID;                   // 组长
  
  // 技能
  skills?: string[];                  // 组技能标签
  
  // 分配策略
  assignmentStrategy: AssignmentStrategy;
  
  // 关联分类
  categoryIds?: UUID[];               // 负责的工单分类
  
  // 状态
  isActive: boolean;
  
  // 审计
  createdAt: Date;
  updatedAt: Date;
}

enum AssignmentStrategy {
  ROUND_ROBIN = 'ROUND_ROBIN',        // 轮询分配
  LOAD_BALANCE = 'LOAD_BALANCE',      // 负载均衡
  MANUAL = 'MANUAL',                  // 手动分配
  SKILL_BASED = 'SKILL_BASED',        // 基于技能
}
```

### 枚举定义

```typescript
// 工单状态
enum TicketStatus {
  OPEN = 'OPEN',                      // 新建/待分配
  ASSIGNED = 'ASSIGNED',              // 已分配/待处理
  IN_PROGRESS = 'IN_PROGRESS',        // 处理中
  PENDING = 'PENDING',                // 挂起（等待用户回复/外部依赖）
  RESOLVED = 'RESOLVED',              // 已解决
  CLOSED = 'CLOSED',                  // 已关闭
  CANCELLED = 'CANCELLED',            // 已取消
}

// 工单优先级
enum TicketPriority {
  LOW = 'LOW',                        // 低
  MEDIUM = 'MEDIUM',                  // 中
  HIGH = 'HIGH',                      // 高
  URGENT = 'URGENT',                  // 紧急
}

// 工单来源
enum TicketSource {
  WEB = 'WEB',                        // 网页
  MOBILE = 'MOBILE',                  // 移动端
  EMAIL = 'EMAIL',                    // 邮件
  API = 'API',                        // API 集成
  CHAT = 'CHAT',                      // 即时通讯
  PHONE = 'PHONE',                    // 电话
  WALK_IN = 'WALK_IN',                // 现场
}
```

### 状态流转

```
                              ┌─────────────┐
                              │  CANCELLED  │
                              │    已取消    │
                              └──────▲──────┘
                                     │
┌──────────┐    ┌───────────┐    ┌───┴────────┐    ┌─────────────┐    ┌──────────┐
│   OPEN   │───>│ ASSIGNED  │───>│IN_PROGRESS │───>│  RESOLVED   │───>│  CLOSED  │
│   新建   │    │  已分配    │    │   处理中   │    │   已解决    │    │  已关闭   │
└──────────┘    └───────────┘    └──────┬─────┘    └──────┬──────┘    └──────────┘
                                        │                 │
                                        ▼                 │
                                 ┌──────────┐             │
                                 │ PENDING  │◄────────────┘
                                 │   挂起   │    (重新打开)
                                 └──────────┘
```

**状态说明**：

| 状态 | 说明 | 允许操作 |
|------|------|----------|
| `OPEN` | 新建工单，等待分配 | 分配、取消 |
| `ASSIGNED` | 已分配处理人 | 开始处理、转派、取消 |
| `IN_PROGRESS` | 正在处理中 | 解决、挂起、转派、取消 |
| `PENDING` | 等待用户回复或外部依赖 | 继续处理、解决、取消 |
| `RESOLVED` | 问题已解决，等待确认 | 关闭、重新打开 |
| `CLOSED` | 工单已关闭 | 重新打开（限定时间内） |
| `CANCELLED` | 工单已取消 | 无 |

---

## 👤 用户角色与故事

### 角色定义

| 角色 | 权限 | 说明 |
|------|------|------|
| 普通用户 | `ticket:create`, `ticket:view:own` | 创建工单、查看自己的工单 |
| 处理人 | `ticket:process`, `ticket:view:assigned` | 处理分配给自己的工单 |
| 组长 | `ticket:manage:group` | 管理本组工单、分配任务 |
| 工单管理员 | `ticket:admin` | 管理所有工单、配置分类和规则 |
| 系统管理员 | `ticket:super` | 所有权限 + SLA 配置 |

### 用户故事

#### 普通用户

```
作为 普通用户
我希望 能够快速创建服务请求工单
以便 获得及时的技术支持
```

```
作为 普通用户
我希望 能够查看我提交的工单状态和处理进度
以便 了解问题何时能够解决
```

```
作为 普通用户
我希望 能够在工单上添加评论和附件
以便 提供更多信息帮助问题解决
```

```
作为 普通用户
我希望 能够对已解决的工单进行满意度评价
以便 反馈服务质量
```

#### 处理人

```
作为 工单处理人
我希望 能够查看分配给我的工单队列
以便 了解待处理的工作量
```

```
作为 工单处理人
我希望 能够更新工单状态和添加处理记录
以便 记录问题解决过程
```

```
作为 工单处理人
我希望 能够将工单转派给其他人
以便 在我无法处理时由他人接手
```

```
作为 工单处理人
我希望 能够看到工单的 SLA 截止时间
以便 优先处理紧急工单
```

#### 组长

```
作为 组长
我希望 能够查看本组所有工单的处理情况
以便 监控团队工作进度
```

```
作为 组长
我希望 能够手动分配工单给组员
以便 合理分配工作负载
```

```
作为 组长
我希望 能够看到组员的工单处理统计
以便 进行绩效评估
```

#### 工单管理员

```
作为 工单管理员
我希望 能够配置工单分类和表单模板
以便 适应不同类型的服务请求
```

```
作为 工单管理员
我希望 能够配置自动分配规则
以便 工单能够自动路由到合适的处理人
```

```
作为 工单管理员
我希望 能够查看工单统计报表
以便 分析服务效率和质量
```

---

## 📦 功能需求

### F1: 工单创建

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F1.1 创建入口 | P0 | 📋 | 提供便捷的工单创建入口 |
| F1.2 分类选择 | P0 | 📋 | 选择工单分类（支持多级） |
| F1.3 优先级设置 | P0 | 📋 | 设置工单优先级 |
| F1.4 详细描述 | P0 | 📋 | 富文本编辑器描述问题 |
| F1.5 附件上传 | P0 | 📋 | 上传截图、文件等附件 |
| F1.6 自定义字段 | P1 | 📋 | 根据分类显示自定义表单字段 |
| F1.7 草稿保存 | P2 | 📋 | 保存草稿，稍后提交 |
| F1.8 工单模板 | P2 | 📋 | 使用预设模板快速创建 |

### F2: 工单列表与查看

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F2.1 我的工单 | P0 | 📋 | 查看自己创建的工单 |
| F2.2 待处理工单 | P0 | 📋 | 查看分配给自己的工单 |
| F2.3 组工单队列 | P0 | 📋 | 查看本组的工单 |
| F2.4 全部工单 | P1 | 📋 | 管理员查看所有工单 |
| F2.5 筛选搜索 | P0 | 📋 | 按状态、分类、时间等筛选 |
| F2.6 排序功能 | P0 | 📋 | 按时间、优先级、SLA 排序 |
| F2.7 快速视图 | P1 | 📋 | 预设视图（今日、紧急、超时） |
| F2.8 工单详情 | P0 | 📋 | 查看工单完整信息 |

### F3: 工单处理

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F3.1 状态更新 | P0 | 📋 | 更新工单状态 |
| F3.2 添加评论 | P0 | 📋 | 添加处理记录/评论 |
| F3.3 内部备注 | P0 | 📋 | 添加内部备注（用户不可见） |
| F3.4 附件管理 | P0 | 📋 | 上传/下载附件 |
| F3.5 @提醒 | P1 | 📋 | 评论中 @其他用户 |
| F3.6 解决方案 | P0 | 📋 | 填写解决方案 |
| F3.7 根因分析 | P2 | 📋 | 记录根本原因 |
| F3.8 知识库关联 | P2 | 📋 | 关联知识库文章 |

### F4: 工单分配

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F4.1 手动分配 | P0 | 📋 | 管理员/组长手动分配 |
| F4.2 自动分配 | P0 | 📋 | 基于规则自动分配 |
| F4.3 轮询分配 | P0 | 📋 | 组内轮询分配 |
| F4.4 负载均衡 | P1 | 📋 | 基于当前工作量分配 |
| F4.5 技能匹配 | P2 | 📋 | 基于技能标签匹配 |
| F4.6 转派功能 | P0 | 📋 | 将工单转给他人 |
| F4.7 升级处理 | P1 | 📋 | 升级到更高级别处理人 |
| F4.8 工单认领 | P1 | 📋 | 从队列中认领工单 |

### F5: 协作沟通

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F5.1 评论系统 | P0 | 📋 | 工单评论和回复 |
| F5.2 附件共享 | P0 | 📋 | 评论中上传附件 |
| F5.3 @提醒 | P1 | 📋 | @用户发送通知 |
| F5.4 关注功能 | P1 | 📋 | 关注工单更新 |
| F5.5 活动日志 | P0 | 📋 | 查看工单操作历史 |
| F5.6 邮件通知 | P0 | 📋 | 工单变更邮件通知 |
| F5.7 站内通知 | P0 | 📋 | 工单变更站内通知 |
| F5.8 实时更新 | P2 | 📋 | WebSocket 实时推送 |

### F6: SLA 管理

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F6.1 SLA 配置 | P1 | 📋 | 配置响应和解决时间 |
| F6.2 工作时间 | P1 | 📋 | 配置工作时间（排除非工作时间） |
| F6.3 节假日排除 | P2 | 📋 | 配置节假日 |
| F6.4 SLA 监控 | P1 | 📋 | 显示 SLA 剩余时间 |
| F6.5 即将超时预警 | P1 | 📋 | 超时前预警通知 |
| F6.6 超时升级 | P1 | 📋 | 超时自动升级 |
| F6.7 暂停 SLA | P2 | 📋 | 挂起时暂停 SLA 计时 |

### F7: 统计分析

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F7.1 工单统计 | P1 | 📋 | 按状态、分类统计 |
| F7.2 趋势分析 | P2 | 📋 | 工单量趋势图 |
| F7.3 处理效率 | P1 | 📋 | 平均响应/解决时间 |
| F7.4 SLA 达成率 | P1 | 📋 | SLA 达成情况统计 |
| F7.5 满意度统计 | P1 | 📋 | 用户满意度分析 |
| F7.6 人员绩效 | P2 | 📋 | 处理人绩效统计 |
| F7.7 分类分析 | P2 | 📋 | 按分类分析问题分布 |
| F7.8 导出报表 | P2 | 📋 | 导出统计报表 |

### F8: 分类与配置管理

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F8.1 分类管理 | P0 | 📋 | 创建、编辑工单分类 |
| F8.2 多级分类 | P1 | 📋 | 支持多级分类结构 |
| F8.3 处理组管理 | P0 | 📋 | 管理处理组和成员 |
| F8.4 分配规则 | P1 | 📋 | 配置自动分配规则 |
| F8.5 表单模板 | P2 | 📋 | 按分类配置表单字段 |
| F8.6 工单模板 | P2 | 📋 | 预设工单模板 |
| F8.7 标签管理 | P2 | 📋 | 管理工单标签 |

### F9: 多区域 / 多租户支持

> 📌 **概念区分**:
> - **Tenant（租户）** = 公司/法律实体级隔离，不同租户**完全不可见**
> - **Region（区域）** = 同一公司下的地域划分，**可按策略跨区域协作**

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F9.1 区域隔离 | P1 | 📋 | 按区域隔离工单数据 |
| F9.2 区域管理员 | P1 | 📋 | 区域级管理员权限 |
| F9.3 跨区域协作 | P2 | 📋 | 跨区域工单转派（需授权） |
| F9.4 租户隔离 | P2 | 📋 | 多公司场景完全隔离 |
| F9.5 租户配置 | P2 | 📋 | 每个租户独立的分类、SLA 配置 |

**数据隔离矩阵**:

| 场景 | 隔离字段 | 可见性规则 |
|------|----------|-----------|
| 同租户同区域 | `tenantId` + `region` | 默认可见 |
| 同租户跨区域 | `tenantId` | 需 `ticket:cross_region` 权限 |
| 跨租户 | `tenantId` | **完全不可见**（硬隔离） |

```typescript
// 多租户/多区域查询过滤
function buildTenantFilter(context: RequestContext): WhereClause {
  const where: WhereClause = {
    tenantId: context.tenantId,  // 租户硬隔离
  };
  
  // 区域过滤
  if (!context.hasPermission('ticket:cross_region')) {
    where.region = context.region;
  }
  
  return where;
}
```

### F10: 满意度调查

| 功能点 | 优先级 | 状态 | 说明 |
|--------|--------|------|------|
| F10.1 评价入口 | P1 | 📋 | 工单解决后邀请评价 |
| F10.2 评分系统 | P1 | 📋 | 1-5 星评分 |
| F10.3 评价反馈 | P1 | 📋 | 填写评价内容 |
| F10.4 匿名评价 | P2 | 📋 | 支持匿名评价 |
| F10.5 自动触发 | P1 | 📋 | 满足条件自动发起评价邀请 |

#### 满意度评价触发规则

> 📌 何时发起评价邀请？

| 触发条件 | 说明 |
|----------|------|
| 状态变为 RESOLVED | 工单解决后**立即**发送评价邀请 |
| RESOLVED 保持 3 天未 reopen | 自动发送**二次提醒** |
| 状态变为 CLOSED | 如果未评价，发送**最后一次邀请** |
| 手动请求 | 处理人可手动触发评价邀请 |

```typescript
// 满意度触发逻辑
const SATISFACTION_TRIGGERS = {
  // 工单解决时
  onResolved: {
    action: 'SEND_INVITATION',
    delay: 0,                      // 立即发送
    channel: ['EMAIL', 'IN_APP'],
  },
  
  // 解决后 N 天未评价且未重开
  onResolvedIdle: {
    action: 'SEND_REMINDER',
    delay: 3 * 24 * 60 * 60 * 1000, // 3 天后
    condition: 'status === RESOLVED && !hasRating',
    channel: ['EMAIL'],
  },
  
  // 关闭时仍未评价
  onClosed: {
    action: 'SEND_FINAL_INVITATION',
    condition: '!hasRating',
    channel: ['EMAIL'],
    message: '感谢您使用我们的服务，您的反馈对我们很重要',
  },
};

// 评价时效限制
const SATISFACTION_LIMITS = {
  allowRatingDays: 30,            // 工单关闭后 30 天内可评价
  reminderMaxCount: 2,            // 最多提醒 2 次
};
```

---

## 🔗 模块集成

### 与审批引擎集成

某些工单类型（如设备采购请求）可能需要审批：

```typescript
// 工单分类配置
interface TicketCategory {
  // ...
  requiresApproval: boolean;          // 是否需要审批
  approvalProcessKey?: string;        // 关联的审批流程
}

// 工单创建时触发审批
async function createTicketWithApproval(ticket: CreateTicketDto) {
  const category = await getCategory(ticket.categoryId);
  
  const createdTicket = await ticketService.create(ticket);
  
  if (category.requiresApproval) {
    const approval = await approvalService.startApproval({
      processDefinitionKey: category.approvalProcessKey,
      businessType: 'TICKET',
      businessId: createdTicket.id,
      initiatorId: ticket.creatorId,
    });
    
    createdTicket.approvalInstanceId = approval.id;
    createdTicket.status = 'PENDING_APPROVAL';
  }
  
  return createdTicket;
}
```

### 与通知引擎集成

工单状态变更触发通知：

```typescript
// 工单事件 → 通知
const ticketNotifications = {
  'ticket.created': ['creator', 'assignee'],
  'ticket.assigned': ['assignee', 'creator'],
  'ticket.status_changed': ['creator', 'assignee', 'watchers'],
  'ticket.commented': ['creator', 'assignee', 'mentioned'],
  'ticket.sla_warning': ['assignee', 'group_manager'],
  'ticket.sla_breached': ['assignee', 'group_manager', 'admin'],
  'ticket.resolved': ['creator'],
  'ticket.satisfaction_requested': ['creator'],
};
```

### 与组织架构集成

```typescript
// 用户信息
- 获取用户部门、职位
- 获取用户所属处理组
- 获取用户上级（用于升级）

// 部门信息
- 获取部门成员（用于分配）
- 获取部门负责人
```

### 与企业智能助手集成

> 🔗 **关联模块**: `platform_ai_assistant` ([企业智能助手 PRD](../../../ai-assistant/docs/PRD.md))

工单来源 `TicketSource.CHAT` 对应来自企业智能助手的升级请求：

```typescript
// AI 对话升级为工单
interface AIEscalationToTicket {
  // 来源标识
  source: 'CHAT';                         // 来自 AI Chat
  channelMetadata: {
    conversationId: UUID;                 // AI 对话 ID
    sessionId: UUID;                      // 会话 ID
    escalationReason: string;             // 升级原因
    userFeedback?: 'NOT_HELPFUL' | 'NEED_HUMAN';  // 用户反馈
  };
  
  // 自动携带内容
  title: string;                          // AI 自动生成标题
  description: string;                    // 包含对话摘要
  
  // 对话上下文作为评论
  initialComment: {
    type: 'AI_CONTEXT';                   // AI 上下文类型
    content: string;                      // AI 对话历史摘要
    visibilityScope: 'AGENT_ONLY';        // 仅处理人可见
  };
}

// 升级工单创建示例
async function createTicketFromAI(conversation: AIConversation) {
  const ticket = await ticketService.create({
    title: `[AI 升级] ${conversation.topic || '用户咨询'}`,
    description: conversation.summary,
    categoryId: conversation.suggestedCategoryId,
    source: 'CHAT',
    channelMetadata: {
      conversationId: conversation.id,
      sessionId: conversation.sessionId,
      escalationReason: conversation.escalationReason,
    },
    creatorId: conversation.userId,
  });
  
  // 添加 AI 对话上下文作为首条评论
  await ticketService.addComment(ticket.id, {
    type: 'AI_CONTEXT',
    content: formatConversationHistory(conversation.messages),
    visibilityScope: 'AGENT_ONLY',
    isInternal: true,
  });
  
  return ticket;
}
```

**集成要点**:

| 场景 | 处理方式 |
|------|----------|
| AI 无法解决 | 用户点击「转人工」→ 创建工单 |
| 用户反馈「未解决」 | 自动提示创建工单 |
| 对话上下文 | 作为 `AI_CONTEXT` 类型评论，仅处理人可见 |
| 分类映射 | AI 对话场景 → 对应工单分类 |

---

## 📐 非功能需求

### 性能

| 指标 | 要求 | 说明 |
|------|------|------|
| 工单创建 | < 200ms (P95) | 包含自动分配逻辑 |
| 列表查询 | < 100ms (P95) | 默认分页 20 条 |
| 详情查询 | < 50ms (P95) | 包含评论和附件 |
| 搜索查询 | < 500ms (P95) | 全文搜索场景 |
| 并发支持 | 500+ TPS | **主要针对查询/列表接口**，创建类允许 100 TPS |

> **说明**: 
> - 时间指标均为 **P95**（95% 请求满足）
> - P99 允许比 P95 高 50%
> - 创建类接口因涉及事务和通知，TPS 要求可适当放宽

### 可用性

| 指标 | 要求 |
|------|------|
| 系统可用性 | 99.9% |
| 数据持久性 | 100% |
| 故障恢复 | < 30min |

### 安全性

| 要求 | 说明 |
|------|------|
| 数据权限 | 用户只能查看有权限的工单 |
| 操作审计 | 所有操作记录日志 |
| 附件安全 | 附件访问需要认证 |

### 数据保留与删除策略

> ⚠️ **重要**: 工单数据涉及服务记录和合规要求，需严格控制删除行为。

| 策略 | 说明 |
|------|------|
| **软删除优先** | 工单默认只允许软删除（`deletedAt` 标记），不允许物理删除 |
| **物理删除限制** | 只有 `ticket:super` 角色可触发物理删除，且需通过后台批处理任务执行 |
| **审计合规** | 带有审计/合规标记的工单不得物理删除，需保留至少 7 年（符合 SOX/内控要求） |
| **附件保留** | 附件随工单软删除，物理删除需单独审批 |
| **数据归档** | 超过 3 年的已关闭工单可归档到冷存储 |

```typescript
// 删除权限控制
const TICKET_DELETE_RULES = {
  // 软删除: 管理员可操作
  softDelete: {
    allowedRoles: ['ticket:admin', 'ticket:super'],
    conditions: ['status !== OPEN'], // 进行中的工单需先关闭
  },
  
  // 物理删除: 仅超级管理员，且需后台任务
  hardDelete: {
    allowedRoles: ['ticket:super'],
    conditions: [
      'deletedAt !== null',        // 必须已软删除
      'deletedAt < 90 days ago',   // 软删除超过 90 天
      'complianceFlag === false',  // 非合规标记工单
    ],
    requireBatchJob: true,         // 必须通过批处理任务
  },
};
```

---

## ✅ 验收标准

### 工单创建验收

- [ ] 可选择工单分类（支持多级）
- [ ] 可设置优先级
- [ ] 可填写标题和详细描述（富文本）
- [ ] 可上传附件（最多 10 个，单个 20MB）
- [ ] 自定义字段按分类显示
- [ ] 创建成功生成工单编号

### 工单处理验收

- [ ] 处理人可查看待处理工单队列
- [ ] 可更新工单状态
- [ ] 可添加评论和附件
- [ ] 可添加内部备注
- [ ] 可填写解决方案
- [ ] 可转派给他人

### 自动分配验收

| 验收项 | Phase | MVP |
|--------|:-----:|:---:|
| 支持按分类配置默认处理组 | 2 | ✅ |
| 支持轮询分配 | 2 | ✅ |
| 无法分配时通知管理员 | 2 | ✅ |
| 支持负载均衡分配 | 3 | ❌ |
| 支持技能匹配分配 | 3 | ❌ |

### SLA 验收

| 验收项 | Phase | MVP |
|--------|:-----:|:---:|
| 显示 SLA 剩余时间（响应/解决时间） | 2 | ✅ |
| 即将超时发送预警 | 4 | ❌ |
| 超时后自动升级 | 4 | ❌ |
| 挂起时暂停 SLA 计时 | 4 | ❌ |
| 多级升级策略配置 | 4 | ❌ |

### 统计分析验收

| 验收项 | Phase | MVP |
|--------|:-----:|:---:|
| 显示工单状态分布 | 2 | ✅ |
| 显示分类分布 | 2 | ✅ |
| 显示处理效率指标（平均响应/解决时间） | 5 | ❌ |
| 显示 SLA 达成率 | 5 | ❌ |
| 支持按时间范围筛选 | 5 | ❌ |
| 人员绩效统计 | 5 | ❌ |
| 导出报表 | 5 | ❌ |

---

## 📅 里程碑

| 阶段 | 内容 | 预计周期 | 状态 |
|------|------|----------|------|
| Phase 0 | 需求分析与设计 | 1 周 | ✅ 已完成 |
| Phase 1 | 基础工单管理（创建、查看、状态） | 2 周 | 📋 待开发 |
| Phase 2 | 自动分配与路由 | 1 周 | 📋 待开发 |
| Phase 3 | 协作与沟通（评论、附件、通知） | 1 周 | 📋 待开发 |
| Phase 4 | SLA 管理 | 1 周 | 📋 待开发 |
| Phase 5 | 统计分析 | 1 周 | 📋 待开发 |
| Phase 6 | 高级功能（模板、知识库） | 2 周 | 📋 待规划 |

---

## 📚 相关文档

### 工单系统文档

- [架构设计](ARCHITECTURE.md)
- [API 接口文档](API.md)
- [开发待办](TODO.md)

### 相关模块文档

- [审批引擎 PRD](../../../approval/docs/PRD.md)
- [通知引擎文档](../../../notification/docs/README.md)
- [用户反馈 PRD](../feedback/01-prd.md)

---

**创建日期**: 2025-12-11  
**最后更新**: 2025-12-11  
**版本**: v1.3
