diff --git a/CRSim.ScreenSimulator/Assets/Hailaer/PrimaryScreen.png b/CRSim.ScreenSimulator/Assets/Hailaer/PrimaryScreen.png deleted file mode 100644 index f9d39a5..0000000 Binary files a/CRSim.ScreenSimulator/Assets/Hailaer/PrimaryScreen.png and /dev/null differ diff --git a/CRSim.ScreenSimulator/Assets/Yakeshi/PlatformScreen.png b/CRSim.ScreenSimulator/Assets/Yakeshi/PlatformScreen.png deleted file mode 100644 index df19e50..0000000 Binary files a/CRSim.ScreenSimulator/Assets/Yakeshi/PlatformScreen.png and /dev/null differ diff --git a/CRSim.ScreenSimulator/Models/StylesInfoData.json b/CRSim.ScreenSimulator/Models/StylesInfoData.json deleted file mode 100644 index 0784ac6..0000000 --- a/CRSim.ScreenSimulator/Models/StylesInfoData.json +++ /dev/null @@ -1,459 +0,0 @@ -[ - { - "UniqueId": "ChengduDong.SecondaryScreen", - "Title": "成都东站次要看板", - "Region": "成都", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "ChengduDong.PrimaryTicketCheckScreen", - "Title": "成都东站检票口主要看板", - "Region": "成都", - "Author": "电排骨", - "Type": "检票口屏", - "Parameters": [ - "Station", - "TicketCheck", - "Text" - ] - }, - { - "UniqueId": "ChengduDong.PillarTicketCheckScreen", - "Title": "成都东站检票口立柱看板", - "Region": "成都", - "Author": "电排骨", - "Type": "检票口屏", - "Parameters": [ - "Station", - "TicketCheck" - ] - }, - { - "UniqueId": "Fuzhou.TicketCheckScreen", - "Title": "福州站检票口看板", - "Region": "福州", - "Author": "电排骨", - "Type": "检票口屏", - "Parameters": [ - "Station", - "TicketCheck", - "Text" - ] - }, - { - "UniqueId": "FuzhouNan.TicketCheckScreen", - "Title": "福州南站检票口看板", - "Region": "福州", - "Author": "电排骨", - "Type": "检票口屏", - "Parameters": [ - "Station", - "TicketCheck", - "Text" - ] - }, - { - "UniqueId": "BeijingXi.PrimaryScreen", - "Title": "北京西站主要看板", - "Region": "北京", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station" - ] - }, - { - "UniqueId": "Harbin.PrimaryScreen", - "Title": "哈尔滨站主要看板", - "Region": "哈尔滨", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "ChengduMetro.PlatformScreen", - "Title": "成都地铁站台看板", - "Region": "成都", - "Author": "电排骨", - "Type": "站台屏", - "Parameters": [ - "Station", - "Text", - "Video", - "Platform" - ] - }, - { - "UniqueId": "XuzhouMetro.PlatformScreen", - "Title": "徐州地铁站台看板", - "Region": "徐州", - "Author": "电排骨", - "Type": "站台屏", - "Parameters": [ - "Station", - "Text", - "Video", - "Platform" - ] - }, - { - "UniqueId": "TianjinMetro.PlatformScreen", - "Title": "天津地铁站台看板", - "Region": "天津", - "Author": "电排骨", - "Type": "站台屏", - "Parameters": [ - "Station", - "Text", - "Video", - "Platform" - ] - }, - { - "UniqueId": "Guangyuan.PrimaryScreen", - "Title": "广元站主要看板", - "Region": "广元", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "ChengduShuangliuAirport.SecondaryScreen", - "Title": "成都双流机场次要看板", - "Region": "成都", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "KunmingChangshuiAirport.PrimaryScreen", - "Title": "昆明长水机场主要看板", - "Region": "昆明", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "Shanghai.OutsideScreen", - "Title": "上海站站外看板", - "Region": "上海", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station" - ] - }, - { - "UniqueId": "Hanzhong.PlatformScreen", - "Title": "汉中站站台看板", - "Region": "汉中", - "Author": "电排骨", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Text" - ] - }, - { - "UniqueId": "Tianjin.PlatformScreen", - "Title": "天津站站台看板", - "Region": "天津", - "Author": "电排骨", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "Mianyang.PlatformScreen", - "Title": "绵阳站站台看板", - "Region": "绵阳", - "Author": "电排骨", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "Zibo.PrimaryScreen", - "Title": "淄博站主要看板", - "Region": "淄博", - "Author": "wxl0430", - "Type": "车站大屏", - "Parameters": [ - "Station" - ] - }, - { - "UniqueId": "Zibo.SecondaryScreen", - "Title": "淄博站次要看板", - "Region": "淄博", - "Author": "wxl0430", - "Type": "车站大屏", - "Parameters": [ - "Station" - ] - }, - { - "UniqueId": "Zibo.TicketCheckScreen", - "Title": "淄博站检票口看板", - "Region": "淄博", - "Author": "wxl0430", - "Type": "检票口屏", - "Parameters": [ - "Station", - "TicketCheck", - "Text" - ] - }, - { - "UniqueId": "Zibo.PlatformScreen", - "Title": "淄博站站台看板", - "Region": "淄博", - "Author": "wxl0430", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location", - "Text" - ] - }, - { - "UniqueId": "Zibo.ConcourseBridgeScreen", - "Title": "淄博站廊桥看板", - "Region": "淄博", - "Author": "wxl0430", - "Type": "走廊出发屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "Zibo.ExitScreen", - "Title": "淄博站出站口看板", - "Region": "淄博", - "Author": "wxl0430", - "Type": "出站口屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "Jinanxi.SmallScreen", - "Title": "济南西站小屏看板", - "Region": "济南", - "Author": "wxl0430", - "Type": "车站大屏", - "Parameters": [ - "Station" - ] - }, - { - "UniqueId": "GuangdongIntercity.SecondaryScreen", - "Title": "广东城际次要看板", - "Region": "广东", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "Ankang.ExitScreen", - "Title": "安康站出站口看板", - "Region": "安康", - "Author": "电排骨", - "Type": "出站口屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "Niuzhou.PrimaryScreen", - "Title": "柳州站主要看板", - "Region": "柳州", - "Author": "电排骨", - "Type": "车站大屏", - "Parameters": [ - "Station", - "Text" - ] - }, - { - "UniqueId": "Beijing.ArrivalScreen", - "Title": "北京站地道到达看板", - "Region": "北京", - "Author": "wxl0430", - "Type": "走廊到达屏", - "Parameters": [ - "Station", - "Platform" - ] - }, - { - "UniqueId": "DaqingDong.ConcourseBridgeScreen", - "Title": "大庆东站廊桥看板", - "Region": "大庆", - "Author": "wxl0430", - "Type": "走廊出发屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "DaqingDong.PlatformScreen", - "Title": "大庆东站站台看板", - "Region": "大庆", - "Author": "wxl0430", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "HarbinXi.PlatformScreen", - "Title": "哈尔滨西站站台看板", - "Region": "哈尔滨", - "Author": "wxl0430", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location", - "Text" - ] - }, - { - "UniqueId": "BeijingNan.PrimaryScreen", - "Title": "北京南站主要看板", - "Region": "北京", - "Author": "wxl0430", - "Type": "车站大屏", - "Parameters": [ - "Station" - ] - }, - { - "UniqueId": "BeijingNan.TicketCheckScreen", - "Title": "北京南站检票口看板", - "Region": "北京", - "Author": "wxl0430", - "Type": "检票口屏", - "Parameters": [ - "Station", - "TicketCheck" - ] - }, - { - "UniqueId": "BeijingNan.PrimaryPlatformScreen", - "Title": "北京南站站台主要看板", - "Region": "北京", - "Author": "电排骨", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "BeijingNan.SecondaryPlatformScreen", - "Title": "北京南站站台次要看板", - "Region": "北京", - "Author": "wxl0430", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "ShenyangBei.PlatformScreen", - "Title": "沈阳北站站台看板", - "Region": "沈阳", - "Author": "电排骨", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "DezhouDong.PrimaryScreen", - "Title": "德州东站主要看板", - "Region": "德州", - "Author": "wxl0430", - "Type": "车站大屏", - "Parameters": [ - "Station" - ] - }, - { - "UniqueId": "DezhouDong.TicketCheckScreen", - "Title": "德州东站检票口看板", - "Region": "德州", - "Author": "wxl0430", - "Type": "检票口屏", - "Parameters": [ - "Station", - "TicketCheck" - ] - }, - { - "UniqueId": "Yakeshi.PlatformScreen", - "Title": "牙克石站站台看板", - "Region": "牙克石", - "Author": "wxl0430", - "Type": "站台屏", - "Parameters": [ - "Station", - "Platform", - "Location" - ] - }, - { - "UniqueId": "Hailaer.PrimaryScreen", - "Title": "海拉尔站主要看板", - "Region": "海拉尔", - "Author": "wxl0430", - "Type": "车站大屏", - "Parameters": [ - "Station", - "Text" - ] - } -] \ No newline at end of file diff --git a/CRSim.ScreenSimulator/ViewModels/Hailaer/PrimaryScreenViewModel.cs b/CRSim.ScreenSimulator/ViewModels/Hailaer/PrimaryScreenViewModel.cs deleted file mode 100644 index 5d1cd47..0000000 --- a/CRSim.ScreenSimulator/ViewModels/Hailaer/PrimaryScreenViewModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using CRSim.Core.Models; -using CRSim.Core.Services; -namespace CRSim.ScreenSimulator.ViewModels.Hailaer -{ - public class PrimaryScreenViewModel : ScreenViewModel - { - public PrimaryScreenViewModel(ITimeService timeService, ISettingsService settingsService) - : base(timeService, settingsService) - { - ItemsPerPage = 6; - ScreenCount = 2; - Text = $" 开车前{settingsService.GetSettings().StopCheckInAdvanceDuration.TotalMinutes}分钟停止检票";; - StationType = StationType.Departure; - } - } -} diff --git a/CRSim.ScreenSimulator/ViewModels/Yakeshi/PlatformScreenViewModel.cs b/CRSim.ScreenSimulator/ViewModels/Yakeshi/PlatformScreenViewModel.cs deleted file mode 100644 index 515b7c7..0000000 --- a/CRSim.ScreenSimulator/ViewModels/Yakeshi/PlatformScreenViewModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -using CRSim.Core.Services; -namespace CRSim.ScreenSimulator.ViewModels.Yakeshi -{ - public class PlatformScreenViewModel : ScreenViewModel - { - public PlatformScreenViewModel(ITimeService timeService, ISettingsService settingsService) - : base(timeService, settingsService) - { - Text = $"上下车不要拥挤,小心列车与站台之间的缝隙,看管好老人和同行的儿童"; - ItemsPerPage = 1; - } - } -} diff --git a/CRSim.ScreenSimulator/Views/Hailaer/PrimaryScreenView.xaml b/CRSim.ScreenSimulator/Views/Hailaer/PrimaryScreenView.xaml deleted file mode 100644 index 8bbac73..0000000 --- a/CRSim.ScreenSimulator/Views/Hailaer/PrimaryScreenView.xaml +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CRSim.ScreenSimulator/Views/Hailaer/PrimaryScreenView.xaml.cs b/CRSim.ScreenSimulator/Views/Hailaer/PrimaryScreenView.xaml.cs deleted file mode 100644 index 1ae1d2e..0000000 --- a/CRSim.ScreenSimulator/Views/Hailaer/PrimaryScreenView.xaml.cs +++ /dev/null @@ -1,14 +0,0 @@ -using CRSim.ScreenSimulator.ViewModels.Hailaer; -namespace CRSim.ScreenSimulator.Views.Hailaer -{ - public partial class PrimaryScreenView : BaseScreenView - { - public PrimaryScreenViewModel ViewModel { get; } - public PrimaryScreenView(PrimaryScreenViewModel viewModel) - { - InitializeComponent(); - ViewModel = viewModel; - DataContext = viewModel; - } - } -} diff --git a/CRSim.ScreenSimulator/Views/Yakeshi/PlatformScreenView.xaml b/CRSim.ScreenSimulator/Views/Yakeshi/PlatformScreenView.xaml deleted file mode 100644 index 5f6896e..0000000 --- a/CRSim.ScreenSimulator/Views/Yakeshi/PlatformScreenView.xaml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CRSim.ScreenSimulator/Views/Yakeshi/PlatformScreenView.xaml.cs b/CRSim.ScreenSimulator/Views/Yakeshi/PlatformScreenView.xaml.cs deleted file mode 100644 index 9978143..0000000 --- a/CRSim.ScreenSimulator/Views/Yakeshi/PlatformScreenView.xaml.cs +++ /dev/null @@ -1,16 +0,0 @@ -using CRSim.ScreenSimulator.ViewModels.Yakeshi; - -namespace CRSim.ScreenSimulator.Views.Yakeshi -{ - public partial class PlatformScreenView : BaseScreenView - { - public PlatformScreenViewModel ViewModel { get; } - public PlatformScreenView(PlatformScreenViewModel viewModel) - { - - InitializeComponent(); - ViewModel = viewModel; - DataContext = viewModel; - } - } -} diff --git a/CRSim/CRSim.csproj b/CRSim/CRSim.csproj index 98e2b15..0c5622f 100644 --- a/CRSim/CRSim.csproj +++ b/CRSim/CRSim.csproj @@ -109,6 +109,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/CRSim/UpdateChecker.cs b/CRSim/UpdateChecker.cs deleted file mode 100644 index 558e720..0000000 --- a/CRSim/UpdateChecker.cs +++ /dev/null @@ -1,373 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Security.Cryptography; -using System.Net.Http; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Reflection; - -namespace CRSim -{ - public class UpdateChecker - { - private const string ApiUrl = "https://crsim.com.cn/api/version"; - private readonly HttpClient _httpClient = new HttpClient(); - private ProgressWindow _progressWindow; - private CancellationTokenSource _cancellationTokenSource; - - public async Task CheckForUpdates() - { - try - { - await ExecuteOnUIThread(async () => - { - var currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - var latestVersionInfo = await GetLatestVersionInfo(); - - if (latestVersionInfo != null && latestVersionInfo.ver != currentVersion) - { - var result = ShowQuestion($"有新版本可用,当前版本:{currentVersion}\n最新版本: {latestVersionInfo.ver}\n\n更新日志:\n{latestVersionInfo.log}\n\n是否更新?(点击更新后请等待,程序将自动重启,时间与下载速度有关)"); - - if (result) - { - _cancellationTokenSource = new CancellationTokenSource(); - ShowProgressWindow("准备下载更新..."); - - try - { - await DownloadAndInitiateUpdate(latestVersionInfo, _cancellationTokenSource.Token); - } - catch (OperationCanceledException) - { - ShowMessage("更新已取消"); - } - finally - { - CloseProgressWindow(); - _cancellationTokenSource = null; - } - } - } - }); - } - catch (Exception ex) - { - CloseProgressWindow(); - ShowError($"更新检查失败:{ex.Message}"); - } - } - - private async Task GetLatestVersionInfo() - { - try - { - var response = await _httpClient.GetAsync(ApiUrl); - if (response.IsSuccessStatusCode) - { - var json = await response.Content.ReadAsStringAsync(); - return JsonSerializer.Deserialize(json); - } - } - catch (Exception ex) - { - ShowError($"调用API失败: {ex.Message}"); - } - return null; - } - - private async Task DownloadAndInitiateUpdate(VersionInfo versionInfo, CancellationToken cancellationToken) - { - try - { - var tempFilePath = await DownloadFileWithProgress(versionInfo.download_file, cancellationToken); - - var isValid = await Task.Run(() => ValidateFile(tempFilePath, versionInfo.file_md5, versionInfo.file_sha256)); - - if (!isValid) - { - var forceUpdate = ShowQuestion("md5和sha256验证失败,可能遭到网络劫持,是否强制更新?"); - if (!forceUpdate) - { - File.Delete(tempFilePath); - return; - } - } - - var programDirectory = AppDomain.CurrentDomain.BaseDirectory; - var appExePath = Process.GetCurrentProcess().MainModule.FileName; - var appName = Path.GetFileName(appExePath); - string batchScript = $@" -@echo off -taskkill /F /IM ""{appName}"" >nul 2>&1 -timeout /t 2 >nul -cd /d ""{programDirectory}"" -powershell -Command ""Expand-Archive -Path '{tempFilePath}' -DestinationPath '{programDirectory}' -Force"" -del /f /q ""{tempFilePath}"" -start """" ""{appExePath}"" -exit /b 0 -"; - - string batchFilePath = Path.Combine(Path.GetTempPath(), "CRSimUpdate.bat"); - File.WriteAllText(batchFilePath, batchScript); - - try - { - var processInfo = new ProcessStartInfo - { - FileName = "cmd.exe", - Arguments = $"/c \"{batchFilePath}\"", - WindowStyle = ProcessWindowStyle.Hidden, - UseShellExecute = false, - CreateNoWindow = true - }; - - Process.Start(processInfo); - Application.Current.Shutdown(); - } - catch (Exception ex) - { - ShowError($"启动更新脚本进程失败: {ex.Message}"); - } - } - catch (Exception ex) - { - ShowError($"更新失败: {ex.Message}"); - throw; - } - } - - private async Task DownloadFileWithProgress(string downloadUrl, CancellationToken cancellationToken) - { - var tempFile = Path.GetTempFileName() + ".zip"; - - try - { - using var response = await _httpClient.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken); - response.EnsureSuccessStatusCode(); - - var contentLength = response.Content.Headers.ContentLength; - UpdateProgress("开始下载更新文件...", 0); - - using var stream = await response.Content.ReadAsStreamAsync(cancellationToken); - using var fileStream = new FileStream(tempFile, FileMode.Create); - - var buffer = new byte[8192]; - var totalBytesRead = 0L; - var lastUpdateBytes = 0L; - var updateIntervalBytes = contentLength.HasValue ? Math.Max(1024 * 1024, contentLength.Value / 100) : 1024 * 1024; - int bytesRead; - - UpdateProgress($"准备下载: {GetSizeString(contentLength ?? 0)}", 0); - - while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0) - { - await fileStream.WriteAsync(buffer, 0, bytesRead, cancellationToken); - totalBytesRead += bytesRead; - - if (totalBytesRead - lastUpdateBytes >= updateIntervalBytes || totalBytesRead == contentLength) - { - if (contentLength.HasValue) - { - var progressPercentage = (int)((totalBytesRead * 100) / contentLength.Value); - UpdateProgress($"下载中: {progressPercentage}%", progressPercentage); - } - else - { - UpdateProgress($"下载中: {GetSizeString(totalBytesRead)}", 0); - } - - lastUpdateBytes = totalBytesRead; - } - } - - UpdateProgress("下载完成,准备更新...", 100); - return tempFile; - } - catch (OperationCanceledException) - { - if (File.Exists(tempFile)) - { - File.Delete(tempFile); - } - throw; - } - catch (Exception ex) - { - if (File.Exists(tempFile)) - { - File.Delete(tempFile); - } - - ShowError($"下载文件失败: {ex.Message}"); - throw; - } - } - - private string GetSizeString(long bytes) - { - if (bytes < 1024) return $"{bytes} B"; - if (bytes < 1024 * 1024) return $"{bytes / 1024.0:F1} KB"; - return $"{bytes / (1024.0 * 1024):F1} MB"; - } - - private bool ValidateFile(string filePath, string expectedMd5, string expectedSha256) - { - try - { - using var md5 = MD5.Create(); - using var sha256 = SHA256.Create(); - using var stream = File.OpenRead(filePath); - - var actualMd5 = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLowerInvariant(); - stream.Position = 0; - var actualSha256 = BitConverter.ToString(sha256.ComputeHash(stream)).Replace("-", "").ToLowerInvariant(); - - return actualMd5 == expectedMd5 && actualSha256 == expectedSha256; - } - catch - { - return false; - } - } - - private void ShowProgressWindow(string message) - { - ExecuteOnUIThread(() => - { - _progressWindow = new ProgressWindow { Owner = Application.Current.MainWindow }; - _progressWindow.UpdateStatus(message); - _progressWindow.Show(); - }); - } - - private void UpdateProgress(string message, int progress) - { - ExecuteOnUIThread(() => - { - if (_progressWindow != null && _progressWindow.IsVisible) - { - _progressWindow.UpdateStatus(message); - _progressWindow.UpdateProgress(progress); - } - }); - } - - private void CloseProgressWindow() - { - ExecuteOnUIThread(() => - { - _progressWindow?.Close(); - _progressWindow = null; - }); - } - - private Task ExecuteOnUIThread(Action action) - { - if (Application.Current == null) - { - action(); - return Task.CompletedTask; - } - - if (Application.Current.Dispatcher.CheckAccess()) - { - action(); - return Task.CompletedTask; - } - else - { - return Application.Current.Dispatcher.InvokeAsync(action).Task; - } - } - - private void ShowMessage(string message) - { - ExecuteOnUIThread(() => - { - MessageBox.Show(message, "CRSim", MessageBoxButton.OK, MessageBoxImage.Information); - }); - } - - private void ShowError(string message) - { - ExecuteOnUIThread(() => - { - MessageBox.Show(message, "CRSim - Error", MessageBoxButton.OK, MessageBoxImage.Error); - }); - } - - private bool ShowQuestion(string message) - { - var result = false; - - ExecuteOnUIThread(() => - { - result = MessageBox.Show(message, "CRSim", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes; - }).Wait(); - - return result; - } - } - - public class ProgressWindow : Window - { - private readonly TextBlock _statusText; - private readonly ProgressBar _progressBar; - - public ProgressWindow() - { - Title = "更新进度"; - Width = 400; - Height = 150; - WindowStartupLocation = WindowStartupLocation.CenterOwner; - ResizeMode = ResizeMode.NoResize; - ShowInTaskbar = false; - - var stackPanel = new StackPanel { Margin = new Thickness(10) }; - - _statusText = new TextBlock - { - Text = "准备中...", - TextWrapping = TextWrapping.Wrap, - Margin = new Thickness(0, 10, 0, 20) - }; - - _progressBar = new ProgressBar - { - Minimum = 0, - Maximum = 100, - Value = 0, - Height = 20 - }; - - stackPanel.Children.Add(_statusText); - stackPanel.Children.Add(_progressBar); - - Content = stackPanel; - } - - public void UpdateStatus(string message) - { - _statusText.Text = message; - } - - public void UpdateProgress(int value) - { - _progressBar.Value = value; - } - } - - public class VersionInfo - { - public string status_code { get; set; } - public string message { get; set; } - public string ver { get; set; } - public string download_file { get; set; } - public string file_md5 { get; set; } - public string file_sha256 { get; set; } - public string log { get; set; } - } -} \ No newline at end of file diff --git a/CRSim/Views/Windows/Dialogs/TrainStopDialog.xaml.cs b/CRSim/Views/Windows/Dialogs/TrainStopDialog.xaml.cs deleted file mode 100644 index d5cfe06..0000000 --- a/CRSim/Views/Windows/Dialogs/TrainStopDialog.xaml.cs +++ /dev/null @@ -1,273 +0,0 @@ -using CRSim.Core.Models; - -namespace CRSim.Views -{ - /// - /// UserInputDialog.xaml 的交互逻辑 - /// - public partial class TrainStopDialog : Window - { - public class ticketCheck - { - public string TicketCheck { get; set; } - public bool Checked { get; set; } = false; - } - - public ObservableCollection Landmarks { get; set; } = ["无", "红色", "绿色", "褐色", "蓝色", "紫色", "黄色", "橙色"]; - - public TrainStop GeneratedTrainStop; - - public ObservableCollection TicketChecksList { get; set; } = []; - - public ObservableCollection Platforms { get; set; } = []; - - public TrainStopDialog(List ticketChecks,List platforms) - { - DataContext = this; - WindowChrome.SetWindowChrome( - this, - new WindowChrome - { - CaptionHeight = 50, - CornerRadius = default, - GlassFrameThickness = new Thickness(-1), - ResizeBorderThickness = ResizeMode == ResizeMode.NoResize ? default : new Thickness(4), - UseAeroCaptionButtons = true - } - ); - InitializeComponent(); - IntermediateStation.IsChecked = true; - LengthTextBox.Text = "16"; - TicketChecksList.Clear(); - foreach (string s in ticketChecks) - { - TicketChecksList.Add(new ticketCheck() - { - TicketCheck = s, - Checked = false - }); - } - foreach (string s in platforms) - { - Platforms.Add(s); - } - ValidateInput(); - } - - public TrainStopDialog(List ticketChecks, List platforms, TrainStop trainStop) - { - DataContext = this; - WindowChrome.SetWindowChrome( - this, - new WindowChrome - { - CaptionHeight = 50, - CornerRadius = default, - GlassFrameThickness = new Thickness(-1), - ResizeBorderThickness = ResizeMode == ResizeMode.NoResize ? default : new Thickness(4), - UseAeroCaptionButtons = true - } - ); - InitializeComponent(); - NumberTextBox.IsEnabled = false; - NumberTextBox.Text = trainStop.Number; - ArrivalTextBox.Text = trainStop.Terminal; - DepartureTextBox.Text = trainStop.Origin; - LengthTextBox.Text = trainStop.Length.ToString(); - StationKindPanel.IsEnabled = false; - if (trainStop.ArrivalTime != null) - { - StartHour.Text = trainStop.ArrivalTime.Value.Hours.ToString(); - StartMinute.Text = trainStop.ArrivalTime.Value.Minutes.ToString(); - } - else - { - StartingStation.IsChecked = true; - } - if (trainStop.DepartureTime != null) - { - EndHour.Text = trainStop.DepartureTime.Value.Hours.ToString(); - EndMinute.Text = trainStop.DepartureTime.Value.Minutes.ToString(); - } - else - { - FinalStation.IsChecked = true; - } - if(!StartingStation.IsChecked.Value && !FinalStation.IsChecked.Value) - { - IntermediateStation.IsChecked = true; - } - TicketChecksList.Clear(); - foreach (string s in ticketChecks) - { - TicketChecksList.Add(new ticketCheck() - { - TicketCheck = s, - Checked = trainStop.TicketChecks.Contains(s) - }); - } - foreach (string s in platforms) - { - Platforms.Add(s); - } - PlatformComboBox.SelectedIndex = Platforms.IndexOf(trainStop.Platform); - LandmarkComboBox.SelectedIndex = trainStop.Landmark == null ? 0 : Landmarks.IndexOf(trainStop.Landmark); - ValidateInput(); - } - - private void OkButton_Click(object sender, RoutedEventArgs e) - { - GeneratedTrainStop = new TrainStop - { - Number = NumberTextBox.Text, - Terminal = ArrivalTextBox.Text, - Origin = DepartureTextBox.Text, - ArrivalTime = StartHour.IsEnabled ? TimeSpan.Parse($"{StartHour.Text}:{StartMinute.Text}") : null, - DepartureTime = EndHour.IsEnabled ? TimeSpan.Parse($"{EndHour.Text}:{EndMinute.Text}") : null, - WaitingArea = TicketChecksList.Where(x => x.Checked).FirstOrDefault()?.TicketCheck.Split(" - ")[0] ?? string.Empty, - TicketChecks = [.. TicketChecksList.Where(x => x.Checked).Select(x => x.TicketCheck.Split(" - ")[1])], - Platform = (string)PlatformComboBox.SelectedItem, - Length = int.Parse(LengthTextBox.Text), - Landmark = (string)LandmarkComboBox.SelectedItem == "无" ? null : (string)LandmarkComboBox.SelectedItem, - }; - DialogResult = true; - Close(); - } - - private void CancelButton_Click(object sender, RoutedEventArgs e) - { - DialogResult = false; - Close(); - } - - private void StartHour_TextChanged(object sender, TextChangedEventArgs e) - { - ValidateInput(); - if (StartHour.Text.Length == 2) StartMinute.Focus(); - } - - private void StartMinute_TextChanged(object sender, TextChangedEventArgs e) - { - ValidateInput(); - if (StartMinute.Text.Length == 2) EndHour.Focus(); - } - - private void EndHour_TextChanged(object sender, TextChangedEventArgs e) - { - ValidateInput(); - if (EndHour.Text.Length == 2) EndMinute.Focus(); - } - - private void EndMinute_TextChanged(object sender, TextChangedEventArgs e) - { - ValidateInput(); - if (EndMinute.Text.Length == 2) AccentButton.Focus(); - } - - private void CheckBox_Checked(object sender, RoutedEventArgs e) - { - ValidateInput(); - } - - private void CheckBox_Unchecked(object sender, RoutedEventArgs e) - { - ValidateInput(); - } - - private static bool ValidateTime(string input, int maxValue) - { - if (!string.IsNullOrWhiteSpace(input) && int.TryParse(input, null, out int time)) - { - return 0 <= time && time < maxValue; - } - return false; - } - - private void ValidateInput() - { - // 检查四个文本框是否非空 - bool areTextBoxesFilled = - (!StartHour.IsEnabled || ValidateTime(StartHour.Text, 24)) && - (!StartMinute.IsEnabled || ValidateTime(StartMinute.Text, 60)) && - (!EndHour.IsEnabled || ValidateTime(EndHour.Text, 24)) && - (!EndMinute.IsEnabled || ValidateTime(EndMinute.Text, 60)); - - AccentButton.IsEnabled = - (!TicketChecksCheckList.IsEnabled || - (TicketChecksList.Any(x => x.Checked) && TicketChecksList.Where(x=>x.Checked).Select(x=>x.TicketCheck.Split(" - ")[0]).Distinct().Count() <= 1)) && - areTextBoxesFilled && - !string.IsNullOrWhiteSpace(NumberTextBox.Text) && - !string.IsNullOrWhiteSpace(ArrivalTextBox.Text) && - !string.IsNullOrWhiteSpace(DepartureTextBox.Text) && - int.TryParse(LengthTextBox.Text, out int i) && i > 0 && - PlatformComboBox.SelectedItem != null; - } - - private T FindVisualChild(DependencyObject obj) where T : DependencyObject - { - if (obj == null) - return null; - - for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) - { - DependencyObject child = VisualTreeHelper.GetChild(obj, i); - if (child is T t) - { - return t; - } - else - { - T childOfChild = FindVisualChild(child); - if (childOfChild != null) - return childOfChild; - } - } - return null; - } - - private void StartingStation_Checked(object sender, RoutedEventArgs e) - { - if (StartHour == null) return; - StartHour.IsEnabled = false; - StartMinute.IsEnabled = false; - EndHour.IsEnabled = true; - EndMinute.IsEnabled = true; - TicketChecksCheckList.IsEnabled = true; - } - - private void IntermediateStation_Checked(object sender, RoutedEventArgs e) - { - if (StartHour == null) return; - StartHour.IsEnabled = true; - StartMinute.IsEnabled = true; - EndHour.IsEnabled = true; - EndMinute.IsEnabled = true; - TicketChecksCheckList.IsEnabled = true; - } - - private void FinalStation_Checked(object sender, RoutedEventArgs e) - { - if (StartHour == null) return; - StartHour.IsEnabled = true; - StartMinute.IsEnabled = true; - EndHour.IsEnabled = false; - EndMinute.IsEnabled = false; - TicketChecksCheckList.IsEnabled = false; - } - - private void TicketChecksCheckList_PreviewMouseWheel(object sender, MouseWheelEventArgs e) - { - var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) - { - RoutedEvent = UIElement.MouseWheelEvent, - Source = sender - }; - TicketChecksCheckList.RaiseEvent(eventArg); - } - - private void NumberTextBox_TextChanged(object sender, TextChangedEventArgs e) - { - ValidateInput(); - } - } -} \ No newline at end of file