feat(hjgl): 增强焊口匹配与任务单打印

焊口台账、材料匹配和任务单打印需要统一到焊口维度处理。
新增焊口查询、匹配保存和打印模板适配,便于按焊口追溯材料和任务。
This commit is contained in:
2026-06-26 00:40:55 +08:00
parent bd9b5a6f4d
commit 02b524b895
14 changed files with 836 additions and 121 deletions
@@ -67,6 +67,12 @@
<f:TextBox ID="txtWeldJointCode" runat="server" Label="焊口号"
LabelAlign="Right" Width="280px">
</f:TextBox>
<f:DropDownList ID="ddlWeldState" runat="server" Label="完成状态"
LabelAlign="Right" Width="200px" LabelWidth="80px">
<f:ListItem Text="全部" Value="" Selected="true" />
<f:ListItem Text="已完成" Value="已完成" />
<f:ListItem Text="未完成" Value="未完成" />
</f:DropDownList>
<f:ToolbarFill ID="ToolbarFill2" runat="server">
</f:ToolbarFill>
<f:Button ID="BtnAnalyse" Text="查询" Icon="SystemSearch"
@@ -79,6 +85,9 @@
Icon="TableGo" EnableAjax="false" DisableControlBeforePostBack="true" EnablePostBack="true">
</f:Button>
<f:Button ID="btnPrintJointNameplate" OnClick="btnPrintJointNameplate_Click" runat="server" Text="打印焊口铭牌"
Icon="Printer" EnableAjax="true" DisableControlBeforePostBack="true" EnablePostBack="true">
</f:Button>
<f:Button ID="btnGetChart" ToolTip="图表" Icon="ChartPie" Text="统计图表"
EnablePostBack="true" OnClick="btnGetChart_Click" runat="server">
</f:Button>
@@ -378,14 +378,11 @@ namespace FineUIPro.Web.HJGL.InfoQuery
private void BindGrid()
{
Model.View_HJGL_WeldJoint model = new Model.View_HJGL_WeldJoint();
model.ProjectId = this.CurrUser.LoginProjectId;
model.WeldJointCode = this.txtWeldJointCode.Text;
Model.View_HJGL_WeldJoint model = GetCurrentWeldJointQueryModel();
if (this.tvControlItem.SelectedNode.CommandName.Split('|').Count() == 2)
{
model.UnitWorkId = this.tvControlItem.SelectedNodeID;
model.WeldJointCode = this.txtWeldJointCode.Text;
var list = BLL.WeldJointService.GetDataBymodel(model, Grid1.PageIndex, Grid1.PageSize);
Grid1.RecordCount = list.Total;
Grid1.DataSource = list.Data;
@@ -403,6 +400,36 @@ namespace FineUIPro.Web.HJGL.InfoQuery
}
}
/// <summary>
/// 汇总当前焊口台账查询条件,保证列表、导出和打印使用同一套过滤规则。
/// </summary>
private Model.View_HJGL_WeldJoint GetCurrentWeldJointQueryModel()
{
return new Model.View_HJGL_WeldJoint
{
ProjectId = this.CurrUser.LoginProjectId,
WeldJointCode = this.txtWeldJointCode.Text.Trim(),
IsWeldOK = this.ddlWeldState.SelectedValue
};
}
/// <summary>
/// 按当前树节点和筛选条件获取焊口铭牌待打印焊口。
/// </summary>
private List<Model.View_HJGL_WeldJoint> GetCurrentWeldJointList()
{
Model.View_HJGL_WeldJoint model = GetCurrentWeldJointQueryModel();
if (this.tvControlItem.SelectedNode.CommandName.Split('|').Count() == 2)
{
model.UnitWorkId = this.tvControlItem.SelectedNodeID;
}
else if (this.tvControlItem.SelectedNode.CommandName == "管线")
{
model.PipelineId = this.tvControlItem.SelectedNodeID;
}
return BLL.WeldJointService.GetViewWeldJointsBymodel(model);
}
private void get3DParmeter_weldjoint(List<View_HJGL_WeldJoint> model)
{
if (model.Any())
@@ -577,7 +604,7 @@ namespace FineUIPro.Web.HJGL.InfoQuery
string fileName = "";
if (this.tvControlItem.SelectedNode.CommandName.Split('|').Count() == 2) //单位工程
{
Model.View_HJGL_WeldJoint model = new Model.View_HJGL_WeldJoint();
Model.View_HJGL_WeldJoint model = GetCurrentWeldJointQueryModel();
model.UnitWorkId = this.tvControlItem.SelectedNodeID;
var list = BLL.WeldJointService.GetViewWeldJointsBymodel(model);
View_HJGL_WeldJoint = list;
@@ -585,6 +612,8 @@ namespace FineUIPro.Web.HJGL.InfoQuery
}
else if (this.tvControlItem.SelectedNode.CommandName == "管线")
{
var list = GetCurrentWeldJointList();
View_HJGL_WeldJoint = list;
fileName = PipelineService.GetPipelineByPipelineId(this.tvControlItem.SelectedNodeID)?.PipelineCode;
}
@@ -737,8 +766,11 @@ namespace FineUIPro.Web.HJGL.InfoQuery
{
if (this.tvControlItem.SelectedNode.CommandName.Split('|').Count() == 2)
{
var currentQuery = GetCurrentWeldJointQueryModel();
var q = (from x in Funs.DB.View_HJGL_WeldJoint
where x.ProjectId == this.CurrUser.LoginProjectId && x.UnitWorkId == this.tvControlItem.SelectedNodeID
&& (string.IsNullOrEmpty(currentQuery.WeldJointCode) || x.WeldJointCode.Contains(currentQuery.WeldJointCode))
&& (string.IsNullOrEmpty(currentQuery.IsWeldOK) || x.IsWeldOK == currentQuery.IsWeldOK)
select new
{
PipelineId = x.PipelineId,
@@ -787,6 +819,206 @@ namespace FineUIPro.Web.HJGL.InfoQuery
}
}
/// <summary>
/// 打印当前筛选范围内的焊口铭牌。
/// </summary>
protected void btnPrintJointNameplate_Click(object sender, EventArgs e)
{
if (this.Grid1.SelectedRowIDArray == null || this.Grid1.SelectedRowIDArray.Length == 0)
{
Alert.Show("请选择要打印的焊口");
return;
}
var weldJointList = GetSelectedWeldJointList();
if (weldJointList == null || weldJointList.Count == 0)
{
Alert.Show("当前条件下没有可打印的焊口");
return;
}
var tb = BuildWeldJointNameplateTable(weldJointList);
if (tb == null || tb.Rows.Count == 0)
{
Alert.Show("当前条件下没有可打印的焊口");
return;
}
BLL.FastReportService.ResetData();
tb.TableName = "Table1";
BLL.FastReportService.AddFastreportTable(tb);
string rootPath = Server.MapPath("~/");
string initTemplatePath = "File\\Fastreport\\焊口铭牌.frx";
if (File.Exists(rootPath + initTemplatePath))
{
PageContext.RegisterStartupScript(Window2.GetShowReference(String.Format("~/Controls/Fastreport.aspx?ReportPath={0}", rootPath + initTemplatePath)));
}
}
/// <summary>
/// 获取当前勾选的焊口。
/// </summary>
private List<Model.View_HJGL_WeldJoint> GetSelectedWeldJointList()
{
var ids = this.Grid1.SelectedRowIDArray;
if (ids == null || ids.Length == 0)
{
return new List<Model.View_HJGL_WeldJoint>();
}
List<Model.View_HJGL_WeldJoint> list = new List<Model.View_HJGL_WeldJoint>();
foreach (string id in ids)
{
var item = WeldJointService.GetViewWeldJointById(id);
if (item != null)
{
list.Add(item);
}
}
return list;
}
/// <summary>
/// 组装焊口铭牌打印数据,材料列优先使用已反写主编码对应的材料库信息。
/// </summary>
private DataTable BuildWeldJointNameplateTable(List<Model.View_HJGL_WeldJoint> weldJointList)
{
DataTable tb = new DataTable();
// FastReport 对中文字段名兼容性不稳定,这里统一改成 ASCII 列名,模板只负责显示中文表头。
tb.Columns.Add("PipelineCode", typeof(string));
tb.Columns.Add("SegmentCode", typeof(string));
tb.Columns.Add("WeldJointNo", typeof(string));
tb.Columns.Add("MaterialText", typeof(string));
tb.Columns.Add("Spec", typeof(string));
tb.Columns.Add("DesignTemperature", typeof(string));
tb.Columns.Add("MaterialCode1", typeof(string));
tb.Columns.Add("MaterialCode2", typeof(string));
tb.Columns.Add("HeatNo1", typeof(string));
tb.Columns.Add("BatchNo1", typeof(string));
tb.Columns.Add("Material1Code", typeof(string));
tb.Columns.Add("Material2Code", typeof(string));
tb.Columns.Add("HeatNo2", typeof(string));
tb.Columns.Add("BatchNo2", typeof(string));
tb.Columns.Add("WelderCode", typeof(string));
tb.Columns.Add("WeldingDate", typeof(string));
tb.Columns.Add("WeldCheck", typeof(string));
tb.Columns.Add("CheckDate", typeof(string));
tb.Columns.Add("CleanCheck", typeof(string));
tb.Columns.Add("CleanCheckDate", typeof(string));
tb.Columns.Add("WeldJointId", typeof(string));
var jointIds = weldJointList.Select(x => x.WeldJointId).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();
var pipelineIds = weldJointList.Select(x => x.PipelineId).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();
var materialRows = (from x in Funs.DB.HJGL_PipeLineMat
where jointIds.Contains(x.WeldJointId) && pipelineIds.Contains(x.PipelineId)
orderby x.WeldJointId, x.Number, x.PipeLineMatId
select x).ToList();
var materialCodes = materialRows.Where(x => !string.IsNullOrEmpty(x.MaterialCode)).Select(x => x.MaterialCode).Distinct().ToList();
var materialCode2s = materialRows.Where(x => !string.IsNullOrEmpty(x.MaterialCode2)).Select(x => x.MaterialCode2).Distinct().ToList();
var libsByMaterialCode = Funs.DB.HJGL_MaterialCodeLib.Where(x => materialCodes.Contains(x.MaterialCode)).ToList().GroupBy(x => x.MaterialCode).ToDictionary(x => x.Key, x => x.First());
var libsByCode = Funs.DB.HJGL_MaterialCodeLib.Where(x => materialCode2s.Contains(x.Code)).ToList().GroupBy(x => x.Code).ToDictionary(x => x.Key, x => x.First());
foreach (var joint in weldJointList)
{
var rows = materialRows.Where(x => x.WeldJointId == joint.WeldJointId).ToList();
var row1 = rows.FirstOrDefault();
var row2 = rows.Skip(1).FirstOrDefault();
// 预制组件号按现有业务即预制组件编码显示,避免和管线号混淆。
string preCode = row1 == null ? string.Empty : row1.PrefabricatedComponents;
if (string.IsNullOrEmpty(preCode))
{
preCode = joint.TaskCode;
}
// 焊口号只显示末级编号,和焊口贴纸二维码对应的展示一致,避免带管线前缀。
string weldJointNo = joint.WeldJointCode;
if (!string.IsNullOrEmpty(weldJointNo) && weldJointNo.Contains("/"))
{
weldJointNo = weldJointNo.Substring(weldJointNo.LastIndexOf("/") + 1);
}
// 优先用已反写主编码匹配材料库;没有主编码时,用导入材料编码 Code 兜底。
HJGL_MaterialCodeLib lib1 = GetMaterialLib(row1, libsByMaterialCode, libsByCode);
HJGL_MaterialCodeLib lib2 = GetMaterialLib(row2, libsByMaterialCode, libsByCode);
DataRow dr = tb.NewRow();
dr["PipelineCode"] = joint.PipelineCode;
dr["SegmentCode"] = preCode;
dr["WeldJointNo"] = weldJointNo;
dr["MaterialText"] = string.IsNullOrEmpty(joint.Material1Code) ? joint.Material2Code : joint.Material1Code;
dr["Spec"] = joint.Specification;
dr["DesignTemperature"] = joint.PreTemperature;
dr["MaterialCode1"] = GetMaterialDisplayCode(row1, lib1);
dr["HeatNo1"] = lib1 == null ? string.Empty : lib1.HeatNo;
dr["BatchNo1"] = lib1 == null ? string.Empty : lib1.BatchNo;
dr["MaterialCode2"] = GetMaterialDisplayCode(row2, lib2);
dr["HeatNo2"] = lib2 == null ? string.Empty : lib2.HeatNo;
dr["BatchNo2"] = lib2 == null ? string.Empty : lib2.BatchNo;
dr["WelderCode"] = string.IsNullOrEmpty(joint.WelderCode) ? (string.IsNullOrEmpty(joint.BackingWelderCode) ? joint.CoverWelderCode : joint.BackingWelderCode) : joint.WelderCode;
dr["WeldingDate"] = joint.WeldingDate;
dr["WeldCheck"] = joint.CheckResult;
dr["CheckDate"] = joint.AuditDate == null ? string.Empty : joint.AuditDate.Value.ToString("yyyy-MM-dd");
dr["CleanCheck"] = joint.IsHotProessStr;
dr["CleanCheckDate"] = joint.AuditDate2 == null ? string.Empty : joint.AuditDate2.Value.ToString("yyyy-MM-dd");
dr["WeldJointId"] = joint.WeldJointId;
dr["Material1Code"] = joint.Material1Code;
dr["Material2Code"] = joint.Material2Code;
tb.Rows.Add(dr);
}
return tb;
}
/// <summary>
/// 获取材料库记录,优先按主编码,其次按导入编码。
/// </summary>
private HJGL_MaterialCodeLib GetMaterialLib(HJGL_PipeLineMat row, Dictionary<string, HJGL_MaterialCodeLib> libsByMaterialCode, Dictionary<string, HJGL_MaterialCodeLib> libsByCode)
{
if (row == null)
{
return null;
}
if (!string.IsNullOrEmpty(row.MaterialCode) && libsByMaterialCode.ContainsKey(row.MaterialCode))
{
return libsByMaterialCode[row.MaterialCode];
}
if (!string.IsNullOrEmpty(row.MaterialCode2) && libsByCode.ContainsKey(row.MaterialCode2))
{
return libsByCode[row.MaterialCode2];
}
return null;
}
/// <summary>
/// 返回打印用物料编码,优先显示导入编码。
/// </summary>
private string GetMaterialDisplayCode(HJGL_PipeLineMat row, HJGL_MaterialCodeLib lib)
{
if (row == null)
{
return string.Empty;
}
if (!string.IsNullOrEmpty(row.MaterialCode2))
{
return row.MaterialCode2;
}
if (lib != null)
{
return lib.Code;
}
return row.MaterialCode;
}
/// <summary>
/// 导出方法
/// </summary>
@@ -873,4 +1105,4 @@ namespace FineUIPro.Web.HJGL.InfoQuery
}
}
}
+19 -1
View File
@@ -155,7 +155,16 @@ namespace FineUIPro.Web.HJGL.InfoQuery {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.TextBox txtWeldJointCode;
/// <summary>
/// ddlWeldState 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.DropDownList ddlWeldState;
/// <summary>
/// ToolbarFill2 控件。
/// </summary>
@@ -191,6 +200,15 @@ namespace FineUIPro.Web.HJGL.InfoQuery {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Button btnOutNoComPipeline;
/// <summary>
/// btnPrintJointNameplate 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Button btnPrintJointNameplate;
/// <summary>
/// btnGetChart 控件。
@@ -146,7 +146,6 @@
<f:Toolbar ID="Toolbar3" Position="Top" runat="server" ToolbarAlign="Left">
<Items>
<f:Label ID="lbRate" runat="server" LabelWidth="100px" Hidden="true"></f:Label>
<f:Label ID="lbNote" runat="server" LabelWidth="100px" Text="绿色为匹配率100%,红色为匹配率小于100%,蓝色为手动优先焊口"></f:Label>
<f:Button ID="btnPriorityComponents" Text="优先匹配选中焊口" Icon="TabGo" runat="server" OnClick="btnPriorityComponents_Click">
</f:Button>
<f:Button ID="btnConfirmMaterialCode" Text="保存匹配结果" Icon="SystemSave" runat="server" OnClick="btnConfirmMaterialCode_Click" ConfirmText="确定根据当前匹配结果反写材料主编码吗?">
@@ -155,6 +154,10 @@
</f:Button>
<f:CheckBox ID="cbSelectCom" ShowLabel="false" runat="server" Text="默认勾选匹配100%" Checked="true">
</f:CheckBox>
<f:ToolbarFill ID="ToolbarFill1" runat="server">
</f:ToolbarFill>
<f:Button ID="btnMatchHelp" ToolTip="说明" Text="说明" Icon="Information" runat="server" OnClick="btnMatchHelp_Click">
</f:Button>
</Items>
</f:Toolbar>
</Toolbars>
@@ -188,7 +191,7 @@
<f:Grid ID="Grid1" ShowBorder="true" ShowHeader="false" Title="材料匹配明细" EnableRowClickEvent="true"
EnableCollapse="true" runat="server" BoxFlex="1" DataKeyNames="Id,PipelineId,PrefabricatedComponents,WeldJointId" ForceFit="true"
EnableColumnLines="true" DataIDField="Id" AllowSorting="true" OnRowDataBound="Grid1_RowDataBound" FixedRowHeight="true" RowHeight="46"
SortField="Id" SortDirection="ASC" OnSort="Grid1_Sort" EnableCheckBoxSelect="true">
SortField="PipelineCode" SortDirection="ASC" OnSort="Grid1_Sort" EnableCheckBoxSelect="true" EnableSummary="true" SummaryPosition="Bottom" >
<Columns>
<f:RenderField Width="200px" ColumnID="PipelineCode" DataField="PipelineCode" SortField="PipelineCode"
FieldType="String" HeaderText="管线号" HeaderTextAlign="Center"
@@ -2,6 +2,7 @@
using FineUIPro.Web.DataShow;
using Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
@@ -88,7 +89,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
}
/// <summary>
/// 页面首次加载时初始化仓库、流水段、匹配状态和左侧WBS管线树。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void Page_Load(object sender, EventArgs e)
{
//ctlAuditFlow.Url = BLL.Project_SysSetService.GetAvevaNetUrl(this.CurrUser.LoginProjectId);
@@ -220,6 +225,10 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
}
}
/// <summary>
/// 按分页方式向试压包节点追加管线子节点。
/// </summary>
/// <param name="node">需要加载管线的试压包树节点。</param>
private void BindNodes(TreeNode node)
{
//var NowComPipelineCode = PipelineService.GetNoComPipelinesByUnitWordId(node.NodeID);
@@ -266,6 +275,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
}
/// <summary>
/// 统计单位工程下各试压包可参与材料匹配的管线数量。
/// </summary>
/// <param name="unitWorkId">单位工程ID。</param>
/// <returns>可参与材料匹配的管线数量。</returns>
private int GetUnitWorkTestPackagePipelineCount(string unitWorkId)
{
var testPackageIds = (from x in Funs.DB.PTP_TestPackage
@@ -275,6 +289,10 @@ namespace FineUIPro.Web.HJGL.WeldingManage
return testPackageIds.Select(x => GetTestPackagePipelineList(x).Count()).Sum();
}
/// <summary>
/// 为单位工程节点绑定包含管线的试压包节点。
/// </summary>
/// <param name="unitWorkNode">单位工程树节点。</param>
private void BindTestPackageNodes(TreeNode unitWorkNode)
{
var testPackages = (from x in Funs.DB.PTP_TestPackage
@@ -308,6 +326,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
}
/// <summary>
/// 获取指定试压包下当前仓库、区域和筛选条件内尚未完成出库的管线。
/// </summary>
/// <param name="ptpId">试压包ID。</param>
/// <returns>符合材料匹配入口条件的管线列表。</returns>
private List<Model.HJGL_Pipeline> GetTestPackagePipelineList(string ptpId)
{
var completeInOutPlanDetailRelationList = from x in Funs.DB.Tw_InOutPlanDetail_Relation
@@ -334,6 +357,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
return pipeline.Distinct().ToList();
}
/// <summary>
/// 展开试压包节点时懒加载管线节点。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">树节点事件参数。</param>
protected void tvControlItem_TreeNodeExpanded(object sender, TreeNodeEventArgs e)
{
if (e.Node.Nodes[0].NodeID == "加载管线...")
@@ -345,6 +373,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
#endregion
/// <summary>
/// 按当前筛选条件重新加载左侧WBS管线树。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void btnTreeFind_Click(object sender, EventArgs e)
{
this.InitTreeMenu();
@@ -375,6 +408,9 @@ namespace FineUIPro.Web.HJGL.WeldingManage
#endregion
#region
/// <summary>
/// 绑定当前选中管线的材料汇总信息。
/// </summary>
private void BindGrid()
{
string strSql = @"SELECT ISNULL(pipe.MaterialCode2, lib.Code) AS MaterialCode,
@@ -469,6 +505,9 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
}
/// <summary>
/// 绑定已加入匹配的管线列表,并标识正在出库中的管线。
/// </summary>
void BindGrid3()
{
@@ -492,6 +531,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
#endregion
#region
/// <summary>
/// 材料匹配明细行绑定事件,保留历史行样式扩展入口。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">Grid行绑定事件参数。</param>
protected void Grid1_RowDataBound(object sender, GridRowEventArgs e)
{
// DataRowView row = e.DataItem as DataRowView;
@@ -506,16 +550,27 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
/// <summary>
/// 绑定指定管线的材料匹配明细,设置行颜色、优先焊口选中状态和可生成任务单合计。
/// </summary>
/// <param name="pipelineId">管线ID。</param>
private void BindMaterialDetail(string pipelineId)
{
// 任务单只允许从未生成任务单的焊口材料中选择,避免重复生成焊接任务。
var tb = GetNoTaskMaterialDetails()
.Where(x => x.PipelineId == pipelineId)
// 明细固定按管线号、预制组件号、焊口号、材料编码排序,便于同一焊口材料连续展示。
.OrderBy(x => x.PipelineCode)
.ThenBy(x => x.PrefabricatedComponents)
.ThenBy(x => x.WeldJointCode)
.ThenBy(x => x.MaterialCode)
.ToList();
Grid1.DataSource = tb;
Grid1.DataBind();
var selectList = new List<string>();
// 明细行绿色必须以数据库已反写字段判断,不能用本次匹配结果中的 MatchMaterialCode。
var confirmedPipeLineMatIds = GetConfirmedPipeLineMatIds(tb);
for (int i = 0; i < Grid1.Rows.Count; i++)
{
var model = Grid1.Rows[i].DataItem as Tw_PipeMatMatchOutput;
@@ -524,10 +579,19 @@ namespace FineUIPro.Web.HJGL.WeldingManage
continue;
}
if (IsPriorityWeldJoint(model.PipelineId, model.WeldJointId))
bool isPriority = IsPriorityWeldJoint(model.PipelineId, model.WeldJointId);
if (isPriority)
{
selectList.Add(model.Id);
}
if (IsMaterialCodeConfirmed(model, confirmedPipeLineMatIds))
{
Grid1.Rows[i].RowCssClass = "green";
}
else if (isPriority)
{
Grid1.Rows[i].RowCssClass = "priority";
selectList.Add(model.Id);
}
else if (model.MatchRate < 1 || model.MatchRate == null)
{
@@ -536,6 +600,22 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
Grid1.SelectedRowIDArray = selectList.ToArray();
BindTaskWeldJointSummary(tb);
}
/// <summary>
/// 在材料明细底部汇总当前明细中真正可生成任务单的焊口数量。
/// </summary>
/// <param name="materialDetails">当前展示的材料匹配明细。</param>
private void BindTaskWeldJointSummary(List<Tw_PipeMatMatchOutput> materialDetails)
{
// 合计行复用生成任务单的同一套判断,保证页面显示数量和按钮实际生成数量一致。
int taskWeldJointCount = GetTaskWeldJointIdsFromMaterialDetails(materialDetails).Count;
JObject summary = new JObject();
summary.Add("PipelineCode", "合计");
summary.Add("PrefabricatedComponents", "可生成任务单焊口数:");
summary.Add("WeldJointCode", taskWeldJointCount.ToString());
Grid1.SummaryData = summary;
}
/// <summary>
@@ -565,6 +645,12 @@ namespace FineUIPro.Web.HJGL.WeldingManage
.ToList();
}
/// <summary>
/// 判断焊口是否被用户设置为当前管线的本次优先匹配焊口。
/// </summary>
/// <param name="pipelineId">管线ID。</param>
/// <param name="weldJointId">焊口ID。</param>
/// <returns>已设置优先匹配返回 true,否则返回 false。</returns>
private bool IsPriorityWeldJoint(string pipelineId, string weldJointId)
{
return !string.IsNullOrEmpty(pipelineId)
@@ -573,6 +659,61 @@ namespace FineUIPro.Web.HJGL.WeldingManage
&& priorityWeldJoints[pipelineId].Contains(weldJointId);
}
/// <summary>
/// 获取材料明细中已持久化反写材料主编码的管线材料ID集合。
/// </summary>
/// <param name="materialDetails">材料匹配明细。</param>
/// <returns>已反写材料主编码的管线材料ID集合。</returns>
private HashSet<string> GetConfirmedPipeLineMatIds(IEnumerable<Tw_PipeMatMatchOutput> materialDetails)
{
// 已反写材料主编码的唯一可信来源是 HJGL_PipeLineMat.MaterialCode。
var pipeLineMatIds = materialDetails == null
? new List<string>()
: materialDetails
.Where(x => x != null && !string.IsNullOrEmpty(x.PipeLineMatId))
.Select(x => x.PipeLineMatId)
.Distinct()
.ToList();
if (!pipeLineMatIds.Any())
{
return new HashSet<string>();
}
var confirmedIds = Funs.DB.HJGL_PipeLineMat
.Where(x => pipeLineMatIds.Contains(x.PipeLineMatId) && x.MaterialCode != null && x.MaterialCode != "")
.Select(x => x.PipeLineMatId)
.ToList();
return new HashSet<string>(confirmedIds);
}
/// <summary>
/// 判断单条材料明细是否已经反写材料主编码。
/// </summary>
/// <param name="model">材料匹配明细。</param>
/// <param name="confirmedPipeLineMatIds">已反写材料主编码的管线材料ID集合。</param>
/// <returns>已反写返回 true,否则返回 false。</returns>
private bool IsMaterialCodeConfirmed(Tw_PipeMatMatchOutput model, HashSet<string> confirmedPipeLineMatIds)
{
return model != null
&& confirmedPipeLineMatIds != null
&& !string.IsNullOrEmpty(model.PipeLineMatId)
&& confirmedPipeLineMatIds.Contains(model.PipeLineMatId);
}
/// <summary>
/// 显示材料匹配颜色和任务单生成规则说明。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void btnMatchHelp_Click(object sender, EventArgs e)
{
Alert.ShowInTop("1、管线绿色为匹配率100%,明细绿色为已反写材料主编码,红色为匹配率小于100%,蓝色为手动优先焊口。<br/>2、一个焊口可能对应多条材料明细,该焊口全部有效明细已反写材料主编码后才允许一键生成任务单。<br/>3、焊口已进行焊前准备,匹配了焊评才能生成任务单", "说明", MessageBoxIcon.Information);
}
/// <summary>
/// 将本次优先匹配焊口状态转换为匹配服务需要的管线-焊口列表结构。
/// </summary>
/// <returns>管线ID到优先焊口ID列表的映射。</returns>
private Dictionary<string, List<string>> GetPriorityWeldJointList()
{
return priorityWeldJoints
@@ -580,6 +721,9 @@ namespace FineUIPro.Web.HJGL.WeldingManage
.ToDictionary(x => x.Key, x => x.Value.ToList());
}
/// <summary>
/// 重新计算材料匹配结果,并在刷新管线汇总后恢复原有管线勾选状态。
/// </summary>
private void RefreshMatchResult()
{
// 重新匹配库存会刷新管线汇总表,先暂存选择状态,绑定完成后再恢复。
@@ -593,11 +737,21 @@ namespace FineUIPro.Web.HJGL.WeldingManage
BindGrid2(keepSelectedPipelineIds);
}
/// <summary>
/// 点击材料匹配管线汇总行时刷新该管线的材料明细。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">Grid行点击事件参数。</param>
protected void Grid2_RowClick(object sender, GridRowClickEventArgs e)
{
BindMaterialDetail(Grid2.SelectedRowID);
}
/// <summary>
/// 点击材料明细行时联动三维模型定位当前管线或单位工程。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">Grid行点击事件参数。</param>
protected void Grid1_RowClick(object sender, GridRowClickEventArgs e)
{
Model.Parameter3D parameter3D = new Model.Parameter3D();
@@ -632,6 +786,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
//ctlAuditFlow.data = parameter3D;
//ctlAuditFlow.BindData();
}
/// <summary>
/// 记录材料明细排序字段,并按当前选中管线重新绑定明细。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">Grid排序事件参数。</param>
protected void Grid1_Sort(object sender, GridSortEventArgs e)
{
Grid1.SortDirection = e.SortDirection;
@@ -650,6 +809,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
#region
/// <summary>
/// 刷新三维模型参数,按当前树节点定位单位工程或管线。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void btnrefresh_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(this.tvControlItem.SelectedNodeID))
@@ -713,6 +877,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
/// <summary>
/// 打开单位工程材料匹配统计窗口。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void btnStatisticsMat_Click(object sender, EventArgs e)
{
Model.WBS_UnitWork unitWork = BLL.UnitWorkService.GetUnitWorkByUnitWorkId(this.tvControlItem.SelectedNodeID);
@@ -726,6 +895,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
}
/// <summary>
/// 将左侧勾选的管线加入本次材料匹配范围并刷新匹配结果。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void btnAddPipelineMatchMat_Click(object sender, EventArgs e)
{
var selectNodes = tvControlItem.GetCheckedNodes();
@@ -739,6 +913,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
RefreshMatchResult();
}
/// <summary>
/// 从本次材料匹配范围移除选中管线,并清理对应的优先焊口状态。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void btnDeletePipelineMatchMat_Click(object sender, EventArgs e)
{
if (Grid3.SelectedRowIDArray != null && Grid3.SelectedRowIDArray.Any())
@@ -757,7 +936,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
RefreshMatchResult();
}
}
/// <summary>
/// 优先匹配选中焊口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnPriorityComponents_Click(object sender, EventArgs e)
{
string selectedPipelineId = Grid2.SelectedRowID;
@@ -804,6 +987,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
BindMaterialDetail(selectedPipelineId);
}
/// <summary>
/// 将当前选中管线的匹配结果反写到管线材料主编码。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void btnConfirmMaterialCode_Click(object sender, EventArgs e)
{
if (Grid2.SelectedRowIDArray == null || !Grid2.SelectedRowIDArray.Any())
@@ -845,44 +1033,58 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
}
/// <summary>
/// 按 Grid2 选中管线下可生成任务单的焊口批量生成焊接任务单。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void btnGenTask_Click(object sender, EventArgs e)
{
if (GetSelectedWeldJointIdsFromGrid1().Any())
if (Grid2.SelectedRowIDArray == null || !Grid2.SelectedRowIDArray.Any())
{
if (SaveTask())
{
ShowNotify("生成任务单成功!", MessageBoxIcon.Warning);
// Alert.Show("生成任务单成功!", MessageBoxIcon.Warning);
Grid1.DataSource = null;
Grid1.DataBind();
Grid2.DataSource = null;
Grid2.DataBind();
Grid3.DataSource = null;
Grid3.DataBind();
}
ShowNotify("请先在材料匹配列表中选择需要生成任务单的管线!", MessageBoxIcon.Warning);
return;
}
else
// 生成任务单按 Grid2 勾选管线批量取焊口,不再要求用户在 Grid1 明细逐条勾选。
var selectedWeldJointIds = GetTaskWeldJointIdsFromSelectedPipelines();
if (!selectedWeldJointIds.Any())
{
ShowNotify("请先在材料匹配明细中选择需要生成任务单焊口!", MessageBoxIcon.Warning);
ShowNotify("选中管线中没有已反写材料主编码的可生成任务单焊口!", MessageBoxIcon.Warning);
return;
}
if (SaveTask(selectedWeldJointIds))
{
ShowNotify("生成任务单成功!", MessageBoxIcon.Warning);
// Alert.Show("生成任务单成功!", MessageBoxIcon.Warning);
Grid1.DataSource = null;
Grid1.DataBind();
BindTaskWeldJointSummary(new List<Tw_PipeMatMatchOutput>());
Grid2.DataSource = null;
Grid2.DataBind();
Grid3.DataSource = null;
Grid3.DataBind();
}
}
private bool SaveTask()
/// <summary>
/// 根据已通过材料齐套和任务单条件过滤的焊口生成焊接任务单。
/// </summary>
/// <param name="selectedWeldJointIds">待生成任务单的焊口ID集合。</param>
/// <returns>生成成功返回 true;校验失败或无可生成焊口返回 false。</returns>
private bool SaveTask(HashSet<string> selectedWeldJointIds)
{
var selectedWeldJointIds = GetSelectedWeldJointIdsFromGrid1();
if (!selectedWeldJointIds.Any())
if (selectedWeldJointIds == null || !selectedWeldJointIds.Any())
{
ShowNotify("请先在材料匹配明细中选择需要生成任务单焊口!", MessageBoxIcon.Warning);
ShowNotify("选中管线中没有已反写材料主编码的可生成任务单焊口!", MessageBoxIcon.Warning);
return false;
}
var weldingRods = from x in Funs.DB.Base_Consumables where x.ConsumablesType == "2" select x;
var weldingWires = from x in Funs.DB.Base_Consumables where x.ConsumablesType == "1" select x;
var selectedWeldJointIdList = selectedWeldJointIds.ToList();
// 任务单按用户在材料匹配明细中勾选的焊口生成,不再按整条管线生成。
var selectRowId = (from x in Funs.DB.View_HJGL_NoWeldJointFind
where selectedWeldJointIdList.Contains(x.WeldJointId) && x.WeldingDailyId == null &&
x.WeldTaskId == null && x.WeldingMethodCode != null
select x).ToList();
var selectRowId = GetTaskableWeldJointRows(selectedWeldJointIdList);
Dictionary<string, string> unitworkTaskCode = new Dictionary<string, string>();
Dictionary<string, string> unitworkSerialNumber = new Dictionary<string, string>();
@@ -892,10 +1094,6 @@ namespace FineUIPro.Web.HJGL.WeldingManage
{
matchPipeline.Add(rowIndex + 1, Grid2.Rows[rowIndex].RowID);
}
if (PipeArea == "1") //工厂预制的管线,则只选择预制口
{
selectRowId = selectRowId.Where(x => x.JointAttribute == "预制口").ToList();
}
if (!selectRowId.Any())
{
ShowNotify("未找到可生成任务单的焊口!", MessageBoxIcon.Warning);
@@ -1012,33 +1210,89 @@ namespace FineUIPro.Web.HJGL.WeldingManage
}
/// <summary>
/// 从材料匹配明细 Grid1 中提取用户选中的焊口ID
/// 按任务单实际生成规则过滤可生成任务单的焊口视图数据
/// </summary>
private HashSet<string> GetSelectedWeldJointIdsFromGrid1()
/// <param name="weldJointIds">候选焊口ID集合。</param>
/// <returns>符合任务单生成条件的焊口视图数据。</returns>
private List<Model.View_HJGL_NoWeldJointFind> GetTaskableWeldJointRows(IEnumerable<string> weldJointIds)
{
var selectedWeldJointIds = new HashSet<string>();
if (Grid1.SelectedRowIndexArray == null)
var weldJointIdList = weldJointIds == null
? new List<string>()
: weldJointIds.Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();
if (!weldJointIdList.Any())
{
return selectedWeldJointIds;
return new List<Model.View_HJGL_NoWeldJointFind>();
}
foreach (int rowIndex in Grid1.SelectedRowIndexArray)
// 合计行和生成按钮必须共用同一套可生成条件:未生成日报、未生成任务单、已维护焊接方法。
var taskableRows = (from x in Funs.DB.View_HJGL_NoWeldJointFind
where weldJointIdList.Contains(x.WeldJointId)
&& x.WeldingDailyId == null
&& x.WeldTaskId == null
&& x.WeldingMethodCode != null
select x).ToList();
if (PipeArea == "1")
{
if (Grid1.DataKeys[rowIndex].Length < 4)
{
continue;
}
string weldJointId = Grid1.DataKeys[rowIndex][3]?.ToString();
if (!string.IsNullOrEmpty(weldJointId))
{
selectedWeldJointIds.Add(weldJointId);
}
// 工厂预制材料匹配只允许预制口生成任务单,现场安装页面不套用该限制。
taskableRows = taskableRows.Where(x => x.JointAttribute == "预制口").ToList();
}
return selectedWeldJointIds;
return taskableRows;
}
/// <summary>
/// 从 Grid2 选中的管线中收集可生成任务单的焊口ID。
/// </summary>
/// <returns>可生成任务单的焊口ID集合。</returns>
private HashSet<string> GetTaskWeldJointIdsFromSelectedPipelines()
{
// Grid2 的选中管线是任务单生成范围,Grid1 当前展示哪条管线不影响批量生成。
var selectedPipelineIds = Grid2.SelectedRowIDArray == null
? new HashSet<string>()
: new HashSet<string>(Grid2.SelectedRowIDArray.Where(x => !string.IsNullOrEmpty(x)));
if (!selectedPipelineIds.Any())
{
return new HashSet<string>();
}
var materialDetails = GetNoTaskMaterialDetails()
// 生成任务单只校验参与匹配的有效材料明细,零用量材料不参与焊口材料齐套判断。
.Where(x => selectedPipelineIds.Contains(x.PipelineId) && !string.IsNullOrEmpty(x.WeldJointId) && (x.NeedNum ?? 0) > 0)
.ToList();
return GetTaskWeldJointIdsFromMaterialDetails(materialDetails);
}
/// <summary>
/// 根据材料明细判断焊口是否材料齐套且满足任务单生成条件。
/// </summary>
/// <param name="materialDetails">候选材料匹配明细。</param>
/// <returns>可生成任务单的焊口ID集合。</returns>
private HashSet<string> GetTaskWeldJointIdsFromMaterialDetails(List<Tw_PipeMatMatchOutput> materialDetails)
{
if (materialDetails == null || !materialDetails.Any())
{
return new HashSet<string>();
}
materialDetails = materialDetails
.Where(x => x != null && !string.IsNullOrEmpty(x.WeldJointId) && (x.NeedNum ?? 0) > 0)
.ToList();
// 同一焊口可能有多条有效材料明细,所有明细都反写材料主编码后才算可生成任务单。
var confirmedPipeLineMatIds = GetConfirmedPipeLineMatIds(materialDetails);
var weldJointIds = materialDetails
.GroupBy(x => x.WeldJointId)
.Where(x => x.All(y => IsMaterialCodeConfirmed(y, confirmedPipeLineMatIds)))
.Select(x => x.Key);
// 材料齐套后还要继续套用任务单视图条件,保证合计数量和点击生成按钮的实际范围一致。
return new HashSet<string>(GetTaskableWeldJointRows(weldJointIds).Select(x => x.WeldJointId));
}
/// <summary>
/// 获取指定管线范围内的优先匹配焊口集合。
/// </summary>
/// <param name="selectedPipelineIds">管线ID列表。</param>
/// <returns>管线ID到优先焊口ID集合的映射。</returns>
private Dictionary<string, HashSet<string>> GetPriorityWeldJointIds(List<string> selectedPipelineIds)
{
var result = new Dictionary<string, HashSet<string>>();
@@ -1054,6 +1308,12 @@ namespace FineUIPro.Web.HJGL.WeldingManage
return result;
}
/// <summary>
/// 判断焊材钢号类别是否能覆盖母材类别。
/// </summary>
/// <param name="wpsClass">焊材钢号类别。</param>
/// <param name="matClass">母材类别。</param>
/// <returns>能覆盖返回 true,否则返回 false。</returns>
private bool IsCoverClass(string wpsClass, string matClass)
{
bool isCover = false;
@@ -1081,6 +1341,11 @@ namespace FineUIPro.Web.HJGL.WeldingManage
#endregion
/// <summary>
/// 仓库切换后刷新当前仓库ID并重新加载左侧管线树。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
protected void drpWarehouse_SelectedIndexChanged(object sender, EventArgs e)
{
WarehouseId = Base_WarehouseService.GetWarehouseList(this.CurrUser.LoginProjectId)
@@ -248,15 +248,6 @@ namespace FineUIPro.Web.HJGL.WeldingManage
/// </remarks>
protected global::FineUIPro.Label lbRate;
/// <summary>
/// lbNote 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label lbNote;
/// <summary>
/// btnPriorityComponents 控件。
/// </summary>
@@ -293,6 +284,24 @@ namespace FineUIPro.Web.HJGL.WeldingManage
/// </remarks>
protected global::FineUIPro.CheckBox cbSelectCom;
/// <summary>
/// ToolbarFill1 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.ToolbarFill ToolbarFill1;
/// <summary>
/// btnMatchHelp 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Button btnMatchHelp;
/// <summary>
/// Grid2 控件。
/// </summary>
@@ -1533,33 +1533,64 @@ namespace FineUIPro.Web.HJGL.WeldingManage
// 添加列
dataTable.Columns.Add("PipelineCode", typeof(string));
dataTable.Columns.Add("FlowingSection", typeof(string));
dataTable.Columns.Add("WeldJointCode", typeof(string));
dataTable.Columns.Add("MaterialCode", typeof(string));
dataTable.Columns.Add("BatchNo", typeof(string));
dataTable.Columns.Add("NeedNum", typeof(string));
dataTable.Columns.Add("MaterialMade", typeof(string));
dataTable.Columns.Add("MaterialSpec", typeof(string));
dataTable.Columns.Add("MatchRate", typeof(string));
dataTable.Columns.Add("Dia", typeof(string));
dataTable.Columns.Add("PaintCode", typeof(string));
dataTable.Columns.Add("WeldingSize", typeof(string));
dataTable.Columns.Add("Remark", typeof(string));
foreach (string pipeline in pipelines)
var taskWeldJointIds = weldTaskList.Where(x => !string.IsNullOrEmpty(x.WeldJointId))
.Select(x => x.WeldJointId).Distinct().ToList();
var pipelineList = Funs.DB.HJGL_Pipeline.Where(x => pipelines.Contains(x.PipelineId)).ToList();
var printMaterials = (from x in Funs.DB.HJGL_PipeLineMat
join y in Funs.DB.HJGL_MaterialCodeLib on x.MaterialCode equals y.MaterialCode
where pipelines.Contains(x.PipelineId)
&& taskWeldJointIds.Contains(x.WeldJointId)
&& x.PrefabricatedComponents != null
select new
{
x.PipelineId,
x.WeldJointId,
x.MaterialCode,
x.Number,
y.Code,
y.HeatNo,
y.BatchNo,
y.MaterialMade,
y.MaterialSpec
}).ToList();
var sortedTaskList = weldTaskList.OrderBy(x => x.PipeLineSortIndex).ThenBy(x => x.WeldJointCode).ToList();
foreach (var task in sortedTaskList)
{
DataRow dr = dataTable.NewRow();
var pipelineModel = PipelineService.GetPipelineByPipelineId(pipeline);
if (pipelineModel == null)
var taskMaterials = printMaterials.Where(x => x.WeldJointId == task.WeldJointId)
.OrderBy(x => x.Code).ToList();
if (!taskMaterials.Any())
{
continue;
taskMaterials.Add(null);
}
dr["PipelineCode"] = pipelineModel.PipelineCode;
dr["FlowingSection"] = pipelineModel.FlowingSection;
// 管线基础资料可能未维护材质,打印时保留空值,避免整张任务单打印失败。
var materialModel = string.IsNullOrEmpty(pipelineModel.MaterialId) ? null : Base_MaterialService.GetMaterialByMaterialId(pipelineModel.MaterialId);
dr["MaterialCode"] = materialModel?.MaterialCode ?? string.Empty;
dr["MaterialSpec"] = string.Join(",", weldTaskList.Select(x => x.Specification).Distinct().ToList());
// 匹配率计算依赖管线仓库,未维护仓库时按0显示,避免基础资料缺项阻断打印。
var warehouseModel = string.IsNullOrEmpty(pipelineModel.WarehouseId) ? null : Base_WarehouseService.GetWarehouseByWarehouseId(pipelineModel.WarehouseId);
var matchRate = warehouseModel == null ? 0 : TwArrivalStatisticsService.GetPipeMatch(pipeline) ?? 0;
dr["MatchRate"] = Math.Round(matchRate * 100, 2).ToString() + "%";
dr["Dia"] = weldTaskList.Where(x => x.PipelineId == pipeline).Sum(x => x.Size ?? 0)
.ToString();
dataTable.Rows.Add(dr);
foreach (var material in taskMaterials)
{
DataRow dr = dataTable.NewRow();
dr["PipelineCode"] = task.PipelineCode;
dr["FlowingSection"] = pipelineList.FirstOrDefault(x => x.PipelineId == task.PipelineId)?.FlowingSection ?? string.Empty;
dr["WeldJointCode"] = !string.IsNullOrEmpty(task.PipelineCode) ? task.WeldJointCode.Replace(task.PipelineCode + "/", "") : task.WeldJointCode;
dr["MaterialCode"] = material?.Code ?? material?.MaterialCode ?? string.Empty;
dr["BatchNo"] = material == null ? string.Empty : string.Join("/", new[] { material.HeatNo, material.BatchNo }.Where(x => !string.IsNullOrEmpty(x)));
dr["NeedNum"] = material?.Number != null ? material.Number.Value.ToString("0.##") : string.Empty;
dr["MaterialMade"] = material?.MaterialMade ?? string.Empty;
dr["MaterialSpec"] = material?.MaterialSpec ?? string.Empty;
// 当前焊接任务单取数链路未维护油漆号,先输出空列,避免模板字段缺失。
dr["PaintCode"] = string.Empty;
dr["WeldingSize"] = task.Size.HasValue ? task.Size.Value.ToString("0.##") : string.Empty;
dr["Remark"] = string.Empty;
dataTable.Rows.Add(dr);
}
}
BLL.FastReportService.AddFastreportTable(Table1);
BLL.FastReportService.AddFastreportTable(dataTable);