Asoka.Wang 2b3f9acdce 123
2025-09-22 19:09:47 +08:00

256 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}