using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; using NPP.SmartSchedue.Api.Contracts.Domain.Time; using NPP.SmartSchedue.Api.Contracts.Domain.Work; using NPP.SmartSchedue.Api.Contracts.Services.Workbench; using NPP.SmartSchedue.Api.Contracts.Services.Workbench.Input; using NPP.SmartSchedue.Api.Contracts.Services.Workbench.Output; using NPP.SmartSchedue.Api.Contracts.Core.Enums; using NPP.SmartSchedue.Api.Contracts.Core.Extensions; using NPP.SmartSchedue.Api.Contracts; using ZhonTai.Admin.Services; using ZhonTai.DynamicApi; using ZhonTai.DynamicApi.Attributes; using Microsoft.AspNetCore.Mvc; namespace NPP.SmartSchedue.Api.Services.Workbench; /// /// 工作台服务实现 /// 提供工作台相关的数据查询和业务逻辑处理 /// [DynamicApi(Area = "app")] public class WorkbenchService : BaseService, IWorkbenchService, IDynamicApi { private readonly IWorkOrderRepository _workOrderRepository; private readonly IShiftUnavailabilityRepository _shiftUnavailabilityRepository; private readonly IShiftRepository _shiftRepository; public WorkbenchService( IWorkOrderRepository workOrderRepository, IShiftUnavailabilityRepository shiftUnavailabilityRepository, IShiftRepository shiftRepository) { _workOrderRepository = workOrderRepository; _shiftUnavailabilityRepository = shiftUnavailabilityRepository; _shiftRepository = shiftRepository; } /// /// 获取用户本周日历数据 /// 包含任务排班信息和班次不可用性信息,用于日历视图展示 /// /// 查询参数 /// 本周日历数据 [HttpPost] public async Task GetWeeklyCalendarAsync(WeeklyCalendarInput input) { // 1. 参数预处理和验证 var currentUserId = User?.Id ?? throw new UnauthorizedAccessException("用户未登录"); var targetPersonnelId = input.PersonnelId ?? currentUserId; var targetDate = input.WeekDate ?? DateTime.Now; // 2. 计算本周的开始和结束日期(周一到周日) var weekStartDate = GetWeekStartDate(targetDate); var weekEndDate = weekStartDate.AddDays(6); // 3. 并行查询数据 var tasksTask = GetWeeklyTasksAsync(targetPersonnelId, weekStartDate, weekEndDate, input.IncludeCompletedTasks); var unavailabilitiesTask = input.IncludeUnavailableSlots ? GetWeeklyUnavailabilitiesAsync(targetPersonnelId, weekStartDate, weekEndDate) : Task.FromResult(new List()); var shiftsTask = GetAllActiveShiftsAsync(); await Task.WhenAll(tasksTask, unavailabilitiesTask, shiftsTask); var tasks = await tasksTask; var unavailabilities = await unavailabilitiesTask; var shifts = await shiftsTask; // 4. 构建日历数据结构 var result = new WeeklyCalendarOutput { WeekStartDate = weekStartDate, WeekEndDate = weekEndDate, PersonnelId = targetPersonnelId, PersonnelName = "当前用户", // TODO: 从用户服务获取用户名 Days = new List() }; // 5. 按天组织数据 for (int dayOffset = 0; dayOffset < 7; dayOffset++) { var currentDate = weekStartDate.AddDays(dayOffset); var dayItem = new CalendarDayItem { Date = currentDate, DayOfWeek = (int)currentDate.DayOfWeek == 0 ? 7 : (int)currentDate.DayOfWeek, DayOfWeekName = GetDayOfWeekName((int)currentDate.DayOfWeek == 0 ? 7 : (int)currentDate.DayOfWeek), Shifts = new List() }; // 6. 为每一天的每个班次构建数据 foreach (var shift in shifts.OrderBy(s => s.StartTime)) { var shiftItem = new CalendarShiftItem { ShiftId = shift.Id, ShiftName = shift.Name, StartTime = shift.StartTime, EndTime = shift.EndTime, Tasks = new List(), UnavailableItems = new List() }; // 7. 填充当前班次的任务数据 var dayTasks = tasks.Where(t => t.WorkOrderDate.Date == currentDate.Date && t.ShiftId == shift.Id).ToList(); foreach (var task in dayTasks) { shiftItem.Tasks.Add(new CalendarTaskItem { TaskId = task.Id, TaskCode = task.WorkOrderCode ?? task.Code ?? "", ProjectNumber = task.ProjectNumber ?? "", ProcessName = task.ProcessName ?? "", Status = task.Status, StatusName = ((WorkOrderStatusEnum)task.Status).ToString(), Priority = task.Priority, EstimatedHours = task.EstimatedHours, PlannedStartTime = task.PlannedStartTime, PlannedEndTime = task.PlannedEndTime, Remarks = task.Remarks ?? "" }); } // 8. 填充当前班次的不可用时间段数据 var dayUnavailabilities = unavailabilities.Where(u => u.Date.Date == currentDate.Date && u.ShiftId == shift.Id).ToList(); foreach (var unavailability in dayUnavailabilities) { shiftItem.UnavailableItems.Add(new CalendarUnavailableItem { UnavailabilityId = unavailability.Id, ReasonType = unavailability.ReasonType, ReasonTypeName = unavailability.ReasonType.GetDisplayName(), Remark = unavailability.Remark ?? "", EffectiveStartTime = unavailability.EffectiveStartTime, EffectiveEndTime = unavailability.EffectiveEndTime, Priority = unavailability.Priority }); } dayItem.Shifts.Add(shiftItem); } result.Days.Add(dayItem); } return result; } #region 私有辅助方法 /// /// 获取指定日期所在周的周一日期 /// /// 指定日期 /// 周一日期 private static DateTime GetWeekStartDate(DateTime date) { var dayOfWeek = (int)date.DayOfWeek; if (dayOfWeek == 0) dayOfWeek = 7; // 将周日从0调整为7 return date.AddDays(-(dayOfWeek - 1)).Date; } /// /// 获取星期几的中文名称 /// /// 星期几(1=周一,7=周日) /// 中文名称 private static string GetDayOfWeekName(int dayOfWeek) { return dayOfWeek switch { 1 => "周一", 2 => "周二", 3 => "周三", 4 => "周四", 5 => "周五", 6 => "周六", 7 => "周日", _ => "" }; } /// /// 获取指定人员本周的工作任务 /// /// 人员ID /// 周开始日期 /// 周结束日期 /// 是否包含已完成任务 /// 任务列表 private async Task> GetWeeklyTasksAsync(long personnelId, DateTime weekStartDate, DateTime weekEndDate, bool includeCompleted) { // 构建查询条件 var query = _workOrderRepository.Where(t => t.AssignedPersonnelId == personnelId && t.WorkOrderDate >= weekStartDate && t.WorkOrderDate <= weekEndDate); // 根据参数决定是否过滤已完成任务 if (!includeCompleted) { query = query.Where(t => t.Status != (int)WorkOrderStatusEnum.Completed); } // 执行查询并包含相关实体 var tasks = await query .Include(t => t.ProcessEntity) .Include(t => t.ShiftEntity) .OrderBy(t => t.WorkOrderDate) .OrderBy(t => t.PlannedStartTime) .ToListAsync(); return tasks; } /// /// 获取指定人员本周的班次不可用记录 /// /// 人员ID /// 周开始日期 /// 周结束日期 /// 不可用记录列表 private async Task> GetWeeklyUnavailabilitiesAsync(long personnelId, DateTime weekStartDate, DateTime weekEndDate) { var unavailabilities = await _shiftUnavailabilityRepository.Where(u => u.PersonnelId == personnelId && u.Date >= weekStartDate && u.Date <= weekEndDate) .OrderBy(u => u.Date) .OrderBy(u => u.Priority) .ToListAsync(); return unavailabilities; } /// /// 获取所有活跃的班次 /// /// 班次列表 private async Task> GetAllActiveShiftsAsync() { var shifts = await _shiftRepository.Where(s => s.IsEnabled) .OrderBy(s => s.StartTime) .ToListAsync(); return shifts; } #endregion }