feat(hjgl): 完善检测结果导入与焊接质量管理

通过批量导入、标准化打印和材料导出,减少检测结果及材料信息的人工整理,确保检测单、委托状态和焊口质量资料保持一致。
This commit is contained in:
2026-08-21 15:22:24 +08:00
parent 42787c1520
commit fdaf615194
20 changed files with 1236 additions and 171 deletions
@@ -44,6 +44,12 @@
</f:TextBox>
</Items>
</f:Toolbar>
<f:Toolbar ID="Toolbar6" Position="Top" runat="server" ToolbarAlign="Right">
<Items>
<f:Button ID="btnUnitWorkImport" Text="检测结果导入" ToolTip="选中单位工程后批量导入检测结果"
Icon="ApplicationGet" runat="server" Hidden="true" OnClick="btnUnitWorkImport_Click" />
</Items>
</f:Toolbar>
</Toolbars>
<Items>
<f:Tree ID="tvControlItem" ShowHeader="false" Title="检测单节点树" OnNodeCommand="tvControlItem_NodeCommand"
@@ -83,6 +83,7 @@ namespace FineUIPro.Web.HJGL.NDT
if (buttonList.Contains(BLL.Const.BtnSave))
{
this.btnEdit.Hidden = false;
this.btnUnitWorkImport.Hidden = false;
}
if (buttonList.Contains(BLL.Const.BtnAuditing))
{
@@ -1073,5 +1074,27 @@ namespace FineUIPro.Web.HJGL.NDT
ShowNotify("请选择委托单号!", MessageBoxIcon.Warning);
}
}
/// <summary>
/// 单位工程级批量导入检测结果
/// </summary>
protected void btnUnitWorkImport_Click(object sender, EventArgs e)
{
if (!CommonService.GetAllButtonPowerList(this.CurrUser.LoginProjectId, this.CurrUser.PersonId, Const.HJGL_NDTBatchMenuId, Const.BtnSave))
{
ShowNotify("您没有这个权限,请与管理员联系!", MessageBoxIcon.Warning);
return;
}
if (this.tvControlItem.SelectedNode == null || this.tvControlItem.SelectedNode.CommandName != "单位工程")
{
ShowNotify("请先选中单位工程节点!", MessageBoxIcon.Warning);
return;
}
string window = string.Format("NDTBatchUnitImport.aspx?unitWorkId={0}&type={1}",
Server.UrlEncode(this.tvControlItem.SelectedNodeID), Server.UrlEncode(this.Type));
PageContext.RegisterStartupScript(Window2.GetShowReference(window));
}
}
}
+62 -42
View File
@@ -7,11 +7,13 @@
// </自动生成>
//------------------------------------------------------------------------------
namespace FineUIPro.Web.HJGL.NDT {
public partial class NDTBatch {
namespace FineUIPro.Web.HJGL.NDT
{
public partial class NDTBatch
{
/// <summary>
/// form1 控件。
/// </summary>
@@ -20,7 +22,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlForm form1;
/// <summary>
/// PageManager1 控件。
/// </summary>
@@ -29,7 +31,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.PageManager PageManager1;
/// <summary>
/// Panel1 控件。
/// </summary>
@@ -38,7 +40,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Panel Panel1;
/// <summary>
/// panelLeftRegion 控件。
/// </summary>
@@ -47,7 +49,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Panel panelLeftRegion;
/// <summary>
/// Toolbar1 控件。
/// </summary>
@@ -56,7 +58,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Toolbar Toolbar1;
/// <summary>
/// txtNDEDateMonth 控件。
/// </summary>
@@ -65,7 +67,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.DatePicker txtNDEDateMonth;
/// <summary>
/// Toolbar3 控件。
/// </summary>
@@ -74,7 +76,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Toolbar Toolbar3;
/// <summary>
/// drpUnit 控件。
/// </summary>
@@ -83,7 +85,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.DropDownList drpUnit;
/// <summary>
/// Toolbar5 控件。
/// </summary>
@@ -92,7 +94,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Toolbar Toolbar5;
/// <summary>
/// txtSearchCode 控件。
/// </summary>
@@ -101,7 +103,25 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.TextBox txtSearchCode;
/// <summary>
/// Toolbar6 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Toolbar Toolbar6;
/// <summary>
/// btnUnitWorkImport 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Button btnUnitWorkImport;
/// <summary>
/// tvControlItem 控件。
/// </summary>
@@ -110,7 +130,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Tree tvControlItem;
/// <summary>
/// panelCenterRegion 控件。
/// </summary>
@@ -119,7 +139,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Panel panelCenterRegion;
/// <summary>
/// Toolbar2 控件。
/// </summary>
@@ -128,7 +148,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Toolbar Toolbar2;
/// <summary>
/// hdTrustBatchId 控件。
/// </summary>
@@ -137,7 +157,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.HiddenField hdTrustBatchId;
/// <summary>
/// ToolbarFill1 控件。
/// </summary>
@@ -146,7 +166,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.ToolbarFill ToolbarFill1;
/// <summary>
/// BtnRepairRecord 控件。
/// </summary>
@@ -155,7 +175,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Button BtnRepairRecord;
/// <summary>
/// SimpleForm1 控件。
/// </summary>
@@ -164,7 +184,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Form SimpleForm1;
/// <summary>
/// txtNDECode 控件。
/// </summary>
@@ -173,7 +193,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label txtNDECode;
/// <summary>
/// txtUnitName 控件。
/// </summary>
@@ -182,7 +202,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label txtUnitName;
/// <summary>
/// txtCheckUnit 控件。
/// </summary>
@@ -191,7 +211,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label txtCheckUnit;
/// <summary>
/// txtDetectionTypeCode 控件。
/// </summary>
@@ -200,7 +220,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label txtDetectionTypeCode;
/// <summary>
/// txtIsCheck 控件。
/// </summary>
@@ -209,7 +229,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label txtIsCheck;
/// <summary>
/// txtNDEDate 控件。
/// </summary>
@@ -218,7 +238,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label txtNDEDate;
/// <summary>
/// Grid1 控件。
/// </summary>
@@ -227,7 +247,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Grid Grid1;
/// <summary>
/// lbCheckDefects 控件。
/// </summary>
@@ -236,7 +256,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::System.Web.UI.WebControls.Label lbCheckDefects;
/// <summary>
/// ToolbarSeparator1 控件。
/// </summary>
@@ -245,7 +265,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.ToolbarSeparator ToolbarSeparator1;
/// <summary>
/// ToolbarText1 控件。
/// </summary>
@@ -254,7 +274,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.ToolbarText ToolbarText1;
/// <summary>
/// ddlPageSize 控件。
/// </summary>
@@ -263,7 +283,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.DropDownList ddlPageSize;
/// <summary>
/// Window1 控件。
/// </summary>
@@ -272,7 +292,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Window Window1;
/// <summary>
/// Window2 控件。
/// </summary>
@@ -281,7 +301,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Window Window2;
/// <summary>
/// WindowRepair 控件。
/// </summary>
@@ -290,7 +310,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Window WindowRepair;
/// <summary>
/// Menu1 控件。
/// </summary>
@@ -299,7 +319,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Menu Menu1;
/// <summary>
/// btnDataIn 控件。
/// </summary>
@@ -308,7 +328,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.MenuButton btnDataIn;
/// <summary>
/// btnNew 控件。
/// </summary>
@@ -317,7 +337,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.MenuButton btnNew;
/// <summary>
/// btnEdit 控件。
/// </summary>
@@ -326,7 +346,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.MenuButton btnEdit;
/// <summary>
/// btnAudit 控件。
/// </summary>
@@ -335,7 +355,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.MenuButton btnAudit;
/// <summary>
/// btnView 控件。
/// </summary>
@@ -344,7 +364,7 @@ namespace FineUIPro.Web.HJGL.NDT {
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.MenuButton btnView;
/// <summary>
/// btnDelete 控件。
/// </summary>
@@ -0,0 +1,80 @@
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NDTBatchUnitImport.aspx.cs" Inherits="FineUIPro.Web.HJGL.NDT.NDTBatchUnitImport" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>检测结果导入</title>
</head>
<body>
<form id="form1" runat="server">
<f:PageManager ID="PageManager1" AutoSizePanelID="SimpleForm1" runat="server" />
<f:Form ID="SimpleForm1" ShowBorder="false" ShowHeader="false" AutoScroll="true"
BodyPadding="10px" runat="server" RedStarPosition="BeforeText" LabelAlign="Right">
<Toolbars>
<f:Toolbar ID="Toolbar1" Position="Top" ToolbarAlign="Left" runat="server">
<Items>
<f:Label ID="lblUnitWork" Label="单位工程" LabelWidth="80px" runat="server" />
<f:ToolbarFill runat="server" />
<f:Button ID="btnDownLoad" runat="server" Icon="ApplicationGo" Text="下载模板"
ToolTip="下载空白检测结果导入模板" OnClick="btnDownLoad_Click"
EnablePostBack="true" EnableAjax="false" />
</Items>
</f:Toolbar>
<f:Toolbar ID="Toolbar2" Position="Top" ToolbarAlign="Right" runat="server">
<Items>
<f:FileUpload ID="fuAttachUrl" runat="server" Label="导入文件" LabelWidth="80px"
EmptyText="选择要导入的 .xlsx 文件" />
<f:ToolbarFill runat="server" />
<f:Button ID="btnAudit" Icon="ApplicationEdit" runat="server" Text="审核并预览"
ToolTip="校验导入文件并预览" OnClick="btnAudit_Click" />
<f:Button ID="btnSave" Icon="SystemSave" runat="server" Text="提交导入"
ToolTip="提交当前预览数据" OnClick="btnSave_Click" />
</Items>
</f:Toolbar>
</Toolbars>
<Rows>
<f:FormRow>
<Items>
<f:Grid ID="Grid1" ShowBorder="true" ShowHeader="false" EnableCollapse="true"
runat="server" Height="520px" DataKeyNames="TrustBatchItemId" DataIDField="TrustBatchItemId"
AllowColumnLocking="true" EnableColumnLines="true" AllowPaging="true" PageSize="100"
EnableTextSelection="true" OnPageIndexChange="Grid1_PageIndexChange">
<Columns>
<f:RenderField Width="60px" DataField="RowNumber" HeaderText="序号"
HeaderTextAlign="Center" TextAlign="Center" />
<f:RenderField Width="180px" DataField="TrustBatchCode" HeaderText="委托编号"
HeaderTextAlign="Center" TextAlign="Left" />
<f:RenderField Width="180px" DataField="PipelineCode" HeaderText="管线号"
HeaderTextAlign="Center" TextAlign="Left" />
<f:RenderField Width="120px" DataField="WeldJointCode" HeaderText="检件焊口号"
HeaderTextAlign="Center" TextAlign="Left" />
<f:RenderField Width="100px" DataField="WelderCode" HeaderText="焊工号"
HeaderTextAlign="Center" TextAlign="Left" />
<f:RenderField Width="90px" DataField="TotalFilm" HeaderText="检测总数"
HeaderTextAlign="Center" TextAlign="Center" />
<f:RenderField Width="80px" DataField="PassFilm" HeaderText="合格数"
HeaderTextAlign="Center" TextAlign="Center" />
<f:RenderField Width="90px" DataField="CheckResultText" HeaderText="是否合格"
HeaderTextAlign="Center" TextAlign="Center" />
<f:RenderField Width="90px" DataField="JudgeGrade" HeaderText="评定级别"
HeaderTextAlign="Center" TextAlign="Center" />
<f:RenderField Width="140px" DataField="CheckDefectsText" HeaderText="缺陷"
HeaderTextAlign="Center" TextAlign="Left" />
<f:RenderField Width="140px" DataField="RepairLocation" HeaderText="返修位置"
HeaderTextAlign="Center" TextAlign="Left" />
<f:RenderField Width="180px" DataField="Remark" HeaderText="备注"
HeaderTextAlign="Center" TextAlign="Left" />
<f:RenderField Width="110px" DataField="FilmDate" HeaderText="检测日期"
FieldType="Date" Renderer="Date" HeaderTextAlign="Center" TextAlign="Center" />
<f:RenderField Width="110px" DataField="ReportDate" HeaderText="报告日期"
FieldType="Date" Renderer="Date" HeaderTextAlign="Center" TextAlign="Center" />
</Columns>
</f:Grid>
</Items>
</f:FormRow>
</Rows>
</f:Form>
</form>
</body>
</html>
@@ -0,0 +1,496 @@
using BLL;
using MiniExcelLibs;
using Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Web;
namespace FineUIPro.Web.HJGL.NDT
{
public partial class NDTBatchUnitImport : PageBase
{
private static readonly string[] TemplateColumns =
{
"序号", "委托编号", "管线号", "检件焊口号", "焊工号", "检测总数",
"合格数", "是否合格", "评定级别", "缺陷", "返修位置", "备注",
"检测日期", "报告日期"
};
private string UnitWorkId
{
get { return Convert.ToString(ViewState["UnitWorkId"]); }
set { ViewState["UnitWorkId"] = value; }
}
private string NDTType
{
get { return Convert.ToString(ViewState["NDTType"]); }
set { ViewState["NDTType"] = value; }
}
private string ImportCacheKey
{
get { return Convert.ToString(ViewState["ImportCacheKey"]); }
set { ViewState["ImportCacheKey"] = value; }
}
private List<UnitWorkNDEImportItem> ImportItems
{
get
{
return Session[ImportCacheKey] as List<UnitWorkNDEImportItem>
?? new List<UnitWorkNDEImportItem>();
}
set { Session[ImportCacheKey] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
UnitWorkId = Request.QueryString["unitWorkId"];
NDTType = Request.QueryString["type"];
ImportCacheKey = "NDTBatchUnitImport_" + Guid.NewGuid().ToString("N");
ImportItems = new List<UnitWorkNDEImportItem>();
WBS_UnitWork unitWork = Funs.DB.WBS_UnitWork.FirstOrDefault(x =>
x.UnitWorkId == UnitWorkId
&& x.ProjectId == CurrUser.LoginProjectId
&& x.SuperUnitWork == null);
if (unitWork == null)
{
btnAudit.Enabled = false;
btnSave.Enabled = false;
btnDownLoad.Enabled = false;
ShowNotify("单位工程不存在或不属于当前项目!", MessageBoxIcon.Warning);
return;
}
lblUnitWork.Text = unitWork.UnitWorkCode + " " + unitWork.UnitWorkName;
BindGrid();
}
}
protected void btnDownLoad_Click(object sender, EventArgs e)
{
string templatePath = Server.MapPath("~/" + Const.NDTBatchUnitImportTemplateUrl.Replace("\\", "/"));
if (!File.Exists(templatePath))
{
ShowNotify("检测结果导入模板不存在,请联系管理员!", MessageBoxIcon.Error);
return;
}
FileInfo info = new FileInfo(templatePath);
Response.ClearContent();
Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode("检测结果导入模板.xlsx", System.Text.Encoding.UTF8));
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.AddHeader("Content-Length", info.Length.ToString());
Response.TransmitFile(templatePath, 0, info.Length);
Response.Flush();
Response.Close();
}
protected void btnAudit_Click(object sender, EventArgs e)
{
if (!fuAttachUrl.HasFile)
{
ShowNotify("请选择要导入的 Excel 文件!", MessageBoxIcon.Warning);
return;
}
string extension = Path.GetExtension(fuAttachUrl.FileName).ToLowerInvariant();
if (extension != ".xlsx")
{
ShowNotify("只能导入 .xlsx 文件!", MessageBoxIcon.Warning);
return;
}
string rootPath = Server.MapPath("~/");
string uploadDirectory = Path.Combine(rootPath, Const.ExcelUrl);
if (!Directory.Exists(uploadDirectory))
{
Directory.CreateDirectory(uploadDirectory);
}
string filePath = Path.Combine(uploadDirectory, Funs.GetNewFileName() + extension);
try
{
fuAttachUrl.PostedFile.SaveAs(filePath);
DataTable table = MiniExcel.QueryAsDataTable(filePath, useHeaderRow: true);
List<string> errors;
List<UnitWorkNDEImportItem> importItems = ParseImportItems(table, out errors);
if (errors.Count > 0)
{
ImportItems = new List<UnitWorkNDEImportItem>();
BindGrid();
ShowErrors(errors);
return;
}
ImportItems = importItems;
BindGrid();
ShowNotify("审核完成,共 " + importItems.Count + " 条,请确认后提交导入!", MessageBoxIcon.Success);
}
catch (Exception ex)
{
ImportItems = new List<UnitWorkNDEImportItem>();
BindGrid();
ShowNotify("读取导入文件失败:" + ex.Message, MessageBoxIcon.Error);
}
finally
{
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}
}
protected void btnSave_Click(object sender, EventArgs e)
{
if (!CommonService.GetAllButtonPowerList(CurrUser.LoginProjectId, CurrUser.PersonId, Const.HJGL_NDTBatchMenuId, Const.BtnSave))
{
ShowNotify("您没有这个权限,请与管理员联系!", MessageBoxIcon.Warning);
return;
}
List<UnitWorkNDEImportItem> importItems = ImportItems;
if (importItems.Count == 0)
{
ShowNotify("请先审核要导入的文件!", MessageBoxIcon.Warning);
return;
}
try
{
Batch_NDEImportService.Import(CurrUser.LoginProjectId, UnitWorkId, CurrUser.PersonId, importItems);
Session.Remove(ImportCacheKey);
ShowNotify("成功导入 " + importItems.Count + " 条检测结果!", MessageBoxIcon.Success);
PageContext.RegisterStartupScript(ActiveWindow.GetHidePostBackReference());
}
catch (Exception ex)
{
ShowNotify("导入失败:" + ex.Message, MessageBoxIcon.Error);
}
}
protected void Grid1_PageIndexChange(object sender, GridPageEventArgs e)
{
Grid1.PageIndex = e.NewPageIndex;
BindGrid();
}
private List<UnitWorkNDEImportItem> ParseImportItems(DataTable table, out List<string> errors)
{
errors = new List<string>();
List<UnitWorkNDEImportItem> result = new List<UnitWorkNDEImportItem>();
if (table == null || table.Rows.Count == 0)
{
errors.Add("导入数据为空!");
return result;
}
List<string> missingColumns = TemplateColumns.Where(x => !table.Columns.Contains(x)).ToList();
if (missingColumns.Count > 0)
{
errors.Add("导入 Excel 格式错误,缺少列:" + string.Join("、", missingColumns));
return result;
}
List<View_Batch_BatchTrustItem> trustItems = GetUnitWorkTrustItems();
Dictionary<string, View_Batch_BatchTrust> trustMap = Funs.DB.View_Batch_BatchTrust
.Where(x => x.ProjectId == CurrUser.LoginProjectId && x.UnitWorkId == UnitWorkId)
.ToList()
.Where(IsCurrentNDTType)
.GroupBy(x => Normalize(x.TrustBatchCode))
.ToDictionary(x => x.Key, x => x.First());
HashSet<string> importedTrustBatchIds = new HashSet<string>(Funs.DB.HJGL_Batch_NDE
.Where(x => x.ProjectId == CurrUser.LoginProjectId && x.UnitWorkId == UnitWorkId)
.Select(x => x.TrustBatchId)
.ToList());
Dictionary<string, Base_Defect> defectMap = Funs.DB.Base_Defect
.ToList()
.GroupBy(x => Normalize(x.DefectName))
.ToDictionary(x => x.Key, x => x.First());
HashSet<string> rowKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
for (int index = 0; index < table.Rows.Count; index++)
{
DataRow row = table.Rows[index];
int excelRowNumber = index + 2;
string trustBatchCode = GetCellValue(row, "委托编号");
string pipelineCode = GetCellValue(row, "管线号");
string weldJointCode = GetCellValue(row, "检件焊口号");
string totalFilmText = GetCellValue(row, "检测总数");
string passFilmText = GetCellValue(row, "合格数");
string filmDateText = GetCellValue(row, "检测日期");
string reportDateText = GetCellValue(row, "报告日期");
if (string.IsNullOrEmpty(trustBatchCode)
&& string.IsNullOrEmpty(pipelineCode)
&& string.IsNullOrEmpty(weldJointCode)
&& string.IsNullOrEmpty(totalFilmText)
&& string.IsNullOrEmpty(passFilmText)
&& string.IsNullOrEmpty(filmDateText)
&& string.IsNullOrEmpty(reportDateText))
{
continue;
}
int errorCount = errors.Count;
int sequence = index + 1;
string sequenceText = GetCellValue(row, "序号");
if (!string.IsNullOrEmpty(sequenceText)
&& (!int.TryParse(sequenceText, out sequence) || sequence <= 0))
{
errors.Add("第" + excelRowNumber + "行:序号必须为大于 0 的整数");
}
View_Batch_BatchTrust trust = null;
if (string.IsNullOrEmpty(trustBatchCode) || !trustMap.TryGetValue(Normalize(trustBatchCode), out trust))
{
errors.Add("第" + excelRowNumber + "行:委托编号[" + trustBatchCode + "]不属于当前单位工程");
}
else if (importedTrustBatchIds.Contains(trust.TrustBatchId))
{
errors.Add("第" + excelRowNumber + "行:委托编号[" + trustBatchCode + "]已存在检测结果,不能重复导入");
}
View_Batch_BatchTrustItem trustItem = null;
if (trust != null)
{
trustItem = trustItems.FirstOrDefault(x =>
x.TrustBatchId == trust.TrustBatchId
&& Normalize(x.PipelineCode) == Normalize(pipelineCode)
&& Normalize(x.WeldJointCode) == Normalize(weldJointCode));
if (trustItem == null)
{
errors.Add("第" + excelRowNumber + "行:管线[" + pipelineCode + "]焊口[" + weldJointCode + "]不存在于该委托单");
}
}
string welderCode = GetCellValue(row, "焊工号");
if (trustItem != null && !string.IsNullOrEmpty(welderCode)
&& Normalize(trustItem.WelderCode) != Normalize(welderCode))
{
errors.Add("第" + excelRowNumber + "行:焊工号[" + welderCode + "]与委托明细不一致");
}
int totalFilm;
if (!int.TryParse(totalFilmText, out totalFilm) || totalFilm <= 0)
{
errors.Add("第" + excelRowNumber + "行:检测总数必须为大于 0 的整数");
}
int passFilm;
if (!int.TryParse(passFilmText, out passFilm) || passFilm < 0)
{
errors.Add("第" + excelRowNumber + "行:合格数必须为不小于 0 的整数");
}
else if (totalFilm > 0 && passFilm > totalFilm)
{
errors.Add("第" + excelRowNumber + "行:合格数不能大于检测总数");
}
string checkResultText = GetCellValue(row, "是否合格");
string checkResult = ConvertCheckResult(checkResultText);
if (string.IsNullOrEmpty(checkResult))
{
errors.Add("第" + excelRowNumber + "行:是否合格只能填写“合格”或“不合格”");
}
string judgeGrade = ConvertJudgeGrade(GetCellValue(row, "评定级别"));
if (judgeGrade == null)
{
errors.Add("第" + excelRowNumber + "行:评定级别只能填写Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ或1-5");
}
string defectText = GetCellValue(row, "缺陷");
List<string> defectIds = new List<string>();
if (!string.IsNullOrEmpty(defectText))
{
foreach (string defectName in SplitDefects(defectText))
{
Base_Defect defect;
if (!defectMap.TryGetValue(Normalize(defectName), out defect))
{
errors.Add("第" + excelRowNumber + "行:缺陷[" + defectName + "]不存在");
}
else
{
defectIds.Add(Convert.ToString(defect.DefectId));
}
}
}
string rowKey = Normalize(trustBatchCode) + "|" + Normalize(pipelineCode) + "|" + Normalize(weldJointCode);
if (!rowKeys.Add(rowKey))
{
errors.Add("第" + excelRowNumber + "行:同一委托、管线和焊口在文件中重复");
}
// 两个日期均为非必填列;兼容 Excel 日期单元格、序列值和常见日期文本。
DateTime? filmDate = ParseOptionalDate(row, "检测日期", excelRowNumber, errors);
DateTime? reportDate = ParseOptionalDate(row, "报告日期", excelRowNumber, errors);
if (errors.Count == errorCount && trust != null && trustItem != null)
{
result.Add(new UnitWorkNDEImportItem
{
RowNumber = sequence,
TrustBatchId = trust.TrustBatchId,
TrustBatchCode = trust.TrustBatchCode,
TrustBatchItemId = trustItem.TrustBatchItemId,
PipelineCode = trustItem.PipelineCode,
WeldJointCode = trustItem.WeldJointCode,
WelderCode = trustItem.WelderCode,
TotalFilm = totalFilm,
PassFilm = passFilm,
CheckResult = checkResult,
CheckResultText = checkResultText == "是" ? "合格" : checkResultText == "否" ? "不合格" : checkResultText,
JudgeGrade = judgeGrade,
CheckDefects = string.Join(",", defectIds.Distinct()),
CheckDefectsText = defectText,
RepairLocation = GetCellValue(row, "返修位置"),
Remark = GetCellValue(row, "备注"),
FilmDate = filmDate,
ReportDate = reportDate
});
}
}
if (result.Count == 0 && errors.Count == 0)
{
errors.Add("导入数据为空!");
}
return result;
}
private List<View_Batch_BatchTrustItem> GetUnitWorkTrustItems()
{
return Funs.DB.View_Batch_BatchTrustItem
.Where(x => x.ProjectId == CurrUser.LoginProjectId && x.UnitWorkId == UnitWorkId && x.PipelineCode !=null)
.ToList()
.Where(IsCurrentNDTType)
.ToList();
}
private bool IsCurrentNDTType(View_Batch_BatchTrustItem item)
{
return NDTType == "R" ? item.TrustType == "R" : string.IsNullOrEmpty(item.TrustType);
}
private bool IsCurrentNDTType(View_Batch_BatchTrust item)
{
return NDTType == "R" ? item.TrustType == "R" : string.IsNullOrEmpty(item.TrustType);
}
private void BindGrid()
{
List<UnitWorkNDEImportItem> items = ImportItems;
Grid1.RecordCount = items.Count;
Grid1.DataSource = items.Skip(Grid1.PageIndex * Grid1.PageSize).Take(Grid1.PageSize).ToList();
Grid1.DataBind();
}
private void ShowErrors(IEnumerable<string> errors)
{
Alert alert = new Alert
{
Message = string.Join("<br/>", errors.Distinct().Select(HttpUtility.HtmlEncode)),
Target = Target.Self
};
alert.Show();
}
private static string GetCellValue(DataRow row, string columnName)
{
return Convert.ToString(row[columnName]).Replace("\n", "").Replace("\t", "").Replace("\r", "").Trim();
}
private static DateTime? ParseOptionalDate(DataRow row, string columnName, int excelRowNumber, ICollection<string> errors)
{
object rawValue = row[columnName];
string value = Convert.ToString(rawValue).Trim();
if (rawValue == null || rawValue == DBNull.Value || string.IsNullOrEmpty(value))
{
return null;
}
if (rawValue is DateTime)
{
return ((DateTime)rawValue).Date;
}
double oaDate;
if (double.TryParse(value, out oaDate))
{
try
{
return DateTime.FromOADate(oaDate).Date;
}
catch (ArgumentException)
{
// 无效序列值继续按日期文本处理,最终给出统一提示。
}
}
DateTime date;
if (DateTime.TryParse(value, out date))
{
return date.Date;
}
errors.Add("第" + excelRowNumber + "行:" + columnName + "格式错误,应填写有效日期");
return null;
}
private static string Normalize(string value)
{
return (value ?? string.Empty).Replace(" ", string.Empty).Trim().ToUpperInvariant();
}
private static string ConvertCheckResult(string value)
{
if (value == "合格" || value == "是")
{
return "1";
}
if (value == "不合格" || value == "否")
{
return "2";
}
return string.Empty;
}
private static string ConvertJudgeGrade(string value)
{
switch (value)
{
case "": return string.Empty;
case "":
case "1": return "";
case "Ⅱ":
case "2": return "Ⅱ";
case "Ⅲ":
case "3": return "Ⅲ";
case "Ⅳ":
case "4": return "Ⅳ";
case "":
case "5": return "";
default: return null;
}
}
private static IEnumerable<string> SplitDefects(string value)
{
return value.Split(new[] { ',', '', '、', ';', '' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim())
.Where(x => !string.IsNullOrEmpty(x));
}
}
}
@@ -0,0 +1,23 @@
//------------------------------------------------------------------------------
// <自动生成>
// 此代码由工具生成。
// </自动生成>
//------------------------------------------------------------------------------
namespace FineUIPro.Web.HJGL.NDT
{
public partial class NDTBatchUnitImport
{
protected global::System.Web.UI.HtmlControls.HtmlForm form1;
protected global::FineUIPro.PageManager PageManager1;
protected global::FineUIPro.Form SimpleForm1;
protected global::FineUIPro.Toolbar Toolbar1;
protected global::FineUIPro.Label lblUnitWork;
protected global::FineUIPro.Button btnDownLoad;
protected global::FineUIPro.Toolbar Toolbar2;
protected global::FineUIPro.FileUpload fuAttachUrl;
protected global::FineUIPro.Button btnAudit;
protected global::FineUIPro.Button btnSave;
protected global::FineUIPro.Grid Grid1;
}
}