如何在angular-calendar中按元数据固定周视图用户事件列位置?
Angular Calendar周视图按用户固定列展示事件实现方案
完全可以实现,核心思路是自定义周视图模板+用户列固定配置,以下是具体步骤:
1. 定义固定的用户列配置
先提前配置好每个用户对应的列位置、颜色,数组的顺序直接决定列的左右排列顺序:
// 组件内定义用户列配置,固定顺序对应列的左右位置 userColumnConfigs = [ { userId: 'user1', columnIndex: 0, color: '#ffb3ba' }, // 粉色列(最左侧) { userId: 'user2', columnIndex: 1, color: '#ff6b6b' }, // 红色列(中间) { userId: 'user3', columnIndex: 2, color: '#86e49d' } // 绿色列(最右侧) ];
2. 给事件关联用户ID
确保每个事件的meta字段携带对应用户ID,用来匹配到对应的列和颜色:
events: CalendarEvent[] = [ { start: new Date(), end: new Date(new Date().setHours(new Date().getHours() + 2)), title: '用户1的项目评审会', meta: { userId: 'user1' } // 绑定用户标识 }, { start: new Date(new Date().setHours(14)), end: new Date(new Date().setHours(16)), title: '用户2的客户对接', meta: { userId: 'user2' } }, // 更多事件... ];
3. 自定义周视图模板
重写angular-calendar的周视图模板,将每一天的区域拆分为预先定义的用户列,把对应用户的事件渲染到固定列中:
<mwl-calendar-week-view [viewDate]="viewDate" [events]="events" [customTemplate]="customWeekViewTemplate" ></mwl-calendar-week-view> <!-- 自定义周视图模板 --> <ng-template #customWeekViewTemplate let-view="view" let-day="day" let-events="events"> <div class="calendar-day"> <!-- 日期头部 --> <div class="day-header">{{ day.date | date:'EEE, MMM d' }}</div> <!-- 用户列容器 --> <div class="user-columns"> <div *ngFor="let userConfig of userColumnConfigs" class="user-column" [style.width]="100 / userColumnConfigs.length + '%'" > <!-- 用户列头部(可选,显示用户名) --> <div class="column-header" [style.backgroundColor]="userConfig.color"> {{ userConfig.userId }} </div> <!-- 渲染当前用户当天的事件 --> <div *ngFor="let event of events.filter(e => e.meta?.userId === userConfig.userId)" class="calendar-event" [style.backgroundColor]="userConfig.color" [style.top]="getEventTop(event, day) + '%'" [style.height]="getEventHeight(event, day) + '%'" > <span class="event-title">{{ event.title }}</span> </div> </div> </div> </div> </ng-template>
4. 实现事件位置计算方法
通过计算事件的开始时间、持续时长,确定事件在列中的垂直位置和高度:
// 计算事件顶部偏移百分比 getEventTop(event: CalendarEvent, day: CalendarDay): number { const dayStart = new Date(day.date); dayStart.setHours(0, 0, 0, 0); const minutesSinceDayStart = (event.start.getTime() - dayStart.getTime()) / (1000 * 60); return (minutesSinceDayStart / (24 * 60)) * 100; } // 计算事件高度百分比 getEventHeight(event: CalendarEvent, day: CalendarDay): number { const durationMinutes = (event.end.getTime() - event.start.getTime()) / (1000 * 60); return (durationMinutes / (24 * 60)) * 100; }
5. 添加样式调整
通过CSS确保列布局和事件展示正常:
.calendar-day { position: relative; height: 600px; /* 自定义日历每天的高度 */ border: 1px solid #eee; margin-bottom: 8px; } .day-header { padding: 8px; background-color: #f5f5f5; border-bottom: 1px solid #eee; font-weight: 500; } .user-columns { display: flex; height: calc(100% - 40px); /* 减去日期头部高度 */ } .user-column { position: relative; border-right: 1px solid #eee; box-sizing: border-box; } .user-column:last-child { border-right: none; } .column-header { padding: 4px; color: #fff; font-size: 12px; text-align: center; } .calendar-event { position: absolute; left: 3px; right: 3px; padding: 4px; border-radius: 4px; color: #fff; font-size: 12px; overflow: hidden; cursor: pointer; }
额外优化点
- 如果需要处理跨天事件,可以在模板中判断事件是否跨天,拆分到对应日期的列中;
- 若存在同用户同时间段的重叠事件,可添加重叠偏移逻辑,避免事件完全覆盖;
- 可以通过angular-calendar的
CalendarWeekViewBeforeRenderEvent钩子,提前对事件进行分组处理,减少模板中的过滤逻辑。
内容的提问来源于stack exchange,提问作者yann Guillerm
相关产品推荐
相关产品推荐

