更新20260604
This commit is contained in:
@@ -33,30 +33,14 @@ public partial class App : Application
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IStandardRepository, StandardRepository>();
|
||||
services.AddSingleton<IPasswordAccessService, PasswordAccessService>();
|
||||
services.AddSingleton<IModbusTelemetryService, ModbusTelemetryService>();
|
||||
services.AddSingleton<IRs485PumpFlowService, Rs485PumpFlowService>();
|
||||
services.AddSingleton<IPumpActuationService, Rs485PumpActuationService>();
|
||||
services.AddTransient<StartupPasswordViewModel>();
|
||||
services.AddTransient<StartupPasswordWindow>();
|
||||
services.AddSingleton<MainViewModel>();
|
||||
services.AddSingleton<MainWindow>();
|
||||
|
||||
_serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var passwordAccessService = _serviceProvider.GetRequiredService<IPasswordAccessService>();
|
||||
var passwordStatus = passwordAccessService.GetStatus();
|
||||
if (passwordStatus.ShouldPromptAtStartup)
|
||||
{
|
||||
var passwordWindow = _serviceProvider.GetRequiredService<StartupPasswordWindow>();
|
||||
var passwordResult = passwordWindow.ShowDialog();
|
||||
if (passwordResult != true || !passwordAccessService.GetStatus().CanLaunch)
|
||||
{
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
|
||||
mainWindow.Show();
|
||||
}
|
||||
|
||||
@@ -19,30 +19,14 @@ public partial class App : Application
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IStandardRepository, StandardRepository>();
|
||||
services.AddSingleton<IPasswordAccessService, PasswordAccessService>();
|
||||
services.AddSingleton<IModbusTelemetryService, ModbusTelemetryService>();
|
||||
services.AddSingleton<IRs485PumpFlowService, Rs485PumpFlowService>();
|
||||
services.AddSingleton<IPumpActuationService, Rs485PumpActuationService>();
|
||||
services.AddTransient<StartupPasswordViewModel>();
|
||||
services.AddTransient<StartupPasswordWindow>();
|
||||
services.AddSingleton<MainViewModel>();
|
||||
services.AddSingleton<MainWindow>();
|
||||
|
||||
_serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var passwordAccessService = _serviceProvider.GetRequiredService<IPasswordAccessService>();
|
||||
var passwordStatus = passwordAccessService.GetStatus();
|
||||
if (passwordStatus.ShouldPromptAtStartup)
|
||||
{
|
||||
var passwordWindow = _serviceProvider.GetRequiredService<StartupPasswordWindow>();
|
||||
var passwordResult = passwordWindow.ShowDialog();
|
||||
if (passwordResult != true || !passwordAccessService.GetStatus().CanLaunch)
|
||||
{
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
|
||||
mainWindow.Show();
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace Cardiopulmonarybypasssystems.Models;
|
||||
|
||||
public sealed class PasswordAccessStatus
|
||||
{
|
||||
public int Stage { get; init; }
|
||||
public bool CanLaunch { get; init; }
|
||||
public bool IsPermanent { get; init; }
|
||||
public bool ShouldPromptAtStartup { get; init; }
|
||||
public bool CanSubmitPassword { get; init; }
|
||||
public bool RequiresPassword => !CanLaunch;
|
||||
public string StageText { get; init; } = string.Empty;
|
||||
public string StatusTitle { get; init; } = string.Empty;
|
||||
public string StatusDetail { get; init; } = string.Empty;
|
||||
public int RemainingDays { get; init; }
|
||||
public DateTime? ExpiresAt { get; init; }
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using Cardiopulmonarybypasssystems.Models;
|
||||
|
||||
namespace Cardiopulmonarybypasssystems.Services;
|
||||
|
||||
public interface IPasswordAccessService
|
||||
{
|
||||
PasswordAccessStatus GetStatus();
|
||||
bool TryUnlock(string password, out PasswordAccessStatus status, out string message);
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using Cardiopulmonarybypasssystems.Models;
|
||||
|
||||
namespace Cardiopulmonarybypasssystems.Services;
|
||||
|
||||
public sealed class PasswordAccessService : IPasswordAccessService
|
||||
{
|
||||
private const int ExpirationReminderDays = 3;
|
||||
private const string SettingsDirectoryName = "Cardiopulmonarybypasssystems";
|
||||
private const string StatusFileName = "password-access.json";
|
||||
public const string FirstStagePassword = "152026001";
|
||||
public const string SecondStagePassword = "302026002";
|
||||
private const int InitialAccessDays = 20;
|
||||
private const int ExtendedAccessDays = 30;
|
||||
|
||||
private static readonly string StatusFilePath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
SettingsDirectoryName,
|
||||
StatusFileName);
|
||||
|
||||
public PasswordAccessStatus GetStatus()
|
||||
{
|
||||
var state = LoadOrCreateState();
|
||||
return BuildStatus(state, persistState: true);
|
||||
}
|
||||
|
||||
public bool TryUnlock(string password, out PasswordAccessStatus status, out string message)
|
||||
{
|
||||
var normalizedPassword = password?.Trim() ?? string.Empty;
|
||||
var state = LoadOrCreateState();
|
||||
var currentStatus = BuildStatus(state, persistState: true);
|
||||
|
||||
if (currentStatus.IsPermanent)
|
||||
{
|
||||
status = currentStatus;
|
||||
message = "当前版本已永久有效,不需要再输入密码。";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentStatus.CanLaunch)
|
||||
{
|
||||
status = currentStatus;
|
||||
message = currentStatus.ShouldPromptAtStartup
|
||||
? $"当前仍在有效期内,可直接进入系统;满 {GetStageDays(currentStatus.Stage)} 天后再输入密码。"
|
||||
: $"{GetStageName(currentStatus.Stage)}仍在有效期内,无需再次输入密码。";
|
||||
return false;
|
||||
}
|
||||
|
||||
var expectedPassword = currentStatus.Stage switch
|
||||
{
|
||||
0 => FirstStagePassword,
|
||||
1 => SecondStagePassword,
|
||||
_ => string.Empty
|
||||
};
|
||||
|
||||
if (!string.Equals(normalizedPassword, expectedPassword, StringComparison.Ordinal))
|
||||
{
|
||||
status = currentStatus;
|
||||
message = currentStatus.Stage switch
|
||||
{
|
||||
0 => "密码错误,请输入第 1 次时效密码。",
|
||||
1 => "密码错误,请输入第 2 次时效密码。",
|
||||
_ => "密码错误。"
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
var now = DateTime.Now;
|
||||
|
||||
if (currentStatus.Stage == 1)
|
||||
{
|
||||
var permanentState = new PasswordAccessState
|
||||
{
|
||||
Stage = 2,
|
||||
ActivatedAt = state?.ActivatedAt ?? now,
|
||||
ExpiresAt = null
|
||||
};
|
||||
|
||||
SaveState(permanentState);
|
||||
status = BuildStatus(permanentState, persistState: false);
|
||||
message = "第 2 次密码验证通过,系统已永久有效。";
|
||||
return true;
|
||||
}
|
||||
|
||||
var expiresAt = now.AddDays(ExtendedAccessDays);
|
||||
var nextState = new PasswordAccessState
|
||||
{
|
||||
Stage = 1,
|
||||
ActivatedAt = now,
|
||||
ExpiresAt = expiresAt
|
||||
};
|
||||
|
||||
SaveState(nextState);
|
||||
status = BuildStatus(nextState, persistState: false);
|
||||
message = $"第 1 次密码验证通过,已继续开放 {ExtendedAccessDays} 天,有效期至 {expiresAt:yyyy-MM-dd HH:mm}。";
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PasswordAccessStatus BuildStatus(PasswordAccessState? state, bool persistState)
|
||||
{
|
||||
if (state is null)
|
||||
{
|
||||
state = CreateInitialState();
|
||||
if (persistState)
|
||||
{
|
||||
SaveState(state);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.Stage >= 2)
|
||||
{
|
||||
return new PasswordAccessStatus
|
||||
{
|
||||
Stage = 2,
|
||||
CanLaunch = true,
|
||||
IsPermanent = true,
|
||||
ShouldPromptAtStartup = false,
|
||||
CanSubmitPassword = false,
|
||||
StageText = "当前阶段:永久有效",
|
||||
StatusTitle = "系统已永久有效",
|
||||
StatusDetail = "当前可直接进入系统。",
|
||||
RemainingDays = int.MaxValue
|
||||
};
|
||||
}
|
||||
|
||||
var now = DateTime.Now;
|
||||
if (state.ExpiresAt > now)
|
||||
{
|
||||
var remainingDays = Math.Max(1, (int)Math.Ceiling((state.ExpiresAt.Value - now).TotalDays));
|
||||
var isReminderWindow = remainingDays <= ExpirationReminderDays;
|
||||
var isInitialStage = state.Stage == 0;
|
||||
return new PasswordAccessStatus
|
||||
{
|
||||
Stage = state.Stage,
|
||||
CanLaunch = true,
|
||||
IsPermanent = false,
|
||||
ShouldPromptAtStartup = isReminderWindow,
|
||||
CanSubmitPassword = false,
|
||||
StageText = isInitialStage ? $"当前阶段:首次使用({InitialAccessDays} 天)" : $"当前阶段:第 1 次续期({ExtendedAccessDays} 天)",
|
||||
StatusTitle = isReminderWindow
|
||||
? isInitialStage ? "首次使用即将到期" : "第 1 次续期即将到期"
|
||||
: "时效有效",
|
||||
StatusDetail = isReminderWindow
|
||||
? isInitialStage
|
||||
? $"剩余 {remainingDays} 天,到期后需输入第 1 次时效密码。"
|
||||
: $"剩余 {remainingDays} 天,到期后需输入第 2 次时效密码。"
|
||||
: $"当前可直接进入系统。",
|
||||
RemainingDays = remainingDays,
|
||||
ExpiresAt = state.ExpiresAt
|
||||
};
|
||||
}
|
||||
|
||||
if (state.Stage == 0)
|
||||
{
|
||||
return new PasswordAccessStatus
|
||||
{
|
||||
Stage = 0,
|
||||
CanLaunch = false,
|
||||
IsPermanent = false,
|
||||
ShouldPromptAtStartup = true,
|
||||
CanSubmitPassword = true,
|
||||
StageText = "当前阶段:首次使用已到期",
|
||||
StatusTitle = "需要输入第 1 次时效密码",
|
||||
StatusDetail = $"输入密码后继续使用 {ExtendedAccessDays} 天。",
|
||||
RemainingDays = 0,
|
||||
ExpiresAt = state.ExpiresAt
|
||||
};
|
||||
}
|
||||
|
||||
return new PasswordAccessStatus
|
||||
{
|
||||
Stage = 1,
|
||||
CanLaunch = false,
|
||||
IsPermanent = false,
|
||||
ShouldPromptAtStartup = true,
|
||||
CanSubmitPassword = true,
|
||||
StageText = "当前阶段:第 1 次续期已到期",
|
||||
StatusTitle = "需要输入第 2 次时效密码",
|
||||
StatusDetail = "输入密码后系统转为永久有效。",
|
||||
RemainingDays = 0,
|
||||
ExpiresAt = state.ExpiresAt
|
||||
};
|
||||
}
|
||||
|
||||
private static int GetStageDays(int stage) => stage switch
|
||||
{
|
||||
0 => InitialAccessDays,
|
||||
1 => ExtendedAccessDays,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
private static string GetStageName(int stage) => stage switch
|
||||
{
|
||||
0 => "首次使用阶段",
|
||||
1 => "第 1 次续期阶段",
|
||||
_ => "当前阶段"
|
||||
};
|
||||
|
||||
private static PasswordAccessState LoadOrCreateState()
|
||||
{
|
||||
var state = LoadState();
|
||||
if (state is not null)
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
var initialState = CreateInitialState();
|
||||
SaveState(initialState);
|
||||
return initialState;
|
||||
}
|
||||
|
||||
private static PasswordAccessState CreateInitialState()
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
return new PasswordAccessState
|
||||
{
|
||||
Stage = 0,
|
||||
ActivatedAt = now,
|
||||
ExpiresAt = now.AddDays(InitialAccessDays)
|
||||
};
|
||||
}
|
||||
|
||||
private static PasswordAccessState? LoadState()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(StatusFilePath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var json = File.ReadAllText(StatusFilePath);
|
||||
return JsonSerializer.Deserialize<PasswordAccessState>(json);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveState(PasswordAccessState state)
|
||||
{
|
||||
var directory = Path.GetDirectoryName(StatusFilePath);
|
||||
if (!string.IsNullOrWhiteSpace(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var json = JsonSerializer.Serialize(state, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(StatusFilePath, json);
|
||||
}
|
||||
|
||||
private sealed class PasswordAccessState
|
||||
{
|
||||
public int Stage { get; set; }
|
||||
public DateTime ActivatedAt { get; set; }
|
||||
public DateTime? ExpiresAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
<Window x:Class="Cardiopulmonarybypasssystems.StartupPasswordWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="系统进入验证"
|
||||
Width="640"
|
||||
Height="500"
|
||||
Loaded="Window_Loaded"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
ResizeMode="NoResize">
|
||||
<Grid Margin="18">
|
||||
<Border CornerRadius="22"
|
||||
Background="#FFF7FAFB"
|
||||
BorderBrush="#FFD7E2E6"
|
||||
BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="126" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Grid.Row="0"
|
||||
CornerRadius="22,22,0,0"
|
||||
Padding="24,20">
|
||||
<Border.Background>
|
||||
<LinearGradientBrush StartPoint="0,0"
|
||||
EndPoint="1,1">
|
||||
<GradientStop Color="#FF123744"
|
||||
Offset="0" />
|
||||
<GradientStop Color="#FF0F5F75"
|
||||
Offset="0.55" />
|
||||
<GradientStop Color="#FF2F7D7A"
|
||||
Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock FontSize="26"
|
||||
FontWeight="Bold"
|
||||
Foreground="White"
|
||||
Text="系统进入验证" />
|
||||
<Border Margin="0,10,0,0"
|
||||
Padding="10,6"
|
||||
HorizontalAlignment="Left"
|
||||
Background="#1FFFFFFF"
|
||||
CornerRadius="12">
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="White"
|
||||
Text="{Binding StageText}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<StackPanel Grid.Row="1"
|
||||
Margin="24,16,24,14">
|
||||
<Border
|
||||
Padding="14,10"
|
||||
Background="#FFEAF3F5"
|
||||
CornerRadius="14">
|
||||
<DockPanel LastChildFill="False">
|
||||
<StackPanel DockPanel.Dock="Left"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock FontSize="12"
|
||||
Foreground="#FF52636B"
|
||||
Text="到期:" />
|
||||
<TextBlock FontSize="13"
|
||||
FontWeight="Bold"
|
||||
Foreground="{StaticResource HeaderBrush}"
|
||||
Text="{Binding ExpiresAtText}" />
|
||||
</StackPanel>
|
||||
<StackPanel DockPanel.Dock="Right"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock FontSize="12"
|
||||
Foreground="#FF52636B"
|
||||
Text="剩余:" />
|
||||
<TextBlock FontSize="13"
|
||||
FontWeight="Bold"
|
||||
Foreground="{StaticResource HeaderBrush}"
|
||||
Text="{Binding RemainingText}" />
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Margin="0,16,0,0"
|
||||
Padding="16"
|
||||
Background="White"
|
||||
BorderBrush="#FFDCE7EA"
|
||||
BorderThickness="1"
|
||||
CornerRadius="16">
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{StaticResource HeaderBrush}"
|
||||
Text="密码输入" />
|
||||
<TextBox x:Name="PasswordInput"
|
||||
Margin="0,10,0,0"
|
||||
MinHeight="38"
|
||||
FontSize="15"
|
||||
Text="{Binding PasswordText, UpdateSourceTrigger=PropertyChanged}"
|
||||
TextChanged="PasswordInput_OnTextChanged" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<Border Grid.Row="2"
|
||||
Padding="18,14"
|
||||
Background="White"
|
||||
BorderBrush="#FFE2EBEE"
|
||||
BorderThickness="1,1,0,0"
|
||||
CornerRadius="0,0,22,22">
|
||||
<UniformGrid Columns="3">
|
||||
<Button Width="112"
|
||||
Margin="0,0,10,0"
|
||||
Command="{Binding CloseCommand}"
|
||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Background="#FF667E88"
|
||||
Content="退出" />
|
||||
<Button Width="112"
|
||||
Margin="0,0,10,0"
|
||||
Command="{Binding ContinueCommand}"
|
||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Background="#FF2B8F6A"
|
||||
Content="继续进入"
|
||||
IsEnabled="{Binding CanContinue}" />
|
||||
<Button Width="112"
|
||||
Margin="0,0,10,0"
|
||||
Command="{Binding SubmitCommand}"
|
||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Background="#FF0F5F75"
|
||||
Content="提交密码"
|
||||
IsEnabled="{Binding CanSubmit}" />
|
||||
</UniformGrid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Cardiopulmonarybypasssystems.ViewModels;
|
||||
|
||||
namespace Cardiopulmonarybypasssystems;
|
||||
|
||||
public partial class StartupPasswordWindow : Window
|
||||
{
|
||||
private readonly StartupPasswordViewModel _viewModel;
|
||||
|
||||
public StartupPasswordWindow(StartupPasswordViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
_viewModel = viewModel;
|
||||
DataContext = viewModel;
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PasswordInput.Focus();
|
||||
Keyboard.Focus(PasswordInput);
|
||||
PasswordInput.SelectAll();
|
||||
}
|
||||
|
||||
private void PasswordInput_OnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
|
||||
{
|
||||
_viewModel.PasswordText = PasswordInput.Text;
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using Cardiopulmonarybypasssystems.Models;
|
||||
using Cardiopulmonarybypasssystems.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace Cardiopulmonarybypasssystems.ViewModels;
|
||||
|
||||
public partial class StartupPasswordViewModel : ObservableObject
|
||||
{
|
||||
private readonly IPasswordAccessService _passwordAccessService;
|
||||
|
||||
public StartupPasswordViewModel(IPasswordAccessService passwordAccessService)
|
||||
{
|
||||
_passwordAccessService = passwordAccessService;
|
||||
ProductName = "心肺转流检测系统";
|
||||
SoftwareVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString(3) ?? "1.0.0";
|
||||
RefreshStatus();
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private string productName = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string softwareVersion = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string passwordText = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string statusTitle = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string statusDetail = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string stageText = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string expiresAtText = "--";
|
||||
|
||||
[ObservableProperty]
|
||||
private string remainingText = "--";
|
||||
|
||||
[ObservableProperty]
|
||||
private string footerHint = "规则:先使用 20 天,提前 3 天提醒;满 20 天输入密码后再使用 30 天,提前 3 天再次提醒。";
|
||||
|
||||
[ObservableProperty]
|
||||
private bool canSubmit;
|
||||
|
||||
public bool CanContinue => _passwordAccessService.GetStatus().CanLaunch;
|
||||
|
||||
[RelayCommand]
|
||||
private void Submit(Window? window)
|
||||
{
|
||||
if (!_passwordAccessService.TryUnlock(PasswordText, out _, out var message))
|
||||
{
|
||||
RefreshStatus();
|
||||
StatusDetail = message;
|
||||
return;
|
||||
}
|
||||
|
||||
PasswordText = string.Empty;
|
||||
RefreshStatus();
|
||||
StatusDetail = message;
|
||||
|
||||
if (_passwordAccessService.GetStatus().CanLaunch && window is not null)
|
||||
{
|
||||
window.DialogResult = true;
|
||||
window.Close();
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Continue(Window? window)
|
||||
{
|
||||
if (!_passwordAccessService.GetStatus().CanLaunch || window is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
window.DialogResult = true;
|
||||
window.Close();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Close(Window? window)
|
||||
{
|
||||
window?.Close();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void AppendPasswordCharacter(string? value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PasswordText += value;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void BackspacePassword()
|
||||
{
|
||||
if (string.IsNullOrEmpty(PasswordText))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PasswordText = PasswordText[..^1];
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ClearPassword()
|
||||
{
|
||||
PasswordText = string.Empty;
|
||||
}
|
||||
|
||||
private void RefreshStatus()
|
||||
{
|
||||
var status = _passwordAccessService.GetStatus();
|
||||
StatusTitle = status.StatusTitle;
|
||||
StatusDetail = status.StatusDetail;
|
||||
StageText = status.StageText;
|
||||
ExpiresAtText = status.ExpiresAt?.ToString("yyyy-MM-dd HH:mm") ?? (status.IsPermanent ? "永久有效" : "--");
|
||||
RemainingText = status.IsPermanent ? "永久" : status.RemainingDays > 0 ? $"{status.RemainingDays} 天" : "需输入密码";
|
||||
CanSubmit = status.CanSubmitPassword;
|
||||
OnPropertyChanged(nameof(CanContinue));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user