using System.Data; using System.Globalization; using DMS.Application.DTOs; using DMS.Application.Interfaces; using DMS.Application.Models; using DMS.Core.Enums; using Microsoft.Extensions.Logging; namespace DMS.Application.Services.Processors; public class ValueConvertProcessor : IVariableProcessor { private readonly ILogger _logger; public ValueConvertProcessor(ILogger logger) { _logger = logger; } public Task ProcessAsync(VariableContext context) { var oldValue = context.Data.DataValue; // 如果值没有变化则中断处理链 if (context.Data.DataValue == context.NewValue) { context.IsHandled = true; } // 步骤 1: 将原始值转换为 DataValue 和 NumericValue context.Data.DataValue = context.NewValue; if (context.Data.DataType == DataType.Bool) { context.Data.NumericValue=context.NewValue=="True"?1:0; context.Data.DisplayValue = context.NewValue; } else { if (double.TryParse(context.Data.DataValue, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsedFromStr)) { context.Data.NumericValue = parsedFromStr; } // 步骤 2: 根据公式计算 DisplayValue CalculateDisplayValue(context.Data); } context.Data.UpdatedAt = DateTime.Now; return Task.CompletedTask; } /// /// 根据转换公式计算用于UI显示的DisplayValue /// /// 需要处理的变量DTO private void CalculateDisplayValue(VariableDto variable) { // 默认情况下,显示值等于原始数据值 variable.DisplayValue = variable.DataValue; // 如果没有转换公式,则直接返回 if (string.IsNullOrWhiteSpace(variable.ConversionFormula)) { return; } try { // 将公式中的 'x' 替换为实际的数值 // 使用 InvariantCulture 确保小数点是 '.' string expression = variable.ConversionFormula.ToLowerInvariant() .Replace("x", variable.NumericValue.ToString(CultureInfo.InvariantCulture)); // 使用 DataTable.Compute 来安全地计算表达式 var result = new DataTable().Compute(expression, null); // 将计算结果格式化后赋给 DisplayValue if (result is double || result is decimal || result is float) { variable.DisplayValue = string.Format("{0:F2}", result); // 默认格式化为两位小数,可根据需要调整 variable.NumericValue = Convert.ToDouble(result); // 更新NumericValue为计算后的值 } else { variable.DisplayValue = result.ToString(); // 尝试将字符串结果解析回double,以更新NumericValue if (double.TryParse(result.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out var parsedResult)) { variable.NumericValue = parsedResult; } } } catch (Exception ex) { _logger.LogError(ex, $"为变量 {variable.Name} (ID: {variable.Id}) 计算DisplayValue时出错。公式: '{variable.ConversionFormula}'"); // 如果计算出错,DisplayValue 将保持为原始的 DataValue,保证程序健壮性 } } /// /// 将从 S7 读取的对象值转换为字符串表示和数值表示 /// /// 关联的变量 DTO /// 从 S7 读取的原始对象值 private void ConvertS7ValueToStringAndNumeric(VariableDto variable, string value) { if (value == null) return; string directConversion = null; double numericValue = 0.0; if (variable.DataType == DataType.Bool) { numericValue=value.ToString()=="True"?1.0:0.0; directConversion = value.ToString(); return; } variable.DataValue = directConversion ?? value.ToString() ?? string.Empty; variable.NumericValue = numericValue; } }