2026-01-28 17:54:15 +08:00
|
|
|
|
using DOAN.Model.MES.product;
|
|
|
|
|
|
using DOAN.Model.MES.product.Dto;
|
|
|
|
|
|
using DOAN.Service.MES.product.IService;
|
|
|
|
|
|
using Infrastructure;
|
|
|
|
|
|
using Infrastructure.Attribute;
|
2026-02-24 15:36:35 +08:00
|
|
|
|
using linesider_screen_tool;
|
|
|
|
|
|
using Microsoft.AspNetCore.Routing.Template;
|
2026-01-28 17:54:15 +08:00
|
|
|
|
|
|
|
|
|
|
namespace DOAN.Service.MES.product
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 工单工具服务
|
|
|
|
|
|
/// </summary>
|
2026-01-28 18:44:44 +08:00
|
|
|
|
[AppService(
|
|
|
|
|
|
ServiceType = typeof(IProWorkorderUtilityService),
|
|
|
|
|
|
ServiceLifetime = LifeTime.Transient
|
|
|
|
|
|
)]
|
2026-01-28 17:54:15 +08:00
|
|
|
|
public class ProWorkorderUtilityService : BaseService<ProWorkorder>, IProWorkorderUtilityService
|
|
|
|
|
|
{
|
2026-02-24 15:36:35 +08:00
|
|
|
|
private readonly BartenderPrintHelper _printHelper = new();
|
2026-01-28 17:54:15 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 生成工单号
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="parm"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public int Generate_workorder(ProWorkorderQueryDto2 parm)
|
|
|
|
|
|
{
|
|
|
|
|
|
DateTime update_time = parm.WorkorderDate.ToLocalTime().Date;
|
|
|
|
|
|
|
|
|
|
|
|
List<ProWorkorder> proWorkorderList = Context
|
|
|
|
|
|
.Queryable<ProWorkorder>()
|
|
|
|
|
|
.Where(it => it.WorkorderDate == update_time)
|
|
|
|
|
|
.Where(it => it.Status == 1)
|
|
|
|
|
|
.OrderBy(it => it.Sort)
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
string maxs = Context
|
|
|
|
|
|
.Queryable<ProWorkorder>()
|
|
|
|
|
|
.Where(it => it.WorkorderDate == update_time)
|
|
|
|
|
|
.Where(it => it.Status == 3)
|
|
|
|
|
|
.Max(it => it.Workorder);
|
|
|
|
|
|
|
|
|
|
|
|
if (proWorkorderList != null && proWorkorderList.Count() > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
string baseSort = update_time.ToString("yyyyMMdd");
|
|
|
|
|
|
int index = 1;
|
|
|
|
|
|
if (!string.IsNullOrEmpty(maxs))
|
|
|
|
|
|
{
|
|
|
|
|
|
index = Convert.ToInt32(maxs.Substring(maxs.Length - 3)) + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (ProWorkorder item in proWorkorderList)
|
|
|
|
|
|
{
|
|
|
|
|
|
item.Workorder = baseSort + index.ToString("000");
|
|
|
|
|
|
item.Sort = index * 10;
|
|
|
|
|
|
index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Context.Updateable(proWorkorderList).ExecuteCommand();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 移动工单
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="id"></param>
|
|
|
|
|
|
/// <param name="type"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public int MoveWorkorder(string id, int type)
|
|
|
|
|
|
{
|
|
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
2026-02-10 12:15:55 +08:00
|
|
|
|
try
|
2026-01-28 17:54:15 +08:00
|
|
|
|
{
|
2026-02-10 12:15:55 +08:00
|
|
|
|
// 获取要移动的工单
|
|
|
|
|
|
ProWorkorder toMove = Context
|
|
|
|
|
|
.Queryable<ProWorkorder>()
|
|
|
|
|
|
.Where(it => it.Id == id)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
|
|
|
|
|
|
// 检查工单是否存在
|
|
|
|
|
|
if (toMove == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查Sort值是否存在
|
|
|
|
|
|
if (!toMove.Sort.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2026-01-28 17:54:15 +08:00
|
|
|
|
|
2026-02-10 12:15:55 +08:00
|
|
|
|
ProWorkorder exchange = null;
|
|
|
|
|
|
|
|
|
|
|
|
// 上移动:找到Sort值小于当前工单的最大Sort值的工单
|
|
|
|
|
|
if (type == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
exchange = Context
|
|
|
|
|
|
.Queryable<ProWorkorder>()
|
|
|
|
|
|
.Where(it => it.WorkorderDate == toMove.WorkorderDate)
|
|
|
|
|
|
.Where(it => it.PlanNum > 0)
|
|
|
|
|
|
.Where(it => it.Sort.HasValue && it.Sort < toMove.Sort)
|
|
|
|
|
|
.OrderByDescending(it => it.Sort)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 下移:找到Sort值大于当前工单的最小Sort值的工单
|
|
|
|
|
|
else if (type == 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
exchange = Context
|
|
|
|
|
|
.Queryable<ProWorkorder>()
|
|
|
|
|
|
.Where(it => it.WorkorderDate == toMove.WorkorderDate)
|
|
|
|
|
|
.Where(it => it.PlanNum > 0)
|
|
|
|
|
|
.Where(it => it.Sort.HasValue && it.Sort > toMove.Sort)
|
|
|
|
|
|
.OrderBy(it => it.Sort)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查交换工单是否存在
|
|
|
|
|
|
if (exchange != null && exchange.Sort.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 使用事务确保两个工单的Sort值同时更新
|
|
|
|
|
|
UseTran2(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
// 交换Sort值
|
|
|
|
|
|
int temp = toMove.Sort.Value;
|
|
|
|
|
|
toMove.Sort = exchange.Sort;
|
|
|
|
|
|
exchange.Sort = temp;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新工单
|
|
|
|
|
|
result += Context.Updateable(toMove).ExecuteCommand();
|
|
|
|
|
|
result += Context.Updateable(exchange).ExecuteCommand();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
2026-01-28 17:54:15 +08:00
|
|
|
|
{
|
2026-02-10 12:15:55 +08:00
|
|
|
|
// 记录错误日志
|
|
|
|
|
|
Console.WriteLine($"移动工单时出错: {ex.Message}");
|
2026-01-28 17:54:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 查询BOM及其所需数量
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="workorder_num"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public List<WorkOrderBom> SearchBOMNum(string workorder_num)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 这里需要实现BOM查询逻辑
|
|
|
|
|
|
// 暂时返回空列表
|
|
|
|
|
|
return new List<WorkOrderBom>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-01-28 18:44:44 +08:00
|
|
|
|
/// 工单变更日志
|
2026-01-28 17:54:15 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="workorder"></param>
|
|
|
|
|
|
/// <param name="log"></param>
|
|
|
|
|
|
/// <param name="Operator"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2026-01-28 18:44:44 +08:00
|
|
|
|
public List<ProWorkorderUpdateLog> WorkOrderLog(string workorder)
|
2026-01-28 17:54:15 +08:00
|
|
|
|
{
|
2026-01-28 18:44:44 +08:00
|
|
|
|
var result = Context
|
|
|
|
|
|
.Queryable<ProWorkorderUpdateLog>()
|
|
|
|
|
|
.Where(it => it.Workorder == workorder)
|
|
|
|
|
|
.OrderByDescending(it => it.ChangeTime)
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
return result;
|
2026-01-28 17:54:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 导出PDF
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="workorderArray"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public Task<(string, Stream)> ExportPDFByQuestPDFDemo(string[] workorderArray)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 这里需要实现PDF导出逻辑
|
|
|
|
|
|
// 暂时返回空结果
|
|
|
|
|
|
return Task.FromResult(("", (Stream)new MemoryStream()));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 打印工单
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="param"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2026-02-24 15:36:35 +08:00
|
|
|
|
public string PrintTicketsByTemplate(ProWorkorderExportDto param)
|
2026-01-28 17:54:15 +08:00
|
|
|
|
{
|
2026-02-24 15:36:35 +08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
string templatePath = param.Path;
|
|
|
|
|
|
if (string.IsNullOrEmpty(templatePath))
|
|
|
|
|
|
{
|
|
|
|
|
|
return "标签地址传入为空!";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查文件是否存在
|
|
|
|
|
|
if (!File.Exists(templatePath))
|
|
|
|
|
|
{
|
|
|
|
|
|
return $"标签文件不存在: {templatePath}";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取标签中的变量名
|
|
|
|
|
|
var subString = _printHelper.GetNamedSubStrings(templatePath: templatePath);
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否成功获取到标签变量
|
|
|
|
|
|
if (subString == null || subString.Result == null || subString.Result.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return $"无法获取标签变量: {templatePath}";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取工单信息
|
|
|
|
|
|
List<ProWorkorder> workorders = Context
|
|
|
|
|
|
.Queryable<ProWorkorder>()
|
|
|
|
|
|
.Where(it => param.WorkorderArray.Contains(it.Workorder))
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
if (workorders.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return "未找到指定的工单信息!";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 对每个工单执行打印
|
|
|
|
|
|
int successCount = 0;
|
|
|
|
|
|
foreach (ProWorkorder workorder in workorders)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 为每个工单生成标签参数
|
|
|
|
|
|
Dictionary<string, string> parameters = new Dictionary<string, string>
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "workorder", workorder.Workorder },
|
|
|
|
|
|
{ "stoveCode", workorder.StoveCode },
|
|
|
|
|
|
{ "qty", workorder.PlanNum.ToString() },
|
|
|
|
|
|
//{ "productionName", workorder.productionName },
|
|
|
|
|
|
//{ "productionCode", workorder.productionCode },
|
|
|
|
|
|
//{ "materialCode", workorder.MaterialCode },
|
|
|
|
|
|
//{ "drawingCode", workorder.DrawingCode }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 过滤出标签中存在的参数
|
|
|
|
|
|
var intersect = parameters.Where(x => subString.Result.Contains(x.Key)).ToDictionary(
|
|
|
|
|
|
x => x.Key, x => x.Value);
|
|
|
|
|
|
|
|
|
|
|
|
// 执行打印
|
|
|
|
|
|
bool printSuccess = _printHelper.PrintLabel(
|
|
|
|
|
|
templatePath: templatePath,
|
|
|
|
|
|
subStringValues: intersect);
|
|
|
|
|
|
|
|
|
|
|
|
if (printSuccess)
|
|
|
|
|
|
{
|
|
|
|
|
|
successCount++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 记录单个工单打印失败的异常,但继续打印其他工单
|
|
|
|
|
|
Console.WriteLine($"打印工单 {workorder.Workorder} 失败: {ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (successCount > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return $"ok";
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return $"工单标签打印失败: {templatePath}";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
return $"打印失败: {ex.Message}";
|
|
|
|
|
|
}
|
2026-01-28 17:54:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|