Files
FootwearTest-20260602/Footwear Test methodsfor wholeshoe Slipresistanceperformance/ViewModels/MainWindowViewModel.cs
2026-06-02 17:41:53 +08:00

438 lines
16 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.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);
}