2024-10-24
重新设计设计师团队分配弹窗中的日历视图,改为月历模式,优化为单屏显示,无需横向滚动,清晰展示所有设计师在每一天的状态。
设计师列 | 日期1 | 日期2 | 日期3 | ... | 日期30+
需要横向滚动才能看到全部日期
<!-- 设计师列表区域 -->
<div class="designers-section">
<!-- 显示所有设计师信息,组长特殊标记 -->
</div>
<!-- 月历网格 -->
<div class="month-calendar-grid">
<!-- 星期标题:日 一 二 三 四 五 六 -->
<div class="weekday-header">...</div>
<!-- 7列 x 5/6行的日期网格 -->
<div class="dates-grid">
<div class="day-cell">
<!-- 日期号 -->
<div class="day-header">1</div>
<!-- 该日期下所有设计师的状态 -->
<div class="designers-status-list">
<div class="designer-status-row">
<span class="designer-initial">张</span>
<div class="status-indicators-mini">
<span class="indicator free">✓</span>
</div>
</div>
<!-- 更多设计师... -->
</div>
</div>
<!-- 更多日期... -->
</div>
</div>
特性:
代码:
<div class="designer-item" [class.is-leader]="designer.isLeader">
<div class="designer-avatar-small">
<img [src]="designer.avatar" />
@if (designer.isLeader) {
<span class="leader-badge-icon" title="组长">👑</span>
}
</div>
<div class="designer-info-compact">
<div class="designer-name-row">
<span class="name">{{ designer.name }}</span>
@if (designer.isLeader) {
<span class="leader-tag">组长</span>
}
</div>
<div class="designer-status-row">
<span class="status-dot" [class]="designer.status"></span>
<span class="status-label">{{ getStatusText(designer.status) }}</span>
<span class="workload-label">{{ designer.workload }}%</span>
</div>
</div>
</div>
特性:
布局:
.month-calendar-grid {
.weekday-header {
display: grid;
grid-template-columns: repeat(7, 1fr);
background: linear-gradient(135deg, #475569 0%, #334155 100%);
}
.dates-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-auto-rows: minmax(120px, auto);
gap: 1px;
background: #e2e8f0; // 网格线颜色
}
}
每个日期单元格内显示:
✓ 绿色 - 空闲可接单◆ 橙色 - 对图日● 红色 - 忙碌中数字 紫色 - 事件数量状态颜色编码:
.designer-status-row {
&.available {
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
border-left: 3px solid #10b981; // 绿色
}
&.review {
background: linear-gradient(135deg, #fed7aa 0%, #fdba74 100%);
border-left: 3px solid #f59e0b; // 橙色
}
&.busy {
background: linear-gradient(135deg, #fecaca 0%, #fca5a5 100%);
border-left: 3px solid #ef4444; // 红色
}
}
// 判断是否是今天
isToday(date: Date): boolean {
const today = new Date();
return date.getDate() === today.getDate() &&
date.getMonth() === today.getMonth() &&
date.getFullYear() === today.getFullYear();
}
// 判断是否是当前月份
isCurrentMonth(date: Date): boolean {
return date.getMonth() === this.currentDate.getMonth() &&
date.getFullYear() === this.currentDate.getFullYear();
}
// 判断是否是周末
isWeekend(date: Date): boolean {
const day = date.getDay();
return day === 0 || day === 6; // 0=周日, 6=周六
}
// 获取设计师在指定日期的状态CSS类
getDesignerDayStatusClass(designer: Designer, date: Date): string {
const classes: string[] = [];
if (this.isDateAvailable(designer, date)) classes.push('available');
if (this.isDateReview(designer, date)) classes.push('review');
if (this.isDateBusy(designer, date)) classes.push('busy');
return classes.join(' ');
}
// 获取设计师在指定日期的状态标题(hover提示)
getDesignerDayStatusTitle(designer: Designer, date: Date): string {
const statuses: string[] = [designer.name];
if (this.isDateAvailable(designer, date)) statuses.push('空闲可接单');
if (this.isDateReview(designer, date)) statuses.push('对图日');
if (this.isDateBusy(designer, date)) statuses.push('忙碌中');
const events = this.getDateEvents(designer, date);
if (events.length > 0) statuses.push(`${events.length}个事件`);
return statuses.join(' · ');
}
// 判断设计师在指定日期是否空闲
isDateAvailable(designer: Designer, date: Date): boolean {
const dateStr = this.formatDateString(date);
return designer.availableDates?.includes(dateStr) ?? false;
}
// 判断设计师在指定日期是否对图
isDateReview(designer: Designer, date: Date): boolean {
const dateStr = this.formatDateString(date);
const events = designer.upcomingEvents || [];
return events.some(e => e.type === 'review' &&
this.formatDateString(e.date) === dateStr);
}
// 判断设计师在指定日期是否忙碌
isDateBusy(designer: Designer, date: Date): boolean {
const events = this.getDateEvents(designer, date);
return events.some(e => e.type === 'project');
}
// 格式化日期为字符串(用于比较)
formatDateString(date: Date): string {
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`;
}
// 获取工作量CSS类
getWorkloadClass(workload: number): string {
if (workload >= 80) return 'high';
if (workload >= 50) return 'medium';
return 'low';
}
.designer-item {
&.is-leader {
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
border-color: #f59e0b;
&:hover {
border-color: #d97706;
box-shadow: 0 2px 8px rgba(217, 119, 6, 0.25);
}
}
.leader-badge-icon {
position: absolute;
top: -6px;
right: -6px;
background: #fbbf24;
border-radius: 50%;
font-size: 10px; // 👑 图标
}
.leader-tag {
padding: 2px 8px;
background: #fbbf24;
color: #78350f;
font-size: 11px;
font-weight: 600;
border-radius: 4px;
}
}
今天:
&.is-today {
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
border: 2px solid #3b82f6;
.day-number {
background: #3b82f6;
color: #ffffff;
}
}
周末:
&.is-weekend {
background: #fef9f3; // 浅黄色
.day-number {
color: #dc2626; // 红色日期号
}
}
非当前月份:
&.not-current-month {
background: #f8fafc;
opacity: 0.5; // 半透明
.day-number {
color: #94a3b8; // 浅灰色
}
}
1400px以下:
.day-cell {
min-height: 100px; // 从120px降至100px
.designers-status-list {
max-height: 65px; // 从80px降至65px
}
}
1024px以下:
.day-cell {
min-height: 90px; // 进一步降低
padding: 4px;
.day-number {
width: 24px;
height: 24px;
font-size: 12px;
}
.designer-initial {
width: 16px;
height: 16px;
font-size: 9px;
}
}
月历标准布局
组长标识
单屏显示优化
状态清晰标注
交互体验
视觉设计
❌ 需要横向滚动
❌ 设计师和日期混在一起
❌ 难以快速查看整月情况
❌ 组长标识不明显
✅ 单屏显示完整月份
✅ 设计师列表独立展示在上方
✅ 传统月历布局,直观易懂
✅ 组长有明显的👑标识和金色背景
✅ 每天的设计师状态一目了然
✅ 清晰的色彩编码系统
识别组长
查看设计师状态
查看日期状态
派单决策
.dates-grid {
display: grid;
grid-template-columns: repeat(7, 1fr); // 7列等宽
grid-auto-rows: minmax(120px, auto); // 自适应行高
gap: 1px; // 网格线
}
<div class="day-cell"
[class.is-today]="isToday(date)"
[class.is-weekend]="isWeekend(date)"
[class.not-current-month]="!isCurrentMonth(date)">
// 综合判断设计师在指定日期的状态
getDesignerDayStatusClass(designer: Designer, date: Date): string {
// 可能同时有多个状态(如:空闲 + 对图)
// 返回空格分隔的类名字符串
}
formatDateString(date: Date): string {
// 统一格式:YYYY-MM-DD
// 用于日期比较和查找
}
yss-project/src/app/pages/customer-service/consultation-order/components/designer-calendar/designer-calendar.component.html
yss-project/src/app/pages/customer-service/consultation-order/components/designer-calendar/designer-calendar.component.ts
isToday(), isCurrentMonth(), isWeekend()getDesignerDayStatusClass(), getDesignerDayStatusTitle()isDateAvailable(), isDateReview(), isDateBusy()formatDateString(), getWorkloadClass()yss-project/src/app/pages/customer-service/consultation-order/components/designer-calendar/designer-calendar.component.scss
.month-calendar-view 主容器.designers-section 设计师列表样式.month-calendar-grid 月历网格样式✅ 无编译错误 ✅ 无Linter警告 ✅ TypeScript类型检查通过 ✅ 样式正确编译
本次重新设计成功将横向滚动的表格视图改造为标准的月历视图,实现了以下核心目标:
✅ 单屏显示 - 无需横向滚动即可查看完整月份
✅ 组长标识 - 👑图标 + 金色背景,一目了然
✅ 状态清晰 - 色彩编码 + 图标系统,快速识别
✅ 精美设计 - 现代化UI,渐变配色,流畅动画
✅ 响应式 - 适配不同屏幕尺寸
新设计大幅提升了设计师日历的可读性和易用性,为项目分配决策提供了更直观的视觉支持。
项目现已可以正常编译和运行 ✅