import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { Project } from '../../interfaces'; @Component({ selector: 'app-project-kanban', standalone: true, imports: [CommonModule, FormsModule], templateUrl: './project-kanban.component.html', styleUrls: ['./project-kanban.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class ProjectKanbanComponent { @Input() corePhases: any[] = []; @Input() projects: Project[] = []; // Outputs for actions that need to be handled by the parent @Output() viewProject = new EventEmitter<{projectId: string, phaseId: string}>(); @Output() openSmartMatch = new EventEmitter(); @Output() assignProject = new EventEmitter(); // projectId @Output() reviewProject = new EventEmitter<{projectId: string, rating: 'excellent' | 'qualified' | 'unqualified'}>(); @Output() markStalled = new EventEmitter(); // 🆕 标记停滞 @Output() markModification = new EventEmitter(); // 🆕 标记改图 @Output() cancelStalled = new EventEmitter(); // 🆕 取消停滞 @Output() cancelModification = new EventEmitter(); // 🆕 取消改图 getProjectCountByCorePhase(coreId: string): number { return this.getProjectsByCorePhase(coreId).length; } getProjectsByCorePhase(coreId: string): Project[] { if (!this.projects) { console.log(`📋 [看板-${coreId}] projects 输入为空`); return []; } console.log(`📋 [看板-${coreId}] 开始筛选,输入项目数: ${this.projects.length}`); const result = this.projects.filter(p => { // 🆕 优先判断是否被标记为停滞或改图 if (coreId === 'stalled') { const match = p.isStalled === true; if (match) { console.log(`📋 [看板-停滞期] 匹配项目: ${p.name}, isStalled=${p.isStalled}`); } return match; } if (coreId === 'modification') { const match = p.isModification === true; if (match) { console.log(`📋 [看板-改图期] 匹配项目: ${p.name}, isModification=${p.isModification}`); } return match; } // 如果被标记为停滞或改图,不应该出现在其他常规列中 if (p.isStalled || p.isModification) { return false; } // 否则,根据 currentStage 映射到常规核心阶段 return this.mapStageToCorePhase(p.currentStage) === coreId; }); console.log(`📋 [看板-${coreId}] 筛选结果: ${result.length} 个项目`); if (coreId === 'stalled' || coreId === 'modification') { result.forEach((p, i) => { console.log(` ${i + 1}. ${p.name} (isStalled=${p.isStalled}, isModification=${p.isModification})`); }); } return result; } private mapStageToCorePhase(stageId: string): 'order' | 'requirements' | 'delivery' | 'aftercare' { if (!stageId) return 'order'; const normalizedStage = stageId.trim().toLowerCase(); // 1. 订单分配阶段 if (normalizedStage === 'order' || normalizedStage === 'pendingapproval' || normalizedStage === 'pendingassignment' || normalizedStage === '订单分配' || normalizedStage === '待审批' || normalizedStage === '待分配') { return 'order'; } // 2. 确认需求阶段 if (normalizedStage === 'requirements' || normalizedStage === 'requirement' || normalizedStage === 'planning' || normalizedStage === '确认需求' || normalizedStage === '需求沟通' || normalizedStage === '方案规划') { return 'requirements'; } // 3. 交付执行阶段 if (normalizedStage === 'delivery' || normalizedStage === 'modeling' || normalizedStage === 'rendering' || normalizedStage === 'postproduction' || normalizedStage === 'review' || normalizedStage === 'revision' || normalizedStage === '交付执行' || normalizedStage === '建模' || normalizedStage === '建模阶段' || normalizedStage === '渲染' || normalizedStage === '渲染阶段' || normalizedStage === '后期制作' || normalizedStage === '评审' || normalizedStage === '修改' || normalizedStage === '修订' || normalizedStage === '白模' || normalizedStage === '软装' || normalizedStage === '后期') { return 'delivery'; } // 4. 售后归档阶段 if (normalizedStage === 'aftercare' || normalizedStage === 'completed' || normalizedStage === 'archived' || normalizedStage === '售后归档' || normalizedStage === '售后' || normalizedStage === '归档' || normalizedStage === '已完成' || normalizedStage === '已交付') { return 'aftercare'; } return 'delivery'; } isPendingApproval(project: Project): boolean { return project.currentStage === 'pendingApproval' || (project.currentStage === 'review' && project.status === 'warning'); } getUrgencyLabel(urgency: string): string { const labels: Record = { 'high': '高', 'medium': '中', 'low': '低' }; return labels[urgency] || '无'; } onViewProject(projectId: string, phaseId: string, event?: Event): void { if (event) { event.stopPropagation(); } this.viewProject.emit({ projectId, phaseId }); } onOpenSmartMatch(project: Project, event?: Event): void { if (event) { event.stopPropagation(); } this.openSmartMatch.emit(project); } onAssignProject(projectId: string, event?: Event): void { if (event) { event.stopPropagation(); } this.assignProject.emit(projectId); } onReviewProject(projectId: string, rating: 'excellent' | 'qualified' | 'unqualified', event?: Event): void { if (event) { event.stopPropagation(); } this.reviewProject.emit({ projectId, rating }); } onMarkStalled(project: Project, event?: Event): void { if (event) { event.stopPropagation(); } this.markStalled.emit(project); } onMarkModification(project: Project, event?: Event): void { if (event) { event.stopPropagation(); } this.markModification.emit(project); } onCancelStalled(project: Project, event?: Event): void { if (event) { event.stopPropagation(); } if (confirm(`确定要取消项目【${project.name}】的停滞期状态吗?`)) { this.cancelStalled.emit(project); } } onCancelModification(project: Project, event?: Event): void { if (event) { event.stopPropagation(); } if (confirm(`确定要取消项目【${project.name}】的改图期状态吗?`)) { this.cancelModification.emit(project); } } }