調整主體架構 20250324

This commit is contained in:
allen.yan 2025-03-24 13:49:48 +08:00
parent 32d47bcf20
commit 7c86f3b6e3
14 changed files with 25 additions and 288 deletions

View File

@ -1,7 +1,7 @@
<Application x:Class="Karaoke_Kingpin.App" <Application x:Class="Karaoke_Kingpin.Controller.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Karaoke_Kingpin" xmlns:local="clr-namespace:Karaoke_Kingpin.Controller"
xmlns:converters="clr-namespace:Karaoke_Kingpin.Converters" xmlns:converters="clr-namespace:Karaoke_Kingpin.Converters"
StartupUri="MainWindow.xaml"> StartupUri="MainWindow.xaml">
<Application.Resources> <Application.Resources>

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
namespace Karaoke_Kingpin namespace Karaoke_Kingpin.Controller
{ {
/// <summary> /// <summary>
/// App.xaml 的互動邏輯 /// App.xaml 的互動邏輯

View File

@ -34,8 +34,9 @@ using ExcelDataReader;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Threading; using System.Windows.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using Karaoke_Kingpin.Models;
namespace Karaoke_Kingpin using Karaoke_Kingpin.Converters;
namespace Karaoke_Kingpin.Controller
{ {
/// <summary> /// <summary>
/// Index.xaml 的互動邏輯 /// Index.xaml 的互動邏輯

View File

@ -9,7 +9,7 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Karaoke_Kingpin namespace Karaoke_Kingpin.Controller
{ {
public class MainViewModel : INotifyPropertyChanged public class MainViewModel : INotifyPropertyChanged
{ {

View File

@ -16,7 +16,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
namespace Karaoke_Kingpin namespace Karaoke_Kingpin.Controller
{ {
/// <summary> /// <summary>
/// MainWindow.xaml 的互動邏輯 /// MainWindow.xaml 的互動邏輯

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
namespace Karaoke_Kingpin namespace Karaoke_Kingpin.Converters
{ {
public class ImagePathConverter : IValueConverter public class ImagePathConverter : IValueConverter
{ {

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Karaoke_Kingpin namespace Karaoke_Kingpin.Converters
{ {
public static class PinyinToZhuyinConverter public static class PinyinToZhuyinConverter
{ {

View File

@ -1,9 +1,10 @@
<Window x:Class="Karaoke_Kingpin.Index" <Window x:Class="Karaoke_Kingpin.Controller.Index"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Karaoke_Kingpin" xmlns:local="clr-namespace:Karaoke_Kingpin.Controller"
xmlns:converters="clr-namespace:Karaoke_Kingpin.Converters"
xmlns:properties="clr-namespace:Karaoke_Kingpin.Properties" xmlns:properties="clr-namespace:Karaoke_Kingpin.Properties"
mc:Ignorable="d" mc:Ignorable="d"
Title="Index" Height="800" Width="950" Title="Index" Height="800" Width="950"
@ -70,7 +71,7 @@
<Rectangle Width="16" Height="16" Fill="{Binding}" /> <Rectangle Width="16" Height="16" Fill="{Binding}" />
</DataTemplate> </DataTemplate>
<local:ImagePathConverter x:Key="ImagePathConverter"/> <converters:ImagePathConverter x:Key="ImagePathConverter"/>
</Window.Resources> </Window.Resources>
<!-- 资源定义结束 --> <!-- 资源定义结束 -->
@ -378,35 +379,6 @@
</Grid> </Grid>
</Grid> </Grid>
</TabItem> </TabItem>
<TabItem Header="包廂設定" Height="19" VerticalAlignment="Top">
<Grid Background="#F4EAD5">
<ItemsControl ItemsSource="{Binding Rooms}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding RoomNumber}" FontWeight="Bold" FontSize="16" HorizontalAlignment="Left" Margin="5,0"/>
<TextBlock Text="{Binding Status}" Foreground="Blue" FontSize="14" HorizontalAlignment="Center" Grid.Row="1"/>
<TextBlock Text="{Binding TimeRange}" FontSize="14" HorizontalAlignment="Center" Grid.Row="2"/>
<Rectangle Fill="Transparent" MouseDown="Rectangle_MouseDown" Grid.Row="0" Grid.RowSpan="3"/>
<Rectangle Width="20" Height="10" HorizontalAlignment="Right" VerticalAlignment="Center" Style="{StaticResource StatusRectangleStyle}" Grid.Row="1"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</TabItem>
<TabItem Header="歌庫目錄" Height="19" VerticalAlignment="Top"> <TabItem Header="歌庫目錄" Height="19" VerticalAlignment="Top">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>

View File

@ -265,8 +265,8 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="ImagePathConverter.cs" /> <Compile Include="Converters\ImagePathConverter.cs" />
<Compile Include="SongData.cs" /> <Compile Include="Models\SongData.cs" />
<Page Include="Index.xaml"> <Page Include="Index.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -275,22 +275,22 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Compile Include="App.xaml.cs"> <Compile Include="Controller\App.cs">
<DependentUpon>App.xaml</DependentUpon> <DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="BitmapToImageSourceConverter.cs" /> <Compile Include="Converters\BitmapToImageSourceConverter.cs" />
<Compile Include="Index.xaml.cs"> <Compile Include="Controller\Index.cs">
<DependentUpon>Index.xaml</DependentUpon> <DependentUpon>Index.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="MainViewModel.cs" /> <Compile Include="Controller\MainViewModel.cs" />
<Compile Include="MainWindow.xaml.cs"> <Compile Include="Controller\MainWindow.cs">
<DependentUpon>MainWindow.xaml</DependentUpon> <DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="PinyinToZhuyinConverter.cs" /> <Compile Include="Converters\PinyinToZhuyinConverter.cs" />
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>

View File

@ -1,9 +1,9 @@
<Window x:Class="Karaoke_Kingpin.MainWindow" <Window x:Class="Karaoke_Kingpin.Controller.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Karaoke_Kingpin" xmlns:local="clr-namespace:Karaoke_Kingpin.Controller"
mc:Ignorable="d" mc:Ignorable="d"
Title="卡拉OK後台管理系統設定" Height="600" Width="900"> Title="卡拉OK後台管理系統設定" Height="600" Width="900">

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Karaoke_Kingpin namespace Karaoke_Kingpin.Models
{ {
public class SongData public class SongData
{ {

View File

@ -1,37 +0,0 @@
<Window x:Class="Karaoke_Kingpin.RoomDetailsWindow"
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:Karaoke_Kingpin"
mc:Ignorable="d"
Title="RoomDetailsWindow" Height="200" Width="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="70"/>
<RowDefinition Height="70"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="6" Background="DarkGray">
<TextBlock Text="{Binding RoomNumber}" FontSize="20" FontWeight="Bold" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
</StackPanel>
<!-- 第一行按钮 -->
<Button Content="開機" Margin="10" Click="Start_Click" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/>
<Button Content="關機" Margin="10" Click="Shutdown_Click" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2"/>
<Button Content="取消" Margin="10" Click="Cancel_Click" Grid.Row="1" Grid.Column="4" Grid.ColumnSpan="2"/>
<!-- 第二行按钮 -->
<Button Content="包廂開帳" Margin="10" Click="OpenAccount_Click" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"/>
<Button Content="包廂關帳" Margin="10" Click="CloseAccount_Click" Grid.Row="2" Grid.Column="3" Grid.ColumnSpan="3"/>
</Grid>
</Window>

View File

@ -1,199 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
namespace Karaoke_Kingpin
{
/// <summary>
/// RoomDetailsWindow.xaml 的互動邏輯
/// </summary>
public partial class RoomDetailsWindow : Window
{
private readonly Room _room;
private readonly TcpServer _tcpServer;
public RoomDetailsWindow(Room room, TcpServer tcpServer)
{
InitializeComponent();
_room = room;
_tcpServer = tcpServer;
DataContext = _room;
CenterWindowOnMainWindow();
// 訂閱 TCP 服務器的命令接收事件
_tcpServer.CommandReceived += HandleCommand;
}
private void CenterWindowOnMainWindow()
{
if (Application.Current.MainWindow != null)
{
this.Owner = Application.Current.MainWindow;
this.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
}
public async void Start_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine($"=== 開始執行開機操作 ===");
string roomNumber = _room.RoomNumber.Substring(1);
Console.WriteLine($"房間號碼: {roomNumber}");
// 保存原始的時間範圍
string originalTimeRange = _room.TimeRange;
await SendTcpSignal(roomNumber, "O");
// 發送完成後,更新房間狀態
_room.Status = "已占用";
_room.TimeRange = originalTimeRange;
// 保存狀態到文件
if (Application.Current.MainWindow is MainWindow mainWindow)
{
mainWindow.SaveRoomsToFile("roomstates.txt");
}
Console.WriteLine($"傳送開機信號 -> 房號: {roomNumber}, 指令: O");
Console.WriteLine($"時間範圍: {_room.TimeRange}");
Console.WriteLine("=== 開機操作完成 ===\n");
}
public async void Shutdown_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine($"=== 開始執行關機操作 ===");
string roomNumber = _room.RoomNumber.Substring(1);
Console.WriteLine($"房間號碼: {roomNumber}");
await SendTcpSignal(roomNumber, "X");
// 手動關機時更新狀態
_room.Status = "可用";
_room.TimeRange = "Not Set";
// 保存狀態到文件
if (Application.Current.MainWindow is MainWindow mainWindow)
{
mainWindow.SaveRoomsToFile("roomstates.txt");
}
Console.WriteLine($"傳送關機信號 -> 房號: {roomNumber}, 指令: X");
Console.WriteLine("=== 關機操作完成 ===\n");
}
// 添加新的方法來處理 TCP 命令
private async void HandleCommand(string roomNumber, string command)
{
await Dispatcher.InvokeAsync(async () =>
{
if (roomNumber == _room.RoomNumber.Substring(1))
{
switch (command)
{
case "O":
await SendTcpSignal(roomNumber, "O");
break;
case "X":
await SendTcpSignal(roomNumber, "X");
break;
}
}
});
}
// 在窗口關閉時取消訂閱事件
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (_tcpServer != null)
{
_tcpServer.CommandReceived -= HandleCommand;
}
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("取消");
}
private void OpenAccount_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("包廂開帳");
}
private void CloseAccount_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("包廂關帳");
}
private async Task SendTcpSignal(string roomNumber, string command)
{
int retryInterval = 10000; // 10秒
int maxDuration = 20 * 60 * 1000; // 20分鐘
int elapsedTime = 0;
bool success = false;
while (elapsedTime < maxDuration && !success)
{
try
{
string message = $"{roomNumber},{command}";
LogToFile($"嘗試發送: {message}");
using (TcpClient client = new TcpClient(_room.RoomPC, 1000))
{
NetworkStream stream = client.GetStream();
byte[] data = Encoding.ASCII.GetBytes(message);
await stream.WriteAsync(data, 0, data.Length);
Console.WriteLine($"房間 {roomNumber} 發送指令: {command}");
success = true;
}
}
catch (Exception ex)
{
Console.WriteLine($"發送失敗10秒後重試");
if (!success)
{
await Task.Delay(retryInterval);
elapsedTime += retryInterval;
}
}
}
if (!success)
{
Console.WriteLine($"房間 {roomNumber} 發送指令失敗: 超過20分鐘重試時間");
}
}
private void LogToFile(string logMessage)
{
string logFilePath = "log.txt"; // 你可以根據需要更改文件路徑
try
{
using (StreamWriter writer = new StreamWriter(logFilePath, true))
{
writer.WriteLine($"{DateTime.Now}: {logMessage}");
}
}
catch (Exception ex)
{
MessageBox.Show($"寫入日誌失敗: {ex.Message}");
}
}
}
}