本次修改完成了两个主要需求:
@employee-detail-panel 组件#fafafa),增强对比度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);
}
}
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)
#1890ff)@employee-detail-panel 组件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
};
}
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>
}
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
│ ├─ 负载概况
│ ├─ 负载日历
│ ├─ 请假明细
│ └─ 能力问卷
│
└─ 导航栏(保持不变)
yss-project/src/app/pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component.scss
.modal-body 浅灰色背景.designer-card 状态颜色样式::before 伪元素彩色边框标识yss-project/src/app/pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component.html
yss-project/src/app/shared/components/employee-info-panel/employee-info-panel.component.ts
EmployeeDetailPanelComponentemployeeDetailForTeamLeader getter 进行数据转换yss-project/src/app/shared/components/employee-info-panel/employee-info-panel.component.html
app-employee-detail-panelyss-project/src/app/shared/components/employee-info-panel/employee-info-panel.component.scss
.team-leader-panel-wrapper 样式适配::ng-deep 隐藏复用组件的外层容器.no-workload-data 空状态样式@employee-detail-panel 组件::ng-deep 隐藏复用组件的外层容器现在,设计师分配弹窗有了更加明显的颜色区分,员工信息面板也严格复用了团队组长端的组件,确保了功能的一致性和代码的可维护性!🎉