Files
lserp_cs_6.0/插件库/Lskj.Control/Model/AuditChangeLog.cs
T
2026-08-04 13:49:05 +08:00

283 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Data;
using Lskj.Business;
using Lskj.Business.Impl;
using Lskj.Core;
using Lskj.Data;
namespace Lskj.Control.Model
{
/// <summary>
/// 审核改动日志处理类。
/// 用来比较单据主表原始数据和当前表头控件值,并把发生变化的字段写入 P_SystemAuditChangeLog。
/// </summary>
public class AuditChangeLog
{
private const string TableName = "P_SystemAuditChangeLog";
private const int MaxOrderNumberLength = 50;
private const int MaxTextLength = 500;
/// <summary>
/// 比较表头字段是否发生变化,并保存审核改动日志。
/// 返回 false 时,errorMessage 会一次性返回所有未记录成功的字段。
/// </summary>
/// <param name="drBillInfoMsg">改动前数据(单表数据或者单据主表数据)</param>
/// <param name="controlObj">控件 mycontrol</param>
/// <param name="orderNumber">单号</param>
/// <param name="stepCode">步骤号</param>
/// <param name="operatorId">登录人id</param>
/// <returns></returns>
public static bool SaveHeaderChangeLog(DataRow drBillInfoMsg, MyControl controlObj, string orderNumber, string stepCode, string operatorId)
{
if (SystemInfo.Instance.AuditChangeRecord)
{
CreateModificationRecordTable();
string errorMessage = string.Empty;
// 原始主表数据或控件对象为空时,没有可比较的数据,直接返回成功。
if (drBillInfoMsg == null || controlObj == null || controlObj.ControlModels == null)
return true;
List<string> errorFields = new List<string>();
// 遍历当前界面的表头控件模型,逐个比较可保存字段。
foreach (ControlModel model in controlObj.ControlModels)
{
string currentFieldName = model == null ? string.Empty : model.FieldName;
try
{
// 只比较可保存、界面真实存在、原始主表行中也存在的普通字段。
if (!CanCompare(model, drBillInfoMsg, controlObj))
continue;
// 旧值来自打开审核界面时加载出来的主表原始行。
string oldValue = GetRowValue(drBillInfoMsg, model.FieldName);
// 新值来自当前界面控件值,也就是用户修改后的值。
string newValue = controlObj.GetControlValue(model);
if (newValue == "****")
continue;
// 日期、数字、空值先做统一处理,避免显示格式不同造成误判。
if (IsSameValue(oldValue, newValue))
continue;
// 字段确实发生变化后写入日志;相同单号、步骤、字段已存在时执行更新。
SaveChangeLog(orderNumber, model.FieldName, oldValue, newValue, stepCode, operatorId);
}
catch (Exception ex)
{
// 单个字段记录失败时先收集错误,继续处理后续字段,最后一次性提示。
errorFields.Add(GetErrorFieldName(model, currentFieldName) + "" + ex.Message + "");
}
}
if (errorFields.Count > 0)
{
errorMessage = "以下字段审核改动日志未记录:" + Environment.NewLine + string.Join(Environment.NewLine, errorFields.ToArray());
MessageUtil.Show(errorMessage);
return false;
}
}
return true;
}
/// <summary>
/// 判断控件字段是否需要参与改动比较。
/// </summary>
private static bool CanCompare(ControlModel model, DataRow drBillInfoMsg, MyControl controlObj)
{
if (model == null)
return false;
// 不保存的字段和图片控件不参与本次表头改动日志记录。
if (!model.IsSave ||
model.FieldType == ControlType.LabPic ||
model.FieldType == ControlType.LabPicEx)
return false;
if (string.IsNullOrWhiteSpace(model.FieldName))
return false;
// 当前界面上没有真实控件的字段不参与比较。
if (controlObj.FindControl(model) == null)
return false;
// 原始主表行里必须存在同名数据库字段。
return drBillInfoMsg.Table != null && drBillInfoMsg.Table.Columns.Contains(model.FieldName);
}
/// <summary>
/// 保存单个字段的改动记录。
/// 如果相同单号、相同步骤、相同字段已存在记录,则更新;否则新增。
/// </summary>
private static void SaveChangeLog(string orderNumber, string fieldName, string oldValue, string newValue, string stepCode, string operatorId)
{
//orderNumber = orderNumber == null ? string.Empty : orderNumber;
//fieldName = fieldName == null ? string.Empty : fieldName;
//oldValue = oldValue == null ? string.Empty : oldValue;
//newValue = newValue == null ? string.Empty : newValue;
//orderNumber = orderNumber.Length > MaxOrderNumberLength ? orderNumber.Substring(0, MaxOrderNumberLength) : orderNumber;
//fieldName = fieldName.Length > MaxTextLength ? fieldName.Substring(0, MaxTextLength) : fieldName;
//oldValue = oldValue.Length > MaxTextLength ? oldValue.Substring(0, MaxTextLength) : oldValue;
//newValue = newValue.Length > MaxTextLength ? newValue.Substring(0, MaxTextLength) : newValue;
//orderNumber = orderNumber.Replace("'", "''");
//fieldName = fieldName.Replace("'", "''");
//oldValue = oldValue.Replace("'", "''");
//newValue = newValue.Replace("'", "''");
string sql = string.Format(@"if exists (select 1 from {0} where orderNumber = '{1}' and stepCode = {2} and fieldName = N'{3}')
begin
update {0}
set oldValue = N'{4}',
newValue = N'{5}',
operatorId = N'{6}'
where orderNumber =N'{1}'
and stepCode = N'{2}'
and fieldName = N'{3}'
end
else
begin
insert into {0} (orderNumber, fieldName, oldValue, newValue, stepCode, operatorId)
values (N'{1}', N'{3}', N'{4}', N'{5}', N'{2}', N'{6}')
end",
TableName,
orderNumber,
stepCode,
fieldName,
oldValue,
newValue,
operatorId);
SqlHelper.ExecuteNonQuery(sql);
}
/// <summary>
/// 从原始主表行中读取字段旧值,数据库 NULL 统一按空字符串处理。
/// </summary>
private static string GetRowValue(DataRow row, string fieldName)
{
if (row[fieldName] == DBNull.Value || row[fieldName] == null)
return string.Empty;
return row[fieldName] + "";
}
/// <summary>
/// 获取错误提示中展示的字段名称,优先显示控件标题,没有标题时显示字段名。
/// </summary>
private static string GetErrorFieldName(ControlModel model, string fieldName)
{
if (model != null && !string.IsNullOrWhiteSpace(model.LabelText))
return model.LabelText + "[" + model.FieldName + "]";
return string.IsNullOrWhiteSpace(fieldName) ? "未知字段" : fieldName;
}
/// <summary>
/// 判断两个值是否相同。
/// 优先按日期、数字进行值比较,最后再按普通字符串比较。
/// </summary>
/// <param name="oldValue">原始值</param>
/// <param name="newValue">当前值</param>
/// <returns>两个值在统一格式后是否相同</returns>
public static bool IsSameValue(string oldValue, string newValue)
{
oldValue = NormalizeValue(oldValue);
newValue = NormalizeValue(newValue);
if (oldValue == string.Empty && newValue == string.Empty)
return true;
DateTime oldDate;
DateTime newDate;
if (DateTime.TryParse(oldValue, out oldDate) && DateTime.TryParse(newValue, out newDate))
return oldDate == newDate;
decimal oldDecimal;
decimal newDecimal;
if (decimal.TryParse(oldValue, out oldDecimal) && decimal.TryParse(newValue, out newDecimal))
return oldDecimal == newDecimal;
return oldValue == newValue;
}
/// <summary>
/// 比较前统一处理 NULL 和首尾空格。
/// </summary>
private static string NormalizeValue(string value)
{
return value == null ? string.Empty : value.Trim();
}
/// <summary>
/// 根据单号获取所有审核改动字段名。
/// </summary>
/// <param name="orderNumber">单号</param>
/// <returns>当前单号对应的审核改动字段名集合</returns>
public static List<string> GetChangeLogFields(string orderNumber)
{
List<string> fields = new List<string>();
if (SystemInfo.Instance.AuditChangeRecord)
{
CreateModificationRecordTable();
orderNumber = orderNumber == null ? string.Empty : orderNumber.Replace("'", "''");
string sqlValue = string.Format(@"
select distinct fieldName
from {0}
where orderNumber = N'{1}'
order by fieldName", TableName, orderNumber);
DataTable dataTable = SqlHelper.ExecuteDataTable(sqlValue);
if (dataTable == null)
return fields;
foreach (DataRow row in dataTable.Rows)
{
string fieldName = row["fieldName"] + "";
if (!string.IsNullOrWhiteSpace(fieldName))
fields.Add(fieldName);
}
}
return fields;
}
/// <summary>
/// 创建修改记录表
/// </summary>
public static void CreateModificationRecordTable()
{
if (!Lskj.Business.Impl.BaseImpl.HasExistsTable("P_SystemAuditChangeLog"))
{
string sqlValue = string.Format(@"CREATE TABLE P_SystemAuditChangeLog (
id BIGINT IDENTITY(1,1) NOT NULL PRIMARY KEY,
orderNumber VARCHAR(50) NOT NULL, -- 单号
fieldName NVARCHAR(500) NOT NULL, -- 字段名称
oldValue NVARCHAR(500) NULL, -- 旧值(改动前)
newValue NVARCHAR(500) NULL, -- 新值(改动后)
stepCode INT NOT NULL, -- 步骤号
operatorId int NOT NULL -- 人员id(改动人)
);");
BaseImpl.ExecSqlValue(sqlValue);
}
}
}
}