438 lines
16 KiB
C#
438 lines
16 KiB
C#
using System;
|
||
using System.Collections.ObjectModel;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text.Json;
|
||
using CommunityToolkit.Mvvm.ComponentModel;
|
||
using CommunityToolkit.Mvvm.Input;
|
||
using LiveChartsCore;
|
||
using LiveChartsCore.Defaults;
|
||
using LiveChartsCore.SkiaSharpView;
|
||
using LiveChartsCore.SkiaSharpView.Painting;
|
||
using SkiaSharp;
|
||
|
||
namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModels
|
||
{
|
||
public partial class MainWindowViewModel : ViewModelBase
|
||
{
|
||
private bool isLoadingDeviceSettings;
|
||
|
||
[ObservableProperty]
|
||
private string testNumber = $"SLIP-{DateTime.Now:yyyyMMdd-HHmm}";
|
||
|
||
[ObservableProperty]
|
||
private string operatorName = string.Empty;
|
||
|
||
[ObservableProperty]
|
||
private string methodName = "GB/T 3903.6-2024";
|
||
|
||
[ObservableProperty]
|
||
private string reportName = string.Empty;
|
||
|
||
[ObservableProperty]
|
||
private string sampleFeature = "整鞋样品 / 瓷砖接触面 / 水平测试";
|
||
|
||
[ObservableProperty]
|
||
private string currentStatus = "测试停止,请按“测试”键进行下次试验";
|
||
|
||
[ObservableProperty]
|
||
private int uploadProgress = 68;
|
||
|
||
[ObservableProperty]
|
||
private string manualDistance = "0";
|
||
|
||
[ObservableProperty]
|
||
private int selectedSampleIndex;
|
||
|
||
[ObservableProperty]
|
||
private bool isSettingsDialogOpen;
|
||
|
||
[ObservableProperty]
|
||
private string manualSpeed = "0.00";
|
||
|
||
[ObservableProperty]
|
||
private string manualDisplacement = "0.00";
|
||
|
||
[ObservableProperty]
|
||
private string testSpeed = "0.30";
|
||
|
||
[ObservableProperty]
|
||
private string normalPressureCoefficient = "0.00";
|
||
|
||
[ObservableProperty]
|
||
private string frictionCoefficient1 = "0.00";
|
||
|
||
[ObservableProperty]
|
||
private string frictionCoefficient2 = "0.00";
|
||
|
||
public string TargetLoadText { get; } = "400 N";
|
||
public string ActualLoadText { get; } = "400 N";
|
||
public string TestSpeedText => $"{TestSpeed} m/s";
|
||
public string SampleRateText { get; } = "30 Hz";
|
||
public string ActiveMode { get; } = "水平模式";
|
||
public string DeviceStatus { get; } = "联机 / 待机";
|
||
public string BatchNumber { get; } = DateTime.Now.ToString("yyyy-MM-dd");
|
||
public string ResultSummary { get; } = "平均 0.62";
|
||
public string UploadProgressText => $"{UploadProgress}%";
|
||
public string StaticCoefficient { get; } = "0.66";
|
||
public string VerticalPressure { get; } = "401.6";
|
||
public string HorizontalForce { get; } = "248.9";
|
||
public string FrictionCoefficient { get; } = "0.62";
|
||
public string Distance { get; } = "218.4";
|
||
public string StandardReference { get; } = "GB/T 3903.6-2024 7.1-8:速度、载荷、三次平均与系数计算";
|
||
|
||
public ObservableCollection<TestSample> Samples { get; } =
|
||
[
|
||
new(16, "08:46:35", "0.58", "0.57", "有效"),
|
||
new(15, "08:46:27", "0.71", "0.61", "有效"),
|
||
new(14, "08:46:12", "0.66", "0.66", "有效"),
|
||
new(13, "08:46:04", "0.77", "0.69", "有效"),
|
||
new(12, "08:45:51", "0.62", "0.62", "有效"),
|
||
new(11, "08:45:43", "0.74", "0.64", "有效"),
|
||
new(10, "08:45:28", "0.64", "0.64", "有效"),
|
||
new(9, "08:45:19", "0.73", "0.66", "有效"),
|
||
new(8, "08:45:03", "0.57", "0.56", "有效"),
|
||
new(7, "08:44:49", "0.65", "0.57", "有效"),
|
||
new(6, "08:44:35", "0.56", "0.54", "有效"),
|
||
new(5, "08:44:27", "0.63", "0.56", "有效"),
|
||
new(4, "08:44:09", "0.56", "0.54", "有效"),
|
||
new(3, "08:44:01", "0.63", "0.56", "有效"),
|
||
new(2, "08:43:41", "0.55", "0.52", "有效"),
|
||
new(1, "08:43:33", "0.62", "0.55", "有效"),
|
||
];
|
||
|
||
public DrawMarginFrame ChartFrame { get; } = new()
|
||
{
|
||
Fill = new SolidColorPaint(SKColor.Parse("#FFFFFF")),
|
||
Stroke = new SolidColorPaint(SKColor.Parse("#CBD5E1")) { StrokeThickness = 1.4f }
|
||
};
|
||
|
||
public SolidColorPaint LegendTextPaint { get; } = new(SKColor.Parse("#334155"));
|
||
|
||
public ISeries[] Series { get; } =
|
||
[
|
||
new LineSeries<ObservablePoint>
|
||
{
|
||
Name = "垂直压力(N)",
|
||
Values = CreatePressureSeries(),
|
||
MiniatureShapeSize = 8,
|
||
MiniatureStrokeThickness = 2,
|
||
Stroke = new SolidColorPaint(SKColor.Parse("#DC2626")) { StrokeThickness = 3.6f },
|
||
Fill = new SolidColorPaint(new SKColor(220, 38, 38, 18)),
|
||
GeometryFill = new SolidColorPaint(SKColors.White),
|
||
GeometryStroke = new SolidColorPaint(SKColor.Parse("#DC2626")) { StrokeThickness = 2 },
|
||
GeometrySize = 5,
|
||
LineSmoothness = 0.65,
|
||
ScalesYAt = 0
|
||
},
|
||
new LineSeries<ObservablePoint>
|
||
{
|
||
Name = "水平拉力(N)",
|
||
Values = CreatePullSeries(),
|
||
MiniatureShapeSize = 8,
|
||
MiniatureStrokeThickness = 2,
|
||
Stroke = new SolidColorPaint(SKColor.Parse("#16A34A")) { StrokeThickness = 3.4f },
|
||
Fill = new SolidColorPaint(new SKColor(22, 163, 74, 16)),
|
||
GeometryFill = new SolidColorPaint(SKColors.White),
|
||
GeometryStroke = new SolidColorPaint(SKColor.Parse("#16A34A")) { StrokeThickness = 2 },
|
||
GeometrySize = 5,
|
||
LineSmoothness = 0.65,
|
||
ScalesYAt = 0
|
||
},
|
||
new LineSeries<ObservablePoint>
|
||
{
|
||
Name = "摩擦系数",
|
||
Values = CreateFrictionSeries(),
|
||
MiniatureShapeSize = 8,
|
||
MiniatureStrokeThickness = 2,
|
||
Stroke = new SolidColorPaint(SKColor.Parse("#C026D3")) { StrokeThickness = 3.4f },
|
||
Fill = new SolidColorPaint(new SKColor(192, 38, 211, 16)),
|
||
GeometryFill = new SolidColorPaint(SKColors.White),
|
||
GeometryStroke = new SolidColorPaint(SKColor.Parse("#C026D3")) { StrokeThickness = 2 },
|
||
GeometrySize = 5,
|
||
LineSmoothness = 0.65,
|
||
ScalesYAt = 1
|
||
},
|
||
new LineSeries<ObservablePoint>
|
||
{
|
||
Name = "距离(mm)",
|
||
Values = CreateDistanceSeries(),
|
||
MiniatureShapeSize = 8,
|
||
MiniatureStrokeThickness = 2,
|
||
Stroke = new SolidColorPaint(SKColor.Parse("#2563EB")) { StrokeThickness = 3.2f },
|
||
Fill = new SolidColorPaint(new SKColor(37, 99, 235, 14)),
|
||
GeometryFill = new SolidColorPaint(SKColors.White),
|
||
GeometryStroke = new SolidColorPaint(SKColor.Parse("#2563EB")) { StrokeThickness = 2 },
|
||
GeometrySize = 5,
|
||
LineSmoothness = 0.35,
|
||
ScalesYAt = 0
|
||
}
|
||
];
|
||
|
||
public Axis[] XAxes { get; } =
|
||
[
|
||
new Axis
|
||
{
|
||
Name = "时间(s)",
|
||
MinLimit = -0.10,
|
||
MaxLimit = 0.62,
|
||
UnitWidth = 0.05,
|
||
SeparatorsPaint = new SolidColorPaint(SKColor.Parse("#D7E0EA")) { StrokeThickness = 1 },
|
||
SubseparatorsPaint = new SolidColorPaint(SKColor.Parse("#EEF3F8")) { StrokeThickness = 1 },
|
||
SubseparatorsCount = 4,
|
||
LabelsPaint = new SolidColorPaint(SKColor.Parse("#475569")),
|
||
NamePaint = new SolidColorPaint(SKColor.Parse("#334155")),
|
||
TextSize = 12,
|
||
NameTextSize = 13,
|
||
Padding = new LiveChartsCore.Drawing.Padding(4, 3, 4, 3)
|
||
}
|
||
];
|
||
|
||
public Axis[] YAxes { get; } =
|
||
[
|
||
new Axis
|
||
{
|
||
Name = "压力 / 拉力 / 距离",
|
||
MinLimit = 0,
|
||
MaxLimit = 800,
|
||
UnitWidth = 50,
|
||
SeparatorsPaint = new SolidColorPaint(SKColor.Parse("#D7E0EA")) { StrokeThickness = 1 },
|
||
SubseparatorsPaint = new SolidColorPaint(SKColor.Parse("#EEF3F8")) { StrokeThickness = 1 },
|
||
SubseparatorsCount = 4,
|
||
LabelsPaint = new SolidColorPaint(SKColor.Parse("#475569")),
|
||
NamePaint = new SolidColorPaint(SKColor.Parse("#334155")),
|
||
TextSize = 11,
|
||
NameTextSize = 12,
|
||
Padding = new LiveChartsCore.Drawing.Padding(2, 2, 3, 2)
|
||
},
|
||
new Axis
|
||
{
|
||
Name = "摩擦系数",
|
||
Position = LiveChartsCore.Measure.AxisPosition.End,
|
||
MinLimit = 0,
|
||
MaxLimit = 1.5,
|
||
UnitWidth = 0.1,
|
||
LabelsPaint = new SolidColorPaint(SKColor.Parse("#7E22CE")),
|
||
NamePaint = new SolidColorPaint(SKColor.Parse("#7E22CE")),
|
||
SeparatorsPaint = new SolidColorPaint(SKColor.Parse("#F1E7FF")) { StrokeThickness = 1 },
|
||
TextSize = 11,
|
||
NameTextSize = 12,
|
||
Padding = new LiveChartsCore.Drawing.Padding(3, 2, 2, 2)
|
||
}
|
||
];
|
||
|
||
public MainWindowViewModel()
|
||
{
|
||
LoadDeviceSettings();
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void Clear()
|
||
{
|
||
UploadProgress = 0;
|
||
CurrentStatus = "传感器已清零,垂直压力与水平拉力基线重置完成";
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void Preload()
|
||
{
|
||
UploadProgress = 34;
|
||
CurrentStatus = "预压中:0.2s 内施加目标垂直载荷,等待滑动动作";
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void StartTest()
|
||
{
|
||
UploadProgress = 86;
|
||
CurrentStatus = "测试运行:正在采集峰值静摩擦力与 0.3s-0.6s 动摩擦力";
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void StopTest()
|
||
{
|
||
UploadProgress = 68;
|
||
CurrentStatus = "测试停止,请按“测试”键进行下次试验";
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void ExportReport()
|
||
{
|
||
UploadProgress = 100;
|
||
CurrentStatus = "报告数据已整理:三次平均、静/动摩擦系数与试验条件可导出";
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void LiftFast() => CurrentStatus = "垂直架快速上升";
|
||
|
||
[RelayCommand]
|
||
private void Lift() => CurrentStatus = "垂直架提升";
|
||
|
||
[RelayCommand]
|
||
private void Lower() => CurrentStatus = "垂直架下降";
|
||
|
||
[RelayCommand]
|
||
private void LowerFast() => CurrentStatus = "垂直架快速下降";
|
||
|
||
[RelayCommand]
|
||
private void MoveLeft() => CurrentStatus = "水平板向左移动";
|
||
|
||
[RelayCommand]
|
||
private void MoveRight() => CurrentStatus = "水平板向右移动";
|
||
|
||
[RelayCommand]
|
||
private void DeleteSelectedSample()
|
||
{
|
||
var sample = Samples.FirstOrDefault(x => x.Index == SelectedSampleIndex);
|
||
if (sample is null)
|
||
{
|
||
CurrentStatus = $"未找到序号 {SelectedSampleIndex} 的实验数据";
|
||
return;
|
||
}
|
||
|
||
Samples.Remove(sample);
|
||
CurrentStatus = $"已删除序号 {SelectedSampleIndex} 的实验数据";
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void ShowSettingsDialog()
|
||
{
|
||
IsSettingsDialogOpen = true;
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void CloseSettingsDialog()
|
||
{
|
||
IsSettingsDialogOpen = false;
|
||
}
|
||
|
||
partial void OnUploadProgressChanged(int value)
|
||
{
|
||
OnPropertyChanged(nameof(UploadProgressText));
|
||
}
|
||
|
||
partial void OnManualSpeedChanged(string value) => SaveDeviceSettings();
|
||
|
||
partial void OnManualDisplacementChanged(string value) => SaveDeviceSettings();
|
||
|
||
partial void OnTestSpeedChanged(string value)
|
||
{
|
||
OnPropertyChanged(nameof(TestSpeedText));
|
||
SaveDeviceSettings();
|
||
}
|
||
|
||
partial void OnNormalPressureCoefficientChanged(string value) => SaveDeviceSettings();
|
||
|
||
partial void OnFrictionCoefficient1Changed(string value) => SaveDeviceSettings();
|
||
|
||
partial void OnFrictionCoefficient2Changed(string value) => SaveDeviceSettings();
|
||
|
||
private void LoadDeviceSettings()
|
||
{
|
||
if (!File.Exists(DeviceSettingsPath))
|
||
{
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
var json = File.ReadAllText(DeviceSettingsPath);
|
||
var settings = JsonSerializer.Deserialize<DeviceSettings>(json);
|
||
if (settings is null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
isLoadingDeviceSettings = true;
|
||
ManualSpeed = settings.ManualSpeed ?? ManualSpeed;
|
||
ManualDisplacement = settings.ManualDisplacement ?? ManualDisplacement;
|
||
TestSpeed = settings.TestSpeed ?? TestSpeed;
|
||
NormalPressureCoefficient = settings.NormalPressureCoefficient ?? NormalPressureCoefficient;
|
||
FrictionCoefficient1 = settings.FrictionCoefficient1 ?? FrictionCoefficient1;
|
||
FrictionCoefficient2 = settings.FrictionCoefficient2 ?? FrictionCoefficient2;
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
finally
|
||
{
|
||
isLoadingDeviceSettings = false;
|
||
}
|
||
}
|
||
|
||
private void SaveDeviceSettings()
|
||
{
|
||
if (isLoadingDeviceSettings)
|
||
{
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
Directory.CreateDirectory(Path.GetDirectoryName(DeviceSettingsPath)!);
|
||
var settings = new DeviceSettings(
|
||
ManualSpeed,
|
||
ManualDisplacement,
|
||
TestSpeed,
|
||
NormalPressureCoefficient,
|
||
FrictionCoefficient1,
|
||
FrictionCoefficient2);
|
||
var json = JsonSerializer.Serialize(settings, new JsonSerializerOptions { WriteIndented = true });
|
||
File.WriteAllText(DeviceSettingsPath, json);
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
}
|
||
|
||
private static string DeviceSettingsPath =>
|
||
Path.Combine(
|
||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||
"FootwearSlipResistance",
|
||
"device-settings.json");
|
||
|
||
private static ObservablePoint[] CreatePressureSeries() =>
|
||
[
|
||
new(-0.10, 36), new(-0.08, 42), new(-0.06, 50), new(-0.04, 90),
|
||
new(-0.02, 400), new(0.00, 405), new(0.05, 407), new(0.10, 409),
|
||
new(0.20, 407), new(0.30, 412), new(0.40, 421), new(0.50, 426),
|
||
new(0.62, 430)
|
||
];
|
||
|
||
private static ObservablePoint[] CreatePullSeries() =>
|
||
[
|
||
new(-0.10, 0), new(-0.05, 0), new(0.00, 160), new(0.04, 226),
|
||
new(0.08, 232), new(0.16, 236), new(0.26, 241), new(0.36, 248),
|
||
new(0.46, 255), new(0.56, 260), new(0.62, 266)
|
||
];
|
||
|
||
private static ObservablePoint[] CreateFrictionSeries() =>
|
||
[
|
||
new(-0.10, 0), new(-0.02, 0), new(0.00, 0.47), new(0.04, 0.55),
|
||
new(0.08, 0.57), new(0.16, 0.56), new(0.26, 0.58), new(0.36, 0.59),
|
||
new(0.46, 0.60), new(0.56, 0.61), new(0.62, 0.62)
|
||
];
|
||
|
||
private static ObservablePoint[] CreateDistanceSeries() =>
|
||
[
|
||
new(-0.10, 0), new(0.00, 0), new(0.06, 20), new(0.12, 42),
|
||
new(0.20, 72), new(0.30, 108), new(0.40, 145), new(0.50, 178),
|
||
new(0.62, 218)
|
||
];
|
||
}
|
||
|
||
public sealed record TestSample(
|
||
int Index,
|
||
string Time,
|
||
string StaticCoefficient,
|
||
string DynamicCoefficient,
|
||
string Verdict);
|
||
|
||
internal sealed record DeviceSettings(
|
||
string ManualSpeed,
|
||
string ManualDisplacement,
|
||
string TestSpeed,
|
||
string NormalPressureCoefficient,
|
||
string FrictionCoefficient1,
|
||
string FrictionCoefficient2);
|
||
}
|