DESIGNER-ASSIGNMENT-COLOR-ENHANCEMENT-AND-PANEL-REUSE.md 13 KB

设计师分配弹窗颜色增强 & 员工信息面板组件复用

📋 任务概述

本次修改完成了两个主要需求:

  1. 设计师组分配弹窗:增强颜色区分,让不同工作量的设计师一目了然
  2. 员工信息侧边栏:严格复用团队组长端的 @employee-detail-panel 组件

🎨 需求一:设计师分配弹窗颜色增强

修改目标

  • 背景改为浅灰色(#fafafa),增强对比度
  • 为不同工作量的设计师卡片添加明显的颜色标识:
    • 🟢 绿色:0 个项目(空闲)
    • 🟠 橙色:1-5 个项目(有项目)
    • 🔴 红色:超过 5 个项目(繁忙)

关键修改

1. SCSS 样式增强 (designer-team-assignment-modal.component.scss)

弹窗背景颜色

.modal-body {
  flex: 1;
  overflow-y: auto;
  padding: 24px 32px;
  background: #fafafa; // 浅灰色背景,增强对比度
}

设计师卡片状态颜色

.designer-card {
  border: 3px solid #e8e8e8;
  border-radius: 10px;
  padding: 16px;
  cursor: pointer;
  transition: all 0.3s ease;
  background: white;
  display: flex;
  gap: 12px;
  position: relative;

  // 🎨 左侧彩色边框标识
  &::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 6px;
    border-radius: 10px 0 0 10px;
    transition: all 0.3s ease;
  }

  // 🟢 空闲(0个项目)- 明显的绿色
  &.status-idle {
    border-color: #52c41a;
    background: linear-gradient(135deg, #f6ffed 0%, #ffffff 100%);
    
    &::before {
      background: linear-gradient(180deg, #73d13d 0%, #52c41a 100%);
      box-shadow: 0 0 10px rgba(82, 196, 26, 0.4);
    }

    &:hover {
      border-color: #73d13d;
      box-shadow: 0 6px 16px rgba(82, 196, 26, 0.25);
      transform: translateY(-2px);
    }
  }

  // 🟠 有项目(1-5个)- 明显的橙色
  &.status-reviewing {
    border-color: #faad14;
    background: linear-gradient(135deg, #fff7e6 0%, #ffffff 100%);
    
    &::before {
      background: linear-gradient(180deg, #ffc53d 0%, #faad14 100%);
      box-shadow: 0 0 10px rgba(250, 173, 20, 0.4);
    }

    &:hover {
      border-color: #ffc53d;
      box-shadow: 0 6px 16px rgba(250, 173, 20, 0.25);
      transform: translateY(-2px);
    }
  }

  // 🔴 繁忙(>5个项目)- 明显的红色
  &.status-stagnant {
    border-color: #ff4d4f;
    background: linear-gradient(135deg, #fff1f0 0%, #ffffff 100%);
    
    &::before {
      background: linear-gradient(180deg, #ff7875 0%, #ff4d4f 100%);
      box-shadow: 0 0 10px rgba(255, 77, 79, 0.4);
    }

    &:hover {
      border-color: #ff7875;
      box-shadow: 0 6px 16px rgba(255, 77, 79, 0.25);
      transform: translateY(-2px);
    }
  }

  // 选中状态保留原有颜色标识
  &.selected {
    border-color: #1890ff;
    border-width: 3px;
    box-shadow: 0 6px 20px rgba(24, 144, 255, 0.25);
    transform: translateY(-2px);
  }
}

2. HTML 模板状态绑定 (designer-team-assignment-modal.component.html)

为所有设计师卡片添加状态类绑定:

推荐分配区域

<div 
  class="designer-card recommended"
  [class.selected]="isDesignerSelected(designer)"
  [class.status-idle]="designer.status === 'idle'"
  [class.status-reviewing]="designer.status === 'reviewing'"
  [class.status-stagnant]="designer.status === 'stagnant'"
  (click)="toggleDesignerSelection(designer)">

所有团队成员区域

<div 
  class="designer-card"
  [class.selected]="isDesignerSelected(designer)"
  [class.status-idle]="designer.status === 'idle'"
  [class.status-reviewing]="designer.status === 'reviewing'"
  [class.status-stagnant]="designer.status === 'stagnant'"
  (click)="toggleDesignerSelection(designer)">

跨团队协作区域

<div 
  class="designer-card cross-team"
  [class.selected]="isCrossTeamCollaborator(designer)"
  [class.status-idle]="designer.status === 'idle'"
  [class.status-reviewing]="designer.status === 'reviewing'"
  [class.status-stagnant]="designer.status === 'stagnant'"
  (click)="toggleCrossTeamCollaborator(designer)">

视觉效果

状态颜色对应关系

🟢 绿色 (status-idle)
├─ 边框颜色: #52c41a
├─ 背景渐变: #f6ffed → #ffffff
├─ 左侧标识: #73d13d → #52c41a
└─ 发光效果: rgba(82, 196, 26, 0.4)

🟠 橙色 (status-reviewing)
├─ 边框颜色: #faad14
├─ 背景渐变: #fff7e6 → #ffffff
├─ 左侧标识: #ffc53d → #faad14
└─ 发光效果: rgba(250, 173, 20, 0.4)

🔴 红色 (status-stagnant)
├─ 边框颜色: #ff4d4f
├─ 背景渐变: #fff1f0 → #ffffff
├─ 左侧标识: #ff7875 → #ff4d4f
└─ 发光效果: rgba(255, 77, 79, 0.4)

交互效果

  • Hover 状态
    • 边框颜色变亮
    • 阴影扩大
    • 卡片上浮 2px
  • 选中状态
    • 边框变为蓝色 (#1890ff)
    • 保留原有的左侧彩色标识
    • 阴影更加明显

🔄 需求二:员工信息面板组件复用

修改目标

关键修改

1. TypeScript 组件集成 (employee-info-panel.component.ts)

导入团队组长端组件

import { EmployeeDetailPanelComponent, EmployeeDetail as TeamLeaderEmployeeDetail } from '../../../pages/team-leader/employee-detail-panel';

添加到 imports

@Component({
  selector: 'app-employee-info-panel',
  standalone: true,
  imports: [CommonModule, FormsModule, DesignerCalendarComponent, EmployeeDetailPanelComponent],
  templateUrl: './employee-info-panel.component.html',
  styleUrls: ['./employee-info-panel.component.scss']
})

数据转换 Getter

/**
 * 将 EmployeeFullInfo 转换为 EmployeeDetail(用于复用组长端组件)
 */
get employeeDetailForTeamLeader(): TeamLeaderEmployeeDetail | null {
  if (!this.employee) return null;

  return {
    name: this.employee.realname || this.employee.name,
    currentProjects: this.employee.currentProjects || 0,
    projectNames: this.employee.projectNames || [],
    projectData: this.employee.projectData || [],
    leaveRecords: this.employee.leaveRecords || [],
    redMarkExplanation: this.employee.redMarkExplanation || '',
    calendarData: this.employee.calendarData,
    surveyCompleted: this.employee.surveyCompleted,
    surveyData: this.employee.surveyData,
    profileId: this.employee.profileId || this.employee.id
  };
}

2. HTML 模板复用 (employee-info-panel.component.html)

替换项目负载标签页内容

<!-- ========== 项目负载标签页 ========== -->
@if (activeTab === 'workload') {
  <div class="tab-content workload-tab">
    
    <!-- 🎯 复用团队组长端的员工详情面板组件 -->
    @if (employeeDetailForTeamLeader) {
      <div class="team-leader-panel-wrapper">
        <app-employee-detail-panel
          [visible]="true"
          [employeeDetail]="employeeDetailForTeamLeader"
          (close)="onClose()"
          (calendarMonthChange)="onChangeMonth($event)"
          (calendarDayClick)="onCalendarDayClick($event)"
          (projectClick)="onProjectClick($event)"
          (refreshSurvey)="onRefreshSurvey()">
        </app-employee-detail-panel>
      </div>
    } @else {
      <div class="no-workload-data">
        <svg class="no-data-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <circle cx="12" cy="12" r="10"></circle>
          <path d="M8 12h8M12 8v8"/>
        </svg>
        <p>暂无项目负载数据</p>
      </div>
    }
    
  </div>
}

原有内容保留为备份(已禁用)

<!-- ========== 原项目负载标签页内容(已弃用,保留备份) ========== -->
@if (false && activeTab === 'workload') {
  <div class="tab-content workload-tab-deprecated">
    <!-- 原有的负载概况、日历、请假明细、能力问卷等内容 -->
  </div>
}

3. SCSS 样式适配 (employee-info-panel.component.scss)

隐藏复用组件的外层容器

// 🎯 复用团队组长端员工详情面板的样式适配
.team-leader-panel-wrapper {
  // 隐藏复用组件的外层容器和关闭按钮,只保留内容
  ::ng-deep {
    // 隐藏遮罩层和外层面板容器
    .employee-detail-overlay,
    .employee-detail-panel-container {
      position: static !important;
      background: transparent !important;
      box-shadow: none !important;
      width: 100% !important;
      height: auto !important;
      max-width: none !important;
      padding: 0 !important;
      margin: 0 !important;
      z-index: auto !important;
    }

    // 隐藏面板标题和关闭按钮
    .panel-header,
    .btn-close-panel {
      display: none !important;
    }

    // 调整内容区域样式
    .panel-content {
      padding: 0 !important;
      margin: 0 !important;
      max-height: none !important;
      overflow: visible !important;
    }

    // 保持原有的section样式
    .section {
      margin-bottom: 16px;
    }

    // 确保日历和其他组件正常显示
    .employee-calendar,
    .section-header,
    .calendar-grid {
      width: 100%;
    }
  }
}

.no-workload-data {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  color: #8c8c8c;

  .no-data-icon {
    width: 64px;
    height: 64px;
    margin-bottom: 16px;
    opacity: 0.5;
  }

  p {
    font-size: 14px;
    margin: 0;
  }
}

复用架构

员工管理页面 (admin/employees)
├─ EmployeeInfoPanelComponent
│   ├─ 基本信息标签页(原有实现)
│   │   ├─ 查看模式
│   │   └─ 编辑模式
│   │
│   └─ 项目负载标签页(复用组长端组件)
│       └─ EmployeeDetailPanelComponent
│           ├─ 负载概况
│           ├─ 负载日历
│           ├─ 请假明细
│           └─ 能力问卷
│
└─ 导航栏(保持不变)

复用优势

  1. 代码复用:避免重复实现相同的功能
  2. 一致性:确保员工管理页面和团队组长页面显示相同的项目负载数据
  3. 可维护性:只需要在一个地方修改项目负载逻辑
  4. 功能完整:自动继承团队组长端所有的项目负载功能

📁 修改的文件

设计师分配弹窗颜色增强

  1. yss-project/src/app/pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component.scss

    • 添加 .modal-body 浅灰色背景
    • 重构 .designer-card 状态颜色样式
    • 添加 ::before 伪元素彩色边框标识
  2. yss-project/src/app/pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component.html

    • 为所有设计师卡片添加状态类绑定(3 处)

员工信息面板组件复用

  1. yss-project/src/app/shared/components/employee-info-panel/employee-info-panel.component.ts

    • 导入 EmployeeDetailPanelComponent
    • 添加 employeeDetailForTeamLeader getter 进行数据转换
  2. yss-project/src/app/shared/components/employee-info-panel/employee-info-panel.component.html

    • 替换项目负载标签页内容为复用 app-employee-detail-panel
    • 保留原有内容为备份(已禁用)
  3. yss-project/src/app/shared/components/employee-info-panel/employee-info-panel.component.scss

    • 添加 .team-leader-panel-wrapper 样式适配
    • 使用 ::ng-deep 隐藏复用组件的外层容器
    • 添加 .no-workload-data 空状态样式

✅ 测试建议

设计师分配弹窗颜色

  1. 打开任意项目的订单分配阶段
  2. 点击"添加协作成员"按钮
  3. 验证:
    • 弹窗背景为浅灰色
    • 0 个项目的设计师显示绿色边框和背景
    • 1-5 个项目的设计师显示橙色边框和背景
    • 超过 5 个项目的设计师显示红色边框和背景
    • 左侧有明显的彩色边框标识
    • Hover 时有动画效果(上浮、阴影、边框变亮)
    • 选中时边框变为蓝色,但保留原有的彩色标识

员工信息面板复用

  1. 访问 http://localhost:4200/admin/employees
  2. 点击任意员工查看详情
  3. 切换到"项目负载"标签页
  4. 验证:
    • 显示与团队组长端相同的项目负载内容
    • 负载概况、日历、请假明细、能力问卷都正常显示
    • 没有显示复用组件的外层容器和关闭按钮
    • 日历交互(切换月份、点击日期)正常工作
    • 项目点击跳转正常工作
  5. 切换回"基本信息"标签页,验证原有功能正常

🎯 总结

设计师分配弹窗颜色增强

  • ✅ 背景改为浅灰色,增强对比度
  • ✅ 为不同工作量的设计师添加明显的颜色标识(绿/橙/红)
  • ✅ 添加左侧彩色边框标识和发光效果
  • ✅ 实现平滑的 Hover 和选中动画
  • ✅ 保持选中状态下的彩色标识

员工信息面板组件复用

  • ✅ 项目负载部分严格复用 @employee-detail-panel 组件
  • ✅ 基本信息保持原有实现
  • ✅ 导航栏保持不变
  • ✅ 使用 ::ng-deep 隐藏复用组件的外层容器
  • ✅ 实现数据转换 Getter 确保接口兼容性
  • ✅ 保留原有内容为备份(已禁用)

现在,设计师分配弹窗有了更加明显的颜色区分,员工信息面板也严格复用了团队组长端的组件,确保了功能的一致性和代码的可维护性!🎉