更新项目配置,新增设备同步模块,优化WebSocket和Swagger配置,增强SCADA系统的免登录接口,支持数据字典项和登录日志的免登录查询与记录。调整Java编译设置,确保更好的开发体验。

This commit is contained in:
geht
2026-04-28 10:23:58 +08:00
parent bbe46dcf2d
commit 142a0bdaba
1013 changed files with 41858 additions and 28 deletions

View File

@@ -0,0 +1,74 @@
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using YY.Admin.Core.LiveCharts2;
namespace YY.Admin.Core.Converter
{
public class BrushToSolidColorPaintConverter : IValueConverter
{
public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter is not CusSolidColorPaint sourcePaint)
return new SolidColorPaint(SKColors.Transparent);
var skColor = ResolveColor(sourcePaint.CusColor);
var targetPaint = new CusSolidColorPaint(skColor);
MapProperties(sourcePaint, targetPaint);
return targetPaint;
}
// 统一的颜色解析方法
private SKColor ResolveColor(string? colorKey)
{
if (SKColor.TryParse(colorKey, out var parsedColor))
return parsedColor;
var resource = Application.Current.FindResource(colorKey);
return resource switch
{
Color mediaColor => new SKColor(mediaColor.R, mediaColor.G, mediaColor.B, mediaColor.A),
SolidColorBrush brush => new SKColor(brush.Color.R, brush.Color.G, brush.Color.B, brush.Color.A),
_ => SKColors.Transparent,
};
}
protected void MapProperties(CusSolidColorPaint sourcePaint, CusSolidColorPaint targetPaint)
{
targetPaint.IsAntialias = sourcePaint.IsAntialias;
targetPaint.StrokeThickness = sourcePaint.StrokeThickness;
targetPaint.StrokeCap = sourcePaint.StrokeCap;
targetPaint.StrokeMiter = sourcePaint.StrokeMiter;
targetPaint.StrokeJoin = sourcePaint.StrokeJoin;
targetPaint.ImageFilter = sourcePaint.ImageFilter;
targetPaint.PathEffect = sourcePaint.PathEffect;
#pragma warning disable CS0618 // Type or member is obsolete
if (sourcePaint.FontWeight != SKFontStyleWeight.Normal || sourcePaint.FontWidth != SKFontStyleWidth.Normal || sourcePaint.FontSlant != SKFontStyleSlant.Upright)
targetPaint.SKFontStyle = new SKFontStyle(sourcePaint.FontWeight, sourcePaint.FontWidth, sourcePaint.FontSlant);
#pragma warning restore CS0618 // Type or member is obsolete
if (sourcePaint?.FontFamily is not null)
{
targetPaint.SKTypeface = SKTypeface.FromFamilyName(sourcePaint?.FontFamily);
}
else if (sourcePaint?.TypefaceMatchesChar is not null && sourcePaint.TypefaceMatchesChar.Length > 0)
{
targetPaint.SKTypeface = SKFontManager.Default.MatchCharacter(sourcePaint.TypefaceMatchesChar[0]);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Globalization;
using System.Reflection;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
public class EnumDescriptionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || value.ToString() == null) return string.Empty;
var field = value.GetType().GetField(value.ToString()!);
if (field == null) return value.ToString()!;
var attribute = field.GetCustomAttribute<DescriptionAttribute>();
return attribute?.Description ?? value.ToString()!;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,60 @@
using System.Globalization;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
/// <summary>
/// 将枚举值和 bool 互转,适用于 ToggleButton 或 RadioButton
/// </summary>
public class EnumToBoolConverter : IValueConverter
{
/// <summary>
/// 将枚举值转换为 bool
/// </summary>
/// <param name="value">绑定的枚举值</param>
/// <param name="targetType"></param>
/// <param name="parameter">ConverterParameter 指定要匹配的枚举值</param>
/// <param name="culture"></param>
/// <returns>匹配返回 true否则 false</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string enumValue = value?.ToString() ?? string.Empty;
string targetValue = parameter?.ToString() ?? string.Empty;
return enumValue.Equals(targetValue, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// 将 bool 转回枚举值
/// </summary>
/// <param name="value">ToggleButton.IsChecked</param>
/// <param name="targetType"></param>
/// <param name="parameter">ConverterParameter 指定对应的枚举值</param>
/// <param name="culture"></param>
/// <returns>如果 true 返回枚举,否则返回 Binding.DoNothing</returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool isChecked && isChecked && parameter != null)
{
// 判断 targetType 是否是 Nullable 类型
if (Nullable.GetUnderlyingType(targetType) != null)
{
// 获取 Nullable 的基础类型
Type underlyingType = Nullable.GetUnderlyingType(targetType)!;
// 确保基础类型是枚举类型
if (underlyingType?.IsEnum == true)
{
return Enum.Parse(underlyingType, parameter.ToString()!);
}
}
// 如果不是枚举类型或 Nullable 类型,返回 Binding.DoNothing
else if (targetType.IsEnum)
{
return Enum.Parse(targetType, parameter.ToString()!);
}
}
return Binding.DoNothing;
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Globalization;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
public class EnumToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Enum enumValue)
{
System.Convert.ToInt32(enumValue);
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is int intValue && parameter is Type enumType && enumType.IsEnum)
{
return Enum.ToObject(enumType, intValue);
}
return value;
}
}
}

View File

@@ -0,0 +1,29 @@
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
public class EnumToTagTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is StatusEnum status)
{
return status switch
{
StatusEnum.Enable => Application.Current.FindResource("SuccessBrush"), // 启用 - 绿色
StatusEnum.Disable => Application.Current.FindResource("DangerBrush"), // 禁用 - 红色
_ => Application.Current.FindResource("InfoBrush")
};
}
return Application.Current.FindResource("InfoBrush");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
/// <summary>
/// 将枚举值转换为Visibility
/// </summary>
public class EnumToVisibilityConverter : IValueConverter
{
/// <summary>
/// 将枚举值转换为 Visibility
/// </summary>
/// <param name="value">绑定的枚举值</param>
/// <param name="targetType"></param>
/// <param name="parameter">ConverterParameter 指定要匹配的枚举值</param>
/// <param name="culture"></param>
/// <returns>匹配返回Visible</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || parameter == null)
return Visibility.Collapsed;
return value.ToString()!.Equals(parameter.ToString(), StringComparison.OrdinalIgnoreCase)
? Visibility.Visible
: Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> throw new NotImplementedException();
}
}

View File

@@ -0,0 +1,23 @@
using System.Globalization;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
public class MaxWidthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is double totalWidth && totalWidth > 0 && parameter != null && double.TryParse(parameter.ToString(), out var offset) && totalWidth >= offset)
{
// 最大宽度
return totalWidth - offset;
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,49 @@
using HandyControl.Data;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
/// <summary>
/// 根据 TitleWidth 计算 Margin.Left如果 TitlePlacement=Top 则不偏移
/// </summary>
public class NegativeLeftThicknessConverter : IMultiValueConverter
{
// 这里改成 MultiBinding方便同时拿 TitleWidth 和 TitlePlacement
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double left = 0;
double bottomShift = -18;
if (parameter != null && double.TryParse(parameter.ToString(), out var p))
bottomShift = p;
// 如果 TitleWidth 还未设置,直接返回默认 Thickness
if (values.Length > 0 && values[0] != DependencyProperty.UnsetValue)
{
var widthValue = values[0];
if (widthValue is GridLength gridLength && gridLength.IsAbsolute)
left = gridLength.Value;
else if (widthValue is double d)
left = d;
}
// 如果 TitlePlacement 还未设置,也要避免异常
if (values.Length > 1 && values[1] != DependencyProperty.UnsetValue)
{
if (values[1] is TitlePlacementType placement)
{
// 如果标题在上方,则不偏移
if (placement == TitlePlacementType.Top)
left = 0;
}
}
return new Thickness(left, 0, 0, bottomShift);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
=> throw new NotSupportedException();
}
}

View File

@@ -0,0 +1,23 @@
using System.Globalization;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
public class PercentageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is double actualHeight && parameter is string paramString)
{
double percentage = double.Parse(paramString);
return actualHeight * percentage;
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,24 @@
using System.Globalization;
using System.Windows.Data;
namespace YY.Admin.Core.Converter
{
public class RadioButtonEnumMultiConverter : IMultiValueConverter
{
// values[0] = RadioButton 自身
// values[1] = SysUser.Status
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length < 2) return false;
if (values[0] == null || values[1] == null) return false;
return values[0].Equals(values[1]);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
// VM中通过事件实现UI -> VM的同步这里不处理直接返回Binding.DoNothing
return new object[] { Binding.DoNothing, Binding.DoNothing };
}
}
}