REVISION_TASK_COMPLETE_ANALYSIS.md 18 KB

改图任务系统 - 完整功能分析

分析时间

2025-11-19 00:50


📋 一、创建工单的填写逻辑

1.1 表单字段和验证规则

必填字段(所有类型)

✅ 修改描述 (description)
   - 类型:文本框
   - 验证:不能为空
   - 最大长度:500字符
   - 提示:"请详细描述需要修改的内容..."

大修改(major)额外必填

✅ 涉及空间 (selectedSpaces)
   - 类型:多选复选框
   - 验证:至少选择1个空间
   - 可选:全选按钮
   - 显示:空间名称列表(主卧、厨房等)

✅ 预计时间 (estimatedDays)
   - 类型:单选按钮
   - 选项:
     * 2-3天
     * 3-5天
     * 5-7天
     * 自定义
   - 默认:2-3天
   
✅ 自定义天数 (customDays)
   - 显示:仅当选择"自定义"时
   - 类型:数字输入
   - 验证:≥1天
   - 默认:3天

小修改(minor)规则

⚠️ 不需要选择空间
⚠️ 不需要选择时间
✅ 只需要填写描述
💡 内部记录,不创建正式工单

1.2 表单验证逻辑

// 验证规则(revision-task-modal.component.ts: 101-112)
isFormValid(): boolean {
  // 1. 描述必填
  if (!this.description.trim()) return false;
  
  // 2. 大修改额外验证
  if (this.taskType === 'major') {
    // 2.1 至少选择一个空间
    if (this.selectedSpaces.length === 0) return false;
    
    // 2.2 自定义天数验证
    if (this.estimatedDays === 'custom' && (!this.customDays || this.customDays < 1)) {
      return false;
    }
  }
  
  return true;
}

1.3 提交按钮状态

按钮禁用条件:
1. !isFormValid()        - 表单验证不通过
2. submitting            - 正在提交中

🔄 二、完整工单流程

2.1 工单类型

小修改(Minor Revision)

特点:
- 不需要审批
- 不需要报价
- 不需要客户确认
- 仅内部记录
- 立即生效

数据存储:
Project.data.minorRevisions = [
  {
    id: "MR_timestamp_randomid",
    projectId: string,
    type: "minor",
    description: string,
    createdBy: string,
    createdByName: string,
    createdAt: Date
  }
]

UI提示:
✅ "小修改已记录"

大修改(Major Revision)

特点:
- 需要组长审批
- 需要客服报价
- 需要客户确认(TODO)
- 创建正式工单
- 有完整状态流转

数据存储:
Project.data.revisionTasks = [
  {
    id: "RT_timestamp_randomid",
    projectId: string,
    type: "major",
    spaceIds: string[],
    spaceNames: string[],
    estimatedDays: string,
    customDays?: number,
    description: string,
    status: RevisionStatus,
    ...审批信息,
    ...报价信息,
    ...完成信息
  }
]

UI提示:
✅ "改图工单已创建,等待组长审批"

2.2 工单状态流转

大修改工单状态机:

1. pending_approval (待审批)
   ↓ 组长审批
   ├─→ approved (已批准)
   │   ↓ 客服报价
   │   └─→ quoted (已报价)
   │       ↓ 客户确认(TODO)
   │       └─→ confirmed (执行中)
   │           ↓ 设计师完成
   │           └─→ completed (已完成) ✅
   │
   └─→ rejected (已驳回) ❌

任何阶段都可以:
   └─→ cancelled (已取消) ⚠️

2.3 角色权限

设计师(Designer)

✅ 创建工单(小修改 + 大修改)
✅ 查看自己创建的工单
✅ 完成工单(status: confirmed → completed)
❌ 审批工单
❌ 报价工单

组长(Team Leader)

✅ 查看所有工单
✅ 审批工单(pending_approval → approved)
✅ 驳回工单(pending_approval → rejected)
✅ 完成工单
❌ 报价工单

客服(Customer Service)

✅ 查看所有工单
✅ 报价工单(approved → quoted)
✅ 取消工单
❌ 审批工单

客户(Customer)- TODO

🚧 查看工单
🚧 确认报价(quoted → confirmed)
🚧 提供反馈

💾 三、数据存储结构

3.1 Project 表的 data 字段

Project.data = {
  // 小修改记录
  minorRevisions: [
    {
      id: string,
      projectId: string,
      type: "minor",
      description: string,
      createdBy: string,
      createdByName: string,
      createdByRole: string,
      createdAt: Date
    }
  ],
  
  // 大修改工单
  revisionTasks: [
    {
      id: string,
      projectId: string,
      type: "major",
      
      // 基本信息
      spaceIds: string[],
      spaceNames: string[],
      estimatedDays: string,
      customDays?: number,
      description: string,
      status: RevisionStatus,
      
      // 创建信息
      createdBy: string,
      createdByName: string,
      createdByRole: string,
      createdAt: Date,
      
      // 组长审批
      approvedBy?: string,
      approvedByName?: string,
      approvedAt?: Date,
      approvalNotes?: string,
      
      // 驳回信息
      rejectedBy?: string,
      rejectedByName?: string,
      rejectedAt?: Date,
      rejectionReason?: string,
      
      // 客服报价
      quotedBy?: string,
      quotedByName?: string,
      quotedAt?: Date,
      quotedPrice?: number,
      quotedNotes?: string,
      
      // 客户确认
      confirmedBy?: string,
      confirmedByName?: string,
      confirmedAt?: Date,
      
      // 完成信息
      completedBy?: string,
      completedByName?: string,
      completedAt?: Date,
      completionNotes?: string,
      
      // 附件
      attachments?: Array<{
        url: string,
        name: string,
        size: number,
        uploadTime: Date
      }>
    }
  ],
  
  // 其他数据...
  deliveryMessages: [...],
  quotation: {...}
}

3.2 数据同步机制

✅ 已实现的同步

1. 创建工单后 → 刷新工单数量徽章
   - stage-delivery.component.ts: loadRevisionTaskCount()
   - 显示未完成工单数量

2. 工单状态变更 → 刷新列表
   - revision-task-list.component.ts: loadTasks()
   - 自动重新加载工单列表

3. 工单操作后 → 触发父组件刷新
   - @Output() refresh = new EventEmitter<void>()
   - 父组件监听并更新数据

🚧 待实现的同步

1. 企业微信通知
   - 创建工单 → 通知组长
   - 审批通过 → 通知客服
   - 报价完成 → 通知客户
   - 工单完成 → 通知相关人员

2. 实时消息推送
   - WebSocket 实时更新
   - 工单状态变化实时通知

3. 与消息系统集成
   - 工单创建后自动发送消息到项目群
   - 状态变更消息通知

📊 四、UI 交互流程

4.1 创建工单流程

1. 用户点击"创建改图任务"按钮
   ↓
2. 弹窗显示 (showRevisionTaskModal = true)
   ↓
3. 用户选择任务类型
   ├─ 小修改 → 仅填写描述
   └─ 大修改 → 填写完整表单
       ├─ 勾选空间
       ├─ 选择预计时间
       └─ 填写描述
   ↓
4. 点击"提交"按钮
   ├─ 验证表单 (isFormValid())
   ├─ submitting = true (禁用按钮)
   └─ 调用 revisionTaskService.createRevisionTask()
   ↓
5. 后端处理
   ├─ 生成工单ID
   ├─ 保存到 Project.data
   └─ 返回工单ID
   ↓
6. 前端反馈
   ├─ 显示成功提示
   ├─ 触发 created 事件
   ├─ 刷新工单数量
   └─ 关闭弹窗

4.2 查看工单列表流程

1. 用户点击"改图工单"按钮
   ↓
2. 显示全屏列表 (showRevisionTaskList = true)
   ↓
3. 加载数据
   ├─ 加载大修改工单 (revisionTasks)
   └─ 加载小修改记录 (minorRevisions)
   ↓
4. 显示两个标签页
   ├─ 大修改:显示正式工单列表
   │   └─ 根据状态显示不同操作按钮
   └─ 小修改:显示记录列表
       └─ 仅显示信息,无操作
   ↓
5. 用户操作
   ├─ 组长:审批/驳回
   ├─ 客服:报价
   └─ 设计师:完成工单

4.3 审批工单流程

组长操作:

1. 点击"审批"按钮
   ↓
2. 弹出审批弹窗
   ├─ 显示工单详情
   ├─ 审批备注输入框
   └─ 驳回原因输入框
   ↓
3. 选择操作
   ├─ 批准
   │   ├─ 可选填写备注
   │   ├─ 调用 approveRevisionTask()
   │   ├─ status: pending_approval → approved
   │   └─ 通知客服报价(TODO)
   │
   └─ 驳回
       ├─ 必填驳回原因
       ├─ 调用 rejectRevisionTask()
       ├─ status: pending_approval → rejected
       └─ 通知创建人(TODO)
   ↓
4. 刷新列表
   └─ 重新加载工单数据

4.4 报价工单流程

客服操作:

1. 点击"报价"按钮
   ↓
2. 弹出报价弹窗
   ├─ 显示工单详情
   ├─ 报价金额输入
   └─ 报价说明输入
   ↓
3. 填写报价
   ├─ 金额:必填,>0
   └─ 说明:可选
   ↓
4. 提交报价
   ├─ 验证:quotePrice > 0
   ├─ 调用 quoteRevisionTask()
   ├─ status: approved → quoted
   └─ 通知客户确认(TODO)
   ↓
5. 刷新列表

五、功能完成度检查

5.1 核心功能 ✅

✅ 创建小修改(内部记录)
✅ 创建大修改(正式工单)
✅ 表单验证逻辑
✅ 空间多选
✅ 预计时间选择
✅ 自定义天数
✅ 工单列表展示
✅ 状态显示和样式
✅ 组长审批功能
✅ 组长驳回功能
✅ 客服报价功能
✅ 工单完成功能
✅ 工单取消功能
✅ 数据持久化(Project.data)
✅ 工单数量徽章
✅ 响应式UI
✅ 加载状态
✅ 错误处理

5.2 部分完成功能 🚧

🚧 客户确认功能
   - 数据结构已定义
   - Service 方法已实现
   - UI 待开发

🚧 附件上传
   - 数据结构已定义
   - 上传逻辑待实现
   - 显示逻辑待实现

5.3 待开发功能 ⚠️

⚠️ 企业微信通知
   - notifyTeamLeader() - TODO
   - notifyCustomerService() - TODO
   - 状态变更推送

⚠️ 实时消息同步
   - WebSocket 集成
   - 工单更新推送
   - 在线状态显示

⚠️ 工单搜索和筛选
   - 按状态筛选
   - 按创建人筛选
   - 按空间筛选
   - 关键词搜索

⚠️ 工单统计
   - 总工单数
   - 各状态数量
   - 平均处理时间
   - 完成率

⚠️ 工单导出
   - Excel 导出
   - PDF 报告生成

⚠️ 权限细化
   - 设计师只看自己的工单
   - 跨部门协作权限
   - 查看权限控制

🔐 六、权限和安全

6.1 当前权限实现

// 通过 @Input 传递权限标志
@Input() isTeamLeader: boolean = false;
@Input() isCustomerService: boolean = false;

// UI 根据权限显示/隐藏按钮
@if (isTeamLeader && task.status === 'pending_approval') {
  <button (click)="openApprovalModal(task)">审批</button>
}

@if (isCustomerService && task.status === 'approved') {
  <button (click)="openQuoteModal(task)">报价</button>
}

6.2 安全建议

⚠️ 建议改进:

1. 后端验证
   - 当前只有前端权限检查
   - 需要在 Parse Cloud Code 中添加权限验证
   - 防止直接调用 API 绕过权限

2. 数据访问控制
   - 使用 Parse ACL
   - 设置对象级别权限
   - 防止未授权访问

3. 操作日志
   - 记录所有关键操作
   - 审计追踪
   - 防止纠纷

4. 输入验证
   - XSS 防护
   - SQL 注入防护
   - 长度限制

📈 七、性能优化

7.1 已实现的优化

✅ OnPush 变更检测策略
   - ChangeDetectionStrategy.OnPush
   - 减少不必要的变更检测

✅ 数组引用缓存
   - cachedRevisionSpaces
   - 避免频繁创建新数组

✅ 延迟加载
   - 组件 Standalone
   - 按需导入

✅ 日志优化
   - 减少控制台输出
   - 只在关键变化时记录

7.2 可进一步优化

🎯 虚拟滚动
   - 大量工单时性能优化
   - 使用 CDK Virtual Scroll

🎯 分页加载
   - 按需加载工单
   - 减少初始加载时间

🎯 缓存策略
   - 本地缓存工单列表
   - 定时同步

🎯 图片懒加载
   - 工单附件延迟加载
   - 减少带宽占用

🧪 八、测试用例

8.1 单元测试建议

describe('RevisionTaskModalComponent', () => {
  // 表单验证测试
  it('should validate required description', () => {
    component.description = '';
    expect(component.isFormValid()).toBe(false);
  });
  
  it('should validate major revision requires spaces', () => {
    component.taskType = 'major';
    component.description = 'test';
    component.selectedSpaces = [];
    expect(component.isFormValid()).toBe(false);
  });
  
  it('should validate custom days', () => {
    component.taskType = 'major';
    component.estimatedDays = 'custom';
    component.customDays = 0;
    expect(component.isFormValid()).toBe(false);
  });
  
  // 提交测试
  it('should create minor revision without spaces', () => {
    component.taskType = 'minor';
    component.description = 'test';
    // should call revisionTaskService.recordMinorRevision
  });
  
  it('should create major revision with approval', () => {
    component.taskType = 'major';
    component.selectedSpaces = [{ id: '1', name: 'Space 1', selected: true }];
    component.description = 'test';
    // should create task with status: pending_approval
  });
});

8.2 集成测试用例

测试场景1:完整的大修改工单流程
1. 设计师创建工单 → status: pending_approval
2. 组长审批通过 → status: approved
3. 客服报价 → status: quoted
4. 客户确认 → status: confirmed
5. 设计师完成 → status: completed
验证:每步状态正确,数据完整保存

测试场景2:工单驳回流程
1. 设计师创建工单 → status: pending_approval
2. 组长驳回 → status: rejected
验证:驳回原因被保存,创建人收到通知

测试场景3:小修改记录
1. 设计师创建小修改 → 保存到 minorRevisions
验证:不创建正式工单,只记录

测试场景4:权限控制
1. 普通设计师尝试审批 → 失败
2. 普通设计师尝试报价 → 失败
验证:权限正确控制

测试场景5:数据同步
1. 创建工单 → 工单数量徽章更新
2. 完成工单 → 列表自动刷新
验证:UI 和数据保持同步

🐛 九、已知问题和修复

9.1 已修复问题

✅ ngOnChanges 频繁调用导致页面卡顿
   - 原因:模板中调用方法创建新数组
   - 修复:使用缓存属性 cachedRevisionSpaces
   - 位置:stage-delivery.component.ts

✅ 拖拽上传弹窗性能问题
   - 原因:availableSpaces 频繁创建
   - 修复:使用 cachedAvailableSpaces
   - 位置:stage-delivery-new.component.html

✅ TypeScript 编译错误
   - 原因:isSupportedFileType 方法丢失
   - 修复:重新添加方法定义
   - 位置:stage-delivery.component.ts:2826

9.2 当前问题

⚠️ 弹窗交互问题(可能仍存在)
   - 现象:点击按钮无响应
   - 原因:浏览器缓存旧代码
   - 解决:强制刷新(Ctrl+Shift+R)

⚠️ WebSocket 连接失败
   - 现象:控制台显示 ERR_CONNECTION_REFUSED
   - 影响:热更新功能失效,不影响核心功能
   - 解决:重启开发服务器

📚 十、相关文档

1. DELIVERY_COMPLETE_IMPLEMENTATION.md
   - 交付执行阶段完整功能文档
   - 消息发送功能
   - 改图任务功能概述

2. NGONCHANGES_PERFORMANCE_FIX.md
   - ngOnChanges 性能问题详细分析
   - 缓存机制实现
   - Angular 最佳实践

3. EMERGENCY_FIX_GUIDE.md
   - 紧急修复指南
   - 故障排查步骤
   - 调试命令集合

4. QUICK_FIX_CHECKLIST.md
   - 快速检查清单
   - 常见问题解决
   - 验证步骤

🎯 十一、下一步开发计划

优先级 P0(核心功能)

✅ 已完成

优先级 P1(重要功能)

1. 客户确认功能
   - 开发客户端界面
   - 实现确认流程
   - 添加反馈功能

2. 企业微信通知
   - 集成企业微信 API
   - 实现消息模板
   - 测试通知功能

3. 后端权限验证
   - 编写 Parse Cloud Code
   - 添加 ACL 控制
   - 测试权限

优先级 P2(增强功能)

1. 附件上传
   - 支持图片上传
   - 支持文档上传
   - 附件预览

2. 工单搜索和筛选
   - 状态筛选
   - 关键词搜索
   - 日期范围

3. 实时消息推送
   - WebSocket 集成
   - 状态变更推送
   - 在线状态显示

优先级 P3(优化功能)

1. 工单统计报表
2. 数据导出功能
3. 性能优化(虚拟滚动等)
4. 移动端适配

十二、使用指南

创建小修改

1. 点击"创建改图任务"
2. 选择"小修改"
3. 填写描述(例如:"客厅沙发颜色调整为灰色")
4. 点击"提交"
✅ 立即记录,无需审批

创建大修改

1. 点击"创建改图任务"
2. 选择"大修改"(默认)
3. 勾选涉及的空间(可多选)
   - 例如:✓ 主卧  ✓ 厨房
4. 选择预计时间
   - 2-3天 / 3-5天 / 5-7天 / 自定义
5. 填写详细描述
   - 例如:"主卧更换床头背景墙材质,厨房增加吊柜"
6. 点击"提交"
✅ 创建工单,等待组长审批

审批工单(组长)

1. 点击"改图工单"
2. 找到"待审批"状态的工单
3. 点击"审批"按钮
4. 选择操作:
   - 批准:填写审批备注(可选)→ 提交
   - 驳回:填写驳回原因(必填)→ 提交
✅ 审批完成,自动通知相关人员

报价工单(客服)

1. 点击"改图工单"
2. 找到"已批准"状态的工单
3. 点击"报价"按钮
4. 填写报价金额(例如:500)
5. 填写报价说明(可选)
6. 点击"提交报价"
✅ 报价完成,等待客户确认

📞 技术支持

常见问题

Q: 为什么点击按钮没反应? A: 请刷新浏览器(Ctrl+Shift+R)清除缓存

Q: 创建工单后看不到? A: 检查工单列表的标签页(大修改/小修改)

Q: 审批按钮不显示? A: 检查当前用户是否为组长权限

Q: 工单数量徽章不更新? A: 刷新页面,数量会自动重新加载


文档版本:v1.0
最后更新:2025-11-19 00:50
维护人:Cascade AI Assistant
状态:✅ 核心功能已完整实现