zhuangpei-mesbackend/DOAN.Service/MES/process/ProcessmodelProjectService.cs
2025-11-05 10:22:05 +08:00

560 lines
26 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 DOAN.Model;
using DOAN.Model.Business;
using DOAN.Model.Dto;
using DOAN.Model.MES.process;
using DOAN.Repository;
using DOAN.Service.Business.IBusinessService;
using Infrastructure;
using Infrastructure.Attribute;
using Infrastructure.Extensions;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using SqlSugar;
using System;
using System.Linq;
namespace DOAN.Service.Business
{
/// <summary>
/// 产品项目表Service业务层处理
/// </summary>
[AppService(ServiceType = typeof(IProcessmodelProjectService), ServiceLifetime = LifeTime.Transient)]
public class ProcessmodelProjectService : BaseService<ProcessmodelProject>, IProcessmodelProjectService
{
// 静态变量,标记是否已执行过删除旧数据
private static bool _hasDeletedOldData = false;
/// <summary>
/// 查询产品项目表列表
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
public PagedInfo<ProcessmodelProjectDto> GetList(ProcessmodelProjectQueryDto parm)
{
var predicate = Expressionable.Create<ProcessmodelProject>()
.AndIF(!string.IsNullOrEmpty(parm.ProjectCode), p => parm.ProjectCode.Contains(p.ProjectCode))
.AndIF(!string.IsNullOrEmpty(parm.ProjectName), p => parm.ProjectName.Contains(p.ProjectName));
var response = Queryable()
.Where(predicate.ToExpression())
.ToPage<ProcessmodelProject, ProcessmodelProjectDto>(parm);
return response;
}
/// <summary>
/// 获取详情
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
public ProcessmodelProject GetInfo(long Id)
{
var response = Queryable()
.Where(x => x.Id == Id)
.First();
return response;
}
/// <summary>
/// 添加产品项目表
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public ProcessmodelProject AddProcessmodelProject(ProcessmodelProject model)
{
return Context.Insertable(model).ExecuteReturnEntity();
}
/// <summary>
/// 修改产品项目表
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public int UpdateProcessmodelProject(ProcessmodelProject model)
{
//var response = Update(w => w.Id == model.Id, it => new ProcessmodelProject()
//{
// ProjectCode = model.ProjectCode,
// ProjectName = model.ProjectName,
// ProductCode = model.ProductCode,
// ProductName = model.ProductName,
// CreatedBy = model.CreatedBy,
// CreatedTime = model.CreatedTime,
// UpdatedBy = model.UpdatedBy,
// UpdatedTime = model.UpdatedTime,
//});
//return response;
return Update(model, true);
}
/// <summary>
/// 新增导入Excel
/// </summary>
/// <param name="formFile"></param>
/// <param name="username"></param>
/// <returns></returns>
public int AddImportExcel(IFormFile formFile, string username)
{
_hasDeletedOldData = false;
int insertCount = 0;
using (var stream = formFile.OpenReadStream())
{
try
{
List<ProcessmodelProject> projectList = new List<ProcessmodelProject>();
List<ProcessmodelRouting> routingList = new List<ProcessmodelRouting>();
List<ProcessmodelProcess> processList = new List<ProcessmodelProcess>();
List<ProcessmodelWorkStep> stepList = new List<ProcessmodelWorkStep>();
IWorkbook workbook = new XSSFWorkbook(stream);
ISheet sheet = workbook.GetSheet("Sheet1");
// 从第二行开始读取
for (int i = 1; i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
if (row == null) continue;
// 读取基础数据
string projectCode = GetCellStringValue(row.GetCell(0)); // A列项目号
string projectName = GetCellStringValue(row.GetCell(1)); // B列项目名称
string productCode = GetCellStringValue(row.GetCell(2)); // C列零件号
string productName = GetCellStringValue(row.GetCell(3)); // D列零件名称
string routingCode = GetCellStringValue(row.GetCell(4)); // E列工艺路线号
string routingName = GetCellStringValue(row.GetCell(5)); // F列工艺路线名称
string processCode = GetCellStringValue(row.GetCell(6)); // G列工序号
string processName = GetCellStringValue(row.GetCell(7)); // H列工序名称
string stepCode = GetCellStringValue(row.GetCell(8)); // I列工步号
string stepName = GetCellStringValue(row.GetCell(9)); // J列工步名称
// 跳过空行
if (string.IsNullOrEmpty(projectCode) && string.IsNullOrEmpty(productCode) &&
string.IsNullOrEmpty(routingCode) && string.IsNullOrEmpty(stepCode))
continue;
// 检查是否已存在相同的项目
var item1 = Context.Queryable<ProcessmodelProject>().Any(p => p.ProjectCode == projectCode);
if (!item1)
{
if (!projectList.Any(p => p.ProjectCode == projectCode))
{
var project = new ProcessmodelProject
{
ProjectCode = projectCode,
ProjectName = projectName,
ProductCode = productCode,
ProductName = productName,
CreatedBy = username,
CreatedTime = DateTime.Now,
};
projectList.Add(project);
}
}
var item2 = Context.Queryable<ProcessmodelRouting>().Any(p => p.RoutingCode == routingCode);
if (!item2)
{
// 检查是否已存在相同的工艺路线
if (!routingList.Any(r => r.RoutingCode == routingCode))
{
var routing = new ProcessmodelRouting
{
RoutingCode = routingCode,
RoutingName = routingName,
ProductCode = productCode,
Description = $"{productName}的工艺路线",
Version = "1.0",
CreateTime = DateTime.Now,
IsActive = "1"
};
routingList.Add(routing);
}
}
var item3 = Context.Queryable<ProcessmodelProcess>().Any(p => p.ProcessCode == processCode);
if (!item3)
{
// 检查是否已存在相同的工序
if (!processList.Any(p => p.ProcessCode == processCode))
{
var process = new ProcessmodelProcess
{
ProcessCode = processCode,
ProcessName = processName,
RoutingCode = routingCode,
//PorcessSeq = processSeq,
WorkCenter = "", // 可根据需要设置默认值
StandardTime = 0, // 可根据需要设置默认值
Description = $"{processName}工序",
CreateTime = DateTime.Now,
IsActive = "1"
};
processList.Add(process);
}
}
// 处理工步和唯一键K列到O列
for (int col = 10; col <= 14; col++) // K列到O列
{
string uniqueValue = GetCellStringValue(row.GetCell(col));
if (!string.IsNullOrEmpty(uniqueValue))
{
if (!stepList.Any(p => p.StepCode == stepCode))
{
var workStep = new ProcessmodelWorkStep
{
StepCode = stepCode,
StepName = stepName,
ProcessCode = processCode,
Description = $"{stepName}工步",
IsActive = "1",
UniqueValue = uniqueValue,
CreateTime = DateTime.Now,
CreateBy = username,
Remark = $"导入自项目:{projectCode}, 产品:{productCode}"
};
stepList.Add(workStep);
}
}
}
}
Context.Ado.BeginTran();
try
{
// 批量插入数据(按依赖顺序)
// 1. 先插入项目表
if (projectList.Count != 0)
{
Context.Insertable(projectList).ExecuteCommand();
insertCount += projectList.Count;
}
// 2. 插入工艺路线表
if (routingList.Count != 0)
{
Context.Insertable(routingList).ExecuteCommand();
insertCount += routingList.Count;
}
// 3. 插入工序表
if (processList.Count != 0)
{
Context.Insertable(processList).ExecuteCommand();
insertCount += processList.Count;
}
// 4. 最后插入工步表
if (stepList.Count != 0)
{
Context.Insertable(stepList).ExecuteCommand();
insertCount += stepList.Count;
}
Context.Ado.CommitTran(); // 成功提交
}
catch
{
Context.Ado.RollbackTran(); // 失败回滚
throw;
}
return insertCount;
}
catch (Exception ex)
{
// 建议记录日志,而不是直接抛出
// Log.Error(ex, "导入Excel失败");
throw; // 不要 throw ex直接 throw 保留堆栈
}
}
}
/// <summary>
/// 覆盖导入Excel
/// </summary>
/// <param name="formFile"></param>
/// <param name="username"></param>
/// <returns></returns>
public int CoverImportExcel(IFormFile formFile, string username)
{
_hasDeletedOldData = false;
int insertCount = 0;
using (var stream = formFile.OpenReadStream())
{
try
{
List<ProcessmodelProject> projectList = new List<ProcessmodelProject>();
List<ProcessmodelRouting> routingList = new List<ProcessmodelRouting>();
List<ProcessmodelProcess> processList = new List<ProcessmodelProcess>();
List<ProcessmodelWorkStep> stepList = new List<ProcessmodelWorkStep>();
IWorkbook workbook = new XSSFWorkbook(stream);
ISheet sheet = workbook.GetSheet("Sheet1");
// 从第二行开始读取
for (int i = 1; i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
if (row == null) continue;
// 读取基础数据
string projectCode = GetCellStringValue(row.GetCell(0)); // A列项目号
string projectName = GetCellStringValue(row.GetCell(1)); // B列项目名称
string productCode = GetCellStringValue(row.GetCell(2)); // C列零件号
string productName = GetCellStringValue(row.GetCell(3)); // D列零件名称
string routingCode = GetCellStringValue(row.GetCell(4)); // E列工艺路线号
string routingName = GetCellStringValue(row.GetCell(5)); // F列工艺路线名称
string processCode = GetCellStringValue(row.GetCell(6)); // G列工序号
string processName = GetCellStringValue(row.GetCell(7)); // H列工序名称
string stepCode = GetCellStringValue(row.GetCell(8)); // I列工步号
string stepName = GetCellStringValue(row.GetCell(9)); // J列工步名称
// 跳过空行
if (string.IsNullOrEmpty(projectCode) && string.IsNullOrEmpty(productCode) &&
string.IsNullOrEmpty(routingCode) && string.IsNullOrEmpty(stepCode))
continue;
// 检查是否已存在相同的项目
if (!projectList.Any(p => p.ProjectCode == projectCode))
{
var project = new ProcessmodelProject
{
ProjectCode = projectCode,
ProjectName = projectName,
ProductCode = productCode,
ProductName = productName,
CreatedBy = username,
CreatedTime = DateTime.Now,
};
projectList.Add(project);
}
// 检查是否已存在相同的工艺路线
if (!routingList.Any(r => r.RoutingCode == routingCode))
{
var routing = new ProcessmodelRouting
{
RoutingCode = routingCode,
RoutingName = routingName,
ProductCode = productCode,
Description = $"{productName}的工艺路线",
Version = "1.0",
CreateTime = DateTime.Now,
IsActive = "1"
};
routingList.Add(routing);
}
// 检查是否已存在相同的工序
if (!processList.Any(p => p.ProcessCode == processCode))
{
var process = new ProcessmodelProcess
{
ProcessCode = processCode,
ProcessName = processName,
RoutingCode = routingCode,
//PorcessSeq = processSeq,
WorkCenter = "", // 可根据需要设置默认值
StandardTime = 0, // 可根据需要设置默认值
Description = $"{processName}工序",
CreateTime = DateTime.Now,
IsActive = "1"
};
processList.Add(process);
}
// 处理工步和唯一键K列到O列
for (int col = 10; col <= 14; col++) // K列到O列
{
string uniqueValue = GetCellStringValue(row.GetCell(col));
if (!string.IsNullOrEmpty(uniqueValue))
{
var workStep = new ProcessmodelWorkStep
{
StepCode = stepCode,
StepName = stepName,
ProcessCode = processCode,
Description = $"{stepName}工步",
IsActive = "1",
UniqueValue = uniqueValue,
CreateTime = DateTime.Now,
CreateBy = username,
Remark = $"导入自项目:{projectCode}, 产品:{productCode}"
};
stepList.Add(workStep);
}
}
}
Context.Ado.BeginTran();
// 开启事务:使用 SqlSugar 的 UsingTran 方法(自动管理事务生命周期)
try
{
// 1. 删除旧数据(子表→父表,避免外键约束)
Context.Deleteable<ProcessmodelWorkStep>().ExecuteCommand();
Context.Deleteable<ProcessmodelProcess>().ExecuteCommand();
Context.Deleteable<ProcessmodelRouting>().ExecuteCommand();
Context.Deleteable<ProcessmodelProject>().ExecuteCommand();
// 2. 插入新数据(父表→子表,保证外键关联有效)
if (projectList != null && projectList.Count != 0)
{
Context.Insertable(projectList).ExecuteCommand();
insertCount += projectList.Count;
}
if (routingList != null && routingList.Count != 0)
{
Context.Insertable(routingList).ExecuteCommand();
insertCount += routingList.Count;
}
if (processList != null && processList.Count != 0)
{
Context.Insertable(processList).ExecuteCommand();
insertCount += processList.Count;
}
if (stepList != null && stepList.Count != 0)
{
Context.Insertable(stepList).ExecuteCommand();
insertCount += stepList.Count;
}
Context.Ado.CommitTran(); // 成功提交
}
catch
{
Context.Ado.RollbackTran(); // 失败回滚
throw;
}
return insertCount;
}
catch (Exception ex)
{
// 记录日志
throw new Exception($"导入Excel失败: {ex.Message}", ex);
}
}
}
/// <summary>
/// 导出
/// </summary>
/// <returns></returns>
public (byte[] fileBytes, string fileName) ExportProjectExcel()
{
// 获取模板文件路径
IWebHostEnvironment webHostEnvironment = (IWebHostEnvironment)App.ServiceProvider.GetService(typeof(IWebHostEnvironment));
string templatePath = Path.Combine(webHostEnvironment.WebRootPath, "ImportTemplate", "processmodel.xlsx");
//if (!System.IO.File.Exists(templatePath))
//{
// throw new Exception("模板文件不存在");
//}
// 读取模板文件
IWorkbook workbook;
using (var templateStream = new FileStream(templatePath, FileMode.Open, FileAccess.Read))
{
workbook = new XSSFWorkbook(templateStream);
}
ISheet sheet = workbook.GetSheetAt(0);
// 查询数据库获取数据
var projects = Context.Queryable<ProcessmodelProject>().ToList();
var routings = Context.Queryable<ProcessmodelRouting>().ToList();
var processes = Context.Queryable<ProcessmodelProcess>().ToList();
var workSteps = Context.Queryable<ProcessmodelWorkStep>().ToList();
// 构建导出数据
var exportData = new List<dynamic>();
foreach (var step in workSteps)
{
var process = processes.FirstOrDefault(p => p.ProcessCode == step.ProcessCode);
var routing = process != null ? routings.FirstOrDefault(r => r.RoutingCode == process.RoutingCode) : null;
var project = routing != null ? projects.FirstOrDefault(p => p.ProductCode == routing.ProductCode) : null;
if (project != null && routing != null && process != null)
{
exportData.Add(new { Project = project, Routing = routing, Process = process, Step = step });
}
}
// 按工步代码和工序代码分组
var groupedData = exportData
.GroupBy(x => new { x.Step.StepCode, x.Process.ProcessCode })
.Select(g => new
{
Project = g.First().Project,
Routing = g.First().Routing,
Process = g.First().Process,
StepCode = g.Key.StepCode,
StepName = g.First().Step.StepName,
UniqueValues = g.Select(x => x.Step.UniqueValue).Distinct().ToList()
})
.ToList();
// 从第二行开始写入数据
int rowIndex = 1;
foreach (var item in groupedData)
{
IRow dataRow = sheet.CreateRow(rowIndex++);
// 填充数据
dataRow.CreateCell(0).SetCellValue(item.Project.ProjectCode ?? "");
dataRow.CreateCell(1).SetCellValue(item.Project.ProjectName ?? "");
dataRow.CreateCell(2).SetCellValue(item.Project.ProductCode ?? "");
dataRow.CreateCell(3).SetCellValue(item.Project.ProductName ?? "");
dataRow.CreateCell(4).SetCellValue(item.Routing.RoutingCode ?? "");
dataRow.CreateCell(5).SetCellValue(item.Routing.RoutingName ?? "");
dataRow.CreateCell(6).SetCellValue(item.Process.ProcessCode ?? "");
dataRow.CreateCell(7).SetCellValue(item.Process.ProcessName ?? "");
dataRow.CreateCell(8).SetCellValue(item.StepCode ?? "");
dataRow.CreateCell(9).SetCellValue(item.StepName ?? "");
// 填充唯一键
for (int col = 10; col <= 15; col++)
{
dataRow.CreateCell(col).SetCellValue(col - 10 < item.UniqueValues.Count ? item.UniqueValues[col - 10] ?? "" : "");
}
}
// 将工作簿写入内存流
using (MemoryStream ms = new MemoryStream())
{
workbook.Write(ms);
return (ms.ToArray(), "工艺建模表导出.xlsx");
}
}
// 辅助方法:获取单元格字符串值
private string GetCellStringValue(ICell cell)
{
if (cell == null) return string.Empty;
switch (cell.CellType)
{
case CellType.String:
return cell.StringCellValue?.Trim();
case CellType.Numeric:
return cell.NumericCellValue.ToString();
case CellType.Boolean:
return cell.BooleanCellValue.ToString();
case CellType.Formula:
try
{
return cell.StringCellValue?.Trim();
}
catch
{
return cell.NumericCellValue.ToString();
}
default:
return string.Empty;
}
}
}
}