安全巡检接入真实数据库:编码字段自动生成、公示牌二维码修复、安全问题统计排除作废

- 安全巡检表新增编码字段(Code,全局唯一 XJ-序号),WebAPI/桌面端新增时自动生成,不可重复
- 修复危大超危工程公示牌二维码不显示:urlName 含非法字符?导致 image.Save 抛异常,改用主键+内容哈希安全文件名
- 安全问题统计(mainProject/main3)排除作废数据(States=4),图表口径与顶部计数一致
- Word 导出文件名改为 监督巡视部位+编号
- Model.cs 由 SqlMetal 重新生成,补齐巡检人ID/签收人ID/发现问题/处理要求等字段;新增 HSSE_SafetyPatrol.Code.cs 补充 Code 列
- 新增安全巡检完整建表脚本(SGGLDB_V2026-08-25-001);删除已过时的接口文档 SafetyPatrol_API.md
This commit is contained in:
2026-08-26 19:13:11 +08:00
parent 55944d732a
commit 192824ea90
27 changed files with 1601 additions and 309 deletions
@@ -0,0 +1,140 @@
-- =====================================================================
-- 安全巡检记录表(危大、超危工程 监督记录)
-- 说明:监督巡视部位即工程名称(取自危大、超危工程 HazardProjectName),
-- 不再单独存 PatrolLocation 列。
-- 本脚本:表存在则删除重建,含全部字段、主键与中文列注释,可直接执行。
-- =====================================================================
-- 如果表存在直接删除
DROP TABLE IF EXISTS [dbo].[HSSE_SafetyPatrol];
GO
CREATE TABLE [dbo].[HSSE_SafetyPatrol] (
[PatrolId] nvarchar(50) COLLATE Chinese_PRC_CI_AS NOT NULL,
[ProjectId] nvarchar(50) COLLATE Chinese_PRC_CI_AS NOT NULL,
[HazardProjectId] nvarchar(50) COLLATE Chinese_PRC_CI_AS NULL,
[HazardProjectName] nvarchar(500) COLLATE Chinese_PRC_CI_AS NULL,
[PatrolDate] datetime NULL,
[PatrolMan] nvarchar(50) COLLATE Chinese_PRC_CI_AS NULL,
[PatrolManId] nvarchar(50) COLLATE Chinese_PRC_CI_AS NULL,
[PatrolStatus] nvarchar(50) COLLATE Chinese_PRC_CI_AS NULL,
[Content] nvarchar(1000) COLLATE Chinese_PRC_CI_AS NULL,
[Problems] nvarchar(1000) COLLATE Chinese_PRC_CI_AS NULL,
[Receiver] nvarchar(50) COLLATE Chinese_PRC_CI_AS NULL,
[ReceiverId] nvarchar(50) COLLATE Chinese_PRC_CI_AS NULL,
[HandleRequire] nvarchar(1000) COLLATE Chinese_PRC_CI_AS NULL,
[RectifyReview] nvarchar(1000) COLLATE Chinese_PRC_CI_AS NULL,
[Remarks] nvarchar(500) COLLATE Chinese_PRC_CI_AS NULL,
[Code] nvarchar(50) COLLATE Chinese_PRC_CI_AS NULL,
CONSTRAINT [PK_HSSE_SafetyPatrol] PRIMARY KEY CLUSTERED ([PatrolId])
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[HSSE_SafetyPatrol] SET (LOCK_ESCALATION = TABLE)
GO
EXEC sp_addextendedproperty
'MS_Description', N'安全巡检记录',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol'
GO
EXEC sp_addextendedproperty
'MS_Description', N'主键',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'PatrolId'
GO
EXEC sp_addextendedproperty
'MS_Description', N'项目',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'ProjectId'
GO
EXEC sp_addextendedproperty
'MS_Description', N'危大、超危工程',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'HazardProjectId'
GO
EXEC sp_addextendedproperty
'MS_Description', N'监督巡视部位(即工程名称)',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'HazardProjectName'
GO
EXEC sp_addextendedproperty
'MS_Description', N'巡检日期',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'PatrolDate'
GO
EXEC sp_addextendedproperty
'MS_Description', N'巡检人名称(监督巡视人员)',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'PatrolMan'
GO
EXEC sp_addextendedproperty
'MS_Description', N'巡检人ID',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'PatrolManId'
GO
EXEC sp_addextendedproperty
'MS_Description', N'巡检状态(正常/待整改/整改待复查)',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'PatrolStatus'
GO
EXEC sp_addextendedproperty
'MS_Description', N'巡视内容(勾选项与其它拼接文本)',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'Content'
GO
EXEC sp_addextendedproperty
'MS_Description', N'发现问题',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'Problems'
GO
EXEC sp_addextendedproperty
'MS_Description', N'签收人名称',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'Receiver'
GO
EXEC sp_addextendedproperty
'MS_Description', N'签收人ID',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'ReceiverId'
GO
EXEC sp_addextendedproperty
'MS_Description', N'处理要求',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'HandleRequire'
GO
EXEC sp_addextendedproperty
'MS_Description', N'整改后复查情况',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'RectifyReview'
GO
EXEC sp_addextendedproperty
'MS_Description', N'备注',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'Remarks'
GO
EXEC sp_addextendedproperty
'MS_Description', N'编码(全局唯一,格式 XJ-序号,自动生成)',
'SCHEMA', N'dbo',
'TABLE', N'HSSE_SafetyPatrol',
'COLUMN', N'Code'
GO
-- 编码唯一索引
CREATE UNIQUE INDEX [UX_HSSE_SafetyPatrol_Code]
ON [dbo].[HSSE_SafetyPatrol] ([Code])
GO
+72 -3
View File
@@ -29,13 +29,21 @@ namespace BLL
select new Model.SafetyPatrolItem
{
PatrolId = x.PatrolId,
Code = x.Code,
ProjectId = x.ProjectId,
HazardProjectId = x.HazardProjectId,
HazardProjectName = x.HazardProjectName,
PatrolDate = x.PatrolDate,
PatrolMan = x.PatrolMan,
PatrolManId = x.PatrolManId,
PatrolStatus = x.PatrolStatus,
Content = x.Content
Content = x.Content,
Problems = x.Problems,
Receiver = x.Receiver,
ReceiverId = x.ReceiverId,
HandleRequire = x.HandleRequire,
RectifyReview = x.RectifyReview,
Remarks = x.Remarks
};
return list.ToList();
}
@@ -58,13 +66,21 @@ namespace BLL
return new Model.SafetyPatrolItem
{
PatrolId = x.PatrolId,
Code = x.Code,
ProjectId = x.ProjectId,
HazardProjectId = x.HazardProjectId,
HazardProjectName = x.HazardProjectName,
PatrolDate = x.PatrolDate,
PatrolMan = x.PatrolMan,
PatrolManId = x.PatrolManId,
PatrolStatus = x.PatrolStatus,
Content = x.Content
Content = x.Content,
Problems = x.Problems,
Receiver = x.Receiver,
ReceiverId = x.ReceiverId,
HandleRequire = x.HandleRequire,
RectifyReview = x.RectifyReview,
Remarks = x.Remarks
};
}
}
@@ -82,16 +98,29 @@ namespace BLL
}
using (Model.SGGLDB db = new Model.SGGLDB(Funs.ConnString))
{
////编码为空时自动生成(全局唯一)
if (string.IsNullOrEmpty(item.Code))
{
item.Code = GetNewCode(db);
}
Model.HSSE_SafetyPatrol newItem = new Model.HSSE_SafetyPatrol
{
PatrolId = item.PatrolId,
Code = item.Code,
ProjectId = item.ProjectId,
HazardProjectId = item.HazardProjectId,
HazardProjectName = item.HazardProjectName,
PatrolDate = item.PatrolDate,
PatrolMan = item.PatrolMan,
PatrolManId = item.PatrolManId,
PatrolStatus = item.PatrolStatus,
Content = item.Content
Content = item.Content,
Problems = item.Problems,
Receiver = item.Receiver,
ReceiverId = item.ReceiverId,
HandleRequire = item.HandleRequire,
RectifyReview = item.RectifyReview,
Remarks = item.Remarks
};
db.HSSE_SafetyPatrol.InsertOnSubmit(newItem);
db.SubmitChanges();
@@ -101,6 +130,11 @@ namespace BLL
{
APIUpLoadFileService.SaveAttachUrl(Const.SafetyPatrolMenuId, item.PatrolId, item.AttachUrl, "0");
}
////保存整改图片附件
if (!string.IsNullOrEmpty(item.RectifyAttachUrl))
{
APIUpLoadFileService.SaveAttachUrl(Const.SafetyPatrolRectifyMenuId, item.PatrolId, item.RectifyAttachUrl, "0");
}
return item.PatrolId;
}
@@ -123,8 +157,15 @@ namespace BLL
newItem.HazardProjectName = item.HazardProjectName;
newItem.PatrolDate = item.PatrolDate;
newItem.PatrolMan = item.PatrolMan;
newItem.PatrolManId = item.PatrolManId;
newItem.PatrolStatus = item.PatrolStatus;
newItem.Content = item.Content;
newItem.Problems = item.Problems;
newItem.Receiver = item.Receiver;
newItem.ReceiverId = item.ReceiverId;
newItem.HandleRequire = item.HandleRequire;
newItem.RectifyReview = item.RectifyReview;
newItem.Remarks = item.Remarks;
db.SubmitChanges();
}
////保存巡检图片附件
@@ -132,7 +173,35 @@ namespace BLL
{
APIUpLoadFileService.SaveAttachUrl(Const.SafetyPatrolMenuId, item.PatrolId, item.AttachUrl, "0");
}
////保存整改图片附件
if (!string.IsNullOrEmpty(item.RectifyAttachUrl))
{
APIUpLoadFileService.SaveAttachUrl(Const.SafetyPatrolRectifyMenuId, item.PatrolId, item.RectifyAttachUrl, "0");
}
return true;
}
/// <summary>
/// 生成新的巡检编码(全局唯一,前缀 XJ-,三位递增序号)
/// </summary>
/// <param name="db">数据库上下文</param>
/// <returns></returns>
private static string GetNewCode(Model.SGGLDB db)
{
int max = 0;
foreach (Model.HSSE_SafetyPatrol item in db.HSSE_SafetyPatrol.ToList())
{
string code = item.Code;
if (!string.IsNullOrEmpty(code) && code.StartsWith("XJ-"))
{
int num = 0;
if (int.TryParse(code.Substring(3), out num) && num > max)
{
max = num;
}
}
}
return string.Format("XJ-{0:D3}", max + 1);
}
}
}
+1
View File
@@ -576,6 +576,7 @@
<Compile Include="HSSE\Hazard\SafetyAcceptanceService.cs" />
<Compile Include="HSSE\Hazard\SafetyDisclosureService.cs" />
<Compile Include="HSSE\Hazard\SafetyPatrolService.cs" />
<Compile Include="HSSE\Hazard\SafetyPatrolWordService.cs" />
<Compile Include="HSSE\Hazard\SpecialPlanService.cs" />
<Compile Include="HSSE\HiddenInspection\HSSE_Hazard_HazardRegisterService.cs" />
<Compile Include="HSSE\HSSESystem\HSSEMainDutyService.cs" />
+4
View File
@@ -2607,6 +2607,10 @@ namespace BLL
/// </summary>
public const string SafetyPatrolMenuId = "3EE924B8-DFB2-47DA-ADC1-FF8190E214F1";
/// <summary>
/// 安全巡检整改图片
/// </summary>
public const string SafetyPatrolRectifyMenuId = "29A1CA62-7D69-4F1C-84BA-F5D7125289F5";
/// <summary>
/// 作业票申请
/// </summary>
public const string ProjectLicenseApplyMenuId = "2E58D4F1-2FF1-450E-8A00-1CE3BBCF8D5B";
+44 -1
View File
@@ -29,6 +29,28 @@ namespace BLL
return Funs.DB.HSSE_SafetyPatrol.FirstOrDefault(x => x.PatrolId == patrolId);
}
/// <summary>
/// 获取新编码(全局唯一,前缀 XJ-,三位递增序号,如 XJ-001)
/// </summary>
/// <returns></returns>
public static string GetNewCode()
{
int max = 0;
foreach (Model.HSSE_SafetyPatrol item in Funs.DB.HSSE_SafetyPatrol.ToList())
{
string code = item.Code;
if (!string.IsNullOrEmpty(code) && code.StartsWith("XJ-"))
{
int num = 0;
if (int.TryParse(code.Substring(3), out num) && num > max)
{
max = num;
}
}
}
return string.Format("XJ-{0:D3}", max + 1);
}
/// <summary>
/// 新增安全巡检记录
/// </summary>
@@ -36,16 +58,30 @@ namespace BLL
public static void Add(Model.HSSE_SafetyPatrol item)
{
Model.SGGLDB db = Funs.DB;
////编码为空时自动生成(全局唯一)
string code = item.Code;
if (string.IsNullOrEmpty(code))
{
code = GetNewCode();
}
Model.HSSE_SafetyPatrol newItem = new Model.HSSE_SafetyPatrol
{
PatrolId = item.PatrolId,
Code = code,
ProjectId = item.ProjectId,
HazardProjectId = item.HazardProjectId,
HazardProjectName = item.HazardProjectName,
PatrolDate = item.PatrolDate,
PatrolMan = item.PatrolMan,
PatrolManId = item.PatrolManId,
PatrolStatus = item.PatrolStatus,
Content = item.Content
Content = item.Content,
Problems = item.Problems,
Receiver = item.Receiver,
ReceiverId = item.ReceiverId,
HandleRequire = item.HandleRequire,
RectifyReview = item.RectifyReview,
Remarks = item.Remarks
};
db.HSSE_SafetyPatrol.InsertOnSubmit(newItem);
db.SubmitChanges();
@@ -65,8 +101,15 @@ namespace BLL
newItem.HazardProjectName = item.HazardProjectName;
newItem.PatrolDate = item.PatrolDate;
newItem.PatrolMan = item.PatrolMan;
newItem.PatrolManId = item.PatrolManId;
newItem.PatrolStatus = item.PatrolStatus;
newItem.Content = item.Content;
newItem.Problems = item.Problems;
newItem.Receiver = item.Receiver;
newItem.ReceiverId = item.ReceiverId;
newItem.HandleRequire = item.HandleRequire;
newItem.RectifyReview = item.RectifyReview;
newItem.Remarks = item.Remarks;
db.SubmitChanges();
}
else
@@ -0,0 +1,500 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.IO;
using System.Linq;
using Aspose.Words;
using Aspose.Words.Tables;
namespace BLL
{
/// <summary>
/// 安全巡检——导出监督记录表 Word
/// </summary>
public static class SafetyPatrolWordService
{
/// <summary>
/// 生成附件9《(危大工程类别)监督记录表》Word 文档(.docx)
/// </summary>
/// <param name="patrolId">巡检记录主键</param>
/// <returns>docx 字节流;记录不存在返回 null</returns>
public static byte[] Generate(string patrolId)
{
Model.HSSE_SafetyPatrol info = SafetyPatrolService.GetById(patrolId);
if (info == null)
{
return null;
}
Document doc = new Document();
DocumentBuilder b = new DocumentBuilder(doc);
AppendRecord(b, info);
ApplyFonts(doc);
ApplyLineSpacing(doc);
MemoryStream ms = new MemoryStream();
doc.Save(ms, SaveFormat.Docx);
return ms.ToArray();
}
/// <summary>
/// 写入单独一条(标题 + 记录表)
/// </summary>
/// <param name="b">文档构建器</param>
/// <param name="info">巡检记录</param>
private static void AppendRecord(DocumentBuilder b, Model.HSSE_SafetyPatrol info)
{
////全局默认字体
b.Font.Name = "微软雅黑";
b.Font.NameFarEast = "微软雅黑";
b.Font.Size = 10.5;
////固定页面为 A4,保证表格宽度不会被压缩(A4 内容宽 = 595 - 40 - 40 = 515 磅)
PageSetup ps = b.Document.FirstSection.PageSetup;
ps.PageWidth = 595;
ps.PageHeight = 842;
ps.LeftMargin = 40;
ps.RightMargin = 40;
ps.TopMargin = 40;
ps.BottomMargin = 40;
////标题(附件9
b.ParagraphFormat.Alignment = ParagraphAlignment.Center;
b.Font.Size = 16;
b.Font.Bold = true;
b.Write("附件9 (危大工程类别)监督记录表");
b.ParagraphFormat.SpaceAfter = 30; // 标题与下方「监督巡视部位」之间留 40px ≈ 30pt
b.Writeln();
b.Font.Bold = false;
b.Font.Size = 10.5;
b.ParagraphFormat.SpaceAfter = 0; // 还原,避免影响后续段落
b.ParagraphFormat.Alignment = ParagraphAlignment.Left;
////监督巡视部位 / 巡视日期:拆成左右两列、各占一行 50%(无边框),
////与下方记录表同宽(412 磅、居中,两列各 206 磅),保证与表格两列精确对齐。
Table head = b.StartTable();
b.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
b.CellFormat.Width = 206;
b.InsertCell();
b.Write("监督巡视部位:" + (info.HazardProjectName ?? ""));
b.CellFormat.Width = 206;
b.InsertCell();
b.Write("巡视日期:" + (info.PatrolDate.HasValue ? info.PatrolDate.Value.ToString("yyyy-MM-dd") : ""));
b.EndRow();
b.EndTable();
////无边框 + 定宽居中,使两列与下方记录表的起止完全对齐
head.AllowAutoFit = false;
head.PreferredWidth = PreferredWidth.FromPoints(412);
head.Alignment = TableAlignment.Center;
head.Rows[0].Cells[0].CellFormat.Width = 206;
head.Rows[0].Cells[1].CellFormat.Width = 206;
////默认表格无边框;个别环境下若带边框则显式清空
foreach (Cell c in head.Rows[0].Cells)
{
foreach (Border bd in c.CellFormat.Borders)
{
bd.LineStyle = LineStyle.None;
}
}
////记录表主体:统一两列(左=标签/内容区,右=发现问题/签收人/空),每行都是独立单元格。
////重要:不要用 VerticalMerge 或全宽 gridSpan —— DocumentBuilder 无法可靠地只合并右列,
////会把左列下部的「处理要求/整改后复查/备注」吞掉或把表格网格弄乱。统一两列最稳定。
Table table = b.StartTable();
b.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
////行1:表头 监督巡视内容 | 发现问题
b.CellFormat.Width = 340;
b.InsertCell();
b.Write("监督巡视内容");
b.CellFormat.Width = 175;
b.InsertCell();
b.Write("发现问题");
b.EndRow();
////行3:勾选项(固定4项+其它) | 发现问题内容
b.CellFormat.Width = 340;
b.InsertCell();
WriteContentLines(b, info.Content);
b.CellFormat.Width = 175;
b.InsertCell();
b.Write(info.Problems ?? "");
b.EndRow();
////行4:处理要求: | 签收人:
b.CellFormat.Width = 340;
b.InsertCell();
b.Write("处理要求:");
b.CellFormat.Width = 175;
b.InsertCell();
b.Write("签收人:" + (string.IsNullOrEmpty(info.Receiver) ? "____________" : info.Receiver));
b.EndRow();
////行5:处理要求内容区(占3行),整格横向合并(横跨两列)
b.CellFormat.Width = 340;
b.InsertCell();
WriteArea(b, info.HandleRequire, 3);
b.CellFormat.Width = 175;
b.InsertCell();
b.EndRow();
////行6-7:整改后复查情况 + 内容区,合并为一个整宽纵向单元格。
////重要:纵并组里只有 restart 格(上半行)的正文会显示,continue 格必须留空,
////因此把「标签:」与内容都写入 restart 格。
b.CellFormat.Width = 340;
b.InsertCell();
WriteLabelArea(b, "整改后复查情况:", info.RectifyReview, 5);
b.CellFormat.Width = 175;
b.InsertCell();
b.EndRow();
////行7:纵并 continue 格(留空)
b.CellFormat.Width = 340;
b.InsertCell();
b.Writeln();
b.CellFormat.Width = 175;
b.InsertCell();
b.Writeln();
b.EndRow();
////行8-9:备注 + 内容区,合并为一个整宽纵向单元格
b.CellFormat.Width = 340;
b.InsertCell();
WriteLabelArea(b, "备注:", info.Remarks, 2);
b.CellFormat.Width = 175;
b.InsertCell();
b.EndRow();
////行9:纵并 continue 格(留空)
b.CellFormat.Width = 340;
b.InsertCell();
b.Writeln();
b.CellFormat.Width = 175;
b.InsertCell();
b.Writeln();
b.EndRow();
b.EndTable();
////表格宽度:占内容区 80%515 × 0.8 = 412 磅),并水平居中
table.AllowAutoFit = false;
table.PreferredWidth = PreferredWidth.FromPoints(412);
table.Alignment = TableAlignment.Center;
double cellWidth = 412 / 2.0; // 两列等宽 = 206 磅
foreach (Row row in table.Rows)
{
row.Cells[0].CellFormat.Width = cellWidth; // 左列
row.Cells[1].CellFormat.Width = cellWidth; // 右列(与左列等宽)
}
////发现问题内容(行1右列):左上显示,不垂直居中。
////DocumentBuilder 中途设置 CellFormat.VerticalAlignment 对当前单元格不生效,
////必须在 post-build 阶段用 Cell 对象设置(与合并同一方式)。
table.Rows[1].Cells[1].CellFormat.VerticalAlignment = CellVerticalAlignment.Top;
////整宽 / 跨行合并:post-build 阶段用 Cell 对象合并,gridCol 仍保持两列。
////表头之下共 8 行:索引0=表头,1=发现问题,2=处理要求/签收人,
////索引3=处理要求内容区(横并),索引4-5=整改后复查(纵并+整宽),索引6-7=备注(纵并+整宽)。
HorizontalMergeRow(table.Rows[3]);
HorizontalMergeRow(table.Rows[4]); VerticalMergeTop(table.Rows[4]);
HorizontalMergeRow(table.Rows[5]); VerticalMergeBottom(table.Rows[5]);
HorizontalMergeRow(table.Rows[6]); VerticalMergeTop(table.Rows[6]);
HorizontalMergeRow(table.Rows[7]); VerticalMergeBottom(table.Rows[7]);
////表格样式:细黑色网格线(与图片一致)
table.StyleIdentifier = StyleIdentifier.TableGrid;
////底部:监督巡视人员(恢复正文大小,签收人已入表格第4行右列)
////右对齐到表格右缘:右缩进 51.5 磅(= 表格居中后右侧留白)
b.Font.Size = 10.5;
b.Font.Bold = false;
b.ParagraphFormat.Alignment = ParagraphAlignment.Right;
b.ParagraphFormat.LeftIndent = 51.5;
b.ParagraphFormat.RightIndent = 51.5;
b.Write("监督巡视人员:" + (info.PatrolMan ?? ""));
b.Writeln();
////注:左对齐到表格左缘(左缩进 51.5 磅),还原右对齐/右缩进
b.ParagraphFormat.Alignment = ParagraphAlignment.Left;
b.ParagraphFormat.RightIndent = 0;
b.Write("注:此表可优化调整,但管理要素不得少于上表。");
b.Writeln();
////巡检附件 / 整改附件:另起一页显示(第二页起)
b.InsertBreak(BreakType.PageBreak);
AppendAttachments(b, info.PatrolId);
}
/// <summary>
/// 在第二页写入巡检附件与整改附件图片(按记录遍历,逐张缩放嵌入)。
/// 附件图片均为磁盘文件,通过 localRoot + AttachUrl 定位;无附件则给出「无」。
/// </summary>
/// <param name="b">文档构建器</param>
/// <param name="patrolId">巡检记录主键</param>
private static void AppendAttachments(DocumentBuilder b, string patrolId)
{
if (string.IsNullOrEmpty(patrolId))
{
return;
}
string localRoot = ConfigurationManager.AppSettings["localRoot"] ?? string.Empty;
b.Font.Bold = false;
b.Font.Size = 10.5;
WriteAttachSection(b, "一、巡检附件", patrolId, Const.SafetyPatrolMenuId, localRoot);
WriteAttachSection(b, "二、整改附件", patrolId, Const.SafetyPatrolRectifyMenuId, localRoot);
}
/// <summary>
/// 写入一个附件分组:标题行 + 该分组下的所有附件图片(缩放至最大宽 412 磅保持原比例)。
/// 非图片文件仅列出文件名;分组无附件则写「无」。
/// </summary>
/// <param name="b">文档构建器</param>
/// <param name="title">分组标题(如「一、巡检附件」)</param>
/// <param name="patrolId">巡检记录主键</param>
/// <param name="menuId">附件菜单ID</param>
/// <param name="localRoot">附件磁盘根目录</param>
private static void WriteAttachSection(DocumentBuilder b, string title, string patrolId, string menuId, string localRoot)
{
b.ParagraphFormat.Alignment = ParagraphAlignment.Left;
b.ParagraphFormat.SpaceBefore = 6;
b.Write(title);
b.Writeln();
b.ParagraphFormat.SpaceBefore = 0;
List<Model.AttachFile> files = Funs.DB.AttachFile
.Where(p => p.ToKeyId == patrolId && p.MenuId == menuId)
.ToList();
if (files == null || files.Count == 0)
{
b.Write("无");
b.Writeln();
return;
}
foreach (Model.AttachFile f in files)
{
if (string.IsNullOrEmpty(f.AttachUrl))
{
continue;
}
string filePath = Path.Combine(localRoot, f.AttachUrl.Replace('/', '\\'));
if (!File.Exists(filePath))
{
continue;
}
string ext = Path.GetExtension(filePath).ToLowerInvariant();
if (ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".bmp")
{
b.ParagraphFormat.SpaceBefore = 4;
InsertImageScaled(b, filePath, 400, 260);
b.Writeln(); // 每张图独占一行,避免后续标题/图片内联到图右侧
b.ParagraphFormat.SpaceBefore = 0;
}
else
{
b.Write(Path.GetFileName(filePath));
b.Writeln();
}
}
}
/// <summary>
/// 插入图片:缩放至不超过指定宽高(磅),保持原始宽高比。
/// </summary>
/// <param name="b">文档构建器</param>
/// <param name="filePath">图片物理路径</param>
/// <param name="maxWidthPt">最大宽(磅)</param>
/// <param name="maxHeightPt">最大高(磅)</param>
private static void InsertImageScaled(DocumentBuilder b, string filePath, double maxWidthPt, double maxHeightPt)
{
try
{
using (Image img = Image.FromFile(filePath))
{
int w = img.Width;
int h = img.Height;
if (w <= 0 || h <= 0)
{
return;
}
double scale = Math.Min(maxWidthPt / w, maxHeightPt / h);
b.InsertImage(filePath, w * scale, h * scale);
}
}
catch
{
// 非图片或读取失败:忽略
}
}
/// <summary>
/// 写入内容区单元格:先写内容,再用空段落撑高到指定行数。
/// 无内容时也保证最小行高,便于手写填写。
/// </summary>
/// <param name="b">文档构建器</param>
/// <param name="text">内容</param>
/// <param name="minLines">最小行数(空段落数)</param>
private static void WriteArea(DocumentBuilder b, string text, int minLines)
{
if (!string.IsNullOrEmpty(text))
{
b.Write(text);
}
for (int i = 0; i < minLines; i++)
{
b.Writeln();
}
}
/// <summary>
/// 监督巡视内容固定项(与编辑页复选框 Text 一致)
/// </summary>
private static readonly string[] PatrolContentItems = new string[]
{
"1、施工条件保持情况",
"2、按方案施工情况,实体与方案参数的对比",
"3、现场安全防护状况",
"4、作业人员持证上岗情况"
};
/// <summary>
/// 将监督巡视内容写入单元格:始终保持 4 个固定项(写死默认值)+ 一行「其它」。
/// 其它:Content 字段以后只存「其它」内容,直接显示;若含「其它:」前缀则取后半段(兼容旧格式);无内容则下划线占位。
/// </summary>
/// <param name="b">文档构建器</param>
/// <param name="content">Content 文本(以后仅存其它内容,如:基坑围挡损坏;旧数据可能形如:1、…;4、…;其它:xxx</param>
private static void WriteContentLines(DocumentBuilder b, string content)
{
bool first = true;
////固定 4 项始终输出(写死默认值)
foreach (string item in PatrolContentItems)
{
if (!first)
{
b.Writeln();
}
b.Write(item);
first = false;
}
////其它行:优先取 Content 中「其它:」后半段(兼容旧格式);否则 Content 即其它内容
b.Writeln();
string other = ExtractOther(content);
if (other.Length == 0)
{
other = content ?? string.Empty;
}
b.Write("其它:" + (other.Length > 0 ? other : "____________"));
}
/// <summary>
/// 从 Content 文本中提取「其它」说明内容(无则返回空串)
/// </summary>
/// <param name="content">Content 文本</param>
/// <returns>其它说明;未包含返回空串</returns>
private static string ExtractOther(string content)
{
if (string.IsNullOrEmpty(content))
{
return string.Empty;
}
foreach (string seg in content.Split(''))
{
string s = seg.Trim();
if (s.Length == 0)
{
continue;
}
if (s.StartsWith("其它") || s.StartsWith("其他"))
{
int idx = s.IndexOf('');
return idx >= 0 ? s.Substring(idx + 1).Trim() : string.Empty;
}
}
return string.Empty;
}
/// <summary>
/// 将一行的左右两格横向合并为整宽单元格(gridSpan=2)。
/// 必须在 post-build 阶段用 Cell 对象合并,避免 DocumentBuilder 把表格网格弄乱。
/// </summary>
/// <param name="row">待合并的行</param>
private static void HorizontalMergeRow(Row row)
{
row.Cells[0].CellFormat.HorizontalMerge = CellMerge.First;
row.Cells[1].CellFormat.HorizontalMerge = CellMerge.Previous;
}
/// <summary>
/// 纵向合并的起始行(restart)。该行正文会被保留,并与其下方 continue 行合并为一个单元格。
/// </summary>
/// <param name="row">起始行</param>
private static void VerticalMergeTop(Row row)
{
row.Cells[0].CellFormat.VerticalMerge = CellMerge.First;
row.Cells[1].CellFormat.VerticalMerge = CellMerge.First;
}
/// <summary>
/// 纵向合并的延续行(continue)。该行正文不会显示,必须留空。
/// </summary>
/// <param name="row">延续行</param>
private static void VerticalMergeBottom(Row row)
{
row.Cells[0].CellFormat.VerticalMerge = CellMerge.Previous;
row.Cells[1].CellFormat.VerticalMerge = CellMerge.Previous;
}
/// <summary>
/// 写入「标签:」+ 内容区,标签独占一行,内容随后以内容/空段落撑高。
/// 用于纵向合并单元格(标签与内容需写入 restart 格)。
/// </summary>
/// <param name="b">文档构建器</param>
/// <param name="label">标签(如「整改后复查情况:」)</param>
/// <param name="text">内容</param>
/// <param name="minLines">最小行数(空段落数)</param>
private static void WriteLabelArea(DocumentBuilder b, string label, string text, int minLines)
{
b.Write(label);
b.Writeln();
WriteArea(b, text, minLines);
}
/// <summary>
/// 统一全文正文字体:仅标题「附件9 …监督记录表」加粗(16 磅),其余一律 10.5 磅、不加粗。
/// DocumentBuilder 在跨表格书写时会丢失字符格式状态(标题的加粗/16 磅曾泄漏到记录表与落款),
/// 故在 post-build 阶段对所有 Run 兜底逐一遍历设置,保证只有标题加粗。
/// </summary>
/// <param name="doc">文档</param>
private static void ApplyFonts(Document doc)
{
foreach (Run run in doc.GetChildNodes(NodeType.Run, true))
{
bool isTitle = run.Text == "附件9 (危大工程类别)监督记录表";
run.Font.Bold = isTitle;
run.Font.Size = isTitle ? 16 : 10.5;
}
}
/// <summary>
/// 为文档中所有段落(含表格单元格内)设置 1.5 倍行距。
/// Aspose 的 Multiple 行距以磅为单位:单倍 = 12 磅,1.5 倍 = 18 磅,
/// 生成 w:line="360" w:lineRule="auto"360/240 = 1.5 倍)。
/// </summary>
/// <param name="doc">文档</param>
private static void ApplyLineSpacing(Document doc)
{
foreach (Paragraph p in doc.GetChildNodes(NodeType.Paragraph, true))
{
p.ParagraphFormat.LineSpacingRule = LineSpacingRule.Multiple;
p.ParagraphFormat.LineSpacing = 14; // 1.5 倍行距(18 磅 → w:line="360"360/240=1.5
}
}
}
}
+1 -1
View File
@@ -547,7 +547,7 @@ namespace Resources {
}
/// <summary>
/// 查找类似 质量管理 的本地化字符串。
/// 查找类似 技术质量管理 的本地化字符串。
/// </summary>
internal static string QualityManage {
get {
@@ -151,7 +151,7 @@
<value>在新标签页中打开</value>
</data>
<data name="QualityManage" xml:space="preserve">
<value>质量管理</value>
<value>技术质量管理</value>
</data>
<data name="quit" xml:space="preserve">
<value>退出</value>
@@ -151,7 +151,7 @@
<value>在新标签页中打开</value>
</data>
<data name="QualityManage" xml:space="preserve">
<value>质量管理</value>
<value>技术质量管理</value>
</data>
<data name="quit" xml:space="preserve">
<value>退出</value>
@@ -201,6 +201,9 @@
<data name="IntegratedManage" xml:space="preserve">
<value>综合管理</value>
</data>
<data name="NoPermission" xml:space="preserve">
<value>您没有权限进入项目管理模块!</value>
</data>
<data name="NoticeManage" xml:space="preserve">
<value>通知管理</value>
</data>
@@ -213,9 +216,6 @@
<data name="SwitchHomePage" xml:space="preserve">
<value>切换首页</value>
</data>
<data name="NoPermission" xml:space="preserve">
<value>您没有权限进入项目管理模块!</value>
</data>
<data name="CertificateWarning" xml:space="preserve">
<value>证书预警</value>
</data>
@@ -196,10 +196,11 @@ namespace FineUIPro.Web.Controls
try
{
string imageUrl = string.Empty;
////QRCodeScale 为每个二维码模块的像素倍数,固定值 5(原为 nr.Length,会随内容长度放大成超大图)
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder
{
QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
QRCodeScale = nr.Length,
QRCodeScale = 5,
QRCodeVersion = 0,
QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M
};
@@ -51,10 +51,11 @@ namespace FineUIPro.Web.Controls
private void CreateCode_Simple(string nr, string urlName)
{
string imageUrl = string.Empty;
////QRCodeScale 为每个二维码模块的像素倍数,固定值 5(原为 nr.Length,会随内容长度放大成超大图)
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder
{
QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
QRCodeScale = nr.Length,
QRCodeScale = 5,
QRCodeVersion = 0,
QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M
};
+1
View File
@@ -19843,6 +19843,7 @@
<Content Include="App_GlobalResources\Lan.resx">
<Generator>GlobalResourceProxyGenerator</Generator>
<LastGenOutput>Lan.designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
@@ -330,10 +330,14 @@ namespace FineUIPro.Web.HSSE.HazardousMG
if (info != null)
{
////二维码内容:危大工程标识(编号),接入数据库后替换为巡检页面URL
string strValue = "hazard$hid=" + info.HazardProjectId;
string urlName = "hazard$hid=" + info.HazardProjectId;
string strValue = "hazard$hid=" + info.HazardProjectId + "&hname=" + info.ProjectName + "&projectId=" + info.ProjectId;
////urlName 仅作生成的二维码图片文件名,用「主键+内容哈希」保证文件名安全(不含 ? / = 等非法字符)且内容变化时不复用旧图
string urlName = info.HazardProjectId + "_" + ((uint)strValue.GetHashCode()).ToString("X");
string title = "危大工程公示牌:" + info.ProjectName;
PageContext.RegisterStartupScript(Window1.GetShowReference(String.Format("~/Controls/ShowQRImage.aspx?strValue={0}&urlName={1}&title={2}", strValue, urlName, System.Web.HttpUtility.UrlEncode(title)), "公示牌二维码", 340, 400));
PageContext.RegisterStartupScript(Window1.GetShowReference(String.Format("~/Controls/ShowQRImage.aspx?strValue={0}&urlName={1}&title={2}",
System.Web.HttpUtility.UrlEncode(strValue),
System.Web.HttpUtility.UrlEncode(urlName),
System.Web.HttpUtility.UrlEncode(title)), "公示牌二维码", 340, 400));
}
}
#endregion
@@ -20,12 +20,12 @@
ShowHeader="false" Layout="VBox" BoxConfigAlign="Stretch">
<Items>
<f:Grid ID="Grid1" ShowBorder="true" ShowHeader="false" Title="危大、超危工程每日巡检记录" EnableCollapse="true"
runat="server" BoxFlex="1" EnableColumnLines="true" DataKeyNames="PatrolId"
EnableAjax="false" runat="server" BoxFlex="1" EnableColumnLines="true" DataKeyNames="PatrolId"
DataIDField="PatrolId" AllowSorting="true"
SortField="PatrolDate" SortDirection="DESC" OnSort="Grid1_Sort" AllowPaging="true"
IsDatabasePaging="true" PageSize="10" OnPageIndexChange="Grid1_PageIndexChange"
EnableRowDoubleClickEvent="true" OnRowDoubleClick="Grid1_RowDoubleClick"
OnRowCommand="Grid1_RowCommand" EnableTextSelection="True">
OnRowCommand="Grid1_RowCommand" EnableTextSelection="True" EnableCheckBoxSelect="true" KeepCurrentSelection="true">
<Toolbars>
<f:Toolbar ID="Toolbar1" Position="Top" runat="server" ToolbarAlign="Left">
<Items>
@@ -46,6 +46,9 @@
</f:Button>
<f:ToolbarFill ID="ToolbarFill1" runat="server">
</f:ToolbarFill>
<f:Button ID="btnOut" OnClick="btnOut_Click" runat="server" ToolTip="导出Word" Text="导出" Icon="FolderUp"
EnableAjax="false" DisableControlBeforePostBack="false">
</f:Button>
<f:Button ID="btnNew" ToolTip="扫码巡检" Icon="Add" runat="server" OnClick="btnNew_Click">
</f:Button>
</Items>
@@ -58,22 +61,18 @@
<asp:Label ID="lblNumber" runat="server" Text='<%# Grid1.PageIndex * Grid1.PageSize + Container.DataItemIndex + 1 %>'></asp:Label>
</ItemTemplate>
</f:TemplateField>
<f:RenderField Width="180px" ColumnID="HazardProjectName" DataField="HazardProjectName"
SortField="HazardProjectName" FieldType="String" HeaderText="工程名称" HeaderTextAlign="Center"
<f:RenderField Width="90px" ColumnID="Code" DataField="Code"
SortField="Code" FieldType="String" HeaderText="编码" HeaderTextAlign="Center"
TextAlign="Center">
</f:RenderField>
<f:RenderField Width="200px" ColumnID="HazardProjectName" DataField="HazardProjectName"
SortField="HazardProjectName" FieldType="String" HeaderText="监督巡视部位" HeaderTextAlign="Center"
TextAlign="Left">
</f:RenderField>
<f:RenderField Width="120px" ColumnID="PatrolDate" DataField="PatrolDate"
SortField="PatrolDate" FieldType="Date" Renderer="Date" HeaderText="巡检日期" HeaderTextAlign="Center"
TextAlign="Center">
</f:RenderField>
<f:RenderField Width="80px" ColumnID="PatrolMan" DataField="PatrolMan"
SortField="PatrolMan" FieldType="String" HeaderText="巡检人" HeaderTextAlign="Center"
TextAlign="Center">
</f:RenderField>
<f:RenderField Width="200px" ColumnID="Content" DataField="Content"
SortField="Content" FieldType="String" HeaderText="巡检内容" HeaderTextAlign="Center" ExpandUnusedSpace="true"
TextAlign="Left">
</f:RenderField>
<f:TemplateField ColumnID="tfPatrolStatus" Width="120px" HeaderText="巡检状态" HeaderTextAlign="Center"
TextAlign="Center">
<ItemTemplate>
@@ -81,8 +80,19 @@
ForeColor='<%# GetPatrolStatusColor(Eval("PatrolStatus")) %>' Font-Bold="true"></asp:Label>
</ItemTemplate>
</f:TemplateField>
<f:RenderField Width="200px" ColumnID="Problems" DataField="Problems"
SortField="Problems" FieldType="String" HeaderText="发现问题" HeaderTextAlign="Center" ExpandUnusedSpace="true"
TextAlign="Left">
</f:RenderField>
<f:RenderField Width="180px" ColumnID="HandleRequire" DataField="HandleRequire"
SortField="HandleRequire" FieldType="String" HeaderText="处理要求" HeaderTextAlign="Center"
TextAlign="Left">
</f:RenderField>
<f:LinkButtonField Width="80px" ColumnID="Attach" CommandName="attchUrl"
HeaderText="巡检图片" HeaderTextAlign="Center" TextAlign="Center" Text="查看">
HeaderText="巡检附件" HeaderTextAlign="Center" TextAlign="Center" Text="查看">
</f:LinkButtonField>
<f:LinkButtonField Width="80px" ColumnID="AttachRectify" CommandName="attchUrlRectify"
HeaderText="整改附件" HeaderTextAlign="Center" TextAlign="Center" Text="查看">
</f:LinkButtonField>
</Columns>
<Listeners>
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
namespace FineUIPro.Web.HSSE.HazardousMG
@@ -35,6 +37,117 @@ namespace FineUIPro.Web.HSSE.HazardousMG
}
}
/// <summary>
/// 导出Word:每条记录生成独立文档(文档名使用监督巡视部位)。
/// 单条直接下载 .docx;多条打包为 .zip,压缩包内每个 .docx 以监督巡视部位命名。
/// </summary>
protected void btnOut_Click(object sender, EventArgs e)
{
string[] ids = Grid1.SelectedRowIDArray;
if (ids == null || ids.Length == 0)
{
Alert.ShowInTop("请先勾选要导出的巡检记录!", MessageBoxIcon.Warning);
return;
}
List<KeyValuePair<string, byte[]>> files = new List<KeyValuePair<string, byte[]>>();
int dupIndex = 0;
foreach (string id in ids)
{
if (string.IsNullOrEmpty(id))
{
continue;
}
Model.HSSE_SafetyPatrol info = BLL.SafetyPatrolService.GetById(id);
if (info == null)
{
continue;
}
byte[] bytes = BLL.SafetyPatrolWordService.Generate(id);
if (bytes == null)
{
continue;
}
////文件名 = 监督巡视部位 + 编号(编码唯一,规避同名覆盖)
string baseName = SanitizeFileName(info.HazardProjectName);
string codeSuffix = string.IsNullOrEmpty(info.Code) ? string.Empty : "_" + info.Code;
string fileName = baseName + codeSuffix + ".docx";
// 同名记录去重,避免覆盖
while (files.Any(f => f.Key == fileName))
{
dupIndex++;
fileName = baseName + "(" + dupIndex + ").docx";
}
files.Add(new KeyValuePair<string, byte[]>(fileName, bytes));
}
if (files.Count == 0)
{
Alert.ShowInTop("未找到有效巡检记录!", MessageBoxIcon.Warning);
return;
}
Response.Clear();
if (files.Count == 1)
{
// 单条:直接下发 .docx
Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
Response.AddHeader("Content-Disposition", "attachment; filename=" + System.Web.HttpUtility.UrlEncode(files[0].Key, System.Text.Encoding.UTF8));
Response.BinaryWrite(files[0].Value);
}
else
{
// 多条:打包为 .zip
Response.ContentType = "application/zip";
Response.AddHeader("Content-Disposition", "attachment; filename=" + System.Web.HttpUtility.UrlEncode("安全巡检记录_" + BLL.Funs.GetNewFileName() + ".zip", System.Text.Encoding.UTF8));
using (MemoryStream ms = new MemoryStream())
{
using (ZipArchive zip = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
foreach (KeyValuePair<string, byte[]> f in files)
{
ZipArchiveEntry entry = zip.CreateEntry(f.Key, CompressionLevel.Optimal);
using (Stream es = entry.Open())
{
es.Write(f.Value, 0, f.Value.Length);
}
}
}
Response.BinaryWrite(ms.ToArray());
}
}
Response.Flush();
Response.End();
}
/// <summary>
/// 清洗文件名(去非法字符),保证文件名合法可下载。
/// </summary>
/// <param name="name">监督巡视部位名称</param>
/// <returns>合法文件名(不含扩展名)</returns>
private static string SanitizeFileName(string name)
{
if (string.IsNullOrEmpty(name))
{
return "监督记录表";
}
string fileName = name;
foreach (char c in Path.GetInvalidFileNameChars())
{
fileName = fileName.Replace(c, '_');
}
fileName = fileName.Trim();
if (fileName.Length == 0)
{
return "监督记录表";
}
if (fileName.Length > 80)
{
fileName = fileName.Substring(0, 80);
}
return fileName;
}
/// <summary>
/// 扫码巡检按钮事件
/// </summary>
@@ -51,12 +164,20 @@ namespace FineUIPro.Web.HSSE.HazardousMG
#region
/// <summary>
/// 巡检状态颜色(待整改标红)
/// 巡检状态颜色(待整改标红、整改待复查标橙、正常标绿
/// </summary>
public Color GetPatrolStatusColor(object value)
{
string state = value == null ? "" : value.ToString();
return state == "待整改" ? Color.Red : Color.Green;
switch (state)
{
case "待整改":
return Color.Red;
case "整改待复查":
return Color.Orange;
default:
return Color.Green;
}
}
#endregion
@@ -217,6 +338,11 @@ namespace FineUIPro.Web.HSSE.HazardousMG
PageContext.RegisterStartupScript(WindowAtt.GetShowReference(String.Format("../../AttachFile/webuploader.aspx?type={0}&toKeyId={1}&path=FileUpload/SafetyPatrol&menuId={2}",
-1, e.RowID, BLL.Const.SafetyPatrolMenuId)));
}
else if (e.CommandName == "attchUrlRectify")
{
PageContext.RegisterStartupScript(WindowAtt.GetShowReference(String.Format("../../AttachFile/webuploader.aspx?type={0}&toKeyId={1}&path=FileUpload/SafetyPatrolCorrect&menuId={2}",
-1, e.RowID, BLL.Const.SafetyPatrolRectifyMenuId)));
}
}
#endregion
}
@@ -7,70 +7,160 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>编辑安全巡检记录</title>
<link href="../../res/css/common.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.patrol-table {
width: 100%;
border-collapse: collapse;
border: 1px solid #000;
}
.patrol-table td {
border: 1px solid #000;
padding: 6px 8px;
vertical-align: middle;
}
.ptitle {
text-align: center;
font-size: 16px;
font-weight: bold;
padding: 10px;
}
.phead {
background-color: #f2f2f2;
text-align: center;
font-weight: bold;
}
.plabel {
white-space: nowrap;
}
.pcell {
vertical-align: top;
}
.cfooter {
text-align: center;
}
/* 让 TextArea 撑满所在单元格(FineUIPro 核心类为 .f-textbox,无 .f-textarea */
.patrol-table td.fillcell,
.patrol-table td.fillcell > * {
width: 100% !important;
box-sizing: border-box;
}
.patrol-table td.fillcell textarea {
width: 100% !important;
box-sizing: border-box;
}
/* 标签与输入框整组水平、垂直居中(其它、签收人、监督巡视人员) */
.pair-center {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
white-space: nowrap;
}
/* 保证组内输入框不被压缩到下一行 */
.pair-center > * {
flex-shrink: 0;
}
#ContentPanel1_txtProblems,#ContentPanel1_txtHandleRequire,#ContentPanel1_txtRectifyReview,#ContentPanel1_txtRemarks{
height: 100%;
width: 100%;
}
.textareaClass {
height: 100%;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<f:PageManager ID="PageManager1" runat="server" AutoSizePanelID="SimpleForm1"/>
<f:Form ID="SimpleForm1" ShowBorder="false" ShowHeader="false" Title="危大、超危工程每日巡检记录" AutoScroll="true"
BodyPadding="10px" runat="server" RedStarPosition="BeforeText" LabelAlign="Right">
<Rows>
<f:FormRow>
<Items>
<f:DropDownList ID="ddlHazardProject" runat="server" Label="扫码工程" LabelAlign="Right"
LabelWidth="100px" Required="true" ShowRedStar="true">
</f:DropDownList>
<f:DatePicker ID="dpPatrolDate" runat="server" Label="巡检日期" LabelAlign="Right"
LabelWidth="90px" DateFormatString="yyyy-MM-dd">
</f:DatePicker>
</Items>
</f:FormRow>
<f:FormRow>
<Items>
<f:DropDownList ID="ddlPatrolStatus" runat="server" Label="巡检状态" LabelAlign="Right"
LabelWidth="100px">
<f:ListItem Text="正常" Value="正常" />
<f:ListItem Text="待整改" Value="待整改" />
</f:DropDownList>
<f:Label ID="lblPatrolMan" runat="server" Label="巡检人" LabelAlign="Right"
LabelWidth="90px">
</f:Label>
</Items>
</f:FormRow>
<f:FormRow>
<Items>
<f:TextArea ID="txtContent" runat="server" Label="巡检内容" LabelAlign="Right" Height="100px"
MaxLength="1000" LabelWidth="100px">
</f:TextArea>
</Items>
</f:FormRow>
<f:FormRow>
<Items>
<f:Panel ID="Panel2" ShowHeader="false" ShowBorder="false" Layout="Column" CssClass="" runat="server">
<Items>
<f:Label ID="Label1" runat="server" ShowRedStar="true" Label="巡检图片"
LabelWidth="100px" LabelAlign="Right">
</f:Label>
<f:Button ID="btnAttach" Icon="TableCell" EnablePostBack="true" Text="上传" runat="server" OnClick="btnAttach_Click">
</f:Button>
</Items>
</f:Panel>
</Items>
</f:FormRow>
</Rows>
<Toolbars>
<f:Toolbar ID="Toolbar1" Position="Bottom" ToolbarAlign="Right" runat="server">
<Items>
<f:ToolbarFill ID="ToolbarFill1" runat="server">
</f:ToolbarFill>
<f:Button ID="btnSave" Icon="SystemSave" runat="server" ToolTip="保存" ValidateForms="SimpleForm1"
OnClick="btnSave_Click">
</f:Button>
<f:Button ID="btnClose" EnablePostBack="false" ToolTip="关闭" runat="server" Icon="SystemClose">
</f:Button>
</Items>
</f:Toolbar>
</Toolbars>
</f:Form>
<f:PageManager ID="PageManager1" AutoSizePanelID="ContentPanel1" runat="server" />
<f:ContentPanel ID="ContentPanel1" ShowBorder="false" ShowHeader="false" BodyPadding="10px"
AutoScroll="true" runat="server">
<div id="patrolContent">
<table class="patrol-table">
<tr>
<td colspan="2" class="ptitle">附件9 &nbsp;&nbsp;(危大工程类别)监督记录表</td>
</tr>
<tr>
<td>
<f:Form ID="FormHazard" ShowBorder="false" ShowHeader="false" BodyPadding="0" LabelAlign="Right" runat="server">
<Rows>
<f:FormRow>
<Items>
<f:DropDownList ID="ddlHazardProject" runat="server" Label="监督巡视部位" LabelWidth="110px" LabelAlign="Right" Required="true" Width="220px"></f:DropDownList>
</Items>
</f:FormRow>
</Rows>
</f:Form>
</td>
<td>
<f:Form ID="FormDate" ShowBorder="false" ShowHeader="false" BodyPadding="0" LabelAlign="Right" runat="server">
<Rows>
<f:FormRow>
<Items>
<f:DatePicker ID="dpPatrolDate" runat="server" Label="巡检日期" LabelWidth="80px" LabelAlign="Right" Width="140px" DateFormatString="yyyy-MM-dd"></f:DatePicker>
</Items>
</f:FormRow>
<f:FormRow>
<Items>
<f:TextBox ID="txtCode" runat="server" Label="编码" LabelWidth="80px" LabelAlign="Right" Width="140px" Readonly="true"></f:TextBox>
</Items>
</f:FormRow>
</Rows>
</f:Form>
</td>
</tr>
<tr>
<td class="phead">监督巡视内容</td>
<td class="phead">发现问题</td>
</tr>
<tr>
<td class="pcell" style="height: 150px;">
<div>1、施工条件保持情况</div>
<div>2、按方案施工情况,实体与方案参数的对比</div>
<div>3、现场安全防护状况</div>
<div>4、作业人员持证上岗情况</div>
<div class="pair-center">其它:<f:TextBox ID="txtContentOther" runat="server" Width="195px"></f:TextBox></div>
</td>
<td class="pcell fillcell">
<f:TextArea ID="txtProblems" runat="server" CssStyle="height:100%;" ></f:TextArea>
</td>
</tr>
<tr>
<td class="plabel">处理要求:</td>
<td class="plabel"><div class="pair-center">签收人:<f:DropDownList ID="ddlReceiver" runat="server" Width="180px"></f:DropDownList></div></td>
</tr>
<tr>
<td colspan="2" class="pcell fillcell">
<f:TextArea ID="txtHandleRequire" runat="server" Height="90px"></f:TextArea>
</td>
</tr>
<tr>
<td colspan="2" class="plabel">整改后复查情况:</td>
</tr>
<tr>
<td colspan="2" class="pcell fillcell">
<f:TextArea ID="txtRectifyReview" runat="server" Height="90px"></f:TextArea>
</td>
</tr>
<tr>
<td colspan="2" class="plabel">备注:</td>
</tr>
<tr>
<td colspan="2" class="pcell fillcell">
<f:TextArea ID="txtRemarks" runat="server" Height="70px"></f:TextArea>
</td>
</tr>
<tr>
<td colspan="2" class="cfooter"><div class="pair-center">监督巡视人员:<f:DropDownList ID="ddlPatrolMan" runat="server" Width="200px"></f:DropDownList></div></td>
</tr>
</table>
</div>
<div style="text-align:center; margin-top:10px;">
<f:Button ID="btnAttach" Icon="TableCell" EnablePostBack="true" Text="上传巡视图片" runat="server" OnClick="btnAttach_Click"></f:Button>
<f:Button ID="btnAttachRectify" Icon="TableCell" EnablePostBack="true" Text="上传整改图片" runat="server" OnClick="btnAttachRectify_Click"></f:Button>
<f:Button ID="btnSave" Icon="SystemSave" runat="server" ToolTip="保存" OnClick="btnSave_Click"></f:Button>
<f:Button ID="btnClose" EnablePostBack="false" ToolTip="关闭" runat="server" Icon="SystemClose" OnClientClick="F.activeWindow.hide();"></f:Button>
</div>
</f:ContentPanel>
<f:Window ID="WindowAtt" Title="附件" Hidden="true" EnableIFrame="true" EnableMaximize="true"
Target="Parent" EnableResize="false" runat="server" IsModal="true" Width="700px"
Height="500px">
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace FineUIPro.Web.HSSE.HazardousMG
{
@@ -24,6 +25,21 @@ namespace FineUIPro.Web.HSSE.HazardousMG
ViewState["PatrolId"] = value;
}
}
/// <summary>
/// 巡检状态(编辑页已不提供选择,加载时保留原值,新增默认正常)
/// </summary>
private string PatrolStatus
{
get
{
return (string)ViewState["PatrolStatus"];
}
set
{
ViewState["PatrolStatus"] = value;
}
}
#endregion
#region
@@ -36,11 +52,6 @@ namespace FineUIPro.Web.HSSE.HazardousMG
{
this.btnClose.OnClientClick = ActiveWindow.GetHideReference();
this.InitDropDownList();
////巡检人关联当前登录账号
if (this.CurrUser != null)
{
this.lblPatrolMan.Text = this.CurrUser.UserName;
}
this.PatrolId = Request.Params["PatrolId"];
if (!string.IsNullOrEmpty(this.PatrolId))
{
@@ -56,19 +67,26 @@ namespace FineUIPro.Web.HSSE.HazardousMG
{
this.dpPatrolDate.SelectedDate = info.PatrolDate.Value;
}
if (!string.IsNullOrEmpty(info.PatrolStatus))
{
this.ddlPatrolStatus.SelectedValue = info.PatrolStatus;
}
this.txtContent.Text = info.Content;
this.txtCode.Text = info.Code;
this.PatrolStatus = string.IsNullOrEmpty(info.PatrolStatus) ? "正常" : info.PatrolStatus;
this.InitUserDropDownList(info.PatrolMan, info.PatrolManId, info.Receiver, info.ReceiverId);
this.RenderContent(info.Content);
this.txtProblems.Text = info.Problems;
this.txtHandleRequire.Text = info.HandleRequire;
this.txtRectifyReview.Text = info.RectifyReview;
this.txtRemarks.Text = info.Remarks;
}
}
else
{
////新增(扫码巡检):默认巡检日期为当天、巡检状态为正常
////新增(扫码巡检):默认巡检日期为当天、巡检状态为正常;巡检人默认当前登录账号
this.dpPatrolDate.SelectedDate = DateTime.Now;
this.ddlPatrolStatus.SelectedValue = "正常";
this.PatrolStatus = "正常";
this.InitUserDropDownList(null, null, null, null);
}
////让父级编辑窗口高度自适应内容,避免固定高度留下大空白;超过 720px 时内部滚动
string fitJs = "setTimeout(function(){try{var w=F.activeWindow;if(w){var el=document.getElementById('patrolContent');var h=el?el.offsetHeight:0;h+=40;if(h>720){h=720;}w.setSize(780,h);}}catch(e){}},200);";
PageContext.RegisterStartupScript(fitJs);
}
}
@@ -87,6 +105,123 @@ namespace FineUIPro.Web.HSSE.HazardousMG
this.ddlHazardProject.Items.Add(new FineUIPro.ListItem(p.ProjectName + "" + p.ProjectCode + "", p.HazardProjectId));
}
}
/// <summary>
/// 绑定巡检人、签收人下拉(来自项目用户)
/// </summary>
/// <param name="patrolMan">巡检人名称(回显用)</param>
/// <param name="patrolManId">巡检人ID(回显用)</param>
/// <param name="receiver">签收人名称(回显用)</param>
/// <param name="receiverId">签收人ID(回显用)</param>
private void InitUserDropDownList(string patrolMan, string patrolManId, string receiver, string receiverId)
{
if (this.CurrUser == null || string.IsNullOrEmpty(this.CurrUser.LoginProjectId))
{
return;
}
List<Model.Sys_User> users = BLL.UserService.GetProjectUserListByProjectId(this.CurrUser.LoginProjectId);
////巡检人(默认当前登录账号);签收人允许留空
this.BindPatrolUser(this.ddlPatrolMan, users, patrolMan, patrolManId, this.CurrUser.UserId);
this.BindPatrolUser(this.ddlReceiver, users, receiver, receiverId, null);
}
/// <summary>
/// 绑定单个用户下拉:优先按ID回显,其次按名称回显;均不匹配且名称有值时保留原名称
/// </summary>
/// <param name="ddl">目标下拉</param>
/// <param name="users">项目用户列表</param>
/// <param name="selectName">回显名称</param>
/// <param name="selectId">回显ID</param>
/// <param name="defaultUserId">默认选中用户ID(可空)</param>
private void BindPatrolUser(FineUIPro.DropDownList ddl, List<Model.Sys_User> users, string selectName, string selectId, string defaultUserId)
{
ddl.Items.Clear();
////签收人允许留空(首项为占位)
if (ddl.ID == "ddlReceiver")
{
ddl.Items.Add(new FineUIPro.ListItem("请选择", ""));
}
string selectValue = string.IsNullOrEmpty(selectId) ? string.Empty : selectId;
foreach (Model.Sys_User u in users)
{
////默认选中项(巡检人默认当前登录账号)
if (string.IsNullOrEmpty(selectValue) && !string.IsNullOrEmpty(defaultUserId) && u.UserId == defaultUserId)
{
selectValue = u.UserId;
}
////名称回显(老数据无ID
if (string.IsNullOrEmpty(selectValue) && !string.IsNullOrEmpty(selectName) && u.UserName == selectName)
{
selectValue = u.UserId;
}
ddl.Items.Add(new FineUIPro.ListItem(u.UserName, u.UserId));
}
////名称在项目用户中找不到(如外部人员):追加原名称选项,保留旧数据
if (string.IsNullOrEmpty(selectValue) && !string.IsNullOrEmpty(selectName))
{
ddl.Items.Insert(0, new FineUIPro.ListItem(selectName, ""));
}
if (!string.IsNullOrEmpty(selectValue))
{
ddl.SelectedValue = selectValue;
}
else if (ddl.Items.Count > 0)
{
ddl.SelectedIndex = 0;
}
}
/// <summary>
/// 根据巡视内容渲染"其它"输入框。1-4 项为固定默认值(写死、始终显示),不再从 Content 解析勾选。
/// Content 以后只存「其它」内容:兼容旧格式「…;其它:xxx」,也兼容直接为其它文本的新格式。
/// </summary>
/// <param name="content">Content 字段(以后仅其它内容;旧数据可能形如:1、…;4、…;其它:xxx</param>
private void RenderContent(string content)
{
if (string.IsNullOrEmpty(content))
{
return;
}
string other = null;
foreach (string seg in content.Split(''))
{
string s = seg.Trim();
if (s.Length == 0)
{
continue;
}
if (s.StartsWith("其它") || s.StartsWith("其他"))
{
int idx = s.IndexOf('');
other = idx >= 0 ? s.Substring(idx + 1).Trim() : string.Empty;
break;
}
}
// 新格式:Content 无「其它:」前缀、且不以项号前缀(1、…)开头,则整段即为其它内容
if (other == null)
{
other = Regex.IsMatch(content, @"^\s*\d+、") ? string.Empty : content.Trim();
}
if (other.Length > 0)
{
this.txtContentOther.Text = other;
}
}
/// <summary>
/// 构造 Content 文本。1-4 项固定写死(始终显示,不参与存储),Content 仅存「其它」内容。
/// 「其它」无多选:输入框有内容即表示选中。
/// </summary>
/// <returns>如:其它:基坑围挡损坏;无其它内容返回空串</returns>
private string BuildContent()
{
string other = this.txtContentOther.Text.Trim();
if (other.Length > 0)
{
return "其它:" + other;
}
return string.Empty;
}
#endregion
#region
@@ -100,16 +235,14 @@ namespace FineUIPro.Web.HSSE.HazardousMG
Alert.ShowInTop("请先选择项目!", MessageBoxIcon.Warning);
return;
}
////新增时先生成主键,保证附件能挂到同一记录
////新增时先生成主键
if (string.IsNullOrEmpty(this.PatrolId))
{
this.PatrolId = Guid.NewGuid().ToString();
}
////校验附件是否已上传
Model.AttachFile attach = BLL.Funs.DB.AttachFile.FirstOrDefault(x => x.ToKeyId == this.PatrolId);
if (attach == null || string.IsNullOrEmpty(attach.AttachUrl))
if (string.IsNullOrEmpty(this.ddlHazardProject.SelectedValue))
{
Alert.ShowInTop("请上传巡检图片", MessageBoxIcon.Warning);
Alert.ShowInTop("请选择危大工程类别", MessageBoxIcon.Warning);
return;
}
////根据所选清单回填工程名称
@@ -119,6 +252,19 @@ namespace FineUIPro.Web.HSSE.HazardousMG
{
hazardProjectName = project.ProjectName;
}
////巡检人、签收人(下拉选中项:ID + 名称;外部人员无ID时仅保留名称)
string patrolManId = this.ddlPatrolMan.SelectedValue;
string patrolManName = this.ddlPatrolMan.SelectedItem == null ? string.Empty : this.ddlPatrolMan.SelectedItem.Text.Trim();
if (patrolManName == "请选择")
{
patrolManName = string.Empty;
}
string receiverId = this.ddlReceiver.SelectedValue;
string receiverName = this.ddlReceiver.SelectedItem == null ? string.Empty : this.ddlReceiver.SelectedItem.Text.Trim();
if (receiverName == "请选择")
{
receiverName = string.Empty;
}
Model.HSSE_SafetyPatrol info = new Model.HSSE_SafetyPatrol
{
PatrolId = this.PatrolId,
@@ -126,9 +272,16 @@ namespace FineUIPro.Web.HSSE.HazardousMG
HazardProjectId = this.ddlHazardProject.SelectedValue,
HazardProjectName = hazardProjectName,
PatrolDate = this.dpPatrolDate.SelectedDate,
PatrolMan = this.CurrUser.UserName,
PatrolStatus = this.ddlPatrolStatus.SelectedValue,
Content = this.txtContent.Text.Trim()
PatrolMan = patrolManName,
PatrolManId = patrolManId,
PatrolStatus = this.PatrolStatus,
Content = this.BuildContent(),
Problems = this.txtProblems.Text.Trim(),
Receiver = receiverName,
ReceiverId = receiverId,
HandleRequire = this.txtHandleRequire.Text.Trim(),
RectifyReview = this.txtRectifyReview.Text.Trim(),
Remarks = this.txtRemarks.Text.Trim()
};
////存在则更新,不存在则新增(服务层已处理)
BLL.SafetyPatrolService.Update(info);
@@ -146,6 +299,18 @@ namespace FineUIPro.Web.HSSE.HazardousMG
}
PageContext.RegisterStartupScript(WindowAtt.GetShowReference(String.Format("~/AttachFile/webuploader.aspx?type=0&toKeyId={0}&path=FileUpload/SafetyPatrol&menuId={1}", this.PatrolId, BLL.Const.SafetyPatrolMenuId)));
}
/// <summary>
/// 上传整改图片
/// </summary>
protected void btnAttachRectify_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(this.PatrolId))
{
this.PatrolId = Guid.NewGuid().ToString();
}
PageContext.RegisterStartupScript(WindowAtt.GetShowReference(String.Format("~/AttachFile/webuploader.aspx?type=0&toKeyId={0}&path=FileUpload/SafetyPatrolCorrect&menuId={1}", this.PatrolId, BLL.Const.SafetyPatrolRectifyMenuId)));
}
#endregion
}
}
@@ -33,13 +33,22 @@ namespace FineUIPro.Web.HSSE.HazardousMG
protected global::FineUIPro.PageManager PageManager1;
/// <summary>
/// SimpleForm1 控件。
/// ContentPanel1 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Form SimpleForm1;
protected global::FineUIPro.ContentPanel ContentPanel1;
/// <summary>
/// FormHazard 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Form FormHazard;
/// <summary>
/// ddlHazardProject 控件。
@@ -50,6 +59,15 @@ namespace FineUIPro.Web.HSSE.HazardousMG
/// </remarks>
protected global::FineUIPro.DropDownList ddlHazardProject;
/// <summary>
/// FormDate 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Form FormDate;
/// <summary>
/// dpPatrolDate 控件。
/// </summary>
@@ -60,49 +78,76 @@ namespace FineUIPro.Web.HSSE.HazardousMG
protected global::FineUIPro.DatePicker dpPatrolDate;
/// <summary>
/// ddlPatrolStatus 控件。
/// txtContentOther 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.DropDownList ddlPatrolStatus;
protected global::FineUIPro.TextBox txtContentOther;
/// <summary>
/// lblPatrolMan 控件。
/// txtCode 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label lblPatrolMan;
protected global::FineUIPro.TextBox txtCode;
/// <summary>
/// txtContent 控件。
/// txtProblems 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.TextArea txtContent;
protected global::FineUIPro.TextArea txtProblems;
/// <summary>
/// Panel2 控件。
/// ddlReceiver 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Panel Panel2;
protected global::FineUIPro.DropDownList ddlReceiver;
/// <summary>
/// Label1 控件。
/// txtHandleRequire 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Label Label1;
protected global::FineUIPro.TextArea txtHandleRequire;
/// <summary>
/// txtRectifyReview 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.TextArea txtRectifyReview;
/// <summary>
/// txtRemarks 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.TextArea txtRemarks;
/// <summary>
/// ddlPatrolMan 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.DropDownList ddlPatrolMan;
/// <summary>
/// btnAttach 控件。
@@ -114,22 +159,13 @@ namespace FineUIPro.Web.HSSE.HazardousMG
protected global::FineUIPro.Button btnAttach;
/// <summary>
/// Toolbar1 控件。
/// btnAttachRectify 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.Toolbar Toolbar1;
/// <summary>
/// ToolbarFill1 控件。
/// </summary>
/// <remarks>
/// 自动生成的字段。
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
/// </remarks>
protected global::FineUIPro.ToolbarFill ToolbarFill1;
protected global::FineUIPro.Button btnAttachRectify;
/// <summary>
/// btnSave 控件。
-1
View File
@@ -13,7 +13,6 @@
<TreeNode id="E85CB915-FAC3-4E59-82E7-28DD5525CCB0" Text="危大工程管控" EnText="危大工程管控" NavigateUrl=""><TreeNode id="0F166DE2-6DF7-49A9-8E4A-93F5AE476F28" Text="专项施工方案" EnText="专项施工方案" NavigateUrl="HSSE/HazardousMG/SpecialPlan.aspx"></TreeNode>
<TreeNode id="1C0D9228-1548-47A8-9BC2-801CFED45915" Text="安全技术交底" EnText="安全技术交底" NavigateUrl="HSSE/HazardousMG/SafetyDisclosure.aspx"></TreeNode>
<TreeNode id="44A8CF73-7F23-40CB-9D64-FD05AB48522D" Text="危大、超危清单" EnText="危大、超危清单" NavigateUrl="HSSE/HazardousMG/HazardProject.aspx"></TreeNode>
<TreeNode id="39C36EF6-A11E-4EA1-B78C-E0F59AAA6EB7" Text="风险分级管控清单" EnText="风险分级管控清单" NavigateUrl="HSSE/HazardousMG/RiskControlList.aspx"></TreeNode>
</TreeNode>
<TreeNode id="3B322232-38A1-4291-9832-CD4A01C2A975" Text="WBS数据" EnText="WBS数据" NavigateUrl=""><TreeNode id="5AA08233-9E04-4808-AC43-DD411C5F9D31" Text="现场控制点裁剪" EnText="现场控制点裁剪" NavigateUrl="CQMS/WBS/ProjectControlPoint.aspx"></TreeNode>
</TreeNode>
+1 -1
View File
@@ -146,7 +146,7 @@ namespace FineUIPro.Web.common
// 检查列表
var query = (
from hsse in Funs.DB.HSSE_Hazard_HazardRegister
where hsse.RectifyName != null && hsse.RegisterDate > startd && hsse.RegisterDate < endd
where hsse.RectifyName != null && hsse.States != "4" && hsse.RegisterDate > startd && hsse.RegisterDate < endd
group hsse by hsse.RectifyName into g1
select new { type = g1.Key, count = g1.Count() }
@@ -129,7 +129,7 @@ namespace FineUIPro.Web.common
// 检查列表
var query =
(from hsse in Funs.DB.HSSE_Hazard_HazardRegister
where hsse.RectifyName != null && hsse.ProjectId == ProjectId && hsse.RegisterDate> startd && hsse.RegisterDate < endd
where hsse.RectifyName != null && hsse.States != "4" && hsse.ProjectId == ProjectId && hsse.RegisterDate> startd && hsse.RegisterDate < endd
group hsse by hsse.RectifyName into g1
select new { type = g1.Key, count = g1.Count() }).Union((from i in Funs.DB.Inspect_Inspection
join itm in Funs.DB.Inspect_InspectionItem on i.InspectionId equals itm.InspectionId
+85 -4
View File
@@ -16,6 +16,15 @@ namespace Model
set;
}
/// <summary>
/// 编码(全局唯一,格式 XJ-序号,自动生成)
/// </summary>
public string Code
{
get;
set;
}
/// <summary>
/// 项目ID
/// </summary>
@@ -53,7 +62,7 @@ namespace Model
}
/// <summary>
/// 巡检人
/// 巡检人名称
/// </summary>
public string PatrolMan
{
@@ -62,7 +71,16 @@ namespace Model
}
/// <summary>
/// 巡检状态(正常/待整改)
/// 巡检人ID
/// </summary>
public string PatrolManId
{
get;
set;
}
/// <summary>
/// 巡检状态(正常/待整改/整改待复查)
/// </summary>
public string PatrolStatus
{
@@ -71,7 +89,7 @@ namespace Model
}
/// <summary>
/// 巡内容
/// 巡内容(勾选项合并后的文本)
/// </summary>
public string Content
{
@@ -80,12 +98,75 @@ namespace Model
}
/// <summary>
/// 附件URL(逗号分隔)
/// 发现问题
/// </summary>
public string Problems
{
get;
set;
}
/// <summary>
/// 签收人名称
/// </summary>
public string Receiver
{
get;
set;
}
/// <summary>
/// 签收人ID
/// </summary>
public string ReceiverId
{
get;
set;
}
/// <summary>
/// 处理要求
/// </summary>
public string HandleRequire
{
get;
set;
}
/// <summary>
/// 整改后复查情况
/// </summary>
public string RectifyReview
{
get;
set;
}
/// <summary>
/// 备注
/// </summary>
public string Remarks
{
get;
set;
}
/// <summary>
/// 附件URL(逗号分隔,巡视图片)
/// </summary>
public string AttachUrl
{
get;
set;
}
/// <summary>
/// 整改图片URL(逗号分隔)
/// </summary>
public string RectifyAttachUrl
{
get;
set;
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using System;
using System.Data.Linq.Mapping;
namespace Model
{
/// <summary>
/// 【补充部分类】为 HSSE_SafetyPatrol 提供编码(Code) 列映射。
/// 说明:该列已由数据库脚本新增(见 DataBase/版本日志/SGGLDB_V2026-08-26-001-zones.sql),
/// 但本地无 SqlMetal,未通过 CreateModel.bat 重新生成 Model.cs,故以 partial 类补齐。
/// 注意:若以后用 CreateModel.bat 重新生成 Model.csSqlMetal 会把 Code 一并生成,
/// 届时请删除本文件,避免出现重复的 Code 成员导致编译错误。
/// </summary>
public partial class HSSE_SafetyPatrol
{
[Column(Name = "Code", DbType = "NVarChar(50)")]
public string Code { get; set; }
}
}
+168
View File
@@ -220506,10 +220506,24 @@ namespace Model
private string _PatrolMan;
private string _PatrolManId;
private string _PatrolStatus;
private string _Content;
private string _Problems;
private string _Receiver;
private string _ReceiverId;
private string _HandleRequire;
private string _RectifyReview;
private string _Remarks;
#region
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
@@ -220526,10 +220540,24 @@ namespace Model
partial void OnPatrolDateChanged();
partial void OnPatrolManChanging(string value);
partial void OnPatrolManChanged();
partial void OnPatrolManIdChanging(string value);
partial void OnPatrolManIdChanged();
partial void OnPatrolStatusChanging(string value);
partial void OnPatrolStatusChanged();
partial void OnContentChanging(string value);
partial void OnContentChanged();
partial void OnProblemsChanging(string value);
partial void OnProblemsChanged();
partial void OnReceiverChanging(string value);
partial void OnReceiverChanged();
partial void OnReceiverIdChanging(string value);
partial void OnReceiverIdChanged();
partial void OnHandleRequireChanging(string value);
partial void OnHandleRequireChanged();
partial void OnRectifyReviewChanging(string value);
partial void OnRectifyReviewChanged();
partial void OnRemarksChanging(string value);
partial void OnRemarksChanged();
#endregion
public HSSE_SafetyPatrol()
@@ -220657,6 +220685,26 @@ namespace Model
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_PatrolManId", DbType="NVarChar(50)")]
public string PatrolManId
{
get
{
return this._PatrolManId;
}
set
{
if ((this._PatrolManId != value))
{
this.OnPatrolManIdChanging(value);
this.SendPropertyChanging();
this._PatrolManId = value;
this.SendPropertyChanged("PatrolManId");
this.OnPatrolManIdChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_PatrolStatus", DbType="NVarChar(50)")]
public string PatrolStatus
{
@@ -220697,6 +220745,126 @@ namespace Model
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Problems", DbType="NVarChar(1000)")]
public string Problems
{
get
{
return this._Problems;
}
set
{
if ((this._Problems != value))
{
this.OnProblemsChanging(value);
this.SendPropertyChanging();
this._Problems = value;
this.SendPropertyChanged("Problems");
this.OnProblemsChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Receiver", DbType="NVarChar(50)")]
public string Receiver
{
get
{
return this._Receiver;
}
set
{
if ((this._Receiver != value))
{
this.OnReceiverChanging(value);
this.SendPropertyChanging();
this._Receiver = value;
this.SendPropertyChanged("Receiver");
this.OnReceiverChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ReceiverId", DbType="NVarChar(50)")]
public string ReceiverId
{
get
{
return this._ReceiverId;
}
set
{
if ((this._ReceiverId != value))
{
this.OnReceiverIdChanging(value);
this.SendPropertyChanging();
this._ReceiverId = value;
this.SendPropertyChanged("ReceiverId");
this.OnReceiverIdChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_HandleRequire", DbType="NVarChar(1000)")]
public string HandleRequire
{
get
{
return this._HandleRequire;
}
set
{
if ((this._HandleRequire != value))
{
this.OnHandleRequireChanging(value);
this.SendPropertyChanging();
this._HandleRequire = value;
this.SendPropertyChanged("HandleRequire");
this.OnHandleRequireChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_RectifyReview", DbType="NVarChar(1000)")]
public string RectifyReview
{
get
{
return this._RectifyReview;
}
set
{
if ((this._RectifyReview != value))
{
this.OnRectifyReviewChanging(value);
this.SendPropertyChanging();
this._RectifyReview = value;
this.SendPropertyChanged("RectifyReview");
this.OnRectifyReviewChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Remarks", DbType="NVarChar(500)")]
public string Remarks
{
get
{
return this._Remarks;
}
set
{
if ((this._Remarks != value))
{
this.OnRemarksChanging(value);
this.SendPropertyChanging();
this._Remarks = value;
this.SendPropertyChanged("Remarks");
this.OnRemarksChanged();
}
}
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
+1
View File
@@ -247,6 +247,7 @@
<Compile Include="JDGL\WBSSetInitItem.cs" />
<Compile Include="JDGL\WBSSetItem.cs" />
<Compile Include="Model.cs" />
<Compile Include="HSSE_SafetyPatrol.Code.cs" />
<Compile Include="ModelProc.cs" />
<Compile Include="Num.cs" />
<Compile Include="Pie.cs" />
@@ -34,6 +34,7 @@ namespace WebAPI.Controllers.HSSE.HazardousMG
foreach (var item in dataList)
{
item.AttachUrl = AttachFileService.getFileUrl(item.PatrolId, Const.SafetyPatrolMenuId);
item.RectifyAttachUrl = AttachFileService.getFileUrl(item.PatrolId, Const.SafetyPatrolRectifyMenuId);
}
responeData.data = new { totalCount, dataList };
}
@@ -62,6 +63,7 @@ namespace WebAPI.Controllers.HSSE.HazardousMG
{
////附件关联
item.AttachUrl = AttachFileService.getFileUrl(item.PatrolId, Const.SafetyPatrolMenuId);
item.RectifyAttachUrl = AttachFileService.getFileUrl(item.PatrolId, Const.SafetyPatrolRectifyMenuId);
}
responeData.data = item;
}
-168
View File
@@ -1,168 +0,0 @@
# 安全巡检接口文档
## 1. 概述
- **基础地址**`http://{host}:{port}`(WebAPI 独立站点,本地调试默认 `http://localhost:7143`
- **路由规则**`api/{controller}/{action}/{id}`
- **Controller**`SafetyPatrol`
- **数据格式**:JSON(请求体、响应体均为 JSON)
## 2. 通用返回结构 `ResponeData`
所有接口统一返回以下结构:
| 字段 | 类型 | 说明 |
|------|------|------|
| `code` | int | `1` 成功,`0` 失败 |
| `message` | string | 提示消息(成功时为空,失败时为异常信息) |
| `data` | object | 业务数据(各接口不同,见下文) |
```json
{
"code": 1,
"message": null,
"data": { }
}
```
## 3. 数据对象 `SafetyPatrolItem`
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `PatrolId` | string | 编辑时必填 | 主键(新增时可不传,服务端自动生成 GUID) |
| `ProjectId` | string | 新增时必填 | 项目主键 |
| `HazardProjectId` | string | 否 | 危大、超危工程主键 |
| `HazardProjectName` | string | 否 | 工程名称 |
| `PatrolDate` | datetime | 否 | 巡检日期(ISO 格式,如 `2026-08-19T10:00:00` |
| `PatrolMan` | string | 否 | 巡检人 |
| `PatrolStatus` | string | 否 | 巡检状态:`正常` / `待整改` |
| `Content` | string | 否 | 巡检内容(语音转文字) |
| `AttachUrl` | string | 否 | 巡检图片附件 URL(逗号分隔);查询接口自动回填,新增/编辑时传入则自动写入附件表关联 |
## 4. 接口列表
### 4.1 获取安全巡检分页列表
- **请求方式**`GET`
- **URL**`/api/SafetyPatrol/getSafetyPatrolList`
**请求参数(Query**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `projectId` | string | 是 | 项目主键 |
| `pageNumber` | int | 否 | 页码,从 1 开始;为 0 时不限制 |
| `pageSize` | int | 否 | 每页条数;为 0 时不限制 |
| `keyword` | string | 否 | 工程名称关键字(模糊匹配) |
**示例**
```
GET /api/SafetyPatrol/getSafetyPatrolList?projectId=xxx&pageNumber=1&pageSize=10&keyword=基坑
```
**返回 `data`**
```json
{
"totalCount": 12,
"dataList": [
{
"PatrolId": "9f1a...",
"ProjectId": "xxx",
"HazardProjectId": "hd-001",
"HazardProjectName": "深基坑土方开挖工程",
"PatrolDate": "2026-08-19T10:00:00",
"PatrolMan": "张建国",
"PatrolStatus": "正常",
"Content": "现场深基坑边坡稳定,无裂缝。",
"AttachUrl": "fileupload/safetypatrol/patrol_001.jpg,fileupload/safetypatrol/patrol_002.jpg"
}
]
}
```
### 4.2 获取安全巡检详情
- **请求方式**`GET`
- **URL**`/api/SafetyPatrol/getSafetyPatrolById`
**请求参数(Query**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `patrolId` | string | 是 | 巡检记录主键 |
**示例**
```
GET /api/SafetyPatrol/getSafetyPatrolById?patrolId=9f1a...
```
**返回 `data`**:单个 `SafetyPatrolItem` 对象(含 `AttachUrl`),不存在时为 `null`
### 4.3 新增安全巡检
- **请求方式**`POST`
- **URL**`/api/SafetyPatrol/addSafetyPatrol`
- **Content-Type**`application/json`
**请求体(JSON**
```json
{
"ProjectId": "xxx",
"HazardProjectId": "hd-001",
"HazardProjectName": "深基坑土方开挖工程",
"PatrolDate": "2026-08-19T10:00:00",
"PatrolMan": "张建国",
"PatrolStatus": "正常",
"Content": "现场深基坑边坡稳定,无裂缝。",
"AttachUrl": "fileupload/safetypatrol/patrol_001.jpg"
}
```
> 说明:`AttachUrl` 非必填;传入图片 URL(多个用英文逗号分隔)时,服务端会自动写入附件表(`ToKeyId`=PatrolId、`MenuId`=SafetyPatrolMenuId),之后查询接口即可回读。
**返回 `data`**
```json
{ "patrolId": "9f1a..." }
```
> 校验:`ProjectId` 为空时返回 `code=0``message="项目主键不能为空!"`
### 4.4 编辑安全巡检
- **请求方式**`POST`
- **URL**`/api/SafetyPatrol/updateSafetyPatrol`
- **Content-Type**`application/json`
**请求体(JSON**(需携带 `PatrolId`
```json
{
"PatrolId": "9f1a...",
"ProjectId": "xxx",
"HazardProjectId": "hd-001",
"HazardProjectName": "深基坑土方开挖工程",
"PatrolDate": "2026-08-19T10:00:00",
"PatrolMan": "张建国",
"PatrolStatus": "待整改",
"Content": "边坡局部有积水,需整改。",
"AttachUrl": "fileupload/safetypatrol/patrol_003.jpg"
}
```
> 说明:传入 `AttachUrl` 时会覆盖该记录的原有附件;不传则保留原附件不变。
**返回 `data`**:成功时无数据(`data` 为空)。
> 校验:`PatrolId` 为空返回 `"巡检主键不能为空!"`;记录不存在返回 `"未找到对应记录!"`
## 5. 错误码
| `code` | 含义 |
|--------|------|
| `1` | 成功 |
| `0` | 失败(`message` 为具体原因,如参数校验失败、数据库异常) |