project-status-badges-implementation.md 13 KB

项目停滞期和改图期状态标记功能实现

📋 功能概述

在项目详情页面的右下角添加停滞期和改图期的状态标记,方便组员和组长实时了解项目状态。

🎯 功能特性

1. 停滞期标记

  • 显示位置:页面右下角,浮动显示
  • 显示内容
    • 停滞期图标(⏸️)
    • 停滞原因(设计师原因/客户原因/自定义原因)
    • 标记人信息
  • 交互功能
    • 可点击取消:点击标记即可取消停滞期状态
    • 悬停效果:鼠标悬停时向左移动并放大阴影
    • 点击确认:弹出确认提示,避免误操作

2. 改图期标记

  • 显示位置:页面右下角,停滞期标记下方
  • 显示内容
    • 改图期图标(🎨)
    • 改图原因(客户要求/设计师优化/自定义原因)
    • 标记人信息
    • 提示文本:"上传图片后自动取消"
  • 自动取消机制
    • 当组员在交付执行阶段上传图片并确认后
    • 系统自动检测项目是否处于改图期
    • 自动清除改图期标记和相关字段
    • 保留历史记录字段(markedAtmarkedBy

📂 修改文件清单

1. project-detail.component.ts

修改内容

  • 添加停滞期和改图期状态的 getter 方法
  • 添加 cancelStagnation() 方法
  • 添加 cancelModification() 方法(备用)
  • 添加 getReasonText() 方法

关键代码

// 停滞期状态
get isStalled(): boolean {
  const data = this.project?.get('data') || {};
  return data.isStalled === true;
}

// 改图期状态
get isModification(): boolean {
  const data = this.project?.get('data') || {};
  return data.isModification === true;
}

// 取消停滞期
async cancelStagnation() {
  const data = this.project.get('data') || {};
  data.isStalled = false;
  data.stagnationReasonType = undefined;
  data.stagnationCustomReason = undefined;
  // ... 清除其他字段
  await this.project.save();
}

2. project-detail.component.html

修改内容

  • 在页面底部添加状态标记容器
  • 添加停滞期标记(可点击)
  • 添加改图期标记(显示提示)

关键代码

<!-- 停滞期和改图期状态标记(右下角) -->
<div class="project-status-badges">
  <!-- 停滞期标记 -->
  @if (isStalled) {
    <div class="status-badge stalled" (click)="cancelStagnation()">
      <div class="badge-icon">⏸️</div>
      <div class="badge-content">
        <div class="badge-title">停滞期</div>
        <div class="badge-reason">{{ getReasonText('stagnation') }}</div>
      </div>
      <div class="badge-action">
        <svg class="icon">...</svg>
      </div>
    </div>
  }
  
  <!-- 改图期标记 -->
  @if (isModification) {
    <div class="status-badge modification">
      <div class="badge-icon">🎨</div>
      <div class="badge-content">
        <div class="badge-title">改图期</div>
        <div class="badge-reason">{{ getReasonText('modification') }}</div>
      </div>
      <div class="badge-tip">上传图片后自动取消</div>
    </div>
  }
</div>

3. project-detail.component.scss

修改内容

  • 添加状态标记容器样式
  • 添加停滞期和改图期的样式
  • 添加动画效果和响应式设计

样式特点

  • 位置position: fixed; bottom: 80px; right: 16px;
  • 动画:从右侧滑入(slideInRight
  • 悬停效果:向左移动4px,阴影加深
  • 颜色区分
    • 停滞期:紫色边框(#8b5cf6)、紫色渐变背景
    • 改图期:橙色边框(#f59e0b)、黄色渐变背景
  • 响应式:小屏幕下自动调整大小和位置

4. stage-delivery.component.ts

修改内容

  • onFileUploaded() 方法中添加自动取消改图期的逻辑

关键代码

async onFileUploaded(event: { productId: string, deliveryType: string, fileCount: number }) {
  if (event.fileCount > 0 && this.project) {
    const projectData = this.project.get('data') || {};
    
    // 🆕 检查是否处于改图期,如果是则自动取消改图期标记
    if (projectData.isModification === true) {
      console.log('🎨 [改图期] 检测到项目处于改图期,上传文件后自动取消改图期标记');
      
      // 清除改图期相关字段
      projectData.isModification = false;
      projectData.modificationReasonType = undefined;
      projectData.modificationCustomReason = undefined;
      
      console.log('✅ [改图期] 改图期标记已自动取消');
    }
    
    this.project.set('data', projectData);
    // ...
  }
}

🗄️ 数据库字段

Project 表的 data 字段

停滞期相关字段

{
  isStalled: boolean,                    // 是否处于停滞期
  stagnationReasonType: 'designer' | 'customer' | 'custom',  // 停滞原因类型
  stagnationCustomReason: string,        // 自定义停滞原因
  estimatedResumeDate: Date,             // 预计恢复时间
  reasonNotes: string,                   // 备注说明
  markedAt: Date,                        // 标记时间
  markedBy: string                       // 标记人
}

改图期相关字段

{
  isModification: boolean,               // 是否处于改图期
  modificationReasonType: 'designer' | 'customer' | 'custom',  // 改图原因类型
  modificationCustomReason: string,      // 自定义改图原因
  reasonNotes: string,                   // 备注说明
  markedAt: Date,                        // 标记时间
  markedBy: string                       // 标记人
}

🎨 UI 效果

停滞期标记

┌──────────────────────────────────┐
│ ⏸️  停滞期              ❌      │
│     客户原因                     │
│     张三 标记                    │
└──────────────────────────────────┘
  ↑紫色边框,可点击取消

改图期标记

┌──────────────────────────────────┐
│ 🎨  改图期                       │
│     客户要求改图                 │
│     李四 标记                    │
│     上传图片后自动取消           │
└──────────────────────────────────┘
  ↑橙色边框,显示提示

🔄 工作流程

停滞期流程

  1. 组长标记:在组长端 Dashboard 标记项目为停滞期
  2. 数据保存:停滞期信息保存到 Project.data.isStalled 等字段
  3. 组员查看:组员进入项目详情页,右下角显示停滞期标记
  4. 手动取消:组员点击停滞期标记,确认后取消停滞期状态
  5. 数据更新isStalled 设为 false,清除相关字段

改图期流程

  1. 组长标记:在组长端 Dashboard 标记项目为改图期
  2. 数据保存:改图期信息保存到 Project.data.isModification 等字段
  3. 组员查看:组员进入项目详情页,右下角显示改图期标记
  4. 上传图片:组员在交付执行阶段上传新图片
  5. 自动取消:系统检测到文件上传,自动清除改图期标记
  6. 数据更新isModification 设为 false,清除相关字段

📊 自动取消改图期的触发时机

改图期标记会在以下情况下自动取消

  1. 白模阶段上传:上传白模文件并确认
  2. 软装阶段上传:上传软装文件并确认
  3. 渲染阶段上传:上传渲染文件并确认
  4. 后期阶段上传:上传后期文件并确认

实现位置stage-delivery.component.tsonFileUploaded() 方法

🎯 用户体验优化

1. 视觉反馈

  • 滑入动画:标记从右侧滑入,流畅自然
  • 悬停效果:鼠标悬停时向左移动,提示可交互
  • 点击效果:点击时轻微缩放,增强反馈感

2. 颜色区分

  • 停滞期:紫色系(#8b5cf6),表示暂停状态
  • 改图期:橙色系(#f59e0b),表示修改进行中

3. 响应式设计

  • 桌面端:右下角固定位置,最大宽度 280px
  • 移动端:自动缩小,适应小屏幕(≤768px)

4. 提示文本

  • 停滞期:显示原因和标记人,点击图标可取消
  • 改图期:显示原因和标记人,提示"上传图片后自动取消"

🐛 测试建议

测试场景

  1. ✅ 测试停滞期标记显示
  2. ✅ 测试停滞期标记点击取消
  3. ✅ 测试改图期标记显示
  4. ✅ 测试改图期上传图片后自动取消
  5. ✅ 测试小屏幕响应式显示
  6. ✅ 测试多个标记同时显示(停滞期+改图期)

测试步骤

停滞期测试

  1. 在组长端标记项目为停滞期
  2. 组员端进入项目详情页
  3. 检查右下角是否显示停滞期标记
  4. 点击停滞期标记
  5. 确认是否成功取消

改图期测试

  1. 在组长端标记项目为改图期
  2. 组员端进入项目详情页
  3. 检查右下角是否显示改图期标记
  4. 在交付执行阶段上传图片
  5. 检查改图期标记是否自动消失

📝 注意事项

  1. 权限控制:只有有编辑权限的用户才能取消停滞期
  2. 数据保留:取消停滞期/改图期时,保留历史记录字段
  3. 防抖处理:文件上传后有1.5秒防抖,避免频繁刷新
  4. 错误处理:所有操作都有 try-catch 包裹,确保不影响主流程
  5. 数据库保存:所有标记和取消操作都会立即保存到 Parse 数据库的 Project.data 字段中

🔧 数据库持久化修复(2024-12-07)

问题描述

之前的实现中存在数据未保存到数据库的问题:

  1. 组长端updateProjectMarkStatus 只更新内存数组,没有调用 project.save()
  2. 组员端:上传文件取消改图期时,依赖 notifyTeamLeaderForApproval 保存,如果通知失败则不会保存

修复方案

1. 组长端修复

文件src/app/pages/team-leader/dashboard/dashboard.ts

修改内容

  • updateProjectMarkStatus 改为异步方法
  • 添加 Parse 数据库查询和保存逻辑
  • 更新项目的 data 字段并调用 save()
  • onStagnationReasonConfirm 改为异步方法,添加错误处理
  • markEventAsStagnantmarkEventAsModification 改为异步方法

关键代码

private async updateProjectMarkStatus(projectId: string, type: 'stagnation' | 'modification', reason: any): Promise<void> {
  // 更新内存中的项目数据
  this.projects = this.projects.map(project => { ... });
  
  // 🆕 保存到Parse数据库
  const Parse = (window as any).Parse;
  const query = new Parse.Query('Project');
  const project = await query.get(projectId);
  
  const projectData = project.get('data') || {};
  // 设置停滞期/改图期相关字段
  projectData.isStalled = true; // 或 isModification
  // ... 其他字段
  
  project.set('data', projectData);
  await project.save();
  
  console.log(`✅ [数据库] 标记已保存到数据库`, projectId);
}

2. 组员端修复

文件src/modules/project/pages/project-detail/stages/stage-delivery.component.ts

修改内容

  • onFileUploaded 方法中,如果取消了改图期,立即调用 this.project.save()
  • 不依赖 notifyTeamLeaderForApproval 的保存
  • 添加独立的错误处理

关键代码

async onFileUploaded(event: { productId: string, deliveryType: string, fileCount: number }) {
  const projectData = this.project.get('data') || {};
  
  // 检查是否处于改图期
  let modificationCancelled = false;
  if (projectData.isModification === true) {
    projectData.isModification = false;
    projectData.modificationReasonType = undefined;
    projectData.modificationCustomReason = undefined;
    modificationCancelled = true;
  }
  
  this.project.set('data', projectData);
  
  // 🆕 立即保存到数据库
  if (modificationCancelled) {
    try {
      await this.project.save();
      console.log('✅ [改图期] 改图期标记已保存到数据库');
    } catch (saveError) {
      console.error('❌ [改图期] 保存改图期取消失败:', saveError);
    }
  }
  
  await this.notifyTeamLeaderForApproval(event.fileCount, event.deliveryType);
}

修复验证

  1. ✅ 组长端标记停滞期/改图期后,刷新页面仍能看到标记
  2. ✅ 组员端上传文件后,改图期标记自动消失且刷新后不再显示
  3. ✅ 所有操作都有日志输出,便于调试
  4. ✅ 错误处理完善,不会因保存失败而中断主流程

🚀 未来优化建议

  1. 历史记录:记录所有停滞期/改图期的标记和取消历史
  2. 统计分析:统计项目停滞时长、改图次数等数据
  3. 通知提醒:停滞期超过一定天数自动提醒
  4. 批量操作:支持批量取消多个项目的停滞期标记

📖 相关文档

  • 组长端停滞期标记功能:参考组长端 Dashboard 实现
  • 项目数据模型:src/app/models/project.model.ts
  • 停滞期判断逻辑:src/app/pages/team-leader/services/designer-workload.service.ts
  • 紧急事件生成:src/app/pages/team-leader/services/urgent-event.service.ts

实现日期:2024年12月 实现人员:AI Assistant 功能状态:✅ 已完成并可用