新增质量模块(工艺执行书 / 样茧试缫)与报表中心

质量模块:
- 11 张工艺执行书表:封面、试产、选剥茧(含混茧明细)、试缫与大样、煮茧(含分车间配温、副煮车间)、自动缫(含大样)、后缫
- 10 张样茧试缫表:原料小样/综合样主表 + 选茧、解舒、茧幅、切剖、清洁洁净、茧丝百回纤度
- 服务与接口、主控指针回写(列表 √ 标记)、封面编号自增、报表数据包
- 前端 8 张报表打印版式、7 类工艺单据与 6 类调查录入弹窗、字段驱动表单/表格组件
- 菜单种子新增「质量」目录,样茧子表增加 YjssType 判别列,避免原料小样与综合样自增 Id 重号串数据

报表中心:
- 报表模板管理、锐浪 grhtml5 加载与预览、全屏设计面板、数据源 Provider(落丝记录、职工花名册)

其他:同步工作进度 1-11 文档、开发数据库快照、.gitignore 忽略运行日志目录
This commit is contained in:
yanpeng200212
2026-10-22 10:30:37 +08:00
parent 8c4c464362
commit a8890c81e9
92 changed files with 14785 additions and 70 deletions
@@ -0,0 +1,551 @@
using F9WebAiTest.Application.Common;
using F9WebAiTest.Application.Dtos.QC;
using F9WebAiTest.Domain.Common;
using F9WebAiTest.Domain.Entities.Base;
using F9WebAiTest.Domain.Entities.QC.Yjss;
using F9WebAiTest.Domain.Entities.SYS.YuanliaoZhuangkous;
namespace F9WebAiTest.Application.Services.QC;
public interface IYjssService
{
Task<PageResult<YjssListItemDto>> GetPagedAsync(int pageIndex, int pageSize, int type, int year, string keyword);
Task<YjssListItemDto> SaveYlxyAsync(YjssMainYlxy dto);
Task<YjssListItemDto> SaveZhyAsync(YjssMainZhy dto);
Task DeleteAsync(int type, long id);
Task<YjssDcXjdc> GetXjdcAsync(int type, long yjssId);
Task<bool> SaveXjdcAsync(int type, YjssDcXjdc dto);
Task<List<YjssDcJsdc>> GetJsdcAsync(int type, long yjssId);
Task<bool> SaveJsdcAsync(int type, YjssDcJsdc dto);
Task DeleteJsdcAsync(int type, long id);
Task<YjssJfdcDto> GetJfdcAsync(int type, long yjssId);
Task<bool> SaveJfdcAsync(int type, YjssJfdcDto dto);
Task<YjssDcQpdc> GetQpdcAsync(int type, long yjssId);
Task<bool> SaveQpdcAsync(int type, YjssDcQpdc dto);
Task<YjssDcQjjj> GetQjjjAsync(int type, long yjssId);
Task<bool> SaveQjjjAsync(int type, YjssDcQjjj dto);
Task<YjssJsbhxdDto> GetJsbhxdAsync(int type, long yjssId);
Task<bool> SaveJsbhxdAsync(int type, YjssJsbhxdDto dto);
/// <summary>整页数据(含报表参数区):用于「综合样报表 / 原料小样报表 / 解舒调查报表」</summary>
Task<YjssFullDto> GetFullAsync(int type, long yjssId);
/// <summary>解舒调查平均值汇总(跨多条记录,口径对齐 F9 GetDataByYjssCommand)</summary>
Task<Dictionary<string, object?>> GetJsdcSummaryAsync(int type, long yjssId);
}
/// <summary>
/// 质量模块 —— 样茧试缫(对应 F9 生产\质量\样茧试缫)。
/// 两类样品:原料小样(选茧 / 解舒 / 清洁洁净)、综合样(加 茧幅 / 切剖 / 茧丝百回纤度)。
/// 子表统一外键 yjss_id;一对一子表保存后回写主表指针,解舒/百回纤度回写记录数。
/// </summary>
public class YjssService : IYjssService
{
private readonly IRepository<YjssMainYlxy> _ylxyRepo;
private readonly IRepository<YjssMainZhy> _zhyRepo;
private readonly IRepository<YjssDcXjdc> _xjdcRepo;
private readonly IRepository<YjssDcJsdc> _jsdcRepo;
private readonly IRepository<YjssDcJfdcMain> _jfdcRepo;
private readonly IRepository<YjssDcJfdcItem> _jfdcItemRepo;
private readonly IRepository<YjssDcQpdc> _qpdcRepo;
private readonly IRepository<YjssDcQjjj> _qjjjRepo;
private readonly IRepository<YjssDcJsbhxdMain> _jsbhxdMainRepo;
private readonly IRepository<YjssDcJsbhxd> _jsbhxdRepo;
private readonly IRepository<YuanliaoZhuangkou> _ylzkRepo;
private readonly IRepository<CraftZhuangKou> _gyzkRepo;
public YjssService(
IRepository<YjssMainYlxy> ylxyRepo,
IRepository<YjssMainZhy> zhyRepo,
IRepository<YjssDcXjdc> xjdcRepo,
IRepository<YjssDcJsdc> jsdcRepo,
IRepository<YjssDcJfdcMain> jfdcRepo,
IRepository<YjssDcJfdcItem> jfdcItemRepo,
IRepository<YjssDcQpdc> qpdcRepo,
IRepository<YjssDcQjjj> qjjjRepo,
IRepository<YjssDcJsbhxdMain> jsbhxdMainRepo,
IRepository<YjssDcJsbhxd> jsbhxdRepo,
IRepository<YuanliaoZhuangkou> ylzkRepo,
IRepository<CraftZhuangKou> gyzkRepo)
{
_ylxyRepo = ylxyRepo;
_zhyRepo = zhyRepo;
_xjdcRepo = xjdcRepo;
_jsdcRepo = jsdcRepo;
_jfdcRepo = jfdcRepo;
_jfdcItemRepo = jfdcItemRepo;
_qpdcRepo = qpdcRepo;
_qjjjRepo = qjjjRepo;
_jsbhxdMainRepo = jsbhxdMainRepo;
_jsbhxdRepo = jsbhxdRepo;
_ylzkRepo = ylzkRepo;
_gyzkRepo = gyzkRepo;
}
private static string SampleTypeName(int t) => t switch
{
1 => "定价抽样",
2 => "入库抽样",
3 => "鲜茧抽样",
_ => ""
};
// ==================== 主表 ====================
public async Task<PageResult<YjssListItemDto>> GetPagedAsync(int pageIndex, int pageSize, int type, int year, string keyword)
{
if (year <= 0) year = DateTime.Today.Year;
var items = new List<YjssListItemDto>();
var ylzks = (await _ylzkRepo.FindAsync(x => !x.IsDeleted)).ToDictionary(x => x.Id, x => x.Name);
var gyzks = (await _gyzkRepo.FindAsync(x => !x.IsDeleted)).ToDictionary(x => x.Id, x => x.ZhuangKouName);
if (type == 1)
{
var rows = await _ylxyRepo.FindAsync(x => !x.IsDeleted && x.Date.Year == year);
items = rows.Select(x => new YjssListItemDto
{
Id = x.Id, Type = 1, ZhuangKouId = x.YlzkId,
ZhuangKouName = ylzks.GetValueOrDefault(x.YlzkId, ""),
Date = x.Date, SampleType = x.Type, SampleTypeName = SampleTypeName(x.Type),
ZhongLiang = x.ZhongLiang, HuiChaoLv = x.HuiChaoLv,
XjdcId = x.XjdcId, JsdcCt = x.JsdcCt, QjjjId = x.QjjjId, Memo = x.Memo
}).ToList();
}
else
{
var rows = await _zhyRepo.FindAsync(x => !x.IsDeleted && x.Date.Year == year);
items = rows.Select(x => new YjssListItemDto
{
Id = x.Id, Type = 2, ZhuangKouId = x.GyzkId,
ZhuangKouName = gyzks.GetValueOrDefault(x.GyzkId, ""),
Date = x.Date, SampleType = 2, SampleTypeName = "综合样",
ZhongLiang = x.ZhongLiang, XjdcId = x.XjdcId, JsdcCt = x.JsdcCt,
JfdcId = x.JfdcId, QpdcId = x.QpdcId, QjjjId = x.QjjjId,
JsbhxdCt = x.JsbhxdCt, Memo = x.Memo
}).ToList();
}
if (!string.IsNullOrWhiteSpace(keyword))
items = items.Where(x => x.ZhuangKouName.Contains(keyword)).ToList();
items = items.OrderByDescending(x => x.Date).ThenByDescending(x => x.Id).ToList();
var total = items.Count;
return new PageResult<YjssListItemDto>
{
Total = total, PageIndex = pageIndex, PageSize = pageSize,
Items = items.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()
};
}
public async Task<YjssListItemDto> SaveYlxyAsync(YjssMainYlxy dto)
{
if (dto.YlzkId <= 0) throw new ServiceException("请选择原料庄口");
if (dto.Date == default) dto.Date = DateTime.Today;
var exist = dto.Id > 0 ? await _ylxyRepo.GetByIdAsync(dto.Id) : null;
if (exist == null)
{
dto.Id = 0; dto.IsDeleted = false;
await _ylxyRepo.AddAsync(dto);
}
else
{
dto.CreatedAt = exist.CreatedAt; dto.IsDeleted = false;
await _ylxyRepo.UpdateAsync(dto);
}
var name = (await _ylzkRepo.GetByIdAsync(dto.YlzkId))?.Name ?? "";
return new YjssListItemDto
{
Id = dto.Id, Type = 1, ZhuangKouId = dto.YlzkId, ZhuangKouName = name,
Date = dto.Date, SampleType = dto.Type, SampleTypeName = SampleTypeName(dto.Type),
ZhongLiang = dto.ZhongLiang, HuiChaoLv = dto.HuiChaoLv,
XjdcId = dto.XjdcId, JsdcCt = dto.JsdcCt, QjjjId = dto.QjjjId, Memo = dto.Memo
};
}
public async Task<YjssListItemDto> SaveZhyAsync(YjssMainZhy dto)
{
if (dto.GyzkId <= 0) throw new ServiceException("请选择工艺庄口");
if (dto.Date == default) dto.Date = DateTime.Today;
var exist = dto.Id > 0 ? await _zhyRepo.GetByIdAsync(dto.Id) : null;
if (exist == null)
{
dto.Id = 0; dto.IsDeleted = false;
await _zhyRepo.AddAsync(dto);
}
else
{
dto.CreatedAt = exist.CreatedAt; dto.IsDeleted = false;
await _zhyRepo.UpdateAsync(dto);
}
var name = (await _gyzkRepo.GetByIdAsync(dto.GyzkId))?.ZhuangKouName ?? "";
return new YjssListItemDto
{
Id = dto.Id, Type = 2, ZhuangKouId = dto.GyzkId, ZhuangKouName = name,
Date = dto.Date, SampleType = 2, SampleTypeName = "综合样",
ZhongLiang = dto.ZhongLiang, XjdcId = dto.XjdcId, JsdcCt = dto.JsdcCt,
JfdcId = dto.JfdcId, QpdcId = dto.QpdcId, QjjjId = dto.QjjjId,
JsbhxdCt = dto.JsbhxdCt, Memo = dto.Memo
};
}
public async Task DeleteAsync(int type, long id)
{
if (type == 1)
{
var e = await _ylxyRepo.GetByIdAsync(id) ?? throw new ServiceException("记录不存在", 404);
await _ylxyRepo.DeleteAsync(e);
}
else
{
var e = await _zhyRepo.GetByIdAsync(id) ?? throw new ServiceException("记录不存在", 404);
await _zhyRepo.DeleteAsync(e);
}
// 连带软删除子单据(按 主表 Id + 样品类型 精确定位)
foreach (var x in await _xjdcRepo.FindAsync(x => !x.IsDeleted && x.YjssId == id && x.YjssType == type)) await _xjdcRepo.DeleteAsync(x);
foreach (var x in await _jsdcRepo.FindAsync(x => !x.IsDeleted && x.YjssId == id && x.YjssType == type)) await _jsdcRepo.DeleteAsync(x);
foreach (var x in await _jfdcItemRepo.FindAsync(x => !x.IsDeleted && x.YjssId == id && x.YjssType == type)) await _jfdcItemRepo.DeleteAsync(x);
foreach (var x in await _jfdcRepo.FindAsync(x => !x.IsDeleted && x.YjssId == id && x.YjssType == type)) await _jfdcRepo.DeleteAsync(x);
foreach (var x in await _qpdcRepo.FindAsync(x => !x.IsDeleted && x.YjssId == id && x.YjssType == type)) await _qpdcRepo.DeleteAsync(x);
foreach (var x in await _qjjjRepo.FindAsync(x => !x.IsDeleted && x.YjssId == id && x.YjssType == type)) await _qjjjRepo.DeleteAsync(x);
foreach (var x in await _jsbhxdRepo.FindAsync(x => !x.IsDeleted && x.YjssId == id && x.YjssType == type)) await _jsbhxdRepo.DeleteAsync(x);
foreach (var x in await _jsbhxdMainRepo.FindAsync(x => !x.IsDeleted && x.YjssId == id && x.YjssType == type)) await _jsbhxdMainRepo.DeleteAsync(x);
}
// ==================== 选茧调查 ====================
public async Task<YjssDcXjdc> GetXjdcAsync(int type, long yjssId)
=> await _xjdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type)
?? new YjssDcXjdc { YjssId = yjssId, YjssType = type };
public async Task<bool> SaveXjdcAsync(int type, YjssDcXjdc dto)
{
dto.YjssType = type;
var exist = await _xjdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == dto.YjssId && x.YjssType == type);
var id = await UpsertAsync(_xjdcRepo, dto, exist);
await SetParentPointerAsync(type, dto.YjssId, xjdcId: id, qjjjId: null, jfdcId: null, qpdcId: null, jsdcCt: null, jsbhxdCt: null);
return true;
}
// ==================== 解舒调查(多条) ====================
public async Task<List<YjssDcJsdc>> GetJsdcAsync(int type, long yjssId)
=> (await _jsdcRepo.FindAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type))
.OrderBy(x => x.XuHao).ThenBy(x => x.Id).ToList();
public async Task<bool> SaveJsdcAsync(int type, YjssDcJsdc dto)
{
dto.YjssType = type;
var exist = dto.Id > 0 ? await _jsdcRepo.GetByIdAsync(dto.Id) : null;
if (exist == null)
{
dto.Id = 0; dto.IsDeleted = false;
if (dto.XuHao <= 0) dto.XuHao = (await GetJsdcAsync(type, dto.YjssId)).Count + 1;
await _jsdcRepo.AddAsync(dto);
}
else
{
dto.CreatedAt = exist.CreatedAt; dto.IsDeleted = false;
await _jsdcRepo.UpdateAsync(dto);
}
var ct = (await _jsdcRepo.FindAsync(x => !x.IsDeleted && x.YjssId == dto.YjssId && x.YjssType == type)).Count;
await SetParentPointerAsync(type, dto.YjssId, null, null, null, null, ct, null);
return true;
}
public async Task DeleteJsdcAsync(int type, long id)
{
var e = await _jsdcRepo.GetByIdAsync(id) ?? throw new ServiceException("记录不存在", 404);
await _jsdcRepo.DeleteAsync(e);
var ct = (await _jsdcRepo.FindAsync(x => !x.IsDeleted && x.YjssId == e.YjssId && x.YjssType == e.YjssType)).Count;
await SetParentPointerAsync(type, e.YjssId, null, null, null, null, ct, null);
}
// ==================== 茧幅调查 ====================
public async Task<YjssJfdcDto> GetJfdcAsync(int type, long yjssId)
{
var main = await _jfdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type);
var dto = new YjssJfdcDto { Main = main ?? new YjssDcJfdcMain { YjssId = yjssId, YjssType = type } };
if (main != null)
dto.Items = (await _jfdcItemRepo.FindAsync(x => !x.IsDeleted && x.JfdcId == main.Id))
.OrderBy(x => x.Sort).ThenBy(x => x.JianFu).ToList();
return dto;
}
public async Task<bool> SaveJfdcAsync(int type, YjssJfdcDto dto)
{
dto.Main.YjssType = type;
var exist = await _jfdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == dto.Main.YjssId && x.YjssType == type);
var id = await UpsertAsync(_jfdcRepo, dto.Main, exist);
var olds = await _jfdcItemRepo.FindAsync(x => x.JfdcId == id);
if (olds.Count > 0) await _jfdcItemRepo.HardDeleteRangeAsync(olds);
var rows = dto.Items ?? new List<YjssDcJfdcItem>();
for (var i = 0; i < rows.Count; i++)
{
rows[i].Id = 0; rows[i].JfdcId = id; rows[i].YjssId = dto.Main.YjssId;
rows[i].YjssType = type; rows[i].Sort = i + 1;
await _jfdcItemRepo.AddAsync(rows[i]);
}
await SetParentPointerAsync(type, dto.Main.YjssId, null, null, id, null, null, null);
return true;
}
// ==================== 切剖调查 ====================
public async Task<YjssDcQpdc> GetQpdcAsync(int type, long yjssId)
=> await _qpdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type)
?? new YjssDcQpdc { YjssId = yjssId, YjssType = type };
public async Task<bool> SaveQpdcAsync(int type, YjssDcQpdc dto)
{
dto.YjssType = type;
var exist = await _qpdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == dto.YjssId && x.YjssType == type);
var id = await UpsertAsync(_qpdcRepo, dto, exist);
await SetParentPointerAsync(type, dto.YjssId, null, null, null, id, null, null);
return true;
}
// ==================== 清洁洁净 ====================
public async Task<YjssDcQjjj> GetQjjjAsync(int type, long yjssId)
=> await _qjjjRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type)
?? new YjssDcQjjj { YjssId = yjssId, YjssType = type };
public async Task<bool> SaveQjjjAsync(int type, YjssDcQjjj dto)
{
dto.YjssType = type;
var exist = await _qjjjRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == dto.YjssId && x.YjssType == type);
var id = await UpsertAsync(_qjjjRepo, dto, exist);
await SetParentPointerAsync(type, dto.YjssId, null, id, null, null, null, null);
return true;
}
// ==================== 茧丝百回纤度 ====================
public async Task<YjssJsbhxdDto> GetJsbhxdAsync(int type, long yjssId)
{
var main = await _jsbhxdMainRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type);
var dto = new YjssJsbhxdDto { Main = main ?? new YjssDcJsbhxdMain { YjssId = yjssId, YjssType = type } };
if (main != null)
dto.Items = (await _jsbhxdRepo.FindAsync(x => !x.IsDeleted && x.JsbhxdMainId == main.Id))
.OrderBy(x => x.HuiShu).ToList();
return dto;
}
public async Task<bool> SaveJsbhxdAsync(int type, YjssJsbhxdDto dto)
{
dto.Main.YjssType = type;
var exist = await _jsbhxdMainRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == dto.Main.YjssId && x.YjssType == type);
var id = await UpsertAsync(_jsbhxdMainRepo, dto.Main, exist);
var olds = await _jsbhxdRepo.FindAsync(x => x.JsbhxdMainId == id);
if (olds.Count > 0) await _jsbhxdRepo.HardDeleteRangeAsync(olds);
var rows = dto.Items ?? new List<YjssDcJsbhxd>();
for (var i = 0; i < rows.Count; i++)
{
rows[i].Id = 0; rows[i].JsbhxdMainId = id; rows[i].YjssId = dto.Main.YjssId;
rows[i].YjssType = type; rows[i].Sort = i + 1;
await _jsbhxdRepo.AddAsync(rows[i]);
}
await SetParentPointerAsync(type, dto.Main.YjssId, null, null, null, null, null, rows.Count);
return true;
}
// ==================== 整页 / 报表 ====================
public async Task<YjssFullDto> GetFullAsync(int type, long yjssId)
{
var dto = new YjssFullDto { Type = type };
if (type == 1)
{
var m = await _ylxyRepo.GetByIdAsync(yjssId) ?? throw new ServiceException("原料小样不存在", 404);
dto.ZhuangKouName = (await _ylzkRepo.GetByIdAsync(m.YlzkId))?.Name ?? "";
dto.Date = m.Date; dto.ZhongLiang = m.ZhongLiang; dto.HuiChaoLv = m.HuiChaoLv;
dto.SampleTypeName = SampleTypeName(m.Type); dto.Memo = m.Memo;
}
else
{
var m = await _zhyRepo.GetByIdAsync(yjssId) ?? throw new ServiceException("综合样不存在", 404);
dto.ZhuangKouName = (await _gyzkRepo.GetByIdAsync(m.GyzkId))?.ZhuangKouName ?? "";
dto.Date = m.Date; dto.ZhongLiang = m.ZhongLiang; dto.SampleTypeName = "综合样"; dto.Memo = m.Memo;
}
var xjdc = await _xjdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type);
if (xjdc != null) dto.Xjdc = xjdc;
dto.Jsdc = await GetJsdcAsync(type, yjssId);
var jfdcMain = await _jfdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type);
if (jfdcMain != null)
dto.Jfdc = new YjssJfdcDto
{
Main = jfdcMain,
Items = (await _jfdcItemRepo.FindAsync(x => !x.IsDeleted && x.JfdcId == jfdcMain.Id)).OrderBy(x => x.JianFu).ToList()
};
dto.Qpdc = await _qpdcRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type);
dto.Qjjj = await _qjjjRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type);
var bhMain = await _jsbhxdMainRepo.FirstOrDefaultAsync(x => !x.IsDeleted && x.YjssId == yjssId && x.YjssType == type);
if (bhMain != null)
dto.Jsbhxd = new YjssJsbhxdDto
{
Main = bhMain,
Items = (await _jsbhxdRepo.FindAsync(x => !x.IsDeleted && x.JsbhxdMainId == bhMain.Id)).OrderBy(x => x.HuiShu).ToList()
};
BuildParameters(dto);
return dto;
}
public async Task<Dictionary<string, object?>> GetJsdcSummaryAsync(int type, long yjssId)
{
var list = await GetJsdcAsync(type, yjssId);
var valid = list.Where(x => x.YiJianSiChang > 0).ToList();
decimal Avg(Func<YjssDcJsdc, decimal> f)
{
var v = list.Where(x => f(x) > 0).Select(f).ToList();
return v.Count == 0 ? 0 : Math.Round(v.Average(), 2, MidpointRounding.AwayFromZero);
}
return new Dictionary<string, object?>
{
["解舒样茧粒数"] = valid.Select(x => x.JieShuLiShu).DefaultIfEmpty(0).Max(),
["解舒样茧重量"] = valid.Select(x => x.JieShuZhongLiang).DefaultIfEmpty(0).Max(),
["一茧丝长"] = Avg(x => x.YiJianSiChang),
["解舒率"] = Avg(x => x.JieShuLv),
["解舒丝长"] = Avg(x => x.JieShuSiChang),
["茧丝纤度"] = Avg(x => x.JianSiXianDu),
["解舒光折"] = Avg(x => x.JieShuGuangZhe),
["万米吊糙"] = Avg(x => x.XwWanMiDiaoCao),
["落绪外"] = Math.Round(list.Where(x => x.LdfbWai > 0).Select(x => (decimal)x.LdfbWai).DefaultIfEmpty(0).Average(), 0, MidpointRounding.AwayFromZero),
["落绪中"] = Math.Round(list.Where(x => x.LdfbZhong > 0).Select(x => (decimal)x.LdfbZhong).DefaultIfEmpty(0).Average(), 0, MidpointRounding.AwayFromZero),
["落绪内"] = Math.Round(list.Where(x => x.LdfbNei > 0).Select(x => (decimal)x.LdfbNei).DefaultIfEmpty(0).Average(), 0, MidpointRounding.AwayFromZero),
["记录数"] = list.Count
};
}
/// <summary>按 F9 RepDt_Qc_Yjss_* 的中文键组装报表参数区</summary>
private static void BuildParameters(YjssFullDto dto)
{
var p = dto.Parameters;
p["查询时间"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
p["庄口名称"] = dto.ZhuangKouName;
p["日期"] = dto.Date.ToString("yyyy/M/d");
p["样茧重量"] = dto.ZhongLiang;
p["类型"] = dto.SampleTypeName;
p["回潮率"] = dto.HuiChaoLv;
p["备注"] = dto.Memo;
var x = dto.Xjdc;
if (x != null)
{
p["公斤茧粒"] = x.GongJinLiShu;
p["解舒样茧粒数"] = x.JieShuLiShu;
p["解舒样茧重量"] = x.JieShuZhongLiang;
p["茧重联统茧"] = x.ZlLtj; p["茧重好五级茧"] = x.ZlHwj; p["茧重五级茧"] = x.ZlWj;
p["茧重棉茧"] = x.ZlMianJian; p["茧重黄斑"] = x.ZlHuangBan; p["茧重蛆茧"] = x.ZlQuJian;
p["茧重双宫"] = x.ZlShuangGong; p["茧重血茧"] = x.ZlXueJian; p["茧重薄皮"] = x.ZlBaoPi;
p["茧重茧衣"] = x.ZlJianYi; p["茧重霉茧"] = x.ZlMeiJian;
p["比例联统茧"] = x.BlLtj; p["比例好五级茧"] = x.BlHwj; p["比例五级茧"] = x.BlWj;
p["比例棉茧"] = x.BlMianJian; p["比例黄斑"] = x.BlHuangBan; p["比例蛆茧"] = x.BlQuJian;
p["比例双宫"] = x.BlShuangGong; p["比例血茧"] = x.BlXueJian; p["比例薄皮"] = x.BlBaoPi;
p["比例茧衣"] = x.BlJianYi; p["比例霉茧"] = x.BlMeiJian;
}
var q = dto.Qpdc;
if (q != null)
{
p["茧层率"] = q.JianCengLv; p["公量茧层率"] = q.JianCengLvGongLiang; p["脱胶率"] = q.TuoJiaoLv;
p["原量全茧"] = q.YlQuanJian; p["原量茧层"] = q.YlJianCeng; p["原量蛹体"] = q.YlYongTi;
p["干量煮茧后"] = q.GlZhuJian; p["干量茧层"] = q.GlJianCeng; p["干量蛹体"] = q.GlYongTi;
p["粒数僵蚕"] = q.LsJiangCan; p["粒数内染"] = q.LsNeiRan; p["粒数霉蛹"] = q.LsMeiYong; p["粒数毛脚"] = q.LsMaoJiao;
p["比例僵蚕"] = q.BlJiangCan; p["比例内染"] = q.BlNeiRan; p["比例霉蛹"] = q.BlMeiYong; p["比例毛脚"] = q.BlMaoJiao;
}
var jj = dto.Qjjj;
if (jj != null)
{
p["清洁"] = jj.QingJie; p["洁净"] = jj.JingJie; p["片数"] = jj.PianShu;
p["一度"] = jj.YdYiDu; p["二度"] = jj.YdErDu; p["三度"] = jj.YdSanDu;
p["洁净100"] = jj.Jj100; p["洁净95"] = jj.Jj95; p["洁净90"] = jj.Jj90; p["洁净85"] = jj.Jj85;
p["洁净80"] = jj.Jj80; p["洁净75"] = jj.Jj75; p["洁净70"] = jj.Jj70; p["洁净65"] = jj.Jj65; p["洁净60"] = jj.Jj60;
p["特大糙"] = jj.QjTdc; p["废丝"] = jj.QjFs; p["大糙"] = jj.QjDc; p["黏附糙"] = jj.QjNfc;
p["大长结"] = jj.QjDcj; p["重螺旋"] = jj.QjZlx;
p["小糙"] = jj.QjXc; p["长结"] = jj.QjCj; p["螺旋"] = jj.QjLx; p["环结及裂丝"] = jj.QjHjls;
}
if (dto.Jfdc != null)
{
p["平均茧幅"] = dto.Jfdc.Main.PingJunJianFu;
p["最大茧幅"] = dto.Jfdc.Main.ZuiDaJianFu;
p["茧幅整齐率"] = dto.Jfdc.Main.ZhengQiLv;
p["茧幅均方差"] = dto.Jfdc.Main.JunFangCha;
}
if (dto.Jsbhxd != null)
{
p["茧丝纤度均方差"] = dto.Jsbhxd.Main.XianDuJunFangCha;
p["最大开差"] = dto.Jsbhxd.Main.ZuiDaKaiCha;
p["内外开差"] = dto.Jsbhxd.Main.NeiWaiKaiCha;
p["外三百回"] = dto.Jsbhxd.Main.WaiSanBaiHui;
p["中三百回"] = dto.Jsbhxd.Main.ZhongSanBaiHui;
p["内三百回"] = dto.Jsbhxd.Main.NeiSanBaiHui;
p["白色茧单纤"] = dto.Jsbhxd.Main.BaiSeJianDanXian;
p["灰色茧单纤"] = dto.Jsbhxd.Main.HuiSeJianDanXian;
p["红色茧单纤"] = dto.Jsbhxd.Main.HongSeJianDanXian;
}
}
// ==================== 内部工具 ====================
private async Task SetParentPointerAsync(int type, long yjssId,
long? xjdcId, long? qjjjId, long? jfdcId, long? qpdcId, int? jsdcCt, int? jsbhxdCt)
{
if (type == 1)
{
var m = await _ylxyRepo.GetByIdAsync(yjssId);
if (m == null) return;
if (xjdcId.HasValue) m.XjdcId = xjdcId.Value;
if (qjjjId.HasValue) m.QjjjId = qjjjId.Value;
if (jsdcCt.HasValue) m.JsdcCt = jsdcCt.Value;
await _ylxyRepo.UpdateAsync(m);
}
else
{
var m = await _zhyRepo.GetByIdAsync(yjssId);
if (m == null) return;
if (xjdcId.HasValue) m.XjdcId = xjdcId.Value;
if (qjjjId.HasValue) m.QjjjId = qjjjId.Value;
if (jfdcId.HasValue) m.JfdcId = jfdcId.Value;
if (qpdcId.HasValue) m.QpdcId = qpdcId.Value;
if (jsdcCt.HasValue) m.JsdcCt = jsdcCt.Value;
if (jsbhxdCt.HasValue) m.JsbhxdCt = jsbhxdCt.Value;
await _zhyRepo.UpdateAsync(m);
}
}
private static async Task<long> UpsertAsync<T>(IRepository<T> repo, T dto, T? exist) where T : class, IEntity
{
if (exist == null)
{
dto.Id = 0;
dto.IsDeleted = false;
await repo.AddAsync(dto);
return dto.Id;
}
dto.Id = exist.Id;
dto.CreatedAt = exist.CreatedAt;
dto.IsDeleted = false;
await repo.UpdateAsync(dto);
return dto.Id;
}
}