import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router, RouterModule } from '@angular/router';
import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/core';
import { ProjectService } from '../../../services/project.service';

// 项目阶段定义
interface ProjectStage {
  id: string;
  name: string;
  order: number;
}

interface ProjectPhase {
  name: string;
  percentage: number;
  startPercentage: number;
  isCompleted: boolean;
  isCurrent: boolean;
}

interface Project {
  id: string;
  name: string;
  type: 'soft' | 'hard';
  memberType: 'vip' | 'normal';
  designerName: string;
  status: string;
  expectedEndDate: Date; // TODO: 兼容旧字段，后续可移除
  deadline: Date; // 真实截止时间字段
  createdAt?: Date; // 真实开始时间字段（可选）
  isOverdue: boolean;
  overdueDays: number;
  dueSoon: boolean;
  urgency: 'high' | 'medium' | 'low';
  phases: ProjectPhase[];
  currentStage: string; // 新增：当前项目阶段
  // 新增：质量评级
  qualityRating?: 'excellent' | 'qualified' | 'unqualified' | 'pending';
  lastCustomerFeedback?: string;
// 预构建的搜索索引，减少重复 toLowerCase 与拼接
  searchIndex?: string;
}

interface TodoTask {
  id: string;
  title: string;
  description: string;
  deadline: Date;
  priority: 'high' | 'medium' | 'low';
  type: 'review' | 'assign' | 'performance';
  targetId: string;
}

// 员工请假记录接口
interface LeaveRecord {
  id: string;
  employeeName: string;
  date: string; // YYYY-MM-DD 格式
  isLeave: boolean;
  leaveType?: 'sick' | 'personal' | 'annual' | 'other'; // 请假类型
  reason?: string; // 请假原因
}

// 员工详情面板数据接口
interface EmployeeDetail {
  name: string;
  currentProjects: number; // 当前负责项目数
  projectNames: string[]; // 项目名称列表（用于显示）
  leaveRecords: LeaveRecord[]; // 未来7天请假记录
  redMarkExplanation: string; // 红色标记说明
}

declare const echarts: any;
@Component({
  selector: 'app-dashboard',
  imports: [CommonModule, FormsModule, RouterModule],
  templateUrl: './dashboard.html',
  styleUrl: './dashboard.scss'
})

export class Dashboard implements OnInit, OnDestroy {
  projects: Project[] = [];
  filteredProjects: Project[] = [];
  todoTasks: TodoTask[] = [];
  overdueProjects: Project[] = [];
  urgentPinnedProjects: Project[] = [];
  showAlert: boolean = false;
  selectedProjectId: string = '';
  // 新增：关键词搜索
  searchTerm: string = '';
  searchSuggestions: Project[] = [];
  showSuggestions: boolean = false;
  private hideSuggestionsTimer: any;
  
  // 搜索性能与交互控制
  private searchDebounceTimer: any;
  private readonly SEARCH_DEBOUNCE_MS = 200; // 防抖时长（毫秒）
  private readonly MIN_SEARCH_LEN = 2; // 最小触发建议长度
  private readonly MAX_SUGGESTIONS = 8; // 建议最大条数
  private isSearchFocused: boolean = false; // 是否处于输入聚焦态
  // 新增：临期项目与筛选状态
  dueSoonProjects: Project[] = [];
  selectedType: 'all' | 'soft' | 'hard' = 'all';
  selectedUrgency: 'all' | 'high' | 'medium' | 'low' = 'all';
  selectedStatus: 'all' | 'progress' | 'completed' | 'overdue' | 'pendingApproval' | 'pendingAssignment' | 'dueSoon' = 'all';
  selectedDesigner: string = 'all';
  selectedMemberType: 'all' | 'vip' | 'normal' = 'all';
  // 新增：时间窗筛选
  selectedTimeWindow: 'all' | 'today' | 'threeDays' | 'sevenDays' = 'all';
  designers: string[] = [];
  // 新增：四大板块筛选
  selectedCorePhase: 'all' | 'order' | 'requirements' | 'delivery' | 'aftercare' = 'all';
  
  // 设计师画像（用于智能推荐）
  designerProfiles: any[] = [
    { id: 'zhang', name: '张三', skills: ['现代风格', '北欧风格'], workload: 95, avgRating: 4.5, experience: 3 },
    { id: 'li', name: '李四', skills: ['新中式', '宋式风格'], workload: 25, avgRating: 4.8, experience: 5 },
    { id: 'wang', name: '王五', skills: ['北欧风格', '日式风格'], workload: 75, avgRating: 4.2, experience: 2 },
    { id: 'zhao', name: '赵六', skills: ['现代风格', '轻奢风格'], workload: 15, avgRating: 4.6, experience: 4 },
    { id: 'sun', name: '孙七', skills: ['简约风格', '工业风格'], workload: 35, avgRating: 4.3, experience: 3 },
    { id: 'zhou', name: '周八', skills: ['欧式风格', '美式风格'], workload: 5, avgRating: 4.7, experience: 6 },
    { id: 'wu', name: '吴九', skills: ['地中海风格', '田园风格'], workload: 60, avgRating: 4.4, experience: 4 },
    { id: 'chen', name: '陈十', skills: ['现代简约', '新古典'], workload: 0, avgRating: 4.9, experience: 7 }
  ];

  // 10个项目阶段
  projectStages: ProjectStage[] = [
    { id: 'pendingApproval', name: '待确认', order: 1 },
    { id: 'pendingAssignment', name: '待分配', order: 2 },
    { id: 'requirement', name: '需求沟通', order: 3 },
    { id: 'planning', name: '方案规划', order: 4 },
    { id: 'modeling', name: '建模阶段', order: 5 },
    { id: 'rendering', name: '渲染阶段', order: 6 },
    { id: 'postProduction', name: '后期处理', order: 7 },
    { id: 'review', name: '方案评审', order: 8 },
    { id: 'revision', name: '方案修改', order: 9 },
    { id: 'delivery', name: '交付完成', order: 10 }
  ];

  // 5大核心阶段（聚合展示）
  corePhases: ProjectStage[] = [
    { id: 'order', name: '订单创建', order: 1 },        // 待确认、待分配
    { id: 'requirements', name: '确认需求', order: 2 },  // 需求沟通、方案规划
    { id: 'delivery', name: '交付执行', order: 3 },      // 建模、渲染、后期/评审/修改
    { id: 'aftercare', name: '售后', order: 4 }          // 交付完成 → 售后
  ];
  // 甘特视图开关与实例引用
  showGanttView: boolean = false;
  private ganttChart: any | null = null;
  @ViewChild('ganttChartRef', { static: false }) ganttChartRef!: ElementRef<HTMLDivElement>;
  // 新增：工作量概览图表引用与实例
  @ViewChild('workloadChartRef', { static: false }) workloadChartRef!: ElementRef<HTMLDivElement>;
  private workloadChart: any | null = null;
  workloadDimension: 'designer' | 'member' = 'designer';
  // 甘特时间尺度：仅周/月
  ganttScale: 'day' | 'week' | 'month' = 'week';
  // 新增：甘特模式（项目 / 设计师排班）
  ganttMode: 'project' | 'designer' = 'project';

  // 个人详情面板相关属性
  showEmployeeDetailPanel: boolean = false;
  selectedEmployeeDetail: EmployeeDetail | null = null;
  
  // 员工请假数据（模拟数据）
  private leaveRecords: LeaveRecord[] = [
    { id: '1', employeeName: '张三', date: '2024-01-20', isLeave: true, leaveType: 'personal', reason: '事假' },
    { id: '2', employeeName: '张三', date: '2024-01-21', isLeave: false },
    { id: '3', employeeName: '张三', date: '2024-01-22', isLeave: false },
    { id: '4', employeeName: '张三', date: '2024-01-23', isLeave: false },
    { id: '5', employeeName: '张三', date: '2024-01-24', isLeave: false },
    { id: '6', employeeName: '张三', date: '2024-01-25', isLeave: false },
    { id: '7', employeeName: '张三', date: '2024-01-26', isLeave: false },
    
    { id: '8', employeeName: '李四', date: '2024-01-20', isLeave: false },
    { id: '9', employeeName: '李四', date: '2024-01-21', isLeave: true, leaveType: 'sick', reason: '病假' },
    { id: '10', employeeName: '李四', date: '2024-01-22', isLeave: true, leaveType: 'sick', reason: '病假' },
    { id: '11', employeeName: '李四', date: '2024-01-23', isLeave: false },
    { id: '12', employeeName: '李四', date: '2024-01-24', isLeave: false },
    { id: '13', employeeName: '李四', date: '2024-01-25', isLeave: false },
    { id: '14', employeeName: '李四', date: '2024-01-26', isLeave: false },
    
    { id: '15', employeeName: '王五', date: '2024-01-20', isLeave: false },
    { id: '16', employeeName: '王五', date: '2024-01-21', isLeave: false },
    { id: '17', employeeName: '王五', date: '2024-01-22', isLeave: false },
    { id: '18', employeeName: '王五', date: '2024-01-23', isLeave: true, leaveType: 'annual', reason: '年假' },
    { id: '19', employeeName: '王五', date: '2024-01-24', isLeave: false },
    { id: '20', employeeName: '王五', date: '2024-01-25', isLeave: false },
    { id: '21', employeeName: '王五', date: '2024-01-26', isLeave: false },
    
    { id: '22', employeeName: '赵六', date: '2024-01-20', isLeave: false },
    { id: '23', employeeName: '赵六', date: '2024-01-21', isLeave: false },
    { id: '24', employeeName: '赵六', date: '2024-01-22', isLeave: false },
    { id: '25', employeeName: '赵六', date: '2024-01-23', isLeave: false },
    { id: '26', employeeName: '赵六', date: '2024-01-24', isLeave: false },
    { id: '27', employeeName: '赵六', date: '2024-01-25', isLeave: false },
    { id: '28', employeeName: '赵六', date: '2024-01-26', isLeave: false }
  ];
  constructor(private projectService: ProjectService, private router: Router) {}

  ngOnInit(): void {
    this.loadProjects();
    this.loadTodoTasks();
    // 首次微任务后尝试初始化一次，确保容器已渲染
    setTimeout(() => this.updateWorkloadChart(), 0);
  }

  loadProjects(): void {
    // 模拟数据加载 - 增强数据结构，添加currentStage
    this.projects = [
      {
        id: 'proj-001',
        name: '现代风格客厅设计',
        type: 'soft',
        memberType: 'vip',
        designerName: '张三',
        status: '进行中',
        expectedEndDate: new Date(2023, 9, 15),
        deadline: new Date(2023, 9, 15),
        isOverdue: true,
        overdueDays: 2,
        dueSoon: false,
        urgency: 'high',
        currentStage: 'rendering',
        phases: [
          { name: '建模', percentage: 15, startPercentage: 0, isCompleted: true, isCurrent: false },
          { name: '渲染', percentage: 20, startPercentage: 15, isCompleted: false, isCurrent: true },
          { name: '后期', percentage: 15, startPercentage: 35, isCompleted: false, isCurrent: false },
          { name: '交付', percentage: 50, startPercentage: 50, isCompleted: false, isCurrent: false }
        ]
      },
      {
        id: 'proj-002',
        name: '北欧风格卧室设计',
        type: 'soft',
        memberType: 'normal',
        designerName: '李四',
        status: '进行中',
        expectedEndDate: new Date(2023, 9, 20),
        deadline: new Date(2023, 9, 20),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'medium',
        currentStage: 'postProduction',
        phases: [
          { name: '建模', percentage: 15, startPercentage: 0, isCompleted: true, isCurrent: false },
          { name: '渲染', percentage: 20, startPercentage: 15, isCompleted: true, isCurrent: false },
          { name: '后期', percentage: 15, startPercentage: 35, isCompleted: false, isCurrent: true },
          { name: '交付', percentage: 50, startPercentage: 50, isCompleted: false, isCurrent: false }
        ]
      },
      {
        id: 'proj-003',
        name: '新中式餐厅设计',
        type: 'hard',
        memberType: 'normal',
        designerName: '王五',
        status: '进行中',
        expectedEndDate: new Date(2023, 9, 25),
        deadline: new Date(2023, 9, 25),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'low',
        currentStage: 'modeling',
        phases: [
          { name: '建模', percentage: 15, startPercentage: 0, isCompleted: false, isCurrent: true },
          { name: '渲染', percentage: 20, startPercentage: 15, isCompleted: false, isCurrent: false },
          { name: '后期', percentage: 15, startPercentage: 35, isCompleted: false, isCurrent: false },
          { name: '交付', percentage: 50, startPercentage: 50, isCompleted: false, isCurrent: false }
        ]
      },
      {
        id: 'proj-004',
        name: '工业风办公室设计',
        type: 'hard',
        memberType: 'normal',
        designerName: '赵六',
        status: '进行中',
        expectedEndDate: new Date(2023, 9, 10),
        deadline: new Date(2023, 9, 10),
        isOverdue: true,
        overdueDays: 7,
        dueSoon: false,
        urgency: 'high',
        currentStage: 'review',
        phases: [
          { name: '建模', percentage: 15, startPercentage: 0, isCompleted: true, isCurrent: false },
          { name: '渲染', percentage: 20, startPercentage: 15, isCompleted: true, isCurrent: false },
          { name: '后期', percentage: 15, startPercentage: 35, isCompleted: false, isCurrent: false },
          { name: '交付', percentage: 50, startPercentage: 50, isCompleted: false, isCurrent: false }
        ]
      },
      // 添加更多不同阶段的项目
      {
        id: 'proj-005',
        name: '现代简约厨房设计',
        type: 'soft',
        memberType: 'normal',
        designerName: '',
        status: '待分配',
        expectedEndDate: new Date(2023, 10, 5),
        deadline: new Date(2023, 10, 5),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'medium',
        currentStage: 'pendingAssignment',
        phases: []
      },
      {
        id: 'proj-006',
        name: '日式风格书房设计',
        type: 'hard',
        memberType: 'normal',
        designerName: '',
        status: '待确认',
        expectedEndDate: new Date(2023, 10, 10),
        deadline: new Date(2023, 10, 10),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'low',
        currentStage: 'pendingApproval',
        phases: []
      },
      {
        id: 'proj-007',
        name: '轻奢风格浴室设计',
        type: 'soft',
        memberType: 'normal',
        designerName: '钱七',
        status: '已完成',
        expectedEndDate: new Date(2023, 9, 5),
        deadline: new Date(2023, 9, 5),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'medium',
        currentStage: 'delivery',
        phases: []
      }
    ];

    // ===== 追加生成示例数据：保证总量达到100条 =====
    const stageIds = this.projectStages.map(s => s.id);
    const designers = ['张三','李四','王五','赵六','孙七','周八','吴九','陈十'];
    const statusMap: Record<string, string> = {
      pendingApproval: '待确认',
      pendingAssignment: '待分配',
      requirement: '进行中',
      planning: '进行中',
      modeling: '进行中',
      rendering: '进行中',
      postProduction: '进行中',
      review: '进行中',
      revision: '进行中',
      delivery: '已完成'
    };

    // 为有项目的设计师分配项目
    const busyDesigners = ['张三', '王五', '吴九']; // 高负荷设计师
    const moderateDesigners = ['孙七']; // 中等负荷设计师
    const idleDesigners = ['李四', '赵六', '周八', '陈十']; // 空闲设计师

    // 为忙碌的设计师分配更多项目
    for (let i = 8; i <= 30; i++) {
      const designerIndex = (i - 8) % busyDesigners.length;
      const designerName = busyDesigners[designerIndex];
      const stageIndex = (i - 1) % 7 + 3; // 主要在进行中的阶段
      const currentStage = stageIds[stageIndex];
      const type: 'soft' | 'hard' = i % 2 === 0 ? 'soft' : 'hard';
      const urgency: 'high' | 'medium' | 'low' = i % 4 === 0 ? 'high' : (i % 3 === 0 ? 'medium' : 'low');
      const isOverdue = i % 8 === 0;
      const overdueDays = isOverdue ? (i % 5) + 1 : 0;
      const status = statusMap[currentStage] || '进行中';
      const expectedEndDate = new Date();
      const daysOffset = isOverdue ? -(overdueDays + (i % 3)) : ((i % 15) + 5);
      expectedEndDate.setDate(expectedEndDate.getDate() + daysOffset);
      const daysToDeadline = Math.ceil((expectedEndDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
      const dueSoon = !isOverdue && daysToDeadline >= 0 && daysToDeadline <= 3;
      const memberType: 'vip' | 'normal' = i % 5 === 0 ? 'vip' : 'normal';

      this.projects.push({
        id: `proj-${String(i).padStart(3, '0')}`,
        name: `${designerName}负责的${type === 'soft' ? '软装' : '硬装'}项目 ${i}`,
        type,
        memberType,
        designerName,
        status,
        expectedEndDate,
        deadline: expectedEndDate,
        isOverdue,
        overdueDays,
        dueSoon,
        urgency,
        currentStage,
        phases: []
      });
    }

    // 为中等负荷设计师分配少量项目
    for (let i = 31; i <= 35; i++) {
      const designerName = moderateDesigners[0];
      const stageIndex = (i - 1) % 5 + 4; // 中间阶段
      const currentStage = stageIds[stageIndex];
      const type: 'soft' | 'hard' = i % 2 === 0 ? 'soft' : 'hard';
      const urgency: 'high' | 'medium' | 'low' = 'medium';
      const status = statusMap[currentStage] || '进行中';
      const expectedEndDate = new Date();
      expectedEndDate.setDate(expectedEndDate.getDate() + (i % 10) + 7);
      const memberType: 'vip' | 'normal' = 'normal';

      this.projects.push({
        id: `proj-${String(i).padStart(3, '0')}`,
        name: `${designerName}负责的${type === 'soft' ? '软装' : '硬装'}项目 ${i}`,
        type,
        memberType,
        designerName,
        status,
        expectedEndDate,
        deadline: expectedEndDate,
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency,
        currentStage,
        phases: []
      });
    }

    // 空闲设计师不分配项目，或只分配很少的已完成项目
    for (let i = 36; i <= 40; i++) {
      const designerIndex = (i - 36) % idleDesigners.length;
      const designerName = idleDesigners[designerIndex];
      const currentStage = 'delivery'; // 已完成的项目
      const type: 'soft' | 'hard' = i % 2 === 0 ? 'soft' : 'hard';
      const urgency: 'high' | 'medium' | 'low' = 'low';
      const status = '已完成';
      const expectedEndDate = new Date();
      expectedEndDate.setDate(expectedEndDate.getDate() - (i % 10) - 5); // 过去的日期
      const memberType: 'vip' | 'normal' = 'normal';

      this.projects.push({
        id: `proj-${String(i).padStart(3, '0')}`,
        name: `${designerName}已完成的${type === 'soft' ? '软装' : '硬装'}项目 ${i}`,
        type,
        memberType,
        designerName,
        status,
        expectedEndDate,
        deadline: expectedEndDate,
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency,
        currentStage,
        phases: []
      });
    }
    // ===== 示例数据生成结束 =====

    // 统一补齐真实时间字段（deadline/createdAt），以真实字段贯通筛选与甘特
    const DAY = 24 * 60 * 60 * 1000;
    this.projects = this.projects.map(p => {
      const deadline = p.deadline || p.expectedEndDate;
      const baseDays = p.type === 'hard' ? 30 : 14;
      const createdAt = p.createdAt || new Date(new Date(deadline).getTime() - baseDays * DAY);
      return { ...p, deadline, createdAt } as Project;
    });

    // 筛选超期与临期项目
    this.overdueProjects = this.projects.filter(project => project.isOverdue);
    this.dueSoonProjects = this.projects.filter(project => project.dueSoon && !project.isOverdue);
    this.filteredProjects = [...this.projects];

    // 供筛选用的设计师列表
    this.designers = Array.from(new Set(this.projects.map(p => p.designerName).filter(n => !!n)));

    // 显示超期提醒
    if (this.overdueProjects.length > 0) {
      this.showAlert = true;
    }
  }

  loadTodoTasks(): void {
    // 模拟待办任务数据
    this.todoTasks = [
      {
        id: 'todo-001',
        title: '待评审效果图',
        description: '现代风格客厅设计项目需要进行效果图评审',
        deadline: new Date(2023, 9, 18, 15, 0),
        priority: 'high',
        type: 'review',
        targetId: 'proj-001'
      },
      {
        id: 'todo-002',
        title: '待分配项目',
        description: '新中式厨房设计项目需要分配给合适的设计师',
        deadline: new Date(2023, 9, 19, 10, 0),
        priority: 'high',
        type: 'assign',
        targetId: 'proj-new'
      },
      {
        id: 'todo-003',
        title: '待确认绩效',
        description: '9月份团队绩效需要进行审核确认',
        deadline: new Date(2023, 9, 22, 18, 0),
        priority: 'medium',
        type: 'performance',
        targetId: 'sep-2023'
      },
      {
        id: 'todo-004',
        title: '待处理客户反馈',
        description: '北欧风格卧室设计项目有客户反馈需要处理',
        deadline: new Date(2023, 9, 20, 14, 0),
        priority: 'medium',
        type: 'review',
        targetId: 'proj-002'
      },
      {
        id: 'todo-005',
        title: '团队会议',
        description: '每周团队进度沟通会议',
        deadline: new Date(2023, 9, 18, 10, 0),
        priority: 'low',
        type: 'performance',
        targetId: 'weekly-meeting'
      }
    ];

    // 按优先级排序：紧急且重要 > 重要不紧急 > 紧急不重要
    this.todoTasks.sort((a, b) => {
      const priorityOrder = {
        'high': 3,
        'medium': 2,
        'low': 1
      };
      return priorityOrder[b.priority] - priorityOrder[a.priority];
    });
  }

  // 筛选项目类型
  filterProjects(event: Event): void {
    const target = event.target as HTMLSelectElement;
    this.selectedType = (target && target.value ? target.value : 'all') as any;
    this.applyFilters();
  }

  // 筛选紧急程度
  filterByUrgency(event: Event): void {
    const target = event.target as HTMLSelectElement;
    this.selectedUrgency = (target && target.value ? target.value : 'all') as any;
    this.applyFilters();
  }

  // 筛选项目状态
  filterByStatus(status: string): void {
    // 点击同一状态时，切换回“全部”，以便恢复全量项目列表
    const next = (this.selectedStatus === status) ? 'all' : (status && status.length ? status : 'all');
    this.selectedStatus = next as any;
    this.applyFilters();
  }
  
  // 处理状态筛选下拉框变化
  onStatusChange(event: Event): void {
    const target = event.target as HTMLSelectElement;
    this.selectedStatus = (target && target.value ? target.value : 'all') as any;
    this.applyFilters();
  }

  // 新增：设计师筛选下拉事件处理
  onDesignerChange(event: Event): void {
    const target = event.target as HTMLSelectElement;
    this.selectedDesigner = (target && target.value ? target.value : 'all');
    this.applyFilters();
  }

  // 新增：会员类型筛选下拉事件处理
  onMemberTypeChange(event: Event): void {
    const select = event.target as HTMLSelectElement;
    this.selectedMemberType = select.value as any;
    this.applyFilters();
  }

  // 新增：四大板块改变
  onCorePhaseChange(event: Event): void {
    const select = event.target as HTMLSelectElement;
    this.selectedCorePhase = select.value as any;
    this.applyFilters();
  }

  // 时间窗快捷筛选（供UI按钮触发）
  filterByTimeWindow(timeWindow: 'all' | 'today' | 'threeDays' | 'sevenDays'): void {
    this.selectedTimeWindow = timeWindow;
    this.applyFilters();
  }

  // 新增：搜索输入变化
  onSearchChange(): void {
    if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer);
    this.searchDebounceTimer = setTimeout(() => {
      this.updateSearchSuggestions();
      this.applyFilters();
    }, this.SEARCH_DEBOUNCE_MS);
  }

  // 新增：搜索框聚焦/失焦控制建议显隐
  onSearchFocus(): void {
    if (this.hideSuggestionsTimer) clearTimeout(this.hideSuggestionsTimer);
    this.isSearchFocused = true;
    this.updateSearchSuggestions();
  }
  onSearchBlur(): void {
    // 延迟隐藏以允许选择项的 mousedown 触发
    this.isSearchFocused = false;
    this.hideSuggestionsTimer = setTimeout(() => {
      this.showSuggestions = false;
    }, 150);
  }

  // 新增：更新搜索建议（不叠加其它筛选，仅基于关键字）
  private updateSearchSuggestions(): void {
    const q = (this.searchTerm || '').trim().toLowerCase();
    if (q.length < this.MIN_SEARCH_LEN) {
      this.searchSuggestions = [];
      this.showSuggestions = false;
      return;
    }

    const scored = this.projects
      .filter(p => (p.searchIndex || `${(p.name || '')}|${(p.designerName || '')}`.toLowerCase()).includes(q))
      .map(p => {
        const dl = p.deadline || p.expectedEndDate;
        const dlTime = dl ? new Date(dl).getTime() : NaN;
        const daysToDl = Math.ceil(((isNaN(dlTime) ? 0 : dlTime) - Date.now()) / (1000 * 60 * 60 * 24));
        const urgencyScore = p.urgency === 'high' ? 3 : p.urgency === 'medium' ? 2 : 1;
        const overdueScore = p.isOverdue ? 10 : 0;
        const score = overdueScore + (4 - urgencyScore) * 2 - (isNaN(daysToDl) ? 0 : daysToDl);
        return { p, score };
      })
      .sort((a, b) => b.score - a.score)
      .slice(0, this.MAX_SUGGESTIONS)
      .map(x => x.p);

    this.searchSuggestions = scored;
    this.showSuggestions = this.isSearchFocused && this.searchSuggestions.length > 0;
  }

  // 新增：选择建议项
  selectSuggestion(project: Project): void {
    this.searchTerm = project.name;
    this.showSuggestions = false;
    this.viewProjectDetails(project.id);
  }

  // 统一筛选
  private applyFilters(): void {
    let result = [...this.projects];

    // 新增：关键词搜索（项目名 / 设计师名 / 含风格关键词的项目名）
    const q = (this.searchTerm || '').trim().toLowerCase();
    if (q) {
      result = result.filter(p => (p.searchIndex || `${(p.name || '')}|${(p.designerName || '')}`.toLowerCase()).includes(q));
    }

    // 类型筛选
    if (this.selectedType !== 'all') {
      result = result.filter(p => p.type === this.selectedType);
    }

    // 紧急程度筛选
    if (this.selectedUrgency !== 'all') {
      result = result.filter(p => p.urgency === this.selectedUrgency);
    }

    // 项目状态筛选
    if (this.selectedStatus !== 'all') {
      if (this.selectedStatus === 'overdue') {
        result = result.filter(p => p.isOverdue);
      } else if (this.selectedStatus === 'dueSoon') {
        result = result.filter(p => p.dueSoon && !p.isOverdue);
      } else if (this.selectedStatus === 'pendingApproval') {
        result = result.filter(p => p.currentStage === 'pendingApproval');
      } else if (this.selectedStatus === 'pendingAssignment') {
        result = result.filter(p => p.currentStage === 'pendingAssignment');
      } else if (this.selectedStatus === 'progress') {
        const progressStages = ['requirement','planning','modeling','rendering','postProduction','review','revision'];
        result = result.filter(p => progressStages.includes(p.currentStage));
      } else if (this.selectedStatus === 'completed') {
        result = result.filter(p => p.currentStage === 'delivery');
      }
    }

    // 新增：四大板块筛选
    if (this.selectedCorePhase !== 'all') {
      result = result.filter(p => this.mapStageToCorePhase(p.currentStage) === this.selectedCorePhase);
    }

    // 设计师筛选
    if (this.selectedDesigner !== 'all') {
      result = result.filter(p => p.designerName === this.selectedDesigner);
    }

    // 会员类型筛选
    if (this.selectedMemberType !== 'all') {
      result = result.filter(p => p.memberType === this.selectedMemberType);
    }

    // 新增：时间窗筛选
    if (this.selectedTimeWindow !== 'all') {
      const now = new Date();
      const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
      
      result = result.filter(p => {
        const projectDeadline = new Date(p.deadline);
        const timeDiff = projectDeadline.getTime() - today.getTime();
        const daysDiff = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
        
        switch (this.selectedTimeWindow) {
          case 'today':
            return daysDiff <= 1 && daysDiff >= 0;
          case 'threeDays':
            return daysDiff <= 3 && daysDiff >= 0;
          case 'sevenDays':
            return daysDiff <= 7 && daysDiff >= 0;
          default:
            return true;
        }
      });
    }

    this.filteredProjects = result;
    // 新增：计算紧急任务固定区（超期 + 高紧急），与筛选联动
    this.urgentPinnedProjects = this.filteredProjects
      .filter(p => p.isOverdue && p.urgency === 'high')
      .sort((a, b) => (b.overdueDays - a.overdueDays) || a.name.localeCompare(b.name, 'zh-Hans-CN'));
    // 当显示甘特卡片时，同步刷新甘特图
    if (this.showGanttView) {
      this.updateGantt();
    }
    // 同步刷新工作量概览图
    this.updateWorkloadChart();
  }

  // 切换项目看板/负载日历（甘特）视图
  toggleView(): void {
    this.showGanttView = !this.showGanttView;
    if (this.showGanttView) {
      setTimeout(() => this.initOrUpdateGantt(), 0);
    } else {
      if (this.ganttChart) {
        this.ganttChart.dispose();
        this.ganttChart = null;
      }
      if (this.workloadChart) {
        this.workloadChart.dispose();
        this.workloadChart = null;
      }
    }
  }

  // 设置甘特时间尺度
  setGanttScale(scale: 'day' | 'week' | 'month'): void {
    if (this.ganttScale !== scale) {
      this.ganttScale = scale;
      this.updateGantt();
    }
  }

  // 新增：切换甘特模式
  setGanttMode(mode: 'project' | 'designer'): void {
    if (this.ganttMode !== mode) {
      this.ganttMode = mode;
      this.updateGantt();
    }
  }

  private initOrUpdateGantt(): void {
    if (!this.ganttChartRef) return;
    const el = this.ganttChartRef.nativeElement;
    if (!this.ganttChart) {
      this.ganttChart = echarts.init(el);
      
      // 添加点击事件监听器
      this.ganttChart.on('click', (params: any) => {
        if (params.componentType === 'series' && params.seriesType === 'custom') {
          // 获取点击的员工名称（从y轴类目数据中获取）
          const yAxisData = this.ganttChart.getOption().yAxis[0].data;
          if (yAxisData && params.dataIndex !== undefined) {
            const employeeName = yAxisData[params.value[0]];
            if (employeeName && employeeName !== '未分配') {
              this.onEmployeeClick(employeeName);
            }
          }
        }
      });
      
      window.addEventListener('resize', () => {
        this.ganttChart && this.ganttChart.resize();
      });
    }
    this.updateGantt();
  }

  private updateGantt(): void {
    if (!this.ganttChart) return;
    if (this.ganttMode === 'designer') {
      this.updateGanttDesigner();
      return;
    }

    // 按紧急程度从上到下排序（高->中->低），同级按到期时间升序
    const urgencyRank: Record<'high'|'medium'|'low', number> = { high: 0, medium: 1, low: 2 };
    const projects = [...this.filteredProjects]
      .sort((a, b) => {
        const u = urgencyRank[a.urgency] - urgencyRank[b.urgency];
        if (u !== 0) return u;
        // 二级排序：临期优先（到期更近）> 已分配人员 > VIP客户 > 其他
        const endDiff = new Date(a.deadline).getTime() - new Date(b.deadline).getTime();
        if (endDiff !== 0) return endDiff;
        const assignedA = !!a.designerName;
        const assignedB = !!b.designerName;
        if (assignedA !== assignedB) return assignedA ? -1 : 1; // 已分配在前
        const vipA = a.memberType === 'vip';
        const vipB = b.memberType === 'vip';
        if (vipA !== vipB) return vipA ? -1 : 1; // VIP在前
        return a.name.localeCompare(b.name, 'zh-CN');
      });

    const categories = projects.map(p => p.name);
    const urgencyMap: Record<string, 'high'|'medium'|'low'> = Object.fromEntries(projects.map(p => [p.name, p.urgency])) as any;

    const colorByUrgency: Record<'high'|'medium'|'low', string> = {
      high: '#ef4444',
      medium: '#f59e0b',
      low: '#22c55e'
    } as const;

    const DAY = 24 * 60 * 60 * 1000;

    const data = projects.map((p, idx) => {
      const end = new Date(p.deadline).getTime();
      const baseDays = p.type === 'hard' ? 30 : 14;
      const start = p.createdAt ? new Date(p.createdAt).getTime() : end - baseDays * DAY;
      const color = colorByUrgency[p.urgency] || '#60a5fa';
      return {
        name: p.name,
        value: [idx, start, end, p.designerName, p.urgency, p.memberType, p.currentStage],
        itemStyle: { color }
      };
    });

    // 计算时间范围（仅周/月）
    const now = new Date();
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const todayTs = today.getTime();

    let xMin: number;
    let xMax: number;
    let xSplitNumber: number;
    let xLabelFormatter: (value: number) => string;

    if (this.ganttScale === 'week') {
      const day = today.getDay(); // 0=周日
      const diffToMonday = (day === 0 ? 6 : day - 1);
      const startOfWeek = new Date(today.getTime() - diffToMonday * DAY);
      const endOfWeek = new Date(startOfWeek.getTime() + 7 * DAY - 1);
      xMin = startOfWeek.getTime();
      xMax = endOfWeek.getTime();
      xSplitNumber = 7;
      const WEEK_LABELS = ['周日','周一','周二','周三','周四','周五','周六'];
      xLabelFormatter = (val) => {
        const d = new Date(val);
        return WEEK_LABELS[d.getDay()];
      };
    } else { // month
      const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
      const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0, 23, 59, 59, 999);
      xMin = startOfMonth.getTime();
      xMax = endOfMonth.getTime();
      xSplitNumber = 4;
      xLabelFormatter = (val) => {
        const d = new Date(val);
        const weekOfMonth = Math.ceil(d.getDate() / 7);
        return `第${weekOfMonth}周`;
      };
    }

    // 计算默认可视区，并尝试保留上一次的滚动/缩放位置
    const total = categories.length;
    const visible = Math.min(total, 15); // 默认首屏展开15条
    const defaultEndPercent = total > 0 ? Math.min(100, (visible / total) * 100) : 100;
    const prevOpt: any = (this.ganttChart as any).getOption ? (this.ganttChart as any).getOption() : null;
    const preservedStart = typeof prevOpt?.dataZoom?.[0]?.start === 'number' ? prevOpt.dataZoom[0].start : 0;
    const preservedEnd = typeof prevOpt?.dataZoom?.[0]?.end === 'number' ? prevOpt.dataZoom[0].end : defaultEndPercent;

    // 生成请假覆盖层数据
    const leaveOverlayData = this.generateLeaveOverlayData(categories, xMin, xMax);

    const option = {
      backgroundColor: 'transparent',
      tooltip: {
        trigger: 'item',
        formatter: (params: any) => {
          const v = params.value;
          const start = new Date(v[1]);
          const end = new Date(v[2]);
          return `项目：${params.name}<br/>负责人：${v[3] || '未分配'}<br/>阶段：${v[6]}<br/>起止：${start.toLocaleDateString()} ~ ${end.toLocaleDateString()}`;
        }
      },
      grid: { left: 100, right: 64, top: 30, bottom: 30 },
      xAxis: {
        type: 'time',
        min: xMin,
        max: xMax,
        splitNumber: xSplitNumber,
        axisLine: { lineStyle: { color: '#e5e7eb' } },
        axisLabel: { color: '#6b7280', formatter: (value: number) => xLabelFormatter(value) },
        splitLine: { lineStyle: { color: '#f1f5f9' } }
      },
      yAxis: {
        type: 'category',
        data: categories,
        inverse: true,
        axisLabel: {
          color: '#374151',
          margin: 8,
          formatter: (val: string) => {
            const u = urgencyMap[val] || 'low';
            const text = val.length > 16 ? val.slice(0, 16) + '…' : val;
            return `{${u}Dot|●} ${text}`;
          },
          rich: {
            highDot: { color: '#ef4444' },
            mediumDot: { color: '#f59e0b' },
            lowDot: { color: '#22c55e' }
          }
        },
        axisTick: { show: false },
        axisLine: { lineStyle: { color: '#e5e7eb' } }
      },
      dataZoom: [
        { type: 'slider', yAxisIndex: 0, orient: 'vertical', right: 6, width: 14, start: preservedStart, end: preservedEnd, zoomLock: false },
        { type: 'inside', yAxisIndex: 0, zoomOnMouseWheel: true, moveOnMouseMove: true, moveOnMouseWheel: true }
      ],
      series: [
        // 项目条形图系列
        {
          type: 'custom',
          name: '项目进度',
          renderItem: (params: any, api: any) => {
            const categoryIndex = api.value(0);
            const start = api.coord([api.value(1), categoryIndex]);
            const end = api.coord([api.value(2), categoryIndex]);
            const height = Math.max(api.size([0, 1])[1] * 0.5, 8);
            const rectShape = echarts.graphic.clipRectByRect({
              x: start[0],
              y: start[1] - height / 2,
              width: Math.max(end[0] - start[0], 2),
              height
            }, {
              x: params.coordSys.x,
              y: params.coordSys.y,
              width: params.coordSys.width,
              height: params.coordSys.height
            });
            return rectShape ? { type: 'rect', shape: rectShape, style: api.style() } : undefined;
          },
          encode: { x: [1, 2], y: 0 },
          data,
          itemStyle: { borderRadius: 4 },
          emphasis: { focus: 'self' },
          markLine: {
            silent: true,
            symbol: 'none',
            lineStyle: { color: '#ef4444', type: 'dashed', width: 1 },
            label: { formatter: '今日', color: '#ef4444', fontSize: 10, position: 'end' },
            data: [ { xAxis: todayTs } ]
          }
        },
        // 请假覆盖层系列
        {
          type: 'custom',
          name: '请假/繁忙标记',
          renderItem: (params: any, api: any) => {
            const categoryIndex = api.value(0);
            const start = api.coord([api.value(1), categoryIndex]);
            const end = api.coord([api.value(2), categoryIndex]);
            const height = Math.max(api.size([0, 1])[1] * 0.8, 12); // 稍微高一点，覆盖项目条
            const rectShape = echarts.graphic.clipRectByRect({
              x: start[0],
              y: start[1] - height / 2,
              width: Math.max(end[0] - start[0], 2),
              height
            }, {
              x: params.coordSys.x,
              y: params.coordSys.y,
              width: params.coordSys.width,
              height: params.coordSys.height
            });
            return rectShape ? { type: 'rect', shape: rectShape, style: api.style() } : undefined;
          },
          encode: { x: [1, 2], y: 0 },
          data: leaveOverlayData,
          itemStyle: { borderRadius: 4 },
          emphasis: { focus: 'self' },
          z: 10 // 确保覆盖层在项目条之上
        }
      ]
    };

    // 强制刷新，避免缓存导致坐标轴不更新
    this.ganttChart.clear();
    this.ganttChart.setOption(option, true);
    this.ganttChart.resize();
  }

  // 新增：设计师排班甘特
  private updateGanttDesigner(): void {
    if (!this.ganttChart) return;

    const DAY = 24 * 60 * 60 * 1000;
    const now = new Date();
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const todayTs = today.getTime();

    // 时间轴按当前周/月/日
    let xMin: number;
    let xMax: number;
    let xSplitNumber: number;
    let xLabelFormatter: (value: number) => string;
    if (this.ganttScale === 'day') {
      // 日视图：显示今日24小时
      const startOfDay = new Date(today.getTime());
      const endOfDay = new Date(today.getTime() + DAY - 1);
      xMin = startOfDay.getTime();
      xMax = endOfDay.getTime();
      xSplitNumber = 24;
      xLabelFormatter = (val) => `${new Date(val).getHours()}:00`;
    } else if (this.ganttScale === 'week') {
      // 周视图：从今天开始显示未来7天的具体日期
      const startOfWeek = new Date(today.getTime());
      const endOfWeek = new Date(today.getTime() + 7 * DAY - 1);
      xMin = startOfWeek.getTime();
      xMax = endOfWeek.getTime();
      xSplitNumber = 7;
      xLabelFormatter = (val) => {
        const date = new Date(val);
        const month = date.getMonth() + 1;
        const day = date.getDate();
        return `${month}月${day}日`;
      };
    } else {
      // 月视图：从当前月份开始显示未来几个月
      const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
      const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 3, 0, 23, 59, 59, 999); // 显示未来3个月
      xMin = startOfMonth.getTime();
      xMax = endOfMonth.getTime();
      xSplitNumber = 3;
      xLabelFormatter = (val) => {
        const date = new Date(val);
        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        return `${year}年${month}月`;
      };
    }

    // 仅统计已分配项目
    const assigned = this.filteredProjects.filter(p => !!p.designerName);
    const designers = Array.from(new Set(assigned.map(p => p.designerName)));

    const byDesigner: Record<string, typeof assigned> = {} as any;
    designers.forEach(n => byDesigner[n] = [] as any);
    assigned.forEach(p => byDesigner[p.designerName].push(p));

    const busyCountMap: Record<string, number> = Object.fromEntries(designers.map(n => [n, byDesigner[n].length]));

    const sortedDesigners = designers.sort((a, b) => {
      const diff = (busyCountMap[b] || 0) - (busyCountMap[a] || 0);
      return diff !== 0 ? diff : a.localeCompare(b, 'zh-CN');
    });

    const categories = sortedDesigners;

    // 工作量等级（用于左侧小圆点颜色和负荷状态判断）
    const workloadLevelMap: Record<string, 'high'|'medium'|'low'> = {} as any;
    const workloadStatusMap: Record<string, 'overloaded'|'busy'|'available'> = {} as any;
    categories.forEach(name => {
      const cnt = busyCountMap[name] || 0;
      if (cnt >= 5) {
        workloadLevelMap[name] = 'high';
        workloadStatusMap[name] = 'overloaded'; // 不宜派单
      } else if (cnt >= 3) {
        workloadLevelMap[name] = 'medium';
        workloadStatusMap[name] = 'busy'; // 适度忙碌
      } else {
        workloadLevelMap[name] = 'low';
        workloadStatusMap[name] = 'available'; // 可接单
      }
    });

    // 条形颜色按项目紧急度，增强高负荷时段的视觉效果
    const colorByUrgency: Record<'high'|'medium'|'low', string> = {
      high: '#dc2626', // 更深的红色，突出高紧急度
      medium: '#ea580c', // 更深的橙色
      low: '#16a34a' // 更深的绿色
    } as const;

    const data = assigned.flatMap(p => {
      const end = new Date(p.deadline).getTime();
      const baseDays = p.type === 'hard' ? 30 : 14;
      const start = p.createdAt ? new Date(p.createdAt).getTime() : end - baseDays * DAY;
      const yIndex = categories.indexOf(p.designerName);
      if (yIndex === -1) return [] as any[];
      
      // 根据设计师工作负荷状态调整项目条的视觉效果
      const workloadStatus = workloadStatusMap[p.designerName];
      let color = colorByUrgency[p.urgency] || '#60a5fa';
      let borderWidth = 1;
      let borderColor = 'transparent';
      
      // 高负荷时段增强视觉效果
      if (workloadStatus === 'overloaded') {
        borderWidth = 3;
        borderColor = '#991b1b'; // 深红色边框
        // 对于超负荷状态，使用更深的红色调
        if (p.urgency === 'high') {
          color = '#7f1d1d'; // 深红色
        } else if (p.urgency === 'medium') {
          color = '#c2410c'; // 深橙色
        } else {
          color = '#dc2626'; // 红色（即使是低紧急度也用红色表示超负荷）
        }
      }
      
      return [{
        name: p.name,
        value: [yIndex, start, end, p.designerName, p.urgency, p.memberType, p.currentStage, workloadStatus],
        itemStyle: { 
          color,
          borderWidth,
          borderColor,
          opacity: workloadStatus === 'overloaded' ? 0.9 : 1.0
        }
      }];
    });

    // 生成空闲时段背景数据 - 只在真正空闲的时间段显示
    const idleBackgroundData: any[] = [];
    
    categories.forEach((designerName, yIndex) => {
      const designerProjects = byDesigner[designerName] || [];
      const workloadStatus = workloadStatusMap[designerName];
      
      // 获取该设计师的所有项目时间段
      const projectTimeRanges = designerProjects.map(p => {
        const end = new Date(p.deadline).getTime();
        const baseDays = p.type === 'hard' ? 30 : 14;
        const start = p.createdAt ? new Date(p.createdAt).getTime() : end - baseDays * DAY;
        return { start, end };
      }).sort((a, b) => a.start - b.start);
      
      // 找出空闲时间段
      const idleTimeRanges: { start: number; end: number }[] = [];
      
      if (projectTimeRanges.length === 0) {
        // 完全没有项目，整个时间轴都是空闲
        idleTimeRanges.push({ start: xMin, end: xMax });
      } else {
        // 检查项目之间的空隙
        let currentTime = xMin;
        
        for (const range of projectTimeRanges) {
          if (currentTime < range.start) {
            // 在项目开始前有空闲时间
            idleTimeRanges.push({ start: currentTime, end: range.start });
          }
          currentTime = Math.max(currentTime, range.end);
        }
        
        // 检查最后一个项目后是否还有空闲时间
        if (currentTime < xMax) {
          idleTimeRanges.push({ start: currentTime, end: xMax });
        }
      }
      
      // 为每个空闲时间段创建背景数据
      idleTimeRanges.forEach((idleRange, index) => {
        // 只有当空闲时间段足够长时才显示（至少1天）
        if (idleRange.end - idleRange.start >= DAY) {
          let backgroundColor = 'transparent';
          
          if (workloadStatus === 'available') {
            backgroundColor = 'rgba(34, 197, 94, 0.15)'; // 淡绿色背景表示空闲可接单
          } else if (workloadStatus === 'overloaded') {
            backgroundColor = 'rgba(239, 68, 68, 0.1)'; // 淡红色背景表示超负荷
          }
          
          if (backgroundColor !== 'transparent') {
            idleBackgroundData.push({
              name: `${designerName}-空闲${index + 1}`,
              value: [yIndex, idleRange.start, idleRange.end, designerName, 'background', workloadStatus],
              itemStyle: { 
                color: backgroundColor,
                borderWidth: 0
              }
            });
          }
        }
      });
    });

    const prevOpt: any = (this.ganttChart as any).getOption ? (this.ganttChart as any).getOption() : null;
    const total = categories.length || 1;
    const visible = Math.min(total, 30);
    const defaultEndPercent = Math.min(100, (visible / total) * 100);
    const preservedStart = typeof prevOpt?.dataZoom?.[0]?.start === 'number' ? prevOpt.dataZoom[0].start : 0;
    const preservedEnd = typeof prevOpt?.dataZoom?.[0]?.end === 'number' ? prevOpt.dataZoom[0].end : defaultEndPercent;

    const option = {
      backgroundColor: 'transparent',
      tooltip: {
        trigger: 'item',
        formatter: (params: any) => {
          const v = params.value;
          if (v[4] === 'background') {
            const workloadStatus = v[5];
            const statusText = workloadStatus === 'available' ? '空闲可接单' : 
                              workloadStatus === 'overloaded' ? '超负荷不宜派单' : '适度忙碌';
            return `设计师：${v[3]}<br/>状态：${statusText}`;
          }
          const start = new Date(v[1]);
          const end = new Date(v[2]);
          const workloadStatus = v[7];
          const statusText = workloadStatus === 'available' ? '可接单' : 
                            workloadStatus === 'overloaded' ? '超负荷' : '适度忙碌';
          return `项目：${params.name}<br/>设计师：${v[3]}（${statusText}）<br/>阶段：${v[6]}<br/>起止：${start.toLocaleDateString()} ~ ${end.toLocaleDateString()}`;
        }
      },
      legend: {
        data: ['空闲可接单', '适度忙碌', '超负荷不宜派单', '高紧急', '中紧急', '低紧急'],
        bottom: 0,
        itemGap: 20,
        textStyle: { fontSize: 12 }
      },
      grid: { left: 110, right: 64, top: 30, bottom: 60 },
      xAxis: {
        type: 'time',
        min: xMin,
        max: xMax,
        splitNumber: xSplitNumber,
        axisLine: { lineStyle: { color: '#e5e7eb' } },
        axisLabel: { color: '#6b7280', formatter: (value: number) => xLabelFormatter(value) },
        splitLine: { lineStyle: { color: '#f1f5f9' } }
      },
      yAxis: {
        type: 'category',
        data: categories,
        inverse: true,
        axisLabel: {
          color: '#374151',
          margin: 8,
          formatter: (val: string) => {
            const lvl = workloadLevelMap[val] || 'low';
            const count = busyCountMap[val] || 0;
            const status = workloadStatusMap[val] || 'available';
            const text = val.length > 8 ? val.slice(0, 8) + '…' : val;
            const statusIcon = status === 'available' ? '🟢' : 
                              status === 'overloaded' ? '🔴' : '🟡';
            return `{${lvl}Dot|●} ${statusIcon} ${text}（${count}项）`;
          },
          rich: {
            highDot: { color: '#dc2626' },
            mediumDot: { color: '#ea580c' },
            lowDot: { color: '#16a34a' }
          }
        },
        axisTick: { show: false },
        axisLine: { lineStyle: { color: '#e5e7eb' } }
      },
      dataZoom: [
        { type: 'slider', yAxisIndex: 0, orient: 'vertical', right: 6, start: preservedStart, end: preservedEnd, zoomLock: false },
        { type: 'inside', yAxisIndex: 0, zoomOnMouseWheel: true, moveOnMouseMove: true, moveOnMouseWheel: true }
      ],
      series: [
        // 背景层 - 显示空闲时段
        {
          type: 'custom',
          name: '工作负荷背景',
          renderItem: (params: any, api: any) => {
            const categoryIndex = api.value(0);
            const start = api.coord([api.value(1), categoryIndex]);
            const end = api.coord([api.value(2), categoryIndex]);
            const height = api.size([0, 1])[1] * 0.8;
            const rectShape = echarts.graphic.clipRectByRect({
              x: start[0],
              y: start[1] - height / 2,
              width: Math.max(end[0] - start[0], 2),
              height
            }, {
              x: params.coordSys.x,
              y: params.coordSys.y,
              width: params.coordSys.width,
              height: params.coordSys.height
            });
            return rectShape ? { type: 'rect', shape: rectShape, style: api.style() } : undefined;
          },
          encode: { x: [1, 2], y: 0 },
          data: idleBackgroundData,
          z: 1
        },
        // 项目条层
        {
          type: 'custom',
          name: '项目进度',
          renderItem: (params: any, api: any) => {
            const categoryIndex = api.value(0);
            const start = api.coord([api.value(1), categoryIndex]);
            const end = api.coord([api.value(2), categoryIndex]);
            const height = Math.max(api.size([0, 1])[1] * 0.5, 8);
            const rectShape = echarts.graphic.clipRectByRect({
              x: start[0],
              y: start[1] - height / 2,
              width: Math.max(end[0] - start[0], 2),
              height
            }, {
              x: params.coordSys.x,
              y: params.coordSys.y,
              width: params.coordSys.width,
              height: params.coordSys.height
            });
            return rectShape ? { type: 'rect', shape: rectShape, style: api.style() } : undefined;
          },
          encode: { x: [1, 2], y: 0 },
          data,
          itemStyle: { borderRadius: 4 },
          emphasis: { focus: 'self' },
          z: 2,
          markLine: {
            silent: true,
            symbol: 'none',
            lineStyle: { color: '#ef4444', type: 'dashed', width: 1 },
            label: { formatter: '今日', color: '#ef4444', fontSize: 10, position: 'end' },
            data: [ { xAxis: todayTs } ]
          }
        }
      ]
    } as any;

    this.ganttChart.clear();
    this.ganttChart.setOption(option, true);
    this.ganttChart.resize();
  }

  ngOnDestroy(): void {
    if (this.ganttChart) {
      this.ganttChart.dispose();
      this.ganttChart = null;
    }
    if (this.workloadChart) {
      this.workloadChart.dispose();
      this.workloadChart = null;
    }
  }
  // 选择单个项目
  selectProject(): void {
    if (this.selectedProjectId) {
      this.router.navigate(['/team-leader/project-detail', this.selectedProjectId]);
    }
  }

  // 获取特定阶段的项目
  getProjectsByStage(stageId: string): Project[] {
    return this.filteredProjects.filter(project => project.currentStage === stageId);
  }

  // 新增：阶段到核心阶段的映射
  private mapStageToCorePhase(stageId: string): 'order' | 'requirements' | 'delivery' | 'aftercare' {
    // 订单创建：立项初期
    if (stageId === 'pendingApproval' || stageId === 'pendingAssignment') return 'order';
    // 确认需求：需求沟通 + 方案规划
    if (stageId === 'requirement' || stageId === 'planning') return 'requirements';
    // 交付执行：制作与评审修订过程
    if (stageId === 'modeling' || stageId === 'rendering' || stageId === 'postProduction' || stageId === 'review' || stageId === 'revision') return 'delivery';
    // 售后：交付完成后的跟进（当前数据以交付完成代表进入售后）
    return 'aftercare';
  }

  // 新增：获取核心阶段的项目
  getProjectsByCorePhase(coreId: string): Project[] {
    return this.filteredProjects.filter(p => this.mapStageToCorePhase(p.currentStage) === coreId);
  }

  // 新增：获取核心阶段的项目数量
  getProjectCountByCorePhase(coreId: string): number {
    return this.getProjectsByCorePhase(coreId).length;
  }

  // 获取特定阶段的项目数量
  getProjectCountByStage(stageId: string): number {
    return this.getProjectsByStage(stageId).length;
  }

  // 待审批项目：currentStage === 'pendingApproval'
  get pendingApprovalProjects(): Project[] {
    const src = (this.filteredProjects && this.filteredProjects.length) ? this.filteredProjects : this.projects;
    return src.filter(p => p.currentStage === 'pendingApproval');
  }

  // 待指派项目：currentStage === 'pendingAssignment'
  get pendingAssignmentProjects(): Project[] {
    const src = (this.filteredProjects && this.filteredProjects.length) ? this.filteredProjects : this.projects;
    return src.filter(p => p.currentStage === 'pendingAssignment');
  }

  // 获取紧急程度标签
  getUrgencyLabel(urgency: string): string {
    const labels = {
      high: '紧急',
      medium: '一般',
      low: '普通'
    };
    return labels[urgency as keyof typeof labels] || urgency;
  }

  // 智能推荐设计师
  private getRecommendedDesigner(projectType: 'soft' | 'hard') {
    if (!this.designerProfiles || !this.designerProfiles.length) return null;
    const scoreOf = (p: any) => {
      const workloadScore = 100 - (p.workload ?? 0); // 负载越低越好
      const ratingScore = (p.avgRating ?? 0) * 10;   // 评分越高越好
      const expScore = (p.experience ?? 0) * 5;      // 经验越高越好
      return workloadScore * 0.5 + ratingScore * 0.3 + expScore * 0.2;
    };
    const sorted = [...this.designerProfiles].sort((a, b) => scoreOf(b) - scoreOf(a));
    return sorted[0] || null;
  }

  // 质量评审
  reviewProjectQuality(projectId: string, rating: 'excellent' | 'qualified' | 'unqualified'): void {
    const project = this.projects.find(p => p.id === projectId);
    if (!project) return;
    project.qualityRating = rating;
    if (rating === 'unqualified') {
      // 不合格：回退到修改阶段
      project.currentStage = 'revision';
    }
    this.applyFilters();
    alert('质量评审已提交');
  }

  // 查看绩效预警（占位：跳转到团队管理）
  viewPerformanceDetails(): void {
    this.router.navigate(['/team-leader/team-management']);
  }

  // 打开负载日历（占位：跳转到团队管理）
  navigateToWorkloadCalendar(): void {
    this.router.navigate(['/team-leader/workload-calendar']);
  }

  // 查看项目详情
  viewProjectDetails(projectId: string): void {
    // 检测是否在iframe中运行（即从客服端访问）
    const isInIframe = window.self !== window.top;
    
    if (isInIframe) {
      // 如果在iframe中，跳转到设计师端项目详情页面，并传递客服角色标识
      // 使用parent.window来在父窗口中进行导航
      const targetUrl = `/designer/project-detail/${projectId}?role=customer-service`;
      if (window.parent) {
        window.parent.postMessage({
          type: 'navigate',
          url: targetUrl
        }, '*');
      }
    } else {
      // 正常情况下跳转到组长端项目详情页面
      this.router.navigate(['/team-leader/project-detail', projectId]);
    }
  }

  // 快速分配项目（增强：加入智能推荐）
  quickAssignProject(projectId: string): void {
    const project = this.projects.find(p => p.id === projectId);
    if (!project) {
      alert('未找到对应项目');
      return;
    }

    const recommended = this.getRecommendedDesigner(project.type);
    if (recommended) {
      const reassigning = !!project.designerName;
      const message = `推荐设计师：${recommended.name}（工作负载：${recommended.workload}%，评分：${recommended.avgRating}分）` +
                (reassigning ? `\n\n该项目当前已由「${project.designerName}」负责，是否改为分配给「${recommended.name}」？` : '\n\n是否确认分配？');
      const confirmAssign = confirm(message);
      if (confirmAssign) {
        project.designerName = recommended.name;
        if (project.currentStage === 'pendingAssignment' || project.currentStage === 'pendingApproval') {
          project.currentStage = 'requirement';
        }
        project.status = '进行中';
        // 更新设计师筛选列表
        this.designers = Array.from(new Set(this.projects.map(p => p.designerName).filter(n => !!n)));
        this.applyFilters();
        alert(`项目已${reassigning ? '重新' : ''}分配给 ${recommended.name}`);
        return;
      }
    }
    // 无推荐或用户取消，跳转到详细分配页面
    // 改为跳转到复用详情（组长视图），通过 query 参数标记 assign 模式
    this.router.navigate(['/team-leader/project-detail', projectId], { queryParams: { mode: 'assign' } });
    }

  // 导航到待办任务
  navigateToTask(task: TodoTask): void {
    switch (task.type) {
      case 'review':
        this.router.navigate(['team-leader/quality-management', task.targetId]);
        break;
      case 'assign':
        this.router.navigate(['/team-leader/dashboard']);
        break;
      case 'performance':
        this.router.navigate(['team-leader/team-management']);
        break;
    }
  }

  // 获取优先级标签
  getPriorityLabel(priority: 'high' | 'medium' | 'low'): string {
    const labels: Record<'high' | 'medium' | 'low', string> = {
      'high': '紧急且重要',
      'medium': '重要不紧急',
      'low': '紧急不重要'
    };
    return labels[priority];
  }

  // 导航到团队管理
  navigateToTeamManagement(): void {
    this.router.navigate(['/team-leader/team-management']);
  }

  // 导航到项目评审
  navigateToProjectReview(): void {
    // 统一入口：跳转到项目列表/看板，而非旧评审页
    this.router.navigate(['/team-leader/dashboard']);
  }

  // 导航到质量管理
  navigateToQualityManagement(): void {
    this.router.navigate(['/team-leader/quality-management']);
  }

  // 打开工作量预估工具（已迁移）
  openWorkloadEstimator(): void {
    // 工具迁移至详情页：引导前往当前选中项目详情
    if (this.selectedProjectId) {
      this.router.navigate(['/team-leader/project-detail', this.selectedProjectId], { queryParams: { tool: 'estimator' } });
    } else {
      this.router.navigate(['/team-leader/dashboard']);
    }
    alert('工作量预估工具已迁移至项目详情页，您可以在建模阶段之前使用该工具进行工作量计算。');
  }

  // 查看所有超期项目
  viewAllOverdueProjects(): void {
    this.filterByStatus('overdue');
    this.closeAlert();
  }

  // 关闭提醒
  closeAlert(): void {
    this.showAlert = false;
  }

  // 维度切换（设计师/会员类型）
  setWorkloadDimension(dim: 'designer' | 'member'): void {
    if (this.workloadDimension !== dim) {
      this.workloadDimension = dim;
      this.updateWorkloadChart();
    }
  }

  // 刷新“工作量概览”图表
  private updateWorkloadChart(): void {
    if (!this.workloadChartRef) { return; }
    const el = this.workloadChartRef.nativeElement;
    if (!el) { return; }

    // 初始化实例（使用 SVG 渲染以获得更佳文本清晰度）
    if (!this.workloadChart) {
      this.workloadChart = echarts.init(el, null, { renderer: 'svg' });
    }

    const data = (this.filteredProjects && this.filteredProjects.length) ? this.filteredProjects : this.projects;
    const byDesigner = this.workloadDimension === 'designer';
    const groupKey = byDesigner ? 'designerName' : 'memberType';

    const labelMap: Record<string, string> = { vip: 'VIP', normal: '普通' };
    const groupSet = new Set<string>();
    data.forEach(p => {
      const val = (p as any)[groupKey] || (byDesigner ? '未分配' : '未知');
      groupSet.add(val);
    });
    const categories = Array.from(groupSet).sort((a, b) => a.localeCompare(b, 'zh-Hans-CN'));

    const count = (urg: 'high'|'medium'|'low', group: string) =>
      data.filter(p => (((p as any)[groupKey] || (byDesigner ? '未分配' : '未知')) === group) && p.urgency === urg).length;

    const high = categories.map(c => count('high', c));
    const medium = categories.map(c => count('medium', c));
    const low = categories.map(c => count('low', c));

    const option = {
      tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
      legend: { data: ['高', '中', '低'] },
      grid: { left: 12, right: 16, top: 28, bottom: 8, containLabel: true },
      xAxis: { type: 'value', boundaryGap: [0, 0.01] },
      yAxis: {
        type: 'category',
        data: categories.map(c => byDesigner ? c : (labelMap[c] || c))
      },
      series: [
        { name: '高', type: 'bar', stack: 'workload', data: high, itemStyle: { color: '#ef4444' } },
        { name: '中', type: 'bar', stack: 'workload', data: medium, itemStyle: { color: '#f59e0b' } },
        { name: '低', type: 'bar', stack: 'workload', data: low, itemStyle: { color: '#10b981' } }
      ]
    } as any;

    this.workloadChart.clear();
    this.workloadChart.setOption(option, true);
    this.workloadChart.resize();
  }

  resetStatusFilter(): void {
    this.selectedStatus = 'all';
    this.applyFilters();
  }

  // 处理甘特图员工点击事件
  onEmployeeClick(employeeName: string): void {
    if (!employeeName || employeeName === '未分配') {
      return;
    }
    
    // 生成员工详情数据
    this.selectedEmployeeDetail = this.generateEmployeeDetail(employeeName);
    this.showEmployeeDetailPanel = true;
  }

  // 生成员工详情数据
  private generateEmployeeDetail(employeeName: string): EmployeeDetail {
    // 获取该员工负责的项目
    const employeeProjects = this.filteredProjects.filter(p => p.designerName === employeeName);
    const currentProjects = employeeProjects.length;
    const projectNames = employeeProjects.slice(0, 3).map(p => p.name); // 最多显示3个项目名称
    
    // 获取该员工的请假记录（未来7天）
    const today = new Date();
    const next7Days = Array.from({ length: 7 }, (_, i) => {
      const date = new Date(today);
      date.setDate(today.getDate() + i);
      return date.toISOString().split('T')[0]; // YYYY-MM-DD 格式
    });
    
    const employeeLeaveRecords = this.leaveRecords.filter(record => 
      record.employeeName === employeeName && next7Days.includes(record.date)
    );
    
    // 生成红色标记说明
    const redMarkExplanation = this.generateRedMarkExplanation(employeeName, employeeLeaveRecords, currentProjects);
    
    return {
      name: employeeName,
      currentProjects,
      projectNames,
      leaveRecords: employeeLeaveRecords,
      redMarkExplanation
    };
  }

  // 生成红色标记说明
  private generateRedMarkExplanation(employeeName: string, leaveRecords: LeaveRecord[], projectCount: number): string {
    const explanations: string[] = [];
    
    // 检查请假情况
    const leaveDays = leaveRecords.filter(record => record.isLeave);
    if (leaveDays.length > 0) {
      leaveDays.forEach(leave => {
        const date = new Date(leave.date);
        const dateStr = `${date.getMonth() + 1}月${date.getDate()}日`;
        explanations.push(`${dateStr}（${leave.reason || '请假'}）`);
      });
    }
    
    // 检查项目繁忙情况
    if (projectCount >= 3) {
      const today = new Date();
      const dateStr = `${today.getMonth() + 1}月${today.getDate()}日`;
      explanations.push(`${dateStr}（${projectCount}个项目繁忙）`);
    }
    
    if (explanations.length === 0) {
      return '当前无红色标记时段';
    }
    
    return `甘特图中红色时段说明：${explanations.map((exp, index) => `${index + 1}${exp}`).join('；')}`;
  }

  // 关闭员工详情面板
  closeEmployeeDetailPanel(): void {
    this.showEmployeeDetailPanel = false;
    this.selectedEmployeeDetail = null;
  }

  // 获取请假类型显示文本
  getLeaveTypeText(leaveType?: string): string {
    const typeMap: Record<string, string> = {
      'sick': '病假',
      'personal': '事假',
      'annual': '年假',
      'other': '其他'
    };
    return typeMap[leaveType || ''] || '请假';
  }

  // 生成请假覆盖层数据
  private generateLeaveOverlayData(categories: string[], xMin: number, xMax: number): any[] {
    const DAY = 24 * 60 * 60 * 1000;
    const overlayData: any[] = [];

    categories.forEach((employeeName, yIndex) => {
      // 获取该员工在时间范围内的请假记录
      const employeeLeaves = this.leaveRecords.filter(record => {
        if (record.employeeName !== employeeName || !record.isLeave) {
          return false;
        }
        
        const recordDate = new Date(record.date).getTime();
        return recordDate >= xMin && recordDate <= xMax;
      });

      // 为每个请假日期创建覆盖层
      employeeLeaves.forEach(leave => {
        const leaveDate = new Date(leave.date);
        const startOfDay = new Date(leaveDate.getFullYear(), leaveDate.getMonth(), leaveDate.getDate()).getTime();
        const endOfDay = startOfDay + DAY - 1;

        overlayData.push({
          name: `${employeeName} - ${this.getLeaveTypeText(leave.leaveType)}`,
          value: [yIndex, startOfDay, endOfDay, employeeName, leave.leaveType, leave.reason],
          itemStyle: { 
            color: 'rgba(239, 68, 68, 0.6)', // 半透明红色
            borderColor: '#ef4444',
            borderWidth: 1
          }
        });
      });

      // 检查项目繁忙情况，如果项目数>=3，也添加红色标记
      const employeeProjects = this.filteredProjects.filter(p => p.designerName === employeeName);
      if (employeeProjects.length >= 3) {
        // 在当前日期添加繁忙标记
        const today = new Date();
        const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate()).getTime();
        const endOfToday = startOfToday + DAY - 1;

        if (startOfToday >= xMin && startOfToday <= xMax) {
          overlayData.push({
            name: `${employeeName} - 项目繁忙（${employeeProjects.length}个项目）`,
            value: [yIndex, startOfToday, endOfToday, employeeName, 'busy', `负责${employeeProjects.length}个项目`],
            itemStyle: { 
              color: 'rgba(239, 68, 68, 0.4)', // 稍微透明的红色
              borderColor: '#ef4444',
              borderWidth: 1,
              borderType: 'dashed' // 虚线边框区分请假和繁忙
            }
          });
        }
      }
    });

    return overlayData;
  }
}
