feat: 更新

This commit is contained in:
GukSang.Jin
2026-02-27 16:56:18 +08:00
parent c7d107c2f1
commit fe0aee16ad
5 changed files with 237 additions and 15 deletions

Binary file not shown.

View File

@@ -9,6 +9,17 @@ namespace PetWashControl
/// </summary> /// </summary>
public partial class App : Application public partial class App : Application
{ {
} protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// 全局异常处理
this.DispatcherUnhandledException += (s, args) =>
{
MessageBox.Show($"应用程序错误:\n{args.Exception.Message}\n\n{args.Exception.StackTrace}",
"错误", MessageBoxButton.OK, MessageBoxImage.Error);
args.Handled = true;
};
}
}
} }

View File

@@ -71,19 +71,19 @@ public class InverseBoolToVisibilityConverter : IValueConverter
} }
} }
public class ProgressToWidthConverter : IValueConverter public class ProgressToWidthConverter : IMultiValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{ {
if (value is int progress) if (values.Length == 2 && values[0] is int progress && values[1] is double containerWidth)
{ {
// 假设进度条容器宽度为300根据百分比计算实际宽度 // 根据进度百分比计算实际宽度
return progress * 3.0; // 300px * (progress/100) return containerWidth * progress / 100.0;
} }
return 0.0; return 0.0;
} }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@@ -125,6 +125,15 @@ public partial class MainViewModel : ObservableObject
[ObservableProperty] [ObservableProperty]
private int _uvSterilizationTime = 3; private int _uvSterilizationTime = 3;
[ObservableProperty]
private bool _isCleaningDialogOpen;
[ObservableProperty]
private string _cleaningMessage = "正在清理笼子...";
[ObservableProperty]
private int _cleaningProgress;
[ObservableProperty] [ObservableProperty]
private int _shampoo1Level = 80; private int _shampoo1Level = 80;
@@ -221,7 +230,7 @@ public partial class MainViewModel : ObservableObject
WashSteps.Add(new WashStep { Name = "第四次冲水", Status = "等待中" }); WashSteps.Add(new WashStep { Name = "第四次冲水", Status = "等待中" });
WashSteps.Add(new WashStep { Name = "热风吹毛", Status = "等待中" }); WashSteps.Add(new WashStep { Name = "热风吹毛", Status = "等待中" });
WashSteps.Add(new WashStep { Name = "冷热风混合", Status = "等待中" }); WashSteps.Add(new WashStep { Name = "冷热风混合", Status = "等待中" });
WashSteps.Add(new WashStep { Name = "紫外线杀菌", Status = "等待中" }); // 紫外线杀菌不在洗护流程中,在流程完成后独立执行
} }
public async Task InitializeAsync() public async Task InitializeAsync()
@@ -800,8 +809,8 @@ public partial class MainViewModel : ObservableObject
("护理液喷洒", SprayShampoo3Time * 60), ("护理液喷洒", SprayShampoo3Time * 60),
("第四次冲水", AfterShampoo3SprayTime * 60), ("第四次冲水", AfterShampoo3SprayTime * 60),
("热风吹毛", HotAirTime * 60), ("热风吹毛", HotAirTime * 60),
("冷热风混合", ColdAirTime * 60), ("冷热风混合", ColdAirTime * 60)
("紫外线杀菌", UvSterilizationTime * 60) // 紫外线杀菌不在洗护流程中
}; };
int totalDuration = steps.Sum(s => s.Item2); int totalDuration = steps.Sum(s => s.Item2);
@@ -864,8 +873,14 @@ public partial class MainViewModel : ObservableObject
} }
}); });
// 洗护完成 // 洗护流程完成,自动开门
await CompleteWashingAsync(); _logger.LogInfo("洗护流程完成,自动开门");
IsDoorOpen = true;
StatusMessage = "洗护完成,请取走宠物";
CurrentStep = "请取走宠物";
// 等待门关闭(模拟宠物取走后关门)
await WaitForDoorCloseAsync();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -874,6 +889,83 @@ public partial class MainViewModel : ObservableObject
} }
} }
/// <summary>
/// 等待门关闭(宠物取走后)
/// </summary>
private async Task WaitForDoorCloseAsync()
{
_logger.LogInfo("等待门关闭...");
// 在实际生产环境中,这里应该监听门传感器信号
// 这里模拟等待10秒后自动关门
await Task.Delay(10000);
IsDoorOpen = false;
_logger.LogInfo("门已关闭,开始清理和杀菌流程");
// 门关闭后,开始清理和杀菌流程
await StartCleaningAndSterilizationAsync();
}
/// <summary>
/// 清理和紫外线杀菌流程(独立于洗护流程)
/// 关门后冲水2分钟清理笼子内多余狗毛同时紫外线灯开启杀菌
/// </summary>
private async Task StartCleaningAndSterilizationAsync()
{
try
{
// 显示清理弹窗(不可手动关闭)
IsCleaningDialogOpen = true;
CleaningProgress = 0;
_logger.LogInfo("开始清理和杀菌流程");
// 冲水2分钟 + 紫外线杀菌时间
int flushDuration = 2 * 60; // 2分钟冲水
int uvDuration = UvSterilizationTime * 60; // 紫外线杀菌时间
int totalDuration = flushDuration + uvDuration;
// 第一阶段冲水2分钟清理狗毛同时开启紫外线灯
_logger.LogInfo("开始冲水清理狗毛,同时开启紫外线灯");
CleaningMessage = "正在冲水清理笼子...";
for (int i = 0; i <= flushDuration; i++)
{
CleaningProgress = (int)((double)i / totalDuration * 100);
await Task.Delay(100);
}
// 第二阶段:继续紫外线杀菌
_logger.LogInfo("冲水完成,继续紫外线杀菌");
CleaningMessage = "正在紫外线杀菌...";
for (int i = flushDuration; i <= totalDuration; i++)
{
CleaningProgress = (int)((double)i / totalDuration * 100);
await Task.Delay(100);
}
CleaningProgress = 100;
CleaningMessage = "清理完成!";
await Task.Delay(1000);
// 关闭清理弹窗
IsCleaningDialogOpen = false;
_logger.LogInfo("清理和杀菌流程完成");
// 全部完成,返回待机界面
await CompleteWashingAsync();
}
catch (Exception ex)
{
_logger.LogError("清理和杀菌流程失败", ex);
StatusMessage = $"清理失败: {ex.Message}";
IsCleaningDialogOpen = false;
}
}
private async Task CompleteWashingAsync() private async Task CompleteWashingAsync()
{ {
if (CurrentOrder == null) return; if (CurrentOrder == null) return;

View File

@@ -1303,11 +1303,17 @@
<Border Background="#E0E0E0" <Border Background="#E0E0E0"
Height="16" Height="16"
CornerRadius="8" CornerRadius="8"
Margin="0,0,0,10"> Margin="0,0,0,10"
x:Name="ProgressBarContainer">
<Border Background="#FFB74D" <Border Background="#FFB74D"
CornerRadius="8" CornerRadius="8"
HorizontalAlignment="Left" HorizontalAlignment="Left">
Width="{Binding WashProgress, Converter={StaticResource ProgressToWidthConverter}}"> <Border.Width>
<MultiBinding Converter="{StaticResource ProgressToWidthConverter}">
<Binding Path="WashProgress"/>
<Binding ElementName="ProgressBarContainer" Path="ActualWidth"/>
</MultiBinding>
</Border.Width>
<Border.Effect> <Border.Effect>
<DropShadowEffect Color="#FF6F00" BlurRadius="8" ShadowDepth="0" Opacity="0.6"/> <DropShadowEffect Color="#FF6F00" BlurRadius="8" ShadowDepth="0" Opacity="0.6"/>
</Border.Effect> </Border.Effect>
@@ -2092,6 +2098,119 @@
</Border> </Border>
</Grid> </Grid>
<!-- 清理和杀菌弹窗(不可手动关闭) -->
<Grid Visibility="{Binding IsCleaningDialogOpen, Converter={StaticResource BoolToVisibilityConverter}}"
Background="#CC000000">
<Border Background="White"
CornerRadius="30"
MaxWidth="600"
MaxHeight="400"
Padding="0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Border.Effect>
<DropShadowEffect Color="#000000" BlurRadius="40" ShadowDepth="15" Opacity="0.6"/>
</Border.Effect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 标题栏 -->
<Border Grid.Row="0"
Background="#4CAF50"
CornerRadius="30,30,0,0"
Padding="40,25,40,25">
<TextBlock Text="设备清理中"
FontSize="32"
FontWeight="Bold"
Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- 内容区 -->
<Border Grid.Row="1"
Padding="40,40,40,40"
Background="White"
CornerRadius="0,0,30,30">
<StackPanel VerticalAlignment="Center">
<!-- 动画图标 -->
<Viewbox Width="80" Height="80" Margin="0,0,0,30">
<Canvas Width="100" Height="100">
<Ellipse Width="100" Height="100"
Stroke="#4CAF50"
StrokeThickness="8"
StrokeDashArray="25 15">
<Ellipse.RenderTransform>
<RotateTransform x:Name="SpinnerRotate" CenterX="50" CenterY="50"/>
</Ellipse.RenderTransform>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="SpinnerRotate"
Storyboard.TargetProperty="Angle"
From="0" To="360"
Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
</Canvas>
</Viewbox>
<!-- 清理消息 -->
<TextBlock Text="{Binding CleaningMessage}"
FontSize="24"
FontWeight="SemiBold"
Foreground="#333"
HorizontalAlignment="Center"
TextAlignment="Center"
Margin="0,0,0,20"/>
<!-- 进度条 -->
<Border Background="#E0E0E0"
CornerRadius="10"
Height="20"
Margin="0,0,0,15">
<Border Background="#4CAF50"
CornerRadius="10"
HorizontalAlignment="Left">
<Border.Width>
<MultiBinding Converter="{StaticResource ProgressToWidthConverter}">
<Binding Path="CleaningProgress"/>
<Binding RelativeSource="{RelativeSource AncestorType=Border, AncestorLevel=1}" Path="ActualWidth"/>
</MultiBinding>
</Border.Width>
</Border>
</Border>
<!-- 进度百分比 -->
<TextBlock FontSize="20"
FontWeight="Bold"
Foreground="#4CAF50"
HorizontalAlignment="Center">
<Run Text="{Binding CleaningProgress, Mode=OneWay}"/>
<Run Text="%"/>
</TextBlock>
<!-- 提示文字 -->
<TextBlock Text="请勿打开设备门"
FontSize="16"
Foreground="#FF5722"
HorizontalAlignment="Center"
Margin="0,20,0,0"
FontWeight="SemiBold"/>
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
<!-- 联系客服弹窗 --> <!-- 联系客服弹窗 -->
<Grid Visibility="{Binding IsCustomerServiceDialogOpen, Converter={StaticResource BoolToVisibilityConverter}}" <Grid Visibility="{Binding IsCustomerServiceDialogOpen, Converter={StaticResource BoolToVisibilityConverter}}"
Background="#80000000"> Background="#80000000">