mirror of
https://github.com/denglihong2007/CRSim
synced 2026-08-12 04:35:39 +08:00
feat: 添加pyETRC/qETRC文件导入支持
This commit is contained in:
@@ -90,8 +90,8 @@ namespace CRSim
|
||||
|
||||
private void UpdateWindowBackground()
|
||||
{
|
||||
if ((!Utility.IsBackdropDisabled() &&
|
||||
!Utility.IsBackdropSupported()))
|
||||
if ((!Utilities.IsBackdropDisabled() &&
|
||||
!Utilities.IsBackdropSupported()))
|
||||
{
|
||||
this.SetResourceReference(BackgroundProperty, "WindowBackground");
|
||||
}
|
||||
@@ -110,7 +110,7 @@ namespace CRSim
|
||||
}
|
||||
private void UpdateTitleBarButtonsVisibility()
|
||||
{
|
||||
if (Utility.IsBackdropDisabled() || !Utility.IsBackdropSupported() ||
|
||||
if (Utilities.IsBackdropDisabled() || !Utilities.IsBackdropSupported() ||
|
||||
SystemParameters.HighContrast == true)
|
||||
{
|
||||
MinimizeButton.Visibility = Visibility.Visible;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace CRSim
|
||||
{
|
||||
internal static class Utility
|
||||
internal static class Utilities
|
||||
{
|
||||
public static bool IsBackdropSupported()
|
||||
{
|
||||
@@ -22,6 +22,12 @@ namespace CRSim
|
||||
|
||||
return disableFluentThemeWindowBackdrop;
|
||||
}
|
||||
public static TimeSpan RoundToMinute(string timeString)
|
||||
{
|
||||
if (TimeSpan.TryParse(timeString, out var time))
|
||||
return TimeSpan.FromMinutes(Math.Round(time.TotalMinutes));
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using CRSim.Core.Models;
|
||||
using OfficeOpenXml;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
|
||||
namespace CRSim.ViewModels;
|
||||
|
||||
@@ -333,6 +334,82 @@ public partial class StationManagementPageViewModel : ObservableObject
|
||||
_dialogService.ShowMessage("导入失败", "文件格式错误或被占用。");
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
public async Task ImportFrompyETRC()
|
||||
{
|
||||
if (!CheckCanImport()) return;
|
||||
|
||||
var path = _dialogService.GetFile("pyETRC 运行图文件 (*.pyetgr;*.json)|*.pyetgr;*.json|pyETRC 车次数据库文件 (*.pyetdb;*.json)|*.pyetdb;*.json|所有文件 (*.*)|*.*");
|
||||
if (path == null) return;
|
||||
try
|
||||
{
|
||||
using var fs = File.OpenRead(path);
|
||||
var doc = await JsonDocument.ParseAsync(fs);
|
||||
|
||||
var root = doc.RootElement;
|
||||
if (!root.TryGetProperty("trains", out var trains)) return;
|
||||
|
||||
foreach (var train in trains.EnumerateArray())
|
||||
{
|
||||
if (!train.TryGetProperty("timetable", out var timetable)) continue;
|
||||
var stops = timetable.EnumerateArray().ToArray();
|
||||
if (stops.Length == 0) continue;
|
||||
|
||||
string origin = stops[0].GetProperty("zhanming").GetString();
|
||||
string terminal = stops[^1].GetProperty("zhanming").GetString();
|
||||
|
||||
TimeSpan? arrivalTime = null;
|
||||
TimeSpan? departureTime = null;
|
||||
|
||||
foreach (var stop in stops)
|
||||
{
|
||||
string name = stop.GetProperty("zhanming").GetString();
|
||||
if (name != SelectedStation.Name) continue;
|
||||
|
||||
string cfsj = stop.GetProperty("cfsj").GetString();
|
||||
string ddsj = stop.GetProperty("ddsj").GetString();
|
||||
|
||||
if (cfsj == ddsj)
|
||||
{
|
||||
if (name == origin)
|
||||
{
|
||||
departureTime = Utilities.RoundToMinute(cfsj);
|
||||
arrivalTime = null;
|
||||
}
|
||||
else if (name == terminal)
|
||||
{
|
||||
departureTime = null;
|
||||
arrivalTime = Utilities.RoundToMinute(ddsj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
departureTime = Utilities.RoundToMinute(cfsj);
|
||||
arrivalTime = Utilities.RoundToMinute(ddsj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (arrivalTime == null && departureTime == null) continue;
|
||||
string number = train.GetProperty("checi").EnumerateArray().FirstOrDefault().GetString()?.Split('/')?.FirstOrDefault() ?? string.Empty;
|
||||
|
||||
var trainStop = new TrainStop
|
||||
{
|
||||
Number = number,
|
||||
Origin = origin,
|
||||
Terminal = terminal,
|
||||
ArrivalTime = arrivalTime,
|
||||
DepartureTime = departureTime,
|
||||
};
|
||||
|
||||
TrainStops.Add(RandomTrainStopProperties(trainStop));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_dialogService.ShowMessage("导入失败", "文件格式错误或被占用。");
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void ImportFromExcel()
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using OfficeOpenXml;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace CRSim.ViewModels;
|
||||
|
||||
@@ -191,30 +192,7 @@ public partial class TrainNumberManagementPageViewModel : ObservableObject
|
||||
await Task.Delay(100);
|
||||
timeTable ??= [];
|
||||
_databaseService.AddTrainNumber(number);
|
||||
var sections = new List<Section>();
|
||||
var isEmu = number.StartsWith('G') || number.StartsWith('D') || number.StartsWith('C');
|
||||
for (int i = 1; i < timeTable.Count; i++)
|
||||
{
|
||||
sections.Add(new Section
|
||||
{
|
||||
From = timeTable[i - 1].Station,
|
||||
To = timeTable[i].Station,
|
||||
Tickets = new Tickets
|
||||
{
|
||||
SW = isEmu ? new() : null,
|
||||
ZYY = isEmu ? new() : null,
|
||||
ZY = isEmu ? new() : null,
|
||||
ZE = isEmu ? new() : null,
|
||||
RZ = !isEmu ? new() : null,
|
||||
GRW = !isEmu ? new() : null,
|
||||
RW = !isEmu ? new() : null,
|
||||
WZ = new(),
|
||||
YW = !isEmu ? new() : null,
|
||||
YZ = !isEmu ? new() : null
|
||||
}
|
||||
});
|
||||
}
|
||||
_databaseService.UpdateTrainNumber(_databaseService.GetTrainNumberByNumber(number), timeTable, sections);
|
||||
_databaseService.UpdateTrainNumber(_databaseService.GetTrainNumberByNumber(number), timeTable, GenerateSections(number,timeTable));
|
||||
}
|
||||
ProgressValue = 0;
|
||||
await _databaseService.SaveData();
|
||||
@@ -226,6 +204,62 @@ public partial class TrainNumberManagementPageViewModel : ObservableObject
|
||||
ProgressValue = 0;
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
public async Task ImportFrompyETRC()
|
||||
{
|
||||
if (TrainNumbers.Count != 0)
|
||||
{
|
||||
if (!_dialogService.GetConfirm("当前操作可能覆盖现有车次配置,是否继续?")) return;
|
||||
}
|
||||
var path = _dialogService.GetFile("pyETRC 运行图文件 (*.pyetgr;*.json)|*.pyetgr;*.json|pyETRC 车次数据库文件 (*.pyetdb;*.json)|*.pyetdb;*.json|所有文件 (*.*)|*.*");
|
||||
if (path == null) return;
|
||||
try
|
||||
{
|
||||
using var fs = File.OpenRead(path);
|
||||
var doc = await JsonDocument.ParseAsync(fs);
|
||||
|
||||
var root = doc.RootElement;
|
||||
if (!root.TryGetProperty("trains", out var trains)) return;
|
||||
|
||||
foreach (var train in trains.EnumerateArray())
|
||||
{
|
||||
if (!train.TryGetProperty("timetable", out var timetable)) continue;
|
||||
var stops = timetable.EnumerateArray().ToArray();
|
||||
if (stops.Length == 0) continue;
|
||||
List<TrainStop>? timeTable = [];
|
||||
string number = train.GetProperty("checi").EnumerateArray().FirstOrDefault().GetString()?.Split('/')?.FirstOrDefault();
|
||||
for (int i = 0; i < stops.Length; i++)
|
||||
{
|
||||
TimeSpan? arrivalTime = null;
|
||||
TimeSpan? departureTime = null;
|
||||
var stop = stops[i];
|
||||
string name = stop.GetProperty("zhanming").GetString();
|
||||
string cfsj = stop.GetProperty("cfsj").GetString();
|
||||
string ddsj = stop.GetProperty("ddsj").GetString();
|
||||
if (i != 0) arrivalTime = Utilities.RoundToMinute(ddsj);
|
||||
if (i != stops.Length-1) departureTime = Utilities.RoundToMinute(cfsj);
|
||||
if (arrivalTime == departureTime) continue;
|
||||
timeTable.Add(new TrainStop
|
||||
{
|
||||
Station = name,
|
||||
ArrivalTime = arrivalTime,
|
||||
DepartureTime = departureTime,
|
||||
});
|
||||
}
|
||||
if (!TrainNumbers.Select(x => x.Number).Contains(number))
|
||||
{
|
||||
_databaseService.AddTrainNumber(number);
|
||||
}
|
||||
_databaseService.UpdateTrainNumber(_databaseService.GetTrainNumberByNumber(number), timeTable, GenerateSections(number, timeTable));
|
||||
}
|
||||
await _databaseService.SaveData();
|
||||
RefreshTrainNumbers();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_dialogService.ShowMessage("导入失败", "文件格式错误或被占用。");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TimeTable
|
||||
@@ -418,6 +452,34 @@ public partial class TrainNumberManagementPageViewModel : ObservableObject
|
||||
#endregion
|
||||
|
||||
#region Sections
|
||||
private static List<Section> GenerateSections(string number,List<TrainStop> timeTable)
|
||||
{
|
||||
var sections = new List<Section>();
|
||||
var isEmu = number.StartsWith('G') || number.StartsWith('D') || number.StartsWith('C');
|
||||
for (int i = 1; i < timeTable.Count; i++)
|
||||
{
|
||||
sections.Add(new Section
|
||||
{
|
||||
From = timeTable[i - 1].Station,
|
||||
To = timeTable[i].Station,
|
||||
Tickets = new Tickets
|
||||
{
|
||||
SW = isEmu ? new() : null,
|
||||
ZYY = isEmu ? new() : null,
|
||||
ZY = isEmu ? new() : null,
|
||||
ZE = isEmu ? new() : null,
|
||||
RZ = !isEmu ? new() : null,
|
||||
GRW = !isEmu ? new() : null,
|
||||
RW = !isEmu ? new() : null,
|
||||
WZ = new(),
|
||||
YW = !isEmu ? new() : null,
|
||||
YZ = !isEmu ? new() : null
|
||||
}
|
||||
});
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void SeatChecked(object? parameter)
|
||||
{
|
||||
|
||||
@@ -568,6 +568,13 @@
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</MenuItem>
|
||||
<MenuItem Header="从pyETRC/qETRC导入" FontSize="14">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding ViewModel.ImportFrompyETRCCommand}"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</MenuItem>
|
||||
<MenuItem Header="从Excel表格导入" FontSize="14">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
|
||||
@@ -184,6 +184,13 @@
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</MenuItem>
|
||||
<MenuItem Header="从pyETRC/qETRC导入" FontSize="14">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding ViewModel.ImportFrompyETRCCommand}"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user