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
}