文件:scripts/repair-project-stages.ts
// 修复前
id: project.id, // ❌ Type 'string | undefined'
// 修复后
id: project.id || 'unknown', // ✅ Type 'string'
文件: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
↓
导航栏显示:
✓ 订单分配(绿色 - 已完成)
● 确认需求(红色 - 当前)
○ 交付执行(灰色 - 未开始)
○ 售后归档(灰色 - 未开始)
文件: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 | ⚪ 灰色 | ○ | 尚未开始 |
文件: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);
}
}
关键点:
project.currentStagethis.currentStageproject.currentStage 只能通过提交按钮来改变对比:
| 操作 | 改变路由 | 改变 this.currentStage |
改变 project.currentStage |
|---|---|---|---|
| 点击导航栏 | ✅ 是 | ✅ 是 | ❌ 否 |
| 点击"确认订单"按钮 | ✅ 是 | ✅ 是 | ✅ 是 |
订单分配阶段 - 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
↓
导航栏更新:
✓ 订单分配(绿色 - 已完成)
● 确认需求(红色 - 新的当前阶段)
○ 交付执行(灰色 - 未开始)
○ 售后归档(灰色 - 未开始)
currentStage = '确认需求')/project/{id}/requirements🎯 [项目详情] 目标路由阶段: requirements/project/{id}/deliveryproject.currentStage 更新为"确认需求"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 |
已有正确的验证和推进逻辑 | ✅ 无需修改 |
从项目列表进入时路由正确
project.currentStage 自动跳转到对应阶段可以点击导航栏查看所有阶段
点击导航栏不改变项目阶段
project.currentStage 保持不变必须完成必填项才能推进
project.currentStage两个独立的状态
project.currentStage:项目实际阶段(存储在数据库)this.currentStage:当前查看阶段(仅影响前端显示)查看 ≠ 推进
状态显示基于实际阶段
project.currentStage验证是必须的
所有功能已完成!您现在可以:
repair-project-stages-browser.js 脚本祝您使用愉快! 🚀