256 lines
10 KiB
C#
256 lines
10 KiB
C#
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;
|
||
|
||
/// <summary>
|
||
/// 工作台服务实现
|
||
/// 提供工作台相关的数据查询和业务逻辑处理
|
||
/// </summary>
|
||
[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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取用户本周日历数据
|
||
/// 包含任务排班信息和班次不可用性信息,用于日历视图展示
|
||
/// </summary>
|
||
/// <param name="input">查询参数</param>
|
||
/// <returns>本周日历数据</returns>
|
||
[HttpPost]
|
||
public async Task<WeeklyCalendarOutput> 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<ShiftUnavailabilityEntity>());
|
||
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<CalendarDayItem>()
|
||
};
|
||
|
||
// 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<CalendarShiftItem>()
|
||
};
|
||
|
||
// 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<CalendarTaskItem>(),
|
||
UnavailableItems = new List<CalendarUnavailableItem>()
|
||
};
|
||
|
||
// 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 私有辅助方法
|
||
|
||
/// <summary>
|
||
/// 获取指定日期所在周的周一日期
|
||
/// </summary>
|
||
/// <param name="date">指定日期</param>
|
||
/// <returns>周一日期</returns>
|
||
private static DateTime GetWeekStartDate(DateTime date)
|
||
{
|
||
var dayOfWeek = (int)date.DayOfWeek;
|
||
if (dayOfWeek == 0) dayOfWeek = 7; // 将周日从0调整为7
|
||
return date.AddDays(-(dayOfWeek - 1)).Date;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取星期几的中文名称
|
||
/// </summary>
|
||
/// <param name="dayOfWeek">星期几(1=周一,7=周日)</param>
|
||
/// <returns>中文名称</returns>
|
||
private static string GetDayOfWeekName(int dayOfWeek)
|
||
{
|
||
return dayOfWeek switch
|
||
{
|
||
1 => "周一",
|
||
2 => "周二",
|
||
3 => "周三",
|
||
4 => "周四",
|
||
5 => "周五",
|
||
6 => "周六",
|
||
7 => "周日",
|
||
_ => ""
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取指定人员本周的工作任务
|
||
/// </summary>
|
||
/// <param name="personnelId">人员ID</param>
|
||
/// <param name="weekStartDate">周开始日期</param>
|
||
/// <param name="weekEndDate">周结束日期</param>
|
||
/// <param name="includeCompleted">是否包含已完成任务</param>
|
||
/// <returns>任务列表</returns>
|
||
private async Task<List<WorkOrderEntity>> 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取指定人员本周的班次不可用记录
|
||
/// </summary>
|
||
/// <param name="personnelId">人员ID</param>
|
||
/// <param name="weekStartDate">周开始日期</param>
|
||
/// <param name="weekEndDate">周结束日期</param>
|
||
/// <returns>不可用记录列表</returns>
|
||
private async Task<List<ShiftUnavailabilityEntity>> 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有活跃的班次
|
||
/// </summary>
|
||
/// <returns>班次列表</returns>
|
||
private async Task<List<ShiftEntity>> GetAllActiveShiftsAsync()
|
||
{
|
||
var shifts = await _shiftRepository.Where(s => s.IsEnabled)
|
||
.OrderBy(s => s.StartTime)
|
||
.ToListAsync();
|
||
|
||
return shifts;
|
||
}
|
||
|
||
#endregion
|
||
} |