Compare commits
10 Commits
b802f2e89b
...
dcd1e247ee
| Author | SHA1 | Date | |
|---|---|---|---|
| dcd1e247ee | |||
| bd849e7de0 | |||
| 56be63db49 | |||
| 57f870ae49 | |||
| 9f1db152eb | |||
| 3c736f9d5b | |||
| a2fffbff37 | |||
| 4b5ac96b7c | |||
| 465d76d0db | |||
| 48f2e586e8 |
|
|
@ -31,8 +31,8 @@ public partial class MainWindow : Window
|
||||||
log = logService;
|
log = logService;
|
||||||
db = databaseService;
|
db = databaseService;
|
||||||
even = eventService;
|
even = eventService;
|
||||||
menu = new MenuController(this);// 初始化菜单控制器
|
menu = new MenuController(this, log, db, even);// 初始化菜单控制器
|
||||||
sensorManager = new SensorChartManager(this)
|
sensorManager = new SensorChartManager(this, log, db, even)
|
||||||
{
|
{
|
||||||
Sensor1 = Sensor1,
|
Sensor1 = Sensor1,
|
||||||
Sensor2 = Sensor2,
|
Sensor2 = Sensor2,
|
||||||
|
|
@ -51,13 +51,11 @@ public partial class MainWindow : Window
|
||||||
|
|
||||||
WindowHelper.SetWindowTitle(this, "FMSDGAUGE"); // 设置标题
|
WindowHelper.SetWindowTitle(this, "FMSDGAUGE"); // 设置标题
|
||||||
|
|
||||||
chartManager = new ChartManager(Dispatcher);
|
chartManager = new ChartManager(Dispatcher, log, db, even);
|
||||||
chartManager.InitCharts(myChart1, myChart2, myChart3); // 初始化图表
|
chartManager.InitChart(myChart1);
|
||||||
|
chartManager.InitChart(myChart2);
|
||||||
|
chartManager.InitChart(myChart3);
|
||||||
|
|
||||||
// 启动实时数据刷新
|
|
||||||
chartManager.StartAutoUpdate(myChart1, chartCts.Token, "myChart1");
|
|
||||||
chartManager.StartAutoUpdate(myChart2, chartCts.Token, "myChart2");
|
|
||||||
chartManager.StartAutoUpdate(myChart3, chartCts.Token, "myChart3");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,6 +90,8 @@ public partial class MainWindow : Window
|
||||||
if (!isDetecting)
|
if (!isDetecting)
|
||||||
{
|
{
|
||||||
// 开始检测
|
// 开始检测
|
||||||
|
// 清空之前图表数据
|
||||||
|
chartManager.ClearAllCharts();
|
||||||
sensorManager.Start();
|
sensorManager.Start();
|
||||||
BtnSensorControl.Content = "检测确定";
|
BtnSensorControl.Content = "检测确定";
|
||||||
isDetecting = true;
|
isDetecting = true;
|
||||||
|
|
|
||||||
|
|
@ -1,105 +1,195 @@
|
||||||
using guoke;
|
using guoke;
|
||||||
|
using LiveCharts;
|
||||||
using LiveCharts.Wpf;
|
using LiveCharts.Wpf;
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
using WpfApp.src.config;
|
|
||||||
using WpfApp.Utils;
|
|
||||||
|
|
||||||
namespace WpfApp.Services
|
namespace WpfApp.Services;
|
||||||
|
|
||||||
|
public class ChartManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly Dispatcher dispatcher;
|
||||||
/// Chart 管理器 - 负责图表初始化和实时更新
|
private readonly LogService log;
|
||||||
/// </summary>
|
private readonly DatabaseService db;
|
||||||
public class ChartManager
|
private readonly EventService<GeneralEventArgs> even;
|
||||||
|
|
||||||
|
private const string SENSOR_DATA_EVENT = "SensorDataUpdate";
|
||||||
|
|
||||||
|
// 最大保留点数
|
||||||
|
private const int MAX_POINTS = 20;
|
||||||
|
|
||||||
|
// 每个图表的数据封装
|
||||||
|
private class ChartData
|
||||||
{
|
{
|
||||||
private readonly Dispatcher dispatcher;
|
public ColumnSeries ColumnSeries;
|
||||||
private readonly LogService log;
|
public ChartValues<double> StandardMin = new ChartValues<double>();
|
||||||
private readonly DatabaseService db;
|
public ChartValues<double> StandardAvg = new ChartValues<double>();
|
||||||
private readonly EventService<GeneralEventArgs> even;
|
public ChartValues<double> StandardMax = new ChartValues<double>();
|
||||||
|
public List<string> Labels = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
public ChartManager(Dispatcher uiDispatcher)
|
// 管理多个图表
|
||||||
{
|
private Dictionary<CartesianChart, ChartData> charts = new Dictionary<CartesianChart, ChartData>();
|
||||||
dispatcher = uiDispatcher;
|
|
||||||
}
|
|
||||||
public ChartManager(LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> eventService)
|
|
||||||
{
|
|
||||||
log = logService;
|
|
||||||
db = databaseService;
|
|
||||||
even = eventService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
public ChartManager(Dispatcher uiDispatcher,
|
||||||
/// 初始化图表
|
LogService logService,
|
||||||
/// </summary>
|
DatabaseService databaseService,
|
||||||
public void InitCharts(params CartesianChart[] charts)
|
EventService<GeneralEventArgs> eventService)
|
||||||
{
|
{
|
||||||
var labels = new[] { "13:27 23", "13:27 45", "13:27 49", "13:27 50", "13:27 55" };
|
dispatcher = uiDispatcher;
|
||||||
|
log = logService;
|
||||||
|
db = databaseService;
|
||||||
|
even = eventService;
|
||||||
|
|
||||||
var config = new ChartConfig
|
SubscribeToSensorDataEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化图表(一次性设置标准线和柱状图)
|
||||||
|
/// </summary>
|
||||||
|
public void InitChart(CartesianChart chart)
|
||||||
|
{
|
||||||
|
dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
if (chart == null) return;
|
||||||
|
|
||||||
|
// 如果已经初始化过,先清除
|
||||||
|
if (charts.ContainsKey(chart))
|
||||||
{
|
{
|
||||||
ColumnData = new List<double> { 20, 10, 12, 5, 9 },
|
charts.Remove(chart);
|
||||||
Labels = labels.ToList(),
|
}
|
||||||
LineConfigs = new List<LineConfig>
|
|
||||||
{
|
var data = new ChartData();
|
||||||
new LineConfig { Title = "标准1", Values = Enumerable.Repeat(5.0,5).ToList(), Stroke = Brushes.Blue },
|
data.ColumnSeries = new ColumnSeries
|
||||||
new LineConfig { Title = "标准2", Values = Enumerable.Repeat(10.0,5).ToList(), Stroke = Brushes.Green },
|
{
|
||||||
new LineConfig { Title = "标准3", Values = Enumerable.Repeat(30.0,5).ToList(), Stroke = Brushes.Red, Unit="A" }
|
Title = "实时值",
|
||||||
}
|
Values = new ChartValues<double>()
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var chart in charts)
|
var line1 = new LineSeries { Title = "标准下限", Values = data.StandardMin };
|
||||||
|
var line2 = new LineSeries { Title = "标准均值", Values = data.StandardAvg };
|
||||||
|
var line3 = new LineSeries { Title = "标准上限", Values = data.StandardMax };
|
||||||
|
|
||||||
|
chart.Series = new SeriesCollection { data.ColumnSeries, line1, line2, line3 };
|
||||||
|
|
||||||
|
chart.AxisX.Clear();
|
||||||
|
chart.AxisY.Clear();
|
||||||
|
|
||||||
|
chart.AxisX.Add(new Axis
|
||||||
{
|
{
|
||||||
InitChart.InitCartesianChart(chart, config);
|
Title = "时间",
|
||||||
|
Labels = data.Labels
|
||||||
|
});
|
||||||
|
|
||||||
|
chart.AxisY.Add(new Axis
|
||||||
|
{
|
||||||
|
Title = "数值"
|
||||||
|
});
|
||||||
|
|
||||||
|
charts[chart] = data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 接收到传感器实时数据(单点更新)
|
||||||
|
/// </summary>
|
||||||
|
private void OnSensorDataReceived(object sender, GeneralEventArgs e)
|
||||||
|
{
|
||||||
|
if (e is SensorDataEventArgs sensorArgs)
|
||||||
|
{
|
||||||
|
string chartTitle = sensorArgs.ChartTitle; // 例如 "myChart1"
|
||||||
|
double value = sensorArgs.SensorValue;
|
||||||
|
string timeLabel = DateTime.Now.ToString("HH:mm:ss");
|
||||||
|
|
||||||
|
// 找到对应图表并更新
|
||||||
|
foreach (var chart in charts.Keys)
|
||||||
|
{
|
||||||
|
if (chart.Name == chartTitle)
|
||||||
|
{
|
||||||
|
UpdateChartPoint(chart, timeLabel, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 动态更新图表数据(线程安全)
|
/// <summary>
|
||||||
/// </summary>
|
/// 更新单个图表的数据点(柱状图 + 标准线 + X轴标签)
|
||||||
public void UpdateChart(CartesianChart chart, List<double> columnData, List<LineConfig> lineData)
|
/// </summary>
|
||||||
|
public void UpdateChartPoint(CartesianChart chart, string label, double value)
|
||||||
|
{
|
||||||
|
if (chart == null || !charts.TryGetValue(chart, out var data))
|
||||||
|
return;
|
||||||
|
|
||||||
|
dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
dispatcher.Invoke(() =>
|
// 保留四位小数
|
||||||
{
|
double roundedValue = Math.Round(value, 4);
|
||||||
var config = new ChartConfig
|
data.ColumnSeries.Values.Add(roundedValue);
|
||||||
{
|
// 对标准线固定值,强制 double
|
||||||
ColumnData = columnData,
|
data.StandardMin.Add(Math.Round((double)5, 4));
|
||||||
Labels = chart.AxisX[0].Labels.ToList(),
|
data.StandardAvg.Add(Math.Round((double)10, 4));
|
||||||
LineConfigs = lineData
|
data.StandardMax.Add(Math.Round((double)30, 4));
|
||||||
};
|
data.Labels.Add(label);
|
||||||
InitChart.InitCartesianChart(chart, config);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
// 超过最大点数时,移除最旧的数据
|
||||||
/// 模拟后台数据采集并实时刷新图表
|
if (data.ColumnSeries.Values.Count > MAX_POINTS)
|
||||||
/// </summary>
|
{
|
||||||
public void StartAutoUpdate(CartesianChart chart, CancellationToken token)
|
data.ColumnSeries.Values.RemoveAt(0);
|
||||||
|
data.StandardMin.RemoveAt(0);
|
||||||
|
data.StandardAvg.RemoveAt(0);
|
||||||
|
data.StandardMax.RemoveAt(0);
|
||||||
|
data.Labels.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新 X 轴标签
|
||||||
|
chart.AxisX[0].Labels = new List<string>(data.Labels);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 手动添加数据到指定图表
|
||||||
|
/// </summary>
|
||||||
|
public void AddData(CartesianChart chart, double value, string label)
|
||||||
|
{
|
||||||
|
UpdateChartPoint(chart, label, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 手动清除指定图表的数据
|
||||||
|
/// </summary>
|
||||||
|
public void ClearChart(CartesianChart chart)
|
||||||
|
{
|
||||||
|
if (chart == null || !charts.TryGetValue(chart, out var data))
|
||||||
|
return;
|
||||||
|
|
||||||
|
dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
data.ColumnSeries.Values.Clear();
|
||||||
{
|
data.StandardMin.Clear();
|
||||||
var rand = new Random();
|
data.StandardAvg.Clear();
|
||||||
|
data.StandardMax.Clear();
|
||||||
|
data.Labels.Clear();
|
||||||
|
chart.AxisX[0].Labels.Clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
while (!token.IsCancellationRequested)
|
/// <summary>
|
||||||
{
|
/// 清除所有图表
|
||||||
// 模拟采集数据
|
/// </summary>
|
||||||
var columnData = Enumerable.Range(0, 5).Select(_ => rand.NextDouble() * 50).ToList();
|
public void ClearAllCharts()
|
||||||
// 这里实时获取从SensorChartManager中
|
{
|
||||||
var lineData = new List<LineConfig>
|
foreach (var chart in charts.Keys)
|
||||||
{
|
{
|
||||||
//new LineConfig { Title = "标准1", Values = Enumerable.Range(0,5).Select(_ => rand.NextDouble()*20).ToList(), Stroke = Brushes.Blue },
|
ClearChart(chart);
|
||||||
//new LineConfig { Title = "标准2", Values = Enumerable.Range(0,5).Select(_ => rand.NextDouble()*30).ToList(), Stroke = Brushes.Green },
|
|
||||||
//new LineConfig { Title = "标准3", Values = Enumerable.Range(0,5).Select(_ => rand.NextDouble()*40).ToList(), Stroke = Brushes.Yellow }
|
|
||||||
new LineConfig { Title = "标准1", Values = new List<double> { 10, 10, 10, 10, 10 }, Stroke = Brushes.Blue },
|
|
||||||
new LineConfig { Title = "标准2", Values = new List<double> { 20, 20, 20, 20, 20 }, Stroke = Brushes.Green },
|
|
||||||
new LineConfig { Title = "标准3", Values = new List<double> { 30, 30, 30, 30, 30 }, Stroke = Brushes.Yellow }
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新图表(通过 Dispatcher 保证线程安全)
|
|
||||||
UpdateChart(chart, columnData, lineData);
|
|
||||||
|
|
||||||
await Task.Delay(6000); // 每秒更新一次
|
|
||||||
}
|
|
||||||
}, token);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订阅传感器数据事件
|
||||||
|
/// </summary>
|
||||||
|
private void SubscribeToSensorDataEvents()
|
||||||
|
{
|
||||||
|
even?.AddEventHandler(SENSOR_DATA_EVENT, OnSensorDataReceived);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,77 +2,94 @@
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using WpfApp.src.components;
|
using WpfApp.src.components;
|
||||||
|
|
||||||
namespace WpfApp.Services
|
namespace WpfApp.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SensorChart 管理器 - 负责传感器数据采集和更新
|
||||||
|
/// </summary>
|
||||||
|
public class SensorChartManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly Window dispatcherOwner;
|
||||||
/// SensorChart 管理器 - 负责传感器数据采集和更新
|
private CancellationTokenSource cts;
|
||||||
/// </summary>
|
private readonly Random rand = new Random();
|
||||||
public class SensorChartManager
|
private readonly LogService log;
|
||||||
|
private readonly DatabaseService db;
|
||||||
|
private readonly EventService<GeneralEventArgs> even;
|
||||||
|
|
||||||
|
// 事件名称常量
|
||||||
|
private const string SENSOR_DATA_EVENT = "SensorDataUpdate";
|
||||||
|
|
||||||
|
|
||||||
|
// 绑定的传感器控件
|
||||||
|
public SensorChart Sensor1 { get; set; }
|
||||||
|
public SensorChart Sensor2 { get; set; }
|
||||||
|
public SensorChart Sensor3 { get; set; }
|
||||||
|
|
||||||
|
public SensorChartManager(Window owner, LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> eventService)
|
||||||
{
|
{
|
||||||
private readonly Window dispatcherOwner;
|
dispatcherOwner = owner;
|
||||||
private CancellationTokenSource cts;
|
log = logService;
|
||||||
private readonly Random rand = new Random();
|
db = databaseService;
|
||||||
private readonly LogService log;
|
even = eventService;
|
||||||
private readonly DatabaseService db;
|
}
|
||||||
private readonly EventService<GeneralEventArgs> even;
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 启动模拟数据采集
|
||||||
|
/// </summary>
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
if (Sensor1 == null || Sensor2 == null || Sensor3 == null)
|
||||||
|
throw new InvalidOperationException("请先绑定传感器控件");
|
||||||
|
|
||||||
// 绑定的传感器控件
|
cts = new CancellationTokenSource();
|
||||||
public SensorChart Sensor1 { get; set; }
|
|
||||||
public SensorChart Sensor2 { get; set; }
|
|
||||||
public SensorChart Sensor3 { get; set; }
|
|
||||||
|
|
||||||
public SensorChartManager(Window owner)
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
dispatcherOwner = owner;
|
while (!cts.Token.IsCancellationRequested)
|
||||||
}
|
|
||||||
public SensorChartManager(LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> eventService)
|
|
||||||
{
|
|
||||||
log = logService;
|
|
||||||
db = databaseService;
|
|
||||||
even = eventService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 启动模拟数据采集
|
|
||||||
/// </summary>
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
if (Sensor1 == null || Sensor2 == null || Sensor3 == null)
|
|
||||||
throw new InvalidOperationException("请先绑定传感器控件");
|
|
||||||
|
|
||||||
cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
{
|
||||||
while (!cts.Token.IsCancellationRequested)
|
// 模拟数据
|
||||||
|
double s1 = rand.NextDouble() * 100 - 50;
|
||||||
|
double s2 = rand.NextDouble() * 100 - 50;
|
||||||
|
double s3 = rand.NextDouble() * 100 - 50;
|
||||||
|
|
||||||
|
// 更新 UI
|
||||||
|
dispatcherOwner.Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
// 模拟数据
|
Sensor1.SetSensorData("传感器1", s1);
|
||||||
double s1 = rand.NextDouble() * 100 - 50;
|
Sensor2.SetSensorData("传感器2", s2);
|
||||||
double s2 = rand.NextDouble() * 100 - 50;
|
Sensor3.SetSensorData("传感器3", s3);
|
||||||
double s3 = rand.NextDouble() * 100 - 50;
|
|
||||||
|
// 通过事件将传感器数据传递到ChartManager
|
||||||
|
PublishSensorData("传感器1", s1, "myChart1");
|
||||||
|
PublishSensorData("传感器2", s2, "myChart2");
|
||||||
|
PublishSensorData("传感器3", s3, "myChart3");
|
||||||
|
});
|
||||||
|
|
||||||
// 更新 UI
|
await Task.Delay(1000); // 每1000毫秒采集一次
|
||||||
dispatcherOwner.Dispatcher.Invoke(() =>
|
}
|
||||||
{
|
}, cts.Token);
|
||||||
Sensor1.SetSensorData("传感器1", s1);
|
}
|
||||||
Sensor2.SetSensorData("传感器2", s2);
|
|
||||||
Sensor3.SetSensorData("传感器3", s3);
|
|
||||||
// 这里应当跨线程将传感器1 2 3的同时将实时值传递到ChartManger中
|
|
||||||
|
|
||||||
});
|
/// <summary>
|
||||||
|
/// 停止采集
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
cts?.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
await Task.Delay(1000); // 每1000毫秒采集一次
|
/// <summary>
|
||||||
}
|
/// 发布传感器数据事件
|
||||||
}, cts.Token);
|
/// </summary>
|
||||||
}
|
/// <param name="sensorTitle">传感器标题</param>
|
||||||
|
/// <param name="sensorValue">传感器值</param>
|
||||||
/// <summary>
|
/// <param name="chartTitle">图表标题</param>
|
||||||
/// 停止采集
|
private void PublishSensorData(string sensorTitle, double sensorValue, string chartTitle)
|
||||||
/// </summary>
|
{
|
||||||
public void Stop()
|
if (even != null)
|
||||||
{
|
{
|
||||||
cts?.Cancel();
|
var eventArgs = new SensorDataEventArgs(sensorTitle, sensorValue, chartTitle);
|
||||||
|
even.TriggerEvent(SENSOR_DATA_EVENT, this, eventArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
Services/SensorDataEventArgs.cs
Normal file
39
Services/SensorDataEventArgs.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
using guoke;
|
||||||
|
|
||||||
|
namespace WpfApp.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 传感器数据事件参数类,用于传递传感器的实时数据
|
||||||
|
/// </summary>
|
||||||
|
public class SensorDataEventArgs : GeneralEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 传感器标题/名称
|
||||||
|
/// </summary>
|
||||||
|
public string SensorTitle { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 传感器实时值
|
||||||
|
/// </summary>
|
||||||
|
public double SensorValue { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图表标题,用于区分不同的图表
|
||||||
|
/// </summary>
|
||||||
|
public string ChartTitle { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化传感器数据事件参数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sensorTitle">传感器标题</param>
|
||||||
|
/// <param name="sensorValue">传感器实时值</param>
|
||||||
|
/// <param name="chartTitle">图表标题</param>
|
||||||
|
public SensorDataEventArgs(string sensorTitle, double sensorValue, string chartTitle)
|
||||||
|
: base($"传感器数据更新: {sensorTitle}", sensorValue)
|
||||||
|
{
|
||||||
|
SensorTitle = sensorTitle;
|
||||||
|
SensorValue = sensorValue;
|
||||||
|
ChartTitle = chartTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,13 @@
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="新文件夹\**" />
|
||||||
|
<EmbeddedResource Remove="新文件夹\**" />
|
||||||
|
<None Remove="新文件夹\**" />
|
||||||
|
<Page Remove="新文件夹\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="src\public\Icons\main1-file-icon.png" />
|
<None Remove="src\public\Icons\main1-file-icon.png" />
|
||||||
<None Remove="src\public\Icons\main2-config-icon.png" />
|
<None Remove="src\public\Icons\main2-config-icon.png" />
|
||||||
|
|
@ -67,7 +74,6 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="src\public\Excel\" />
|
<Folder Include="src\public\Excel\" />
|
||||||
<Folder Include="新文件夹\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,14 @@
|
||||||
"Connection": "DataSource=LocalData.db",
|
"Connection": "DataSource=LocalData.db",
|
||||||
"Remarks": "",
|
"Remarks": "",
|
||||||
"Print": false
|
"Print": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "D1",
|
||||||
|
"Enabled": true,
|
||||||
|
"Type": 2,
|
||||||
|
"Connection": "DataSource=D1.db",
|
||||||
|
"Remarks": "产品数据库",
|
||||||
|
"Print": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Windows;
|
using guoke;
|
||||||
|
using System.Windows;
|
||||||
using WpfApp.src.view;
|
using WpfApp.src.view;
|
||||||
using WpfApp.Utils;
|
using WpfApp.Utils;
|
||||||
|
|
||||||
|
|
@ -10,9 +11,14 @@ namespace WpfApp.src.controllers
|
||||||
public class MenuController
|
public class MenuController
|
||||||
{
|
{
|
||||||
private readonly Window mainWindow;
|
private readonly Window mainWindow;
|
||||||
|
private readonly LogService log;
|
||||||
public MenuController(Window window)
|
private readonly DatabaseService db;
|
||||||
|
private readonly EventService<GeneralEventArgs> even;
|
||||||
|
public MenuController(Window window, LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> eventService)
|
||||||
{
|
{
|
||||||
|
log = logService;
|
||||||
|
db = databaseService;
|
||||||
|
even = eventService;
|
||||||
mainWindow = window;
|
mainWindow = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,7 +38,7 @@ namespace WpfApp.src.controllers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void OpenConfigPage()
|
public void OpenConfigPage()
|
||||||
{
|
{
|
||||||
WindowHelper.ShowPageDialog(new ConfigPage(),
|
WindowHelper.ShowPageDialog(new ConfigPage(log, db, even),
|
||||||
"配置", 972, 648,
|
"配置", 972, 648,
|
||||||
isResizable: false,
|
isResizable: false,
|
||||||
IconHelper.GetIconPath("main2-Config.ico"));
|
IconHelper.GetIconPath("main2-Config.ico"));
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -43,8 +43,8 @@
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="产品名称" FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,10,0"/>
|
<TextBlock Text="产品名称" FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,10,0"/>
|
||||||
<TextBox Grid.Column="1" Text="DFPV C15TE" Height="30" Background="#E6F3FF" VerticalContentAlignment="Center"/>
|
<TextBox Grid.Column="1" x:Name="ProductNameTextBox" Text="DFPV C15TE" Height="30" Background="#E6F3FF" VerticalContentAlignment="Center"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
|
@ -63,10 +63,10 @@
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<CheckBox Grid.Row="0" Grid.Column="0" Content="数字传感器1" IsChecked="True" Margin="5"/>
|
<CheckBox x:Name="chkDigitalSensor1" Grid.Row="0" Grid.Column="0" Content="数字传感器1" IsChecked="True" Margin="5"/>
|
||||||
<CheckBox Grid.Row="0" Grid.Column="1" Content="数字传感器2" IsChecked="True" Margin="5"/>
|
<CheckBox x:Name="chkDigitalSensor2" Grid.Row="0" Grid.Column="1" Content="数字传感器2" IsChecked="True" Margin="5"/>
|
||||||
<CheckBox Grid.Row="1" Grid.Column="0" Content="数字传感器3" IsChecked="True" Margin="5"/>
|
<CheckBox x:Name="chkDigitalSensor3" Grid.Row="1" Grid.Column="0" Content="数字传感器3" IsChecked="True" Margin="5"/>
|
||||||
<CheckBox Grid.Row="1" Grid.Column="1" Content="数字传感器4" Margin="5"/>
|
<CheckBox x:Name="chkDigitalSensor4" Grid.Row="1" Grid.Column="1" Content="数字传感器4" Margin="5"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
@ -141,10 +141,10 @@
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<RadioButton Grid.Row="0" Grid.Column="0" Content="数字传感器1" IsChecked="True" GroupName="MainSensor" Margin="5"/>
|
<RadioButton x:Name="chkDigitalMainSensor1" Grid.Row="0" Grid.Column="0" Content="数字传感器1" IsChecked="True" GroupName="MainSensor" Margin="5"/>
|
||||||
<RadioButton Grid.Row="0" Grid.Column="1" Content="数字传感器2" GroupName="MainSensor" Margin="5"/>
|
<RadioButton x:Name="chkDigitalMainSensor2" Grid.Row="0" Grid.Column="1" Content="数字传感器2" GroupName="MainSensor" Margin="5"/>
|
||||||
<RadioButton Grid.Row="1" Grid.Column="0" Content="数字传感器3" GroupName="MainSensor" Margin="5"/>
|
<RadioButton x:Name="chkDigitalMainSensor3" Grid.Row="1" Grid.Column="0" Content="数字传感器3" GroupName="MainSensor" Margin="5"/>
|
||||||
<RadioButton Grid.Row="1" Grid.Column="1" Content="数字传感器4" GroupName="MainSensor" Margin="5"/>
|
<RadioButton x:Name="chkDigitalMainSensor4" Grid.Row="1" Grid.Column="1" Content="数字传感器4" GroupName="MainSensor" Margin="5"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
@ -215,11 +215,11 @@
|
||||||
Background="#333333" Foreground="White" HorizontalAlignment="Center" Margin="0,30,0,0"/>
|
Background="#333333" Foreground="White" HorizontalAlignment="Center" Margin="0,30,0,0"/>
|
||||||
|
|
||||||
<!-- 数值行 -->
|
<!-- 数值行 -->
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="下限" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,30,0,0" />
|
<TextBlock Grid.Row="1" Grid.Column="0" x:Name="LowerLimitTextBlock" Text="下限" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,30,0,0" />
|
||||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="<" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16" Margin="0,30,0,0"/>
|
<TextBlock Grid.Row="1" Grid.Column="1" Text="<" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16" Margin="0,30,0,0"/>
|
||||||
<TextBox Grid.Row="1" Grid.Column="2" Text="-0.0090" Height="30" Background="#E6F3FF" HorizontalAlignment="Center" Width="100" Margin="0,30,0,0"/>
|
<TextBox Grid.Row="1" Grid.Column="2" x:Name="HighLimitTextBox" Text="-0.0090" Height="30" Background="#E6F3FF" HorizontalAlignment="Center" Width="100" Margin="0,30,0,0"/>
|
||||||
<Border Grid.Row="1" Grid.Column="3" Background="#CCCCCC" Height="30" Width="50" Margin="0,30,0,0">
|
<Border Grid.Row="1" Grid.Column="3" Background="#CCCCCC" Height="30" Width="50" Margin="0,30,0,0">
|
||||||
<TextBlock Text="NG" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold"/>
|
<TextBlock x:Name="UnitMarkTextBlock" Text="NG" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold"/>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
@ -234,7 +234,7 @@
|
||||||
<!-- 底部按钮区域 -->
|
<!-- 底部按钮区域 -->
|
||||||
<Border Grid.Row="1" Background="#E0E0E0" BorderBrush="#CCCCCC" BorderThickness="0,1,0,0">
|
<Border Grid.Row="1" Background="#E0E0E0" BorderBrush="#CCCCCC" BorderThickness="0,1,0,0">
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="20,0">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="20,0">
|
||||||
<Button Content="保存" Width="80" Height="35" Background="#90EE90" Margin="10,0"/>
|
<Button Click="CreateOrUpdateData_Click" Content="保存" Width="80" Height="35" Background="#90EE90" Margin="10,0"/>
|
||||||
<Button Content="取消" Width="80" Height="35" Background="#F0F0F0" Margin="10,0"/>
|
<Button Content="取消" Width="80" Height="35" Background="#F0F0F0" Margin="10,0"/>
|
||||||
<Button Content="完成" Width="80" Height="35" Background="#F0F0F0" Margin="10,0"/>
|
<Button Content="完成" Width="80" Height="35" Background="#F0F0F0" Margin="10,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
|
||||||
|
|
@ -1,137 +1,508 @@
|
||||||
using System;
|
using guoke;
|
||||||
using System.Collections.Generic;
|
using SqlSugar;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using WpfApp.src.model;
|
||||||
using System.Windows.Navigation;
|
namespace WpfApp.src.view;
|
||||||
using System.Windows.Shapes;
|
|
||||||
|
|
||||||
namespace WpfApp.src.view
|
/// <summary>
|
||||||
|
/// ConfigPage.xaml 的交互逻辑
|
||||||
|
/// </summary>
|
||||||
|
public partial class ConfigPage : Page
|
||||||
{
|
{
|
||||||
/// <summary>
|
// 等级数据字典,每个等级对应 LevelInfo
|
||||||
/// ConfigPage.xaml 的交互逻辑
|
private Dictionary<string, LevelInfo> levelData;
|
||||||
/// </summary>
|
private Dictionary<int, SensorToleranceData> sensorData;
|
||||||
public partial class ConfigPage : Page
|
private readonly LogService log;
|
||||||
{
|
private readonly DatabaseService db;
|
||||||
// 传感器数据字典,存储每个传感器的公差设定值
|
private readonly EventService<GeneralEventArgs> even;
|
||||||
private Dictionary<int, SensorToleranceData> sensorData;
|
|
||||||
|
|
||||||
public ConfigPage()
|
public ConfigPage(LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> eventService)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
log = logService;
|
||||||
|
db = databaseService;
|
||||||
|
even = eventService;
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
scope.guokeCheckToCreate<Product>();
|
||||||
|
scope.guokeCheckToCreate<SensorSelection>();
|
||||||
|
scope.guokeCheckToCreate<SensorToleranceData>();
|
||||||
|
scope.guokeCheckToCreate<MainSensorSelection>();
|
||||||
|
scope.guokeCheckToCreate<LevelInfo>();
|
||||||
|
|
||||||
|
// 传感器选择
|
||||||
|
LoadSensorSelectionFromDb();
|
||||||
|
// 传感器公差
|
||||||
|
InitializeSensorData();
|
||||||
|
// 主传感器选择
|
||||||
|
LoadMainSensorSelectionFromDb();
|
||||||
|
// 等级
|
||||||
|
InitializeLevelData();
|
||||||
|
// 加载产品名称
|
||||||
|
LoadProductGroupName();
|
||||||
|
|
||||||
|
|
||||||
|
// 注册等级标签按钮点击事件
|
||||||
|
LevelTabUnder.Click += LevelTab_Click;
|
||||||
|
LevelTabA.Click += LevelTab_Click;
|
||||||
|
LevelTabB.Click += LevelTab_Click;
|
||||||
|
LevelTabC.Click += LevelTab_Click;
|
||||||
|
LevelTabD.Click += LevelTab_Click;
|
||||||
|
LevelTabE.Click += LevelTab_Click;
|
||||||
|
LevelTabF.Click += LevelTab_Click;
|
||||||
|
LevelTabG.Click += LevelTab_Click;
|
||||||
|
LevelTabOver.Click += LevelTab_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 第一部分 组名
|
||||||
|
// 加载产品名称
|
||||||
|
private void LoadProductGroupName() {
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
var ProductGroupName = scope.Queryable<Product>().First();
|
||||||
|
if (ProductGroupName != null) {
|
||||||
|
LoadProductGroup(ProductGroupName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadProductGroup(Product product)
|
||||||
|
{
|
||||||
|
ProductNameTextBox.Text = product.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveProductGroupNameToDb()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 第二部分 多选
|
||||||
|
// 从数据库加载传感器选择
|
||||||
|
private void LoadSensorSelectionFromDb()
|
||||||
|
{
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
// 假设只取第一个产品的主传感器数据
|
||||||
|
var mainSensor = scope.Queryable<SensorSelection>().First();
|
||||||
|
if (mainSensor != null)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
LoadSensorSelection(mainSensor);
|
||||||
InitializeSensorData();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 每次 CheckBox 状态改变保存到数据库
|
||||||
|
private void Sensor_CheckedChanged(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
SaveSensorToDb();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 将数据库中的主传感器数据加载到界面 CheckBox
|
||||||
|
/// </summary>
|
||||||
|
private void LoadSensorSelection(SensorSelection data)
|
||||||
|
{
|
||||||
|
chkDigitalSensor1.IsChecked = data.Sensor1;
|
||||||
|
chkDigitalSensor2.IsChecked = data.Sensor2;
|
||||||
|
chkDigitalSensor3.IsChecked = data.Sensor3;
|
||||||
|
chkDigitalSensor4.IsChecked = data.Sensor4;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 保存界面 CheckBox 状态到数据库
|
||||||
|
/// </summary>
|
||||||
|
private void SaveSensorToDb()
|
||||||
|
{
|
||||||
|
var data = new SensorSelection
|
||||||
|
{
|
||||||
|
Sensor1 = chkDigitalSensor1.IsChecked == true,
|
||||||
|
Sensor2 = chkDigitalSensor2.IsChecked == true,
|
||||||
|
Sensor3 = chkDigitalSensor3.IsChecked == true,
|
||||||
|
Sensor4 = chkDigitalSensor4.IsChecked == true,
|
||||||
|
ProductName = "默认产品名" // 可以根据实际情况设置
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
|
||||||
|
// 如果数据库已存在该产品的主传感器数据,则更新,否则插入
|
||||||
|
var exist = scope.Queryable<SensorSelection>()
|
||||||
|
.Where(s => s.ProductName == data.ProductName)
|
||||||
|
.First();
|
||||||
|
|
||||||
|
if (exist != null)
|
||||||
|
{
|
||||||
|
data.Id = exist.Id; // 设置 Id 才能更新
|
||||||
|
scope.Updateable(data).ExecuteCommand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scope.Insertable(data).ExecuteCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化传感器数据
|
log.Info($"保存传感器选择:{data.ProductName}");
|
||||||
private void InitializeSensorData()
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 第三部分 公差
|
||||||
|
// 初始化传感器数据
|
||||||
|
private void InitializeSensorData()
|
||||||
|
{
|
||||||
|
sensorData = new Dictionary<int, SensorToleranceData>();
|
||||||
|
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
if (scope == null)
|
||||||
{
|
{
|
||||||
sensorData = new Dictionary<int, SensorToleranceData>
|
MessageBox.Show("SqlSugarScope 获取失败!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string productName = "DFPV C15TE"; // TODO: 根据实际选择的产品替换
|
||||||
|
|
||||||
|
// 查询数据库
|
||||||
|
var sensors = scope.Queryable<SensorToleranceData>()
|
||||||
|
.Where(s => s.ProductName == productName)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
for (int i = 1; i <= 4; i++)
|
||||||
|
{
|
||||||
|
var sensor = sensors.FirstOrDefault(s => s.SensorName == $"传感器{i}");
|
||||||
|
sensorData[i] = sensor ?? new SensorToleranceData
|
||||||
{
|
{
|
||||||
{ 1, new SensorToleranceData { MaxTolerance = "9.00", BaseTolerance = "72.9410", MinTolerance = "-9.00" } },
|
SensorName = $"传感器{i}",
|
||||||
{ 2, new SensorToleranceData { MaxTolerance = "8.50", BaseTolerance = "72.8500", MinTolerance = "-8.50" } },
|
MaxTolerance = "0.00",
|
||||||
{ 3, new SensorToleranceData { MaxTolerance = "7.80", BaseTolerance = "72.7800", MinTolerance = "-7.80" } },
|
BaseTolerance = "0.00",
|
||||||
{ 4, new SensorToleranceData { MaxTolerance = "6.90", BaseTolerance = "72.6900", MinTolerance = "-6.90" } }
|
MinTolerance = "0.00",
|
||||||
|
ProductName = productName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 传感器标签页点击事件处理
|
// 加载第一个传感器数据到界面
|
||||||
private void SensorTab_Click(object sender, RoutedEventArgs e)
|
LoadSensorData(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签切换事件(只加载,不保存)
|
||||||
|
private void SensorTab_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is Button clickedButton && int.TryParse(clickedButton.Tag?.ToString(), out int sensorIndex))
|
||||||
{
|
{
|
||||||
Button clickedButton = sender as Button;
|
|
||||||
if (clickedButton == null) return;
|
|
||||||
|
|
||||||
int sensorIndex = int.Parse(clickedButton.Tag.ToString());
|
|
||||||
|
|
||||||
// 保存当前传感器的数据
|
|
||||||
SaveCurrentSensorData();
|
|
||||||
|
|
||||||
// 更新标签页样式
|
|
||||||
UpdateTabStyles(sensorIndex);
|
UpdateTabStyles(sensorIndex);
|
||||||
|
|
||||||
// 加载选中传感器的数据
|
|
||||||
LoadSensorData(sensorIndex);
|
LoadSensorData(sensorIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存当前传感器的数据
|
|
||||||
private void SaveCurrentSensorData()
|
|
||||||
{
|
|
||||||
// 获取当前选中的传感器索引
|
|
||||||
int currentSensorIndex = GetCurrentSelectedSensorIndex();
|
|
||||||
|
|
||||||
if (sensorData.ContainsKey(currentSensorIndex))
|
|
||||||
{
|
|
||||||
sensorData[currentSensorIndex].MaxTolerance = MaxToleranceTextBox.Text;
|
|
||||||
sensorData[currentSensorIndex].BaseTolerance = BaseToleranceTextBox.Text;
|
|
||||||
sensorData[currentSensorIndex].MinTolerance = MinToleranceTextBox.Text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前选中的传感器索引
|
|
||||||
private int GetCurrentSelectedSensorIndex()
|
|
||||||
{
|
|
||||||
if (SensorTab1.Background is SolidColorBrush brush1 && brush1.Color == ((SolidColorBrush)new BrushConverter().ConvertFrom("#E6F3FF")).Color)
|
|
||||||
return 1;
|
|
||||||
if (SensorTab2.Background is SolidColorBrush brush2 && brush2.Color == ((SolidColorBrush)new BrushConverter().ConvertFrom("#E6F3FF")).Color)
|
|
||||||
return 2;
|
|
||||||
if (SensorTab3.Background is SolidColorBrush brush3 && brush3.Color == ((SolidColorBrush)new BrushConverter().ConvertFrom("#E6F3FF")).Color)
|
|
||||||
return 3;
|
|
||||||
if (SensorTab4.Background is SolidColorBrush brush4 && brush4.Color == ((SolidColorBrush)new BrushConverter().ConvertFrom("#E6F3FF")).Color)
|
|
||||||
return 4;
|
|
||||||
return 1; // 默认返回传感器1
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新标签页样式
|
|
||||||
private void UpdateTabStyles(int selectedIndex)
|
|
||||||
{
|
|
||||||
// 重置所有标签页样式
|
|
||||||
SensorTab1.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F0F0F0"));
|
|
||||||
SensorTab2.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F0F0F0"));
|
|
||||||
SensorTab3.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F0F0F0"));
|
|
||||||
SensorTab4.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F0F0F0"));
|
|
||||||
|
|
||||||
// 设置选中标签页样式
|
|
||||||
switch (selectedIndex)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
SensorTab1.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E6F3FF"));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
SensorTab2.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E6F3FF"));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
SensorTab3.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E6F3FF"));
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
SensorTab4.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E6F3FF"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载传感器数据
|
|
||||||
private void LoadSensorData(int sensorIndex)
|
|
||||||
{
|
|
||||||
if (sensorData.ContainsKey(sensorIndex))
|
|
||||||
{
|
|
||||||
var data = sensorData[sensorIndex];
|
|
||||||
MaxToleranceTextBox.Text = data.MaxTolerance;
|
|
||||||
BaseToleranceTextBox.Text = data.BaseTolerance;
|
|
||||||
MinToleranceTextBox.Text = data.MinTolerance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 传感器公差数据类
|
// 更新标签页样式
|
||||||
public class SensorToleranceData
|
private void UpdateTabStyles(int selectedIndex)
|
||||||
{
|
{
|
||||||
public string MaxTolerance { get; set; }
|
var buttons = new[] { SensorTab1, SensorTab2, SensorTab3, SensorTab4 };
|
||||||
public string BaseTolerance { get; set; }
|
for (int i = 0; i < buttons.Length; i++)
|
||||||
public string MinTolerance { get; set; }
|
{
|
||||||
|
buttons[i].Background = (i + 1 == selectedIndex)
|
||||||
|
? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E6F3FF"))
|
||||||
|
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F0F0F0"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// 加载数据到界面
|
||||||
|
private void LoadSensorData(int sensorIndex)
|
||||||
|
{
|
||||||
|
if (sensorData.ContainsKey(sensorIndex) &&
|
||||||
|
MaxToleranceTextBox != null &&
|
||||||
|
BaseToleranceTextBox != null &&
|
||||||
|
MinToleranceTextBox != null)
|
||||||
|
{
|
||||||
|
var data = sensorData[sensorIndex];
|
||||||
|
MaxToleranceTextBox.Text = data.MaxTolerance;
|
||||||
|
BaseToleranceTextBox.Text = data.BaseTolerance;
|
||||||
|
MinToleranceTextBox.Text = data.MinTolerance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存按钮事件
|
||||||
|
private void SaveButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
int currentSensorIndex = GetCurrentSelectedSensorIndex();
|
||||||
|
|
||||||
|
// 保存当前界面数据到字典
|
||||||
|
if (sensorData.ContainsKey(currentSensorIndex))
|
||||||
|
{
|
||||||
|
sensorData[currentSensorIndex].MaxTolerance = MaxToleranceTextBox.Text;
|
||||||
|
sensorData[currentSensorIndex].BaseTolerance = BaseToleranceTextBox.Text;
|
||||||
|
sensorData[currentSensorIndex].MinTolerance = MinToleranceTextBox.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写回数据库
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
foreach (var sensor in sensorData.Values)
|
||||||
|
{
|
||||||
|
var exist = scope.Queryable<SensorToleranceData>()
|
||||||
|
.Where(s => s.ProductName == sensor.ProductName && s.SensorName == sensor.SensorName)
|
||||||
|
.First();
|
||||||
|
if (exist != null)
|
||||||
|
{
|
||||||
|
sensor.Id = exist.Id;
|
||||||
|
scope.Updateable(sensor).ExecuteCommand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scope.Insertable(sensor).ExecuteCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBox.Show("保存成功!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前选中的传感器索引
|
||||||
|
private int GetCurrentSelectedSensorIndex()
|
||||||
|
{
|
||||||
|
if (SensorTab1.Background is SolidColorBrush brush1 && brush1.Color == ((SolidColorBrush)new BrushConverter().ConvertFrom("#E6F3FF")).Color)
|
||||||
|
return 1;
|
||||||
|
if (SensorTab2.Background is SolidColorBrush brush2 && brush2.Color == ((SolidColorBrush)new BrushConverter().ConvertFrom("#E6F3FF")).Color)
|
||||||
|
return 2;
|
||||||
|
if (SensorTab3.Background is SolidColorBrush brush3 && brush3.Color == ((SolidColorBrush)new BrushConverter().ConvertFrom("#E6F3FF")).Color)
|
||||||
|
return 3;
|
||||||
|
if (SensorTab4.Background is SolidColorBrush brush4 && brush4.Color == ((SolidColorBrush)new BrushConverter().ConvertFrom("#E6F3FF")).Color)
|
||||||
|
return 4;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存传感器公差数据到数据库
|
||||||
|
private void SaveSensorToleranceDataToDb()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 第四部分 单选
|
||||||
|
// 主传感器
|
||||||
|
private void LoadMainSensorSelectionFromDb()
|
||||||
|
{
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
// 假设只取第一个产品的主传感器数据
|
||||||
|
var mainSensor = scope.Queryable<MainSensorSelection>().First();
|
||||||
|
if (mainSensor != null)
|
||||||
|
{
|
||||||
|
LoadMainSensorSelection(mainSensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将数据库中的主传感器数据加载到界面 CheckBox
|
||||||
|
/// </summary>
|
||||||
|
private void LoadMainSensorSelection(MainSensorSelection data)
|
||||||
|
{
|
||||||
|
chkDigitalMainSensor1.IsChecked = data.DigitalSensor1;
|
||||||
|
chkDigitalMainSensor2.IsChecked = data.DigitalSensor2;
|
||||||
|
chkDigitalMainSensor3.IsChecked = data.DigitalSensor3;
|
||||||
|
chkDigitalMainSensor4.IsChecked = data.DigitalSensor4;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 保存界面 CheckBox 状态到数据库
|
||||||
|
/// </summary>
|
||||||
|
private void SaveMainSensorToDb()
|
||||||
|
{
|
||||||
|
var data = new MainSensorSelection
|
||||||
|
{
|
||||||
|
DigitalSensor1 = chkDigitalMainSensor1.IsChecked == true,
|
||||||
|
DigitalSensor2 = chkDigitalMainSensor2.IsChecked == true,
|
||||||
|
DigitalSensor3 = chkDigitalMainSensor3.IsChecked == true,
|
||||||
|
DigitalSensor4 = chkDigitalMainSensor4.IsChecked == true,
|
||||||
|
ProductName = "默认产品名" // 可以根据实际情况设置
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
|
||||||
|
// 如果数据库已存在该产品的主传感器数据,则更新,否则插入
|
||||||
|
var exist = scope.Queryable<SensorSelection>()
|
||||||
|
.Where(s => s.ProductName == data.ProductName)
|
||||||
|
.First();
|
||||||
|
|
||||||
|
if (exist != null)
|
||||||
|
{
|
||||||
|
data.Id = exist.Id; // 设置 Id 才能更新
|
||||||
|
scope.Updateable(data).ExecuteCommand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scope.Insertable(data).ExecuteCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info($"保存传感器选择:{data.ProductName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 第五部分 等级
|
||||||
|
|
||||||
|
// 初始化等级数据
|
||||||
|
private void InitializeLevelData()
|
||||||
|
{
|
||||||
|
levelData = new Dictionary<string, LevelInfo>();
|
||||||
|
|
||||||
|
SqlSugarScope scope = db.GetScope("D1");
|
||||||
|
if (scope == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show("SqlSugarScope 获取失败!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string productName = "DFPV C15TE"; // TODO: 根据实际选择的产品替换
|
||||||
|
string[] tabs = { "Under", "A", "B", "C", "D", "E", "F", "G", "Over" };
|
||||||
|
|
||||||
|
// 从数据库查询该产品的等级数据
|
||||||
|
var sensorsRank = scope.Queryable<LevelInfo>()
|
||||||
|
.Where(s => s.ProductName == productName)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// 初始化每个等级
|
||||||
|
foreach (var tab in tabs)
|
||||||
|
{
|
||||||
|
var sensorRank = sensorsRank.FirstOrDefault(s => s.Name == tab);
|
||||||
|
if (sensorRank != null)
|
||||||
|
{
|
||||||
|
levelData[tab] = sensorRank;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 没有数据库记录则初始化默认值
|
||||||
|
levelData[tab] = new LevelInfo
|
||||||
|
{
|
||||||
|
Name = tab,
|
||||||
|
Low = "0.0",
|
||||||
|
High = "0.0",
|
||||||
|
Mark = "NG",
|
||||||
|
Status = "NG",
|
||||||
|
ProductName = productName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认加载第一个等级
|
||||||
|
LoadLevelData(tabs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载数据到界面
|
||||||
|
private void LoadLevelData(string sensorIndex)
|
||||||
|
{
|
||||||
|
if (!levelData.ContainsKey(sensorIndex))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var data = levelData[sensorIndex];
|
||||||
|
|
||||||
|
// 加强防护,防止 NullReferenceException
|
||||||
|
if (LowerLimitTextBlock != null)
|
||||||
|
LowerLimitTextBlock.Text = data.Low ?? "下限";
|
||||||
|
|
||||||
|
if (HighLimitTextBox != null)
|
||||||
|
HighLimitTextBox.Text = data.High ?? "0.0";
|
||||||
|
|
||||||
|
if (UnitMarkTextBlock != null)
|
||||||
|
UnitMarkTextBlock.Text = data.Mark ?? "NG";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等级标签按钮点击事件
|
||||||
|
private void LevelTab_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is Button btn && btn.Tag is string tabName)
|
||||||
|
{
|
||||||
|
// 保存当前等级修改
|
||||||
|
SaveCurrentLevelData();
|
||||||
|
|
||||||
|
// 更新标签样式
|
||||||
|
UpdateTabStyles(btn);
|
||||||
|
|
||||||
|
// 加载新等级
|
||||||
|
LoadLevelData(tabName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存当前显示的等级数据
|
||||||
|
private void SaveCurrentLevelData()
|
||||||
|
{
|
||||||
|
string currentTab = GetCurrentSelectedTab();
|
||||||
|
if (currentTab == null || !levelData.ContainsKey(currentTab))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var data = levelData[currentTab];
|
||||||
|
|
||||||
|
// 直接取命名控件的值最稳妥
|
||||||
|
if (LowerLimitTextBlock != null)
|
||||||
|
data.Low = LowerLimitTextBlock.Text ?? "0.0";
|
||||||
|
|
||||||
|
if (HighLimitTextBox != null)
|
||||||
|
data.High = HighLimitTextBox.Text ?? "0.0";
|
||||||
|
|
||||||
|
if (UnitMarkTextBlock != null)
|
||||||
|
data.Mark = UnitMarkTextBlock.Text ?? "NG";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前选中的标签名
|
||||||
|
private string GetCurrentSelectedTab()
|
||||||
|
{
|
||||||
|
if (LevelTabUnder?.Parent is Grid grid)
|
||||||
|
{
|
||||||
|
foreach (var child in grid.Children)
|
||||||
|
{
|
||||||
|
if (child is Button b && b.Background is SolidColorBrush brush)
|
||||||
|
{
|
||||||
|
var activeColor = (Color)ColorConverter.ConvertFromString("#E6F3FF");
|
||||||
|
if (brush.Color == activeColor)
|
||||||
|
return b.Tag?.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新等级标签按钮样式
|
||||||
|
private void UpdateTabStyles(Button selectedBtn)
|
||||||
|
{
|
||||||
|
if (selectedBtn?.Parent is Grid grid)
|
||||||
|
{
|
||||||
|
foreach (var child in grid.Children)
|
||||||
|
{
|
||||||
|
if (child is Button b)
|
||||||
|
{
|
||||||
|
b.Background = (b == selectedBtn)
|
||||||
|
? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E6F3FF")) // 选中浅蓝
|
||||||
|
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F0F0F0")); // 未选灰
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存等级数据到数据库
|
||||||
|
private void SaveLevelDataToDb()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 新建||更新数据
|
||||||
|
private void CreateOrUpdateData_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
MessageBox.Show("保存数据!");
|
||||||
|
// 这里分成四个部分 进行保存判定
|
||||||
|
/*
|
||||||
|
第一部分 默认选择的都是当前数据库数据表中的第一组的数据
|
||||||
|
1、如果没做任何修改 点击修改 应当不往数据库更新数据
|
||||||
|
2、如果仅对数据做了修改那应该更新 组号一样的数据
|
||||||
|
3、如果仅对组号进行了修改那么应当 新建一条组数据 然后 相关联的应当也新增记录
|
||||||
|
4、如果对组号和数据都进行了修改 都新增记录 组号也是修改后的
|
||||||
|
*/
|
||||||
|
// 1-保存产品组名称到数据库
|
||||||
|
SaveProductGroupNameToDb();
|
||||||
|
// 2-保存多选传感器的状态到数据库
|
||||||
|
SaveSensorToDb();
|
||||||
|
// 3-保存传感器公差数据到数据库
|
||||||
|
SaveSensorToleranceDataToDb();
|
||||||
|
// 4-保存单选主传感器的状态到数据库
|
||||||
|
SaveMainSensorToDb();
|
||||||
|
// 5-
|
||||||
|
SaveLevelDataToDb();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user