using F9WebAiTest.Application.Dtos.SYS.Reports; using F9WebAiTest.Domain.Common; using F9WebAiTest.Domain.Entities.Base; using F9WebAiTest.Domain.Entities.Prod; using MediatR; using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments; namespace F9WebAiTest.Application.CQRS.SYS.Reports.Queries; /// /// 落丝记录报表查询(对应 DsName = RepDt_Prod_Lsjl)。 /// 参数:日期范围 / 车间(含子车间)/ 机组 / 庄口 / 关键字(庄口、规格、颜色)。 /// 输出字段名与 F9 落丝记录报表模板一致(中文列名)。 /// public record GetLsjlRepQuery( DateTime? DateStart, DateTime? DateEnd, long DepId, int Jizu, long GyzkId, string Like) : IRequest; public class GetLsjlRepQueryHandler : IRequestHandler { private readonly IRepository _repo; private readonly IRepository _deptRepo; private readonly IRepository _zkRepo; public GetLsjlRepQueryHandler( IRepository repo, IRepository deptRepo, IRepository zkRepo) { _repo = repo; _deptRepo = deptRepo; _zkRepo = zkRepo; } public async Task Handle(GetLsjlRepQuery query, CancellationToken cancellationToken) { var all = await _repo.GetAllAsync(); var depts = await _deptRepo.GetAllAsync(); var zks = await _zkRepo.GetAllAsync(); var deptDict = depts.GroupBy(d => d.Id).ToDictionary(g => g.Key, g => g.First().Name); var zkDict = zks.GroupBy(z => z.Id).ToDictionary(g => g.Key, g => g.First().ZhuangKouName); var depIds = ResolveDepIds(depts, query.DepId); IEnumerable rows = all; if (query.DateStart.HasValue) { var start = query.DateStart.Value.Date; rows = rows.Where(x => x.WorkDate.Date >= start); } if (query.DateEnd.HasValue) { var end = query.DateEnd.Value.Date; rows = rows.Where(x => x.WorkDate.Date <= end); } if (depIds != null) rows = rows.Where(x => depIds.Contains(x.DeptId)); if (query.Jizu > 0) rows = rows.Where(x => x.Jizu == query.Jizu); if (query.GyzkId > 0) rows = rows.Where(x => x.GyzkId == query.GyzkId); if (!string.IsNullOrWhiteSpace(query.Like)) { var kw = query.Like.Trim(); rows = rows.Where(x => deptDict.GetValueOrDefault(x.DeptId, "").Contains(kw) || zkDict.GetValueOrDefault(x.GyzkId, "").Contains(kw) || (x.Guige ?? "").Contains(kw) || (x.Yanse ?? "").Contains(kw)); } var list = rows .OrderBy(x => x.WorkDate) .ThenBy(x => deptDict.GetValueOrDefault(x.DeptId, "")) .ThenBy(x => x.Jizu) .ThenBy(x => x.LuosiTime) .ToList(); // 明细行:键名与 .grf 模板 DetailGrid.Recordset.Field 完全一致(中文列名) var fieldRows = new List(list.Count); foreach (var x in list) { var depName = deptDict.GetValueOrDefault(x.DeptId, ""); var zkName = zkDict.GetValueOrDefault(x.GyzkId, ""); fieldRows.Add(new Dictionary(StringComparer.Ordinal) { ["日期"] = x.WorkDate.ToString("yyyy-MM-dd"), ["车间"] = depName, ["机组"] = x.Jizu, ["庄口"] = zkName, ["回数"] = x.Huishu, ["颜色"] = x.Yanse ?? "", ["半车"] = x.Isbanche ? "半车" : "整车", ["落丝时间"] = x.LuosiTime ?? "", ["缫丝桶数"] = x.Chetaishu, // 以下是备选列(模板未使用时不显示,可用于自定义模板) ["规格"] = x.Guige ?? "", ["车台范围"] = x.ChetaiStart > 0 ? $"{x.ChetaiStart}-{x.ChetaiEnd}" : "", ["缫丝时长"] = Math.Round(x.Hours, 2), ["车速"] = Math.Round(x.Chesu, 2), }); } var depText = query.DepId > 0 ? deptDict.GetValueOrDefault(query.DepId, "") : "(全部)"; var zkText = query.GyzkId > 0 ? zkDict.GetValueOrDefault(query.GyzkId, "") : "(全部)"; var paramData = new ReportDataDto_Data { Field_Data = fieldRows }; paramData.Parameter_Data = new { 开始日期 = query.DateStart?.ToString("yyyy-MM-dd") ?? "", 结束日期 = query.DateEnd?.ToString("yyyy-MM-dd") ?? "", 车间 = string.IsNullOrWhiteSpace(depText) ? "(全部)" : depText, 机组 = query.Jizu > 0 ? query.Jizu.ToString() : "(全部)", 庄口 = string.IsNullOrWhiteSpace(zkText) ? "(全部)" : zkText, 记录数 = fieldRows.Count, 查询时间 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), }; var dto = new ReportDto_DataSource(); dto.Report_Data.Add("main", paramData); return dto; } /// 车间 Id → 自身 + 全部子孙车间 Id(null 表示不限) private static HashSet? ResolveDepIds(List depts, long depId) { if (depId <= 0) return null; var children = depts .GroupBy(d => d.ParentId) .ToDictionary(g => g.Key, g => g.Select(d => d.Id).ToList()); var result = new HashSet { depId }; var stack = new Stack(); stack.Push(depId); while (stack.Count > 0) { var cur = stack.Pop(); if (!children.TryGetValue(cur, out var kids)) continue; foreach (var k in kids) if (result.Add(k)) stack.Push(k); } return result; } }