STAGE_NAVIGATION_COMPLETE.md 11 KB

项目阶段导航 - 完成总结

✅ 所有问题已解决

1️⃣ TypeScript错误已修复

文件scripts/repair-project-stages.ts

// 修复前
id: project.id,  // ❌ Type 'string | undefined'

// 修复后
id: project.id || 'unknown',  // ✅ Type 'string'

2️⃣ 从项目列表进入时路由正确加载

文件project-detail.component.ts 第462-494行

逻辑

// 1. 获取项目当前阶段
const projectStage = this.project.get('currentStage'); // 例如:"确认需求"

// 2. 映射到路由ID
const stageMap = {
  '订单分配': 'order',
  '确认需求': 'requirements',
  '交付执行': 'delivery',
  '售后归档': 'aftercare'
  // ... 其他阶段映射
};

const targetStage = stageMap[projectStage] || 'order';

// 3. 自动导航到对应阶段
this.router.navigate([targetStage], { 
  relativeTo: this.route, 
  replaceUrl: true 
});

效果

项目列表 → 点击项目(currentStage = "确认需求")
    ↓
自动跳转到:/wxwork/{cid}/project/{projectId}/requirements
    ↓
导航栏显示:
  ✓ 订单分配(绿色 - 已完成)
  ● 确认需求(红色 - 当前)
  ○ 交付执行(灰色 - 未开始)
  ○ 售后归档(灰色 - 未开始)

3️⃣ 导航栏状态显示正确

文件project-detail.component.ts 第544-592行

逻辑getStageStatus() 方法基于 project.currentStage 计算状态

getStageStatus(stageId: string): 'completed' | 'active' | 'pending' {
  const workflowCurrent = this.project?.get('currentStage'); // 项目实际阶段
  
  // 映射中文阶段名到英文ID
  const stageNameToId = {
    '订单分配': 'order',
    '确认需求': 'requirements',
    '交付执行': 'delivery',
    '售后归档': 'aftercare'
  };
  
  const currentIdx = stageOrder.indexOf(workflowCurrent);
  const idx = stageOrder.indexOf(stageId);
  
  if (idx < currentIdx) return 'completed';  // 已完成(绿色)
  if (idx === currentIdx) return 'active';   // 当前(红色)
  return 'pending';                          // 未开始(灰色)
}

状态显示: | 状态 | 颜色 | 图标 | 说明 | |------|------|------|------| | completed | 🟢 绿色 | ✓ | 已完成该阶段 | | active | 🔴 红色 | ● | 项目当前阶段 | | pending | ⚪ 灰色 | ○ | 尚未开始 |


4️⃣ 可以点击导航栏查看所有阶段

文件project-detail.component.ts 第503-542行

新逻辑:允许查看所有阶段(包括未开始的)

switchStage(stageId: string) {
  // ✅ 允许查看所有阶段(包括未开始的)
  const status = this.getStageStatus(stageId);
  
  // ⚠️ 如果查看未开始的阶段,给予友好提示
  if (status === 'pending') {
    console.warn('⚠️ 正在查看未开始的阶段');
    console.warn('💡 提示: 这是查看模式,项目实际阶段不会改变');
  }
  
  // 更新本地视图状态(仅影响显示,不影响项目实际阶段)
  this.currentStage = stageId;
  
  // 导航到指定阶段(查看模式)
  this.router.navigate([stageId], { relativeTo: this.route });
}

文件project-detail.component.html 第4-11行

<!-- 允许点击所有阶段 -->
<div class="stage-item"
  [class.clickable]="true"
  (click)="switchStage(stage.id)">

文件project-detail.component.scss 第204-227行

// 待开始状态(灰色,可点击查看)
&.pending {
  opacity: 0.7; // 半透明提示这是预览模式
  
  &:hover {
    opacity: 1; // 悬停时变清晰
    transform: translateY(-1px);
  }
}

5️⃣ 点击导航栏不会改变项目实际阶段

关键点

  • ❌ 点击导航栏不会修改 project.currentStage
  • ✅ 只改变路由和本地视图状态 this.currentStage
  • project.currentStage 只能通过提交按钮来改变

对比

操作 改变路由 改变 this.currentStage 改变 project.currentStage
点击导航栏 ✅ 是 ✅ 是 ❌ 否
点击"确认订单"按钮 ✅ 是 ✅ 是 ✅ 是

6️⃣ 必须完成必填项才能推进到下一阶段

订单分配阶段 - stage-order.component.ts 第1192-1331行

async submitForOrder() {
  // 1️⃣ 验证必填项
  if (!this.projectInfo.title.trim()) {
    alert('请填写项目名称');
    return;  // ❌ 验证失败,不推进
  }
  if (!this.projectInfo.projectType) {
    alert('请选择项目类型');
    return;
  }
  if (!this.projectInfo.demoday) {
    alert('请选择小图日期');
    return;
  }
  if (this.quotation.total === 0) {
    alert('请配置报价明细');
    return;
  }
  
  // 2️⃣ 检查设计师分配
  const assignedTeams = await query.find();
  const hasAssignedDesigners = assignedTeams.length > 0;
  
  // 3️⃣ 推进到下一阶段
  if (hasAssignedDesigners) {
    this.project.set('currentStage', '确认需求');  // ✅ 改变实际阶段
    await this.project.save();
    
    // 派发事件,触发自动跳转
    document.dispatchEvent(new CustomEvent('stage:completed', {
      detail: { stage: 'order', nextStage: 'requirements' }
    }));
  }
}

确认需求阶段 - stage-requirements.component.ts

async saveDeliverables() {
  // 保存需求数据
  await this.project.save();
  
  // 推进到交付执行
  this.project.set('currentStage', '交付执行');
  await this.project.save();
  
  // 派发事件
  document.dispatchEvent(new CustomEvent('stage:completed', {
    detail: { stage: 'requirements', nextStage: 'delivery' }
  }));
}

交付执行阶段 - stage-delivery.component.ts

async approveDelivery() {
  // 检查所有子阶段是否完成
  if (allStagesApproved) {
    this.project.set('currentStage', '售后归档');
    await this.project.save();
    
    // 派发事件
    document.dispatchEvent(new CustomEvent('stage:completed', {
      detail: { stage: 'delivery', nextStage: 'aftercare' }
    }));
  }
}

📊 完整流程图

查看模式(点击导航栏)

用户点击导航栏"交付执行"
    ↓
switchStage('delivery')
    ↓
检查状态:getStageStatus('delivery') = 'pending'
    ↓
控制台提示:
  ⚠️ 正在查看未开始的阶段: 交付执行
  💡 这是查看模式,项目实际阶段不会改变
    ↓
更新本地视图:this.currentStage = 'delivery'
    ↓
路由跳转:/project/{id}/delivery
    ↓
显示交付执行页面(可能为空或提示)
    ↓
导航栏状态保持不变:
  ✓ 订单分配(绿色)
  ● 确认需求(红色 - 实际当前阶段)
  ○ 交付执行(灰色 - 查看中)
  ○ 售后归档(灰色)

推进模式(点击提交按钮)

用户在订单分配阶段
    ↓
填写所有必填项:
  ✓ 项目名称
  ✓ 项目类型
  ✓ 小图日期
  ✓ 报价明细
  ✓ 分配设计师
    ↓
点击"确认订单"按钮
    ↓
submitForOrder()
    ↓
验证所有必填项
    ├─ 失败 → 弹出提示,停止推进
    └─ 成功 → 继续
    ↓
保存项目数据
    ↓
更新实际阶段:project.currentStage = '确认需求'  ✅ 关键
    ↓
保存到数据库
    ↓
派发事件:stage:completed
    ↓
advanceToNextStage() 监听到事件
    ↓
路由跳转:/project/{id}/requirements
    ↓
导航栏更新:
  ✓ 订单分配(绿色 - 已完成)
  ● 确认需求(红色 - 新的当前阶段)
  ○ 交付执行(灰色 - 未开始)
  ○ 售后归档(灰色 - 未开始)

🔍 验证方法

测试1:从项目列表进入

  1. 打开项目列表
  2. 点击一个项目(假设 currentStage = '确认需求'
  3. 预期结果
    • ✅ 自动跳转到 /project/{id}/requirements
    • ✅ 导航栏显示:订单分配(绿色✓)、确认需求(红色●)、其他(灰色○)
    • ✅ 控制台显示:🎯 [项目详情] 目标路由阶段: requirements

测试2:点击导航栏查看

  1. 在确认需求阶段
  2. 点击导航栏"交付执行"(未开始)
  3. 预期结果
    • ✅ 路由跳转到 /project/{id}/delivery
    • ✅ 可以查看交付执行页面
    • ✅ 导航栏状态不变(确认需求仍然是红色)
    • ✅ 控制台提示:"⚠️ 正在查看未开始的阶段"

测试3:点击提交按钮推进

  1. 在订单分配阶段
  2. 填写所有必填项
  3. 点击"确认订单"
  4. 预期结果
    • ✅ 验证通过
    • project.currentStage 更新为"确认需求"
    • ✅ 自动跳转到确认需求页面
    • ✅ 导航栏更新:订单分配变绿色,确认需求变红色

测试4:验证失败阻止推进

  1. 在订单分配阶段
  2. 不填写项目名称
  3. 点击"确认订单"
  4. 预期结果
    • ✅ 弹出提示:"请填写项目名称"
    • ✅ 不跳转页面
    • project.currentStage 保持不变
    • ✅ 导航栏状态不变

📝 修改文件清单

文件 修改内容 状态
scripts/repair-project-stages.ts 修复TypeScript错误 ✅ 完成
project-detail.component.ts 修改 switchStage 方法,允许查看所有阶段 ✅ 完成
project-detail.component.html 移除禁用逻辑,允许点击所有阶段 ✅ 完成
project-detail.component.scss 调整pending状态样式 ✅ 完成
stage-order.component.ts 已有正确的验证和推进逻辑 ✅ 无需修改
stage-requirements.component.ts 已有正确的验证和推进逻辑 ✅ 无需修改
stage-delivery.component.ts 已有正确的验证和推进逻辑 ✅ 无需修改

🎉 功能总结

✅ 已实现

  1. 从项目列表进入时路由正确

    • 根据 project.currentStage 自动跳转到对应阶段
    • 导航栏状态正确显示
  2. 可以点击导航栏查看所有阶段

    • 包括未开始的阶段
    • 控制台给予友好提示
    • 半透明样式提示这是查看模式
  3. 点击导航栏不改变项目阶段

    • 只改变路由和视图
    • project.currentStage 保持不变
  4. 必须完成必填项才能推进

    • 每个阶段都有验证逻辑
    • 验证失败会弹出提示
    • 验证通过才更新 project.currentStage

🔑 核心要点

  1. 两个独立的状态

    • project.currentStage:项目实际阶段(存储在数据库)
    • this.currentStage:当前查看阶段(仅影响前端显示)
  2. 查看 ≠ 推进

    • 点击导航栏 = 查看
    • 点击提交按钮 = 推进
  3. 状态显示基于实际阶段

    • 导航栏颜色基于 project.currentStage
    • 不受当前查看的阶段影响
  4. 验证是必须的

    • 每个阶段都有必填项
    • 验证通过才能推进
    • 控制台会详细记录日志

📚 相关文档

  1. STAGE_NAVIGATION_LOGIC.md - 详细的逻辑说明
  2. STAGE_SWITCH_VALIDATION_FIXED.md - 验证逻辑修复记录
  3. DATA_REPAIR_STAGE_ROLLBACK.md - 数据修复方案
  4. REPAIR_STAGES_QUICK_GUIDE.md - 数据修复快速指南

🎯 下一步

所有功能已完成!您现在可以:

  1. 测试阶段导航:从项目列表进入,点击导航栏查看不同阶段
  2. 测试阶段推进:填写必填项,点击提交按钮推进阶段
  3. 运行数据修复(如需要):使用 repair-project-stages-browser.js 脚本

祝您使用愉快! 🚀