feat: 新增天津站站台看版

This commit is contained in:
denglihong2007
2025-03-09 15:15:30 +08:00
parent c13d35cd60
commit 6596cd8777
14 changed files with 288 additions and 13 deletions

1
.gitattributes vendored
View File

@@ -2,6 +2,7 @@
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
*.cs text eol=lf working-tree-encoding=UTF-8
###############################################################################
# Set default behavior for command prompt diff.

View File

@@ -21,11 +21,6 @@ jobs:
with:
fetch-depth: 0 # 获取全部提交历史以便比较标签
- name: Setup .NET 9.0
uses: actions/setup-dotnet@v3
with:
dotnet-version: '9.0.x'
- name: Extract version from csproj
id: get_version
shell: pwsh
@@ -73,6 +68,12 @@ jobs:
with:
dotnet-version: '9.0.x'
- name: Set Encoding
run: |
echo "DOTNET_CLI_UI_LANGUAGE=zh-CN" >> $GITHUB_ENV
chcp 65001
- name: Restore and Build
run: |
dotnet restore

View File

@@ -59,6 +59,8 @@
services.AddTransient<Views.Jinanxi.SmallScreenView>();
services.AddTransient<ViewModels.GuangdongIntercity.SecondaryScreenViewModel>();
services.AddTransient<Views.GuangdongIntercity.SecondaryScreenView>();
services.AddTransient<ViewModels.Tianjin.PlatformScreenViewModel>();
services.AddTransient<Views.Tianjin.PlatformScreenView>();
}).Build();
[STAThread]

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -9,11 +9,13 @@
<LangVersion>13.0</LangVersion>
<StartupObject>CRSim.App</StartupObject>
<ApplicationIcon>Assets\CRSimIcon.ico</ApplicationIcon>
<Version>1.2.5.0</Version>
<Version>1.2.6.0</Version>
</PropertyGroup>
<ItemGroup>
<ApplicationDefinition Remove="App.xaml" />
<None Remove="Assets\StyleImages\Tianjin\image.png" />
<None Remove="Assets\StyleImages\Tianjin\PlatformScreen.png" />
<Content Include="Assets\Advertisement.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -42,6 +44,8 @@
<Resource Include="Assets\StyleImages\Harbin\PrimaryScreen.png" />
<Resource Include="Assets\StyleImages\Jinanxi\SmallScreen.png" />
<Resource Include="Assets\StyleImages\Shanghai\OutsideScreen.png" />
<Resource Include="Assets\StyleImages\Tianjin\image.png" />
<Resource Include="Assets\StyleImages\Tianjin\PlatformScreen.png" />
<Resource Include="Assets\StyleImages\Zibo\PrimaryScreen.png" />
<Resource Include="Assets\StyleImages\Zibo\SecondaryScreen.png" />
<Resource Include="Assets\win11-dashboard.dark.png" />
@@ -78,6 +82,9 @@
<Compile Update="Views\Windows\Stations\ChengduDong\PrimaryTicketCheckScreenView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Windows\Stations\Tianjin\PlatformScreenView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Windows\Stations\Hanzhong\PlatformScreenView.xaml.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -0,0 +1,32 @@
namespace CRSim.Converters
{
public class LocationToStringConverter : IMultiValueConverter
{
object IMultiValueConverter.Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values[0] is int Length&& values[1] is int Location)
{
if (Location > Length)
{
return $"当前无车1-{Length}车向后。";
}
if (Location == Length)
{
return $"当前{Length}车1-{Length-1}车向后。";
}
if (Location == 1)
{
return $"当前1车2-{Length}车向前。";
}
return $"当前{Location}车1-{Location - 1}车向前,{Location + 1}-{Length}车向后。";
}
return string.Empty;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
// 通常不需要实现 ConvertBack
return null;
}
}
}

View File

@@ -87,6 +87,18 @@
"Text"
]
},
{
"UniqueId": "Tianjin PlatformScreen",
"Title": "天津站站台看板",
"Station": "Tianjin",
"StyleName": "PlatformScreenView",
"ImagePath": "Assets/StyleImages/Tianjin/PlatformScreen.png",
"Parameters": [
"Station",
"Platform",
"Location"
]
},
{
"UniqueId": "Zibo PrimaryScreen",
"Title": "淄博站主要看板",

View File

@@ -28,6 +28,9 @@ public partial class ScreenSimulationPageViewModel : ObservableObject
[ObservableProperty]
private bool _textNeeded;
[ObservableProperty]
private bool _locationNeeded;
[ObservableProperty]
private string _text = "";
@@ -37,9 +40,12 @@ public partial class ScreenSimulationPageViewModel : ObservableObject
public string SelectedPlatformName = "";
public int SelectedLoaction = 0;
public ObservableCollection<string> StationNames { get; private set; } = [];
public ObservableCollection<string> TicketChecks { get; private set; } = [];
public ObservableCollection<Platform> Platforms { get; private set; } = [];
public ObservableCollection<int> Locations { get; private set; } = [];
[ObservableProperty]
private bool _isStartSimulationAvailable = false;
@@ -62,9 +68,10 @@ public partial class ScreenSimulationPageViewModel : ObservableObject
private void CheckCanStart()
{
IsStartSimulationAvailable = selectedStyle!=null &&
(!StationNeeded || !string.IsNullOrWhiteSpace(SelectedStationName))&&
IsStartSimulationAvailable = selectedStyle != null &&
(!StationNeeded || !string.IsNullOrWhiteSpace(SelectedStationName)) &&
(!TicketCheckNeeded || !string.IsNullOrWhiteSpace(SelectedTicketCheck)) &&
(!LocationNeeded || SelectedLoaction != 0) &&
(!PlatformNeeded || !string.IsNullOrWhiteSpace(SelectedPlatformName));
}
@@ -80,27 +87,31 @@ public partial class ScreenSimulationPageViewModel : ObservableObject
TicketCheckNeeded = neededParameters.Contains("TicketCheck");
PlatformNeeded = neededParameters.Contains("Platform");
TextNeeded = neededParameters.Contains("Text");
LocationNeeded = neededParameters.Contains("Location");
}
CheckCanStart();
}
[RelayCommand]
public void SelectStation(object s)
{
if(s is string station)
if(s is string v)
{
SelectedStationName = station;
var station = _databaseService.GetStationByName(v);
SelectedStationName = station.Name;
SelectedPlatformName = "";
SelectedTicketCheck = "";
SelectedLoaction = 0;
TicketChecks.Clear();
foreach(string ticketCheck in _databaseService.GetStationByName(SelectedStationName).TicketChecks)
foreach(string ticketCheck in station.TicketChecks)
{
TicketChecks.Add(ticketCheck);
}
Platforms.Clear();
foreach (var platform in _databaseService.GetStationByName(SelectedStationName).Platforms)
foreach (var platform in station.Platforms)
{
Platforms.Add(platform);
}
Locations.Clear();
}
CheckCanStart();
}
@@ -114,11 +125,26 @@ public partial class ScreenSimulationPageViewModel : ObservableObject
CheckCanStart();
}
[RelayCommand]
public void SelectLocation(object s)
{
if (s is int location)
{
SelectedLoaction = location;
}
CheckCanStart();
}
[RelayCommand]
public void SelectPlatform(object s)
{
if (s is Platform platform)
{
SelectedPlatformName = platform.Name;
SelectedLoaction = 0;
Locations.Clear();
for (int i = 1; i <= platform.Length; i++)
{
Locations.Add(i);
}
}
CheckCanStart();
}
@@ -131,6 +157,10 @@ public partial class ScreenSimulationPageViewModel : ObservableObject
{
Window.ViewModel.Text = Text;
}
if (LocationNeeded && SelectedLoaction != 0)
{
Window.ViewModel.Location = SelectedLoaction;
}
Window.ViewModel.LoadData(_databaseService.GetStationByName(SelectedStationName),
TicketCheckNeeded ? SelectedTicketCheck : string.Empty,

View File

@@ -14,7 +14,11 @@ namespace CRSim.ViewModels
[ObservableProperty]
private string _text = "";
[ObservableProperty]
public int _location;
[ObservableProperty]
private Station _thisStation;
[ObservableProperty]
private string _thisPlatform;
public event PropertyChangedEventHandler PropertyChanged;
public List<TrainInfo> TrainInfo { get; set; } = [];
@@ -55,6 +59,7 @@ namespace CRSim.ViewModels
public void LoadData(Station station,string ticketCheck,string platform)
{
ThisStation = station;
ThisPlatform = platform;
var trains = station.StationStops;
foreach (var trainNumber in trains)
{

View File

@@ -0,0 +1,41 @@
namespace CRSim.ViewModels.Tianjin
{
public class PlatformScreenViewModel : ScreenViewModel
{
private ITimeService _timeService;
public ObservableCollection<TrainInfo> Screen { get; set; } = [];
public PlatformScreenViewModel(ITimeService timeService, ISettingsService settingsService)
: base(timeService, settingsService)
{
_timeService = timeService;
timeService.RefreshSecondsElapsed += RefreshDisplay;
Initialize();
}
private async void Initialize()
{
await WaitForDataLoadAsync();
Text = ThisPlatform;
RefreshDisplay(null,null);
}
private void RefreshDisplay(object? sender, EventArgs e)
{
Application.Current.Dispatcher.Invoke(() =>
{
Screen.Add(TrainInfo.Count > 0 ? TrainInfo[0] : new());
if (Screen.Count == 1) return;
Screen.RemoveAt(0);
});
}
public override void RefreshData(object? sender, EventArgs e)
{
if (CurrentPageIndex == 0)
{
List<TrainInfo> itemsToRemove = [.. TrainInfo.Where(info => info.DepartureTime < _timeService.GetDateTimeNow())];
foreach (var item in itemsToRemove)
{
TrainInfo.Remove(item);
}
}
}
}
}

View File

@@ -125,7 +125,6 @@
</ComboBox>
</Grid>
</Border>
<Border Style="{StaticResource SettingsCardStyle}" Visibility="{Binding ViewModel.TicketCheckNeeded,Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid>
<Grid.ColumnDefinitions>
@@ -144,6 +143,25 @@
</ComboBox>
</Grid>
</Border>
<Border Style="{StaticResource SettingsCardStyle}" Visibility="{Binding ViewModel.LocationNeeded,Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="位置" Style="{StaticResource BodyTextBlockStyle}" VerticalAlignment="Center"/>
<ComboBox Grid.Column="2" MinWidth="128" ItemsSource="{Binding ViewModel.Locations}" x:Name="LocationsComboBox">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ViewModel.SelectLocationCommand}"
CommandParameter="{Binding SelectedItem,ElementName=LocationsComboBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</Grid>
</Border>
<Border Style="{StaticResource BottomSettingsCardStyle}">
<Grid IsEnabled="{Binding ViewModel.TextNeeded}">
<Grid.ColumnDefinitions>

View File

@@ -0,0 +1,93 @@
<Window x:Class="CRSim.Views.Tianjin.PlatformScreenView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CRSim.Views.Tianjin"
mc:Ignorable="d"
xmlns:converters="clr-namespace:CRSim.Converters"
FontFamily="黑体" FontSize="28"
Title="引导屏" SizeToContent="WidthAndHeight"
WindowStyle="None" AllowsTransparency="True" Background="Black"
KeyDown="Window_KeyDown"
ResizeMode="NoResize" MouseDown="Window_MouseDown">
<Window.Resources>
<converters:DateTimeToStringConverter x:Key="DateTimeToStringConverter" Format="HH:mm" />
<converters:LocationToStringConverter x:Key="LocationToStringConverter" />
</Window.Resources>
<StackPanel Orientation="Horizontal">
<Grid Width="100">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Text}" Foreground="Yellow" FontWeight="Bold" FontSize="64" TextAlignment="Center"/>
<TextBlock Grid.Row="1" Text="站台" Foreground="Yellow" TextAlignment="Center" FontSize="32"/>
<TextBlock Grid.Row="2" Text="platform" Foreground="Yellow" FontSize="12" TextAlignment="Center" Margin="0,0,0,8"/>
</Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="22"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Height="44">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" CornerRadius="4,0,0,4" Background="#830DFF">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Screen[0].TrainNumber}" Foreground="White" VerticalAlignment="Center" Margin="8,0,0,0"/>
<TextBlock Text="次" Foreground="White" VerticalAlignment="Center" Margin="20,0"/>
</StackPanel>
</Border>
<Rectangle Grid.Column="1" Fill="#830DFF"/>
<Border Grid.Column="2" CornerRadius="0,4,4,0" Background="Yellow" x:Name="Panel">
<StackPanel Orientation="Horizontal">
<Image Grid.Column="0" Source="pack://application:,,,/Assets/StyleImages/Tianjin/Image.png" Height="{Binding ActualHeight,ElementName=Panel}"/>
<TextBlock Grid.Column="1" Text="{Binding Screen[0].DepartureTime,Converter={StaticResource DateTimeToStringConverter}}" Foreground="Black" VerticalAlignment="Center" Padding="12,0,64,0"/>
</StackPanel>
</Border>
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" TextAlignment="Center" Text="{Binding Screen[0].Origin}" FontSize="32" Foreground="White" FontWeight="Bold"/>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Text="开往" Foreground="White" TextAlignment="Center" FontSize="22"/>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Width="64" Height="1.6" Fill="White" />
<Polygon Grid.Column="1" Points="0,0 0,8 8.66,4" Fill="White" Margin="0"/>
</Grid>
</Grid>
<TextBlock Grid.Column="2" TextAlignment="Center" Text="{Binding Screen[0].Terminal}" FontSize="32" Foreground="White" FontWeight="Bold"/>
</Grid>
<Border Grid.Row="3" CornerRadius="8" Background="#830DFF">
<TextBlock TextAlignment="Center" Foreground="White" FontSize="20" Padding="2">
<TextBlock.Text>
<MultiBinding Mode="OneWay" Converter="{StaticResource LocationToStringConverter}">
<Binding Path="Screen[0].Length" />
<Binding Path="Location" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Border>
</Grid>
</StackPanel>
</Window>

View File

@@ -0,0 +1,33 @@
using CRSim.ViewModels.Tianjin;
namespace CRSim.Views.Tianjin
{
/// <summary>
/// SecondaryScreen.xaml 的交互逻辑
/// </summary>
public partial class PlatformScreenView : Window
{
public PlatformScreenViewModel ViewModel { get; }
public PlatformScreenView(PlatformScreenViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
DataContext = viewModel;
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
DragMove();
}
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
Close();
}
}
}
}