Files
yanpeng200212 8c4c464362 完善机组车台功能,并导入机组车台 / 车间班次数据
一、机组车台功能完善
- 车间下拉改为只取「前缫」职责类型的部门(新增接口 /api/jizuchetai/qianxian-deps)
- 补齐校验:车间、机组号、开始车台号必填;结束车台号不得小于开始车台号;同车间同机组不可重复
- 前端页面同步调整:车间改为下拉选择、增加必填提示、表格加 row-key

二、数据导入(新增 ProdSeedData,幂等导入器)
- biz_prod_qs_jzct:机组车台 35 条(其中 11 条已删除)→ 有效 24 条
- biz_prod_qs_cjbc:车间班次 7 条(其中 1 条已删除)→ 有效 6 条
- F9 的部门 Id 通过部门名称映射到本系统部门;已删除的数据不导入;
  已存在且一致的数据不重复写入,缺失的自动补回
2026-10-14 09:42:06 +08:00

358 lines
16 KiB
C#

using F9WebAiTest.Application.Common;
using F9WebAiTest.Application.Dtos;
using F9WebAiTest.Application.Dtos.Base;
using F9WebAiTest.Domain.Common;
using F9WebAiTest.Domain.Entities;
using F9WebAiTest.Domain.Entities.Base;
using F9WebAiTest.Domain.Enums.SYS.Departments;
using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments;
namespace F9WebAiTest.Application.Services.Base;
// ==================== 工艺庄口 ====================
public interface ICraftZhuangKouService
{
Task<PageResult<CraftZhuangKouDto>> GetPagedAsync(int pageIndex, int pageSize, string keyword, int? year);
Task<CraftZhuangKouDto> CreateAsync(CraftZhuangKouCreateDto dto);
Task<CraftZhuangKouDto> UpdateAsync(long id, CraftZhuangKouCreateDto dto);
Task DeleteAsync(long id);
}
public class CraftZhuangKouService : ICraftZhuangKouService
{
private readonly IRepository<CraftZhuangKou> _repo;
public CraftZhuangKouService(IRepository<CraftZhuangKou> repo) => _repo = repo;
private static string BendiWaidiName(int v) => v switch { 1 => "本地", 2 => "外地", _ => "" };
public async Task<PageResult<CraftZhuangKouDto>> GetPagedAsync(int pageIndex, int pageSize, string keyword, int? year)
{
var all = await _repo.GetAllAsync();
var q = all.AsQueryable();
if (!string.IsNullOrWhiteSpace(keyword))
q = q.Where(x => x.ZhuangKouName.Contains(keyword) || x.ZhuangKouCode.Contains(keyword) || x.ProductionDisplayName.Contains(keyword));
if (year.HasValue)
q = q.Where(x => x.BelongingYear == year.Value);
var total = q.LongCount();
var items = q.OrderBy(x => x.Sort).ThenBy(x => x.Id)
.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new PageResult<CraftZhuangKouDto>
{
Items = items.Select(ToDto).ToList(),
Total = total, PageIndex = pageIndex, PageSize = pageSize
};
}
public async Task<CraftZhuangKouDto> CreateAsync(CraftZhuangKouCreateDto dto)
{
if (string.IsNullOrWhiteSpace(dto.ZhuangKouName)) throw new ServiceException("庄口名称不能为空");
var e = new CraftZhuangKou
{
BelongingYear = dto.BelongingYear, BendiWaidi = dto.BendiWaidi, JidiWaigou = dto.JidiWaigou,
ZhuangKouCode = dto.ZhuangKouCode, ZhuangKouName = dto.ZhuangKouName,
ProductionDisplayName = dto.ProductionDisplayName, Chandi = dto.Chandi,
Sort = dto.Sort, Memo = dto.Memo, IsJiezhuang = dto.IsJiezhuang
};
await _repo.AddAsync(e);
await _repo.SaveChangesAsync();
return ToDto(e);
}
public async Task<CraftZhuangKouDto> UpdateAsync(long id, CraftZhuangKouCreateDto dto)
{
var e = await _repo.GetByIdAsync(id);
if (e == null) throw new ServiceException("记录不存在", 404);
e.BelongingYear = dto.BelongingYear; e.BendiWaidi = dto.BendiWaidi; e.JidiWaigou = dto.JidiWaigou;
e.ZhuangKouCode = dto.ZhuangKouCode; e.ZhuangKouName = dto.ZhuangKouName;
e.ProductionDisplayName = dto.ProductionDisplayName; e.Chandi = dto.Chandi;
e.Sort = dto.Sort; e.Memo = dto.Memo; e.IsJiezhuang = dto.IsJiezhuang;
await _repo.UpdateAsync(e);
await _repo.SaveChangesAsync();
return ToDto(e);
}
public async Task DeleteAsync(long id)
{
var e = await _repo.GetByIdAsync(id);
if (e == null) throw new ServiceException("记录不存在", 404);
await _repo.DeleteAsync(e);
await _repo.SaveChangesAsync();
}
private static CraftZhuangKouDto ToDto(CraftZhuangKou e) => new()
{
Id = e.Id, BelongingYear = e.BelongingYear, BendiWaidi = e.BendiWaidi, BendiWaidiName = BendiWaidiName(e.BendiWaidi),
JidiWaigou = e.JidiWaigou, ZhuangKouCode = e.ZhuangKouCode, ZhuangKouName = e.ZhuangKouName,
ProductionDisplayName = e.ProductionDisplayName, Chandi = e.Chandi, Sort = e.Sort, Memo = e.Memo, IsJiezhuang = e.IsJiezhuang
};
}
// ==================== 生丝规格 ====================
public interface IShengsiGuigeService
{
Task<PageResult<ShengsiGuigeDto>> GetPagedAsync(int pageIndex, int pageSize, string keyword);
Task<List<string>> GetAllGuigeAsync();
Task<ShengsiGuigeDto> CreateAsync(ShengsiGuigeDto dto);
Task<ShengsiGuigeDto> UpdateAsync(long id, ShengsiGuigeDto dto);
Task DeleteAsync(long id);
}
public class ShengsiGuigeService : IShengsiGuigeService
{
private readonly IRepository<ShengsiGuige> _repo;
public ShengsiGuigeService(IRepository<ShengsiGuige> repo) => _repo = repo;
public async Task<PageResult<ShengsiGuigeDto>> GetPagedAsync(int pageIndex, int pageSize, string keyword)
{
var all = await _repo.GetAllAsync();
var q = all.AsQueryable();
if (!string.IsNullOrWhiteSpace(keyword)) q = q.Where(x => x.Guige.Contains(keyword));
var total = q.LongCount();
var items = q.OrderBy(x => x.Sort).ThenBy(x => x.Id).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new PageResult<ShengsiGuigeDto> { Items = items.Select(ToDto).ToList(), Total = total, PageIndex = pageIndex, PageSize = pageSize };
}
public async Task<List<string>> GetAllGuigeAsync()
=> (await _repo.GetAllAsync()).OrderBy(x => x.Sort).Select(x => x.Guige).Distinct().ToList();
public async Task<ShengsiGuigeDto> CreateAsync(ShengsiGuigeDto dto)
{
if (string.IsNullOrWhiteSpace(dto.Guige)) throw new ServiceException("规格不能为空");
var e = Map(new ShengsiGuige(), dto);
await _repo.AddAsync(e);
await _repo.SaveChangesAsync();
return ToDto(e);
}
public async Task<ShengsiGuigeDto> UpdateAsync(long id, ShengsiGuigeDto dto)
{
var e = await _repo.GetByIdAsync(id);
if (e == null) throw new ServiceException("记录不存在", 404);
Map(e, dto);
await _repo.UpdateAsync(e);
await _repo.SaveChangesAsync();
return ToDto(e);
}
public async Task DeleteAsync(long id)
{
var e = await _repo.GetByIdAsync(id);
if (e == null) throw new ServiceException("记录不存在", 404);
await _repo.DeleteAsync(e);
await _repo.SaveChangesAsync();
}
private static ShengsiGuige Map(ShengsiGuige e, ShengsiGuigeDto d)
{
e.Guige = d.Guige; e.CenterrangeLolimit = d.CenterrangeLolimit; e.CenterrangeUplimit = d.CenterrangeUplimit;
e.CenterXiandu = d.CenterXiandu; e.ValidLolimit = d.ValidLolimit; e.ValidUplimit = d.ValidUplimit;
e.XiaoyeLolimit = d.XiaoyeLolimit; e.XiaoyeUplimit = d.XiaoyeUplimit;
e.DayeLolimit = d.DayeLolimit; e.DayeUplimit = d.DayeUplimit;
e.TeyeLolimit = d.TeyeLolimit; e.TeyeUplimit = d.TeyeUplimit;
e.YexianNkLolimitLeft = d.YexianNkLolimitLeft; e.YexianNkLolimitRight = d.YexianNkLolimitRight;
e.YexianNkUplimitLeft = d.YexianNkUplimitLeft; e.YexianNkUplimitRight = d.YexianNkUplimitRight;
e.LaodongJingsaiYexianLolimit = d.LaodongJingsaiYexianLolimit; e.LaodongJingsaiYexianUplimit = d.LaodongJingsaiYexianUplimit;
e.Sort = d.Sort; e.Memo = d.Memo;
return e;
}
private static ShengsiGuigeDto ToDto(ShengsiGuige e) => new()
{
Id = e.Id, Guige = e.Guige, CenterrangeLolimit = e.CenterrangeLolimit, CenterrangeUplimit = e.CenterrangeUplimit,
CenterXiandu = e.CenterXiandu, ValidLolimit = e.ValidLolimit, ValidUplimit = e.ValidUplimit,
XiaoyeLolimit = e.XiaoyeLolimit, XiaoyeUplimit = e.XiaoyeUplimit,
DayeLolimit = e.DayeLolimit, DayeUplimit = e.DayeUplimit,
TeyeLolimit = e.TeyeLolimit, TeyeUplimit = e.TeyeUplimit,
YexianNkLolimitLeft = e.YexianNkLolimitLeft, YexianNkLolimitRight = e.YexianNkLolimitRight,
YexianNkUplimitLeft = e.YexianNkUplimitLeft, YexianNkUplimitRight = e.YexianNkUplimitRight,
LaodongJingsaiYexianLolimit = e.LaodongJingsaiYexianLolimit, LaodongJingsaiYexianUplimit = e.LaodongJingsaiYexianUplimit,
Sort = e.Sort, Memo = e.Memo
};
}
// ==================== 生丝定级指标 ====================
public interface IShengsiDingjizhibiaoService
{
Task<PageResult<ShengsiDingjizhibiaoDto>> GetPagedAsync(int pageIndex, int pageSize, string keyword, int? standard, string guige);
Task<ShengsiDingjizhibiaoDto> CreateAsync(ShengsiDingjizhibiaoDto dto);
Task<ShengsiDingjizhibiaoDto> UpdateAsync(long id, ShengsiDingjizhibiaoDto dto);
Task DeleteAsync(long id);
}
public class ShengsiDingjizhibiaoService : IShengsiDingjizhibiaoService
{
private readonly IRepository<ShengsiDingjizhibiao> _repo;
public ShengsiDingjizhibiaoService(IRepository<ShengsiDingjizhibiao> repo) => _repo = repo;
private static string StandardName(int v) => v switch { 0 => "厂标", 1 => "国标", 2 => "个人", _ => "" };
public async Task<PageResult<ShengsiDingjizhibiaoDto>> GetPagedAsync(int pageIndex, int pageSize, string keyword, int? standard, string guige)
{
var all = await _repo.GetAllAsync();
var q = all.AsQueryable();
if (!string.IsNullOrWhiteSpace(keyword)) q = q.Where(x => x.Grade.Contains(keyword));
if (standard.HasValue) q = q.Where(x => x.Standard == standard.Value);
if (!string.IsNullOrWhiteSpace(guige)) q = q.Where(x => x.Guige == guige);
var total = q.LongCount();
var items = q.OrderBy(x => x.Standard).ThenBy(x => x.Guige).ThenBy(x => x.GradeScore)
.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new PageResult<ShengsiDingjizhibiaoDto> { Items = items.Select(ToDto).ToList(), Total = total, PageIndex = pageIndex, PageSize = pageSize };
}
public async Task<ShengsiDingjizhibiaoDto> CreateAsync(ShengsiDingjizhibiaoDto dto)
{
if (string.IsNullOrWhiteSpace(dto.Grade)) throw new ServiceException("等级不能为空");
var e = Map(new ShengsiDingjizhibiao(), dto);
await _repo.AddAsync(e);
await _repo.SaveChangesAsync();
return ToDto(e);
}
public async Task<ShengsiDingjizhibiaoDto> UpdateAsync(long id, ShengsiDingjizhibiaoDto dto)
{
var e = await _repo.GetByIdAsync(id);
if (e == null) throw new ServiceException("记录不存在", 404);
Map(e, dto);
await _repo.UpdateAsync(e);
await _repo.SaveChangesAsync();
return ToDto(e);
}
public async Task DeleteAsync(long id)
{
var e = await _repo.GetByIdAsync(id);
if (e == null) throw new ServiceException("记录不存在", 404);
await _repo.DeleteAsync(e);
await _repo.SaveChangesAsync();
}
private static ShengsiDingjizhibiao Map(ShengsiDingjizhibiao e, ShengsiDingjizhibiaoDto d)
{
e.Standard = d.Standard; e.Guige = d.Guige; e.Grade = d.Grade; e.GradeScore = d.GradeScore;
e.Piancha = d.Piancha; e.Dacha = d.Dacha; e.Erdu = d.Erdu; e.Sandu = d.Sandu;
e.Qingjie = d.Qingjie; e.Jiejing = d.Jiejing;
return e;
}
private static ShengsiDingjizhibiaoDto ToDto(ShengsiDingjizhibiao e) => new()
{
Id = e.Id, Standard = e.Standard, StandardName = StandardName(e.Standard), Guige = e.Guige, Grade = e.Grade,
GradeScore = e.GradeScore, Piancha = e.Piancha, Dacha = e.Dacha, Erdu = e.Erdu, Sandu = e.Sandu,
Qingjie = e.Qingjie, Jiejing = e.Jiejing
};
}
// ==================== 机组车台 ====================
public interface IJizuChetaiService
{
Task<PageResult<JizuChetaiDto>> GetPagedAsync(int pageIndex, int pageSize, string keyword);
Task<JizuChetaiDto> GetByDepIdAndJizuAsync(long deptId, int jizu);
Task<JizuChetaiDto> CreateAsync(JizuChetaiDto dto);
Task<JizuChetaiDto> UpdateAsync(long id, JizuChetaiDto dto);
Task DeleteAsync(long id);
/// <summary>车间下拉:只取职责类型为「前缫」的部门</summary>
Task<List<DeptOptionDto>> GetQianxianDepsAsync();
}
public class JizuChetaiService : IJizuChetaiService
{
private readonly IRepository<JizuChetai> _repo;
private readonly IRepository<SysDept.Department> _deptRepo;
public JizuChetaiService(IRepository<JizuChetai> repo, IRepository<SysDept.Department> deptRepo)
{
_repo = repo; _deptRepo = deptRepo;
}
public async Task<PageResult<JizuChetaiDto>> GetPagedAsync(int pageIndex, int pageSize, string keyword)
{
var all = await _repo.GetAllAsync();
var q = all.AsQueryable();
var depts = await _deptRepo.GetAllAsync();
var deptDict = depts.ToDictionary(d => d.Id, d => d.Name);
if (!string.IsNullOrWhiteSpace(keyword))
{
var kwDeptIds = depts.Where(d => d.Name.Contains(keyword)).Select(d => d.Id).ToHashSet();
q = q.Where(x => kwDeptIds.Contains(x.DepartmentId) || x.Jizu.ToString().Contains(keyword));
}
var total = q.LongCount();
var items = q.OrderBy(x => x.DepartmentId).ThenBy(x => x.Jizu).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new PageResult<JizuChetaiDto>
{
Items = items.Select(x => new JizuChetaiDto
{
Id = x.Id, DepartmentId = x.DepartmentId, DepartmentName = deptDict.GetValueOrDefault(x.DepartmentId, ""),
Jizu = x.Jizu, ChetaiStart = x.ChetaiStart, ChetaiEnd = x.ChetaiEnd
}).ToList(),
Total = total, PageIndex = pageIndex, PageSize = pageSize
};
}
public async Task<JizuChetaiDto> GetByDepIdAndJizuAsync(long deptId, int jizu)
{
var e = await _repo.FirstOrDefaultAsync(x => x.DepartmentId == deptId && x.Jizu == jizu);
if (e == null) return null;
return await GetDto(e);
}
public async Task<JizuChetaiDto> CreateAsync(JizuChetaiDto dto)
{
await ValidateAsync(dto, 0);
var e = new JizuChetai { DepartmentId = dto.DepartmentId, Jizu = dto.Jizu, ChetaiStart = dto.ChetaiStart, ChetaiEnd = dto.ChetaiEnd };
await _repo.AddAsync(e);
await _repo.SaveChangesAsync();
return await GetDto(e);
}
public async Task<JizuChetaiDto> UpdateAsync(long id, JizuChetaiDto dto)
{
var e = await _repo.GetByIdAsync(id);
if (e == null) throw new ServiceException("记录不存在", 404);
await ValidateAsync(dto, id);
e.DepartmentId = dto.DepartmentId; e.Jizu = dto.Jizu; e.ChetaiStart = dto.ChetaiStart; e.ChetaiEnd = dto.ChetaiEnd;
await _repo.UpdateAsync(e);
await _repo.SaveChangesAsync();
return await GetDto(e);
}
/// <summary>校验:车间、机组号、车台范围必填且合理,同一车间的机组不可重复</summary>
private async Task ValidateAsync(JizuChetaiDto dto, long excludeId)
{
if (dto.DepartmentId <= 0) throw new ServiceException("请选择车间");
if (dto.Jizu <= 0) throw new ServiceException("机组号必须大于 0");
if (dto.ChetaiStart <= 0) throw new ServiceException("开始车台号必须大于 0");
if (dto.ChetaiEnd < dto.ChetaiStart) throw new ServiceException("结束车台号不能小于开始车台号");
var all = await _repo.GetAllAsync();
if (all.Any(x => x.Id != excludeId && x.DepartmentId == dto.DepartmentId && x.Jizu == dto.Jizu))
throw new ServiceException("该车间的此机组已存在,请勿重复配置");
}
public async Task<List<DeptOptionDto>> GetQianxianDepsAsync()
{
var depts = await _deptRepo.GetAllAsync();
return depts
.Where(d => d.DutyType == Department_DutyType_Enum.前缫)
.OrderBy(d => d.SortOrder).ThenBy(d => d.Id)
.Select(d => new DeptOptionDto { Id = d.Id, Name = d.Name })
.ToList();
}
public async Task DeleteAsync(long id)
{
var e = await _repo.GetByIdAsync(id);
if (e == null) throw new ServiceException("记录不存在", 404);
await _repo.DeleteAsync(e);
await _repo.SaveChangesAsync();
}
private async Task<JizuChetaiDto> GetDto(JizuChetai e)
{
var dept = await _deptRepo.GetByIdAsync(e.DepartmentId);
return new JizuChetaiDto { Id = e.Id, DepartmentId = e.DepartmentId, DepartmentName = dept?.Name ?? "", Jizu = e.Jizu, ChetaiStart = e.ChetaiStart, ChetaiEnd = e.ChetaiEnd };
}
}