# 改图任务系统 - 完整功能分析 ## 分析时间 2025-11-19 00:50 --- ## 📋 **一、创建工单的填写逻辑** ### 1.1 表单字段和验证规则 #### 必填字段(所有类型) ```typescript ✅ 修改描述 (description) - 类型:文本框 - 验证:不能为空 - 最大长度:500字符 - 提示:"请详细描述需要修改的内容..." ``` #### 大修改(major)额外必填 ```typescript ✅ 涉及空间 (selectedSpaces) - 类型:多选复选框 - 验证:至少选择1个空间 - 可选:全选按钮 - 显示:空间名称列表(主卧、厨房等) ✅ 预计时间 (estimatedDays) - 类型:单选按钮 - 选项: * 2-3天 * 3-5天 * 5-7天 * 自定义 - 默认:2-3天 ✅ 自定义天数 (customDays) - 显示:仅当选择"自定义"时 - 类型:数字输入 - 验证:≥1天 - 默认:3天 ``` #### 小修改(minor)规则 ```typescript ⚠️ 不需要选择空间 ⚠️ 不需要选择时间 ✅ 只需要填写描述 💡 内部记录,不创建正式工单 ``` --- ### 1.2 表单验证逻辑 ```typescript // 验证规则(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 提交按钮状态 ```typescript 按钮禁用条件: 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) ```typescript ✅ 创建工单(小修改 + 大修改) ✅ 查看自己创建的工单 ✅ 完成工单(status: confirmed → completed) ❌ 审批工单 ❌ 报价工单 ``` #### 组长(Team Leader) ```typescript ✅ 查看所有工单 ✅ 审批工单(pending_approval → approved) ✅ 驳回工单(pending_approval → rejected) ✅ 完成工单 ❌ 报价工单 ``` #### 客服(Customer Service) ```typescript ✅ 查看所有工单 ✅ 报价工单(approved → quoted) ✅ 取消工单 ❌ 审批工单 ``` #### 客户(Customer)- TODO ```typescript 🚧 查看工单 🚧 确认报价(quoted → confirmed) 🚧 提供反馈 ``` --- ## 💾 **三、数据存储结构** ### 3.1 Project 表的 data 字段 ```typescript 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 数据同步机制 #### ✅ 已实现的同步 ```typescript 1. 创建工单后 → 刷新工单数量徽章 - stage-delivery.component.ts: loadRevisionTaskCount() - 显示未完成工单数量 2. 工单状态变更 → 刷新列表 - revision-task-list.component.ts: loadTasks() - 自动重新加载工单列表 3. 工单操作后 → 触发父组件刷新 - @Output() refresh = new EventEmitter() - 父组件监听并更新数据 ``` #### 🚧 待实现的同步 ```typescript 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 当前权限实现 ```typescript // 通过 @Input 传递权限标志 @Input() isTeamLeader: boolean = false; @Input() isCustomerService: boolean = false; // UI 根据权限显示/隐藏按钮 @if (isTeamLeader && task.status === 'pending_approval') { } @if (isCustomerService && task.status === 'approved') { } ``` --- ### 6.2 安全建议 ``` ⚠️ 建议改进: 1. 后端验证 - 当前只有前端权限检查 - 需要在 Parse Cloud Code 中添加权限验证 - 防止直接调用 API 绕过权限 2. 数据访问控制 - 使用 Parse ACL - 设置对象级别权限 - 防止未授权访问 3. 操作日志 - 记录所有关键操作 - 审计追踪 - 防止纠纷 4. 输入验证 - XSS 防护 - SQL 注入防护 - 长度限制 ``` --- ## 📈 **七、性能优化** ### 7.1 已实现的优化 ```typescript ✅ OnPush 变更检测策略 - ChangeDetectionStrategy.OnPush - 减少不必要的变更检测 ✅ 数组引用缓存 - cachedRevisionSpaces - 避免频繁创建新数组 ✅ 延迟加载 - 组件 Standalone - 按需导入 ✅ 日志优化 - 减少控制台输出 - 只在关键变化时记录 ``` --- ### 7.2 可进一步优化 ``` 🎯 虚拟滚动 - 大量工单时性能优化 - 使用 CDK Virtual Scroll 🎯 分页加载 - 按需加载工单 - 减少初始加载时间 🎯 缓存策略 - 本地缓存工单列表 - 定时同步 🎯 图片懒加载 - 工单附件延迟加载 - 减少带宽占用 ``` --- ## 🧪 **八、测试用例** ### 8.1 单元测试建议 ```typescript 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 **状态**:✅ 核心功能已完整实现