添加登录ui以及部分交互逻辑

This commit is contained in:
绪山七寻 2025-06-01 22:34:58 +08:00
parent c410cacc65
commit b58016caf4
6 changed files with 230 additions and 58 deletions

View File

@ -1,43 +1,82 @@
<Window x:Class="chatclient.LoginWindow" <Window
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:chatclient" xmlns:local="clr-namespace:chatclient"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" x:Class="chatclient.LoginWindow"
mc:Ignorable="d" mc:Ignorable="d"
Title="LoginWindow" Height="590" Width="360" MinHeight="590" MinWidth="360" MaxHeight="590" MaxWidth="360" Title="LoginWindow" Height="590" Width="360" MinHeight="590" MinWidth="360" MaxHeight="590" MaxWidth="360"
ResizeMode="NoResize"> ResizeMode="NoResize">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="6*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="10"> <TabControl>
<StackPanel> <TabItem Header="登录账号" Cursor="Hand">
<Grid> <Grid Background="#FFE5E5E5">
<materialDesign:PackIcon Kind="LoginVariant" Width="48" Height="48" Margin="54,0,0,0" VerticalAlignment="Center"/> <Grid.RowDefinitions>
<TextBlock Style="{StaticResource MaterialDesignHeadline3TextBlock}" Text="登录" HorizontalAlignment="Left" Margin="107,0,0,4"/> <RowDefinition Height="1.2*"/>
</Grid> <RowDefinition Height="6*"/>
<Grid Width="280"> <RowDefinition Height="0.8*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="10" Cursor="Hand">
<StackPanel> <StackPanel>
<TextBox VerticalAlignment="Top" materialDesign:HintAssist.Hint="用户名" Text="{Binding UserName}" Style="{StaticResource MaterialDesignOutlinedTextBox}" Margin="0,2,0,5"/>
<PasswordBox VerticalContentAlignment="Bottom" materialDesign:HintAssist.Hint="密码"
materialDesign:TextFieldAssist.HasClearButton="False" Margin="0,10,0,5"
materialDesign:PasswordBoxAssist.Password="{Binding UserPassword}"
Style="{StaticResource MaterialDesignOutlinedRevealPasswordBox}"/>
<Grid> <Grid>
<CheckBox x:Name="jzw" Content="记住我"/> <materialDesign:PackIcon Kind="LoginVariant" Width="48" Height="48" Margin="54,0,0,0" VerticalAlignment="Center"/>
<TextBlock Text="{Binding LoginMsg}" Style="{StaticResource MaterialDesignBody2TextBlock}" HorizontalAlignment="Right" Foreground="#FFCC3333"/> <TextBlock Style="{StaticResource MaterialDesignHeadline3TextBlock}" Text="登录" HorizontalAlignment="Left" Margin="107,0,0,4"/>
</Grid>
<Grid Width="280">
<StackPanel>
<TextBox VerticalAlignment="Top" materialDesign:HintAssist.Hint="用户名" Text="{Binding UserName}" Style="{StaticResource MaterialDesignOutlinedTextBox}" Margin="0,2,0,5"/>
<PasswordBox VerticalContentAlignment="Bottom" materialDesign:HintAssist.Hint="密码"
materialDesign:TextFieldAssist.HasClearButton="False" Margin="0,10,0,5"
materialDesign:PasswordBoxAssist.Password="{Binding UserPassword}"
Style="{StaticResource MaterialDesignOutlinedRevealPasswordBox}"/>
<Grid>
<CheckBox Content="记住我" IsChecked="{Binding SaveAccount}"/>
<TextBlock x:Name="LoginMsg" Text="" Style="{StaticResource MaterialDesignBody2TextBlock}" HorizontalAlignment="Right" Foreground="#FFCC3333"/>
</Grid>
<Button Content="登录" Margin="0,20,0,0" Click="Login_Click" Style="{StaticResource MaterialDesignRaisedButton}" ToolTip="登录账号" FontWeight="Normal"/>
</StackPanel>
</Grid> </Grid>
<Button Content="登录" Margin="0,20,0,0" Click="Login_Click"
IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
Style="{StaticResource MaterialDesignRaisedButton}" ToolTip="登录账号" FontWeight="Normal"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
</StackPanel> </Grid>
</Grid> </TabItem>
</Grid> <TabItem Header="注册账号">
<Grid Background="#FFE5E5E5">
<Grid.RowDefinitions>
<RowDefinition Height="0.8*"/>
<RowDefinition Height="6*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="10" Cursor="Hand">
<StackPanel>
<Grid>
<materialDesign:PackIcon Kind="LoginVariant" Width="48" Height="48" Margin="54,0,0,0" VerticalAlignment="Center"/>
<TextBlock Style="{StaticResource MaterialDesignHeadline3TextBlock}" Text="注册" HorizontalAlignment="Left" Margin="107,0,0,4"/>
</Grid>
<Grid Width="280">
<StackPanel>
<TextBox VerticalAlignment="Top" materialDesign:HintAssist.Hint="用户名" Text="{Binding SignName}" Style="{StaticResource MaterialDesignOutlinedTextBox}" Margin="0,2,0,5"/>
<PasswordBox VerticalContentAlignment="Bottom" materialDesign:HintAssist.Hint="密码"
materialDesign:TextFieldAssist.HasClearButton="False" Margin="0,10,0,5"
materialDesign:PasswordBoxAssist.Password="{Binding SignPassword1}"
Style="{StaticResource MaterialDesignOutlinedRevealPasswordBox}"/>
<PasswordBox VerticalContentAlignment="Bottom" materialDesign:HintAssist.Hint="确认密码"
materialDesign:TextFieldAssist.HasClearButton="False" Margin="0,10,0,5"
materialDesign:PasswordBoxAssist.Password="{Binding SignPassword2}"
Style="{StaticResource MaterialDesignOutlinedRevealPasswordBox}"/>
<Grid>
<CheckBox Content="记住我" IsChecked="{Binding SaveAccount}"/>
<TextBlock Text="{Binding SignMsg}" Style="{StaticResource MaterialDesignBody2TextBlock}" HorizontalAlignment="Right" Foreground="#FFCC3333"/>
</Grid>
<Button Content="注册" Margin="0,20,0,0" Click="Sign_Click" Style="{StaticResource MaterialDesignRaisedButton}" ToolTip="注册账号" FontWeight="Normal"/>
</StackPanel>
</Grid>
</StackPanel>
</Grid>
</Grid>
</TabItem>
</TabControl>
</Window> </Window>

View File

@ -17,6 +17,9 @@ using System.Net.Sockets;
using System.IO; using System.IO;
using log4net; using log4net;
using log4net.Config; using log4net.Config;
using System.Windows.Interop;
using chatapi;
using System.Runtime.CompilerServices;
namespace chatclient namespace chatclient
@ -24,7 +27,7 @@ namespace chatclient
/// <summary> /// <summary>
/// LoginWindow.xaml 的交互逻辑 /// LoginWindow.xaml 的交互逻辑
/// </summary> /// </summary>
public partial class LoginWindow : Window,INotifyPropertyChanged public partial class LoginWindow : Window, INotifyPropertyChanged
{ {
private static readonly ILog log = LogManager.GetLogger(typeof(LoginWindow)); private static readonly ILog log = LogManager.GetLogger(typeof(LoginWindow));
public LoginWindow() public LoginWindow()
@ -32,37 +35,45 @@ namespace chatclient
InitializeComponent(); InitializeComponent();
this.DataContext = this; this.DataContext = this;
} }
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
private void Update (string UpdateName) private void Update(string UpdateName)
{ {
PropertyChangedEventHandler? handler = PropertyChanged; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(UpdateName));
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(UpdateName));
}
} }
private string? _LoginMsg; public static string UserName { get; set; } = "";
public string UserName { get; set; } = ""; public static string UserPassword { get; set; } = "";
public string UserPassword { get; set; } = ""; public static string SignName { get; set; } = "";
public string? LoginMsg public static string SignPassword1 { get; set; } = "";
public static string SignPassword2 { get; set; } = "";
private string? _SignMsg;
public string? SignMsg
{ {
get { return _LoginMsg; } get { return _SignMsg; }
set set
{ {
_LoginMsg = value; _SignMsg = value;
Update("LoginMsg"); Update("SignMsg");
}
}
private bool _SaveAccount;
public bool SaveAccount
{
get { return _SaveAccount; }
set
{
_SaveAccount = value;
Update("SaveAccount");
} }
} }
private void Login_Click(object sender, RoutedEventArgs e) private void Login_Click(object sender, RoutedEventArgs e)
{ {
if (UserName == "") if (UserName == "")
{ {
LoginMsg = "用户名不能为空"; LoginMsg.Text = "用户名不能为空";
} }
else if (UserPassword == "") else if (UserPassword == "")
{ {
LoginMsg = "密码不能为空"; LoginMsg.Text = "密码不能为空";
} }
else else
{ {
@ -72,9 +83,91 @@ namespace chatclient
username = UserName, username = UserName,
password = UserPassword password = UserPassword
}; };
string LoginLsonData = JsonSerializer.Serialize(LoginData); string LoginJsonData = JsonSerializer.Serialize(LoginData);
byte[] dataBytes = Encoding.UTF8.GetBytes(LoginLsonData); byte[] dataBytes = Encoding.UTF8.GetBytes(LoginJsonData);
MainWindow.Client.Send(dataBytes); log.Info($"向服务器发送登录请求UserName:{UserName}");
if (MainWindow.Client is not null)
{
if (MainWindow.Client.Connected)
{
MainWindow.Client.Send(dataBytes);
}
else
{
try
{
log.Info("未连接服务器,尝试连接");
MainWindow.Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
MainWindow.Client.Connect("127.0.0.1", 5555);
}
catch (Exception ex)
{
log.Error(ex);
MainWindow.Client.Close();
}
finally
{
LoginMsg.Text = "服务器连接失败或已断开连接";
}
}
}
}
}
private void Sign_Click(object sender, RoutedEventArgs e)
{
if (SignName == "")
{
SignMsg = "用户名不能为空";
}
else if (SignPassword1 == "")
{
SignMsg = "密码不能为空";
}
else if (SignPassword2 == "")
{
SignMsg = "请再次确认密码";
}
else if (SignPassword1 != SignPassword2)
{
SignMsg = "两次密码输入不一致";
}
else
{
var SignData = new
{
type = "register",
username = SignName,
password = SignPassword1
};
string SignJsonData = JsonSerializer.Serialize(SignData);
byte[] dataBytes = Encoding.UTF8.GetBytes(SignJsonData);
log.Info($"向服务器发送注册请求UserName:{SignName}");
Update("LoginMsg");
if (MainWindow.Client is not null)
{
if (MainWindow.Client.Connected)
{
MainWindow.Client.Send(dataBytes);
}
else
{
try
{
log.Info("未连接服务器,尝试连接");
MainWindow.Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
MainWindow.Client.Connect("127.0.0.1", 5555);
}
catch (Exception ex)
{
log.Error(ex);
MainWindow.Client.Close();
}
finally
{
SignMsg = "服务器连接失败或已断开连接";
}
}
}
} }
} }
} }

View File

@ -12,8 +12,7 @@
<materialDesign:Card> <materialDesign:Card>
<TabControl VerticalContentAlignment="Bottom" materialDesign:ColorZoneAssist.Mode="PrimaryMid" Style="{StaticResource MaterialDesignNavigationRailTabControl}"> <TabControl VerticalContentAlignment="Bottom" materialDesign:ColorZoneAssist.Mode="PrimaryMid" Style="{StaticResource MaterialDesignNavigationRailTabControl}">
<materialDesign:NavigationRailAssist.FloatingContent> <materialDesign:NavigationRailAssist.FloatingContent>
<Button IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" <Button Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}" Margin="12" ToolTip="name">
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}" Margin="12" ToolTip="name">
<Image Source="/user.png" /> <Image Source="/user.png" />
</Button> </Button>
</materialDesign:NavigationRailAssist.FloatingContent> </materialDesign:NavigationRailAssist.FloatingContent>

View File

@ -15,7 +15,13 @@ using System;
using System.Security.Policy; using System.Security.Policy;
using log4net; using log4net;
using log4net.Config; using log4net.Config;
using System.Text.Json;
using chatapi;
using System.Diagnostics;
using System.Windows.Interop;
using ControlzEx.Standard;
[assembly: XmlConfigurator(ConfigFile = "config/log4net.config", Watch = true)]
namespace chatclient namespace chatclient
{ {
/// <summary> /// <summary>
@ -23,9 +29,12 @@ namespace chatclient
/// </summary> /// </summary>
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
LoginWindow Login = new();
static string? receive; static string? receive;
public static int user_id = 0;
public static string? LoginMsg = "123";
private static readonly ILog log = LogManager.GetLogger(typeof(MainWindow)); private static readonly ILog log = LogManager.GetLogger(typeof(MainWindow));
public static Socket Client; public static Socket? Client;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
@ -37,10 +46,11 @@ namespace chatclient
log.Info("连接服务器 127.0.0.1:5555 "); log.Info("连接服务器 127.0.0.1:5555 ");
Client.Connect("127.0.0.1", 5555); Client.Connect("127.0.0.1", 5555);
} }
catch (Exception ex) { catch (Exception ex)
{
Client.Close();
log.Error(ex); log.Error(ex);
} }
LoginWindow Login = new LoginWindow();
Login.Show(); Login.Show();
Thread th = new Thread(Receive); Thread th = new Thread(Receive);
th.Start(); th.Start();
@ -52,8 +62,13 @@ namespace chatclient
{ {
while (true) while (true)
{ {
int num = Client.Receive(buffer); int num = Client!.Receive(buffer);
if (num == 0) break; if (num == 0) break;
if (Client.Poll(100, SelectMode.SelectRead) && Client.Available == 0 || !Client.Connected)
{
log.Error("连接已断开");
break;
}
receive = Encoding.UTF8.GetString(buffer, 0, num); receive = Encoding.UTF8.GetString(buffer, 0, num);
response(receive); response(receive);
} }
@ -61,12 +76,22 @@ namespace chatclient
catch (Exception ex) { catch (Exception ex) {
log.Error(ex); log.Error(ex);
} }
finally finally
{ {
Client.Close(); Client?.Close();
} }
} }
static void response(string msg) { static void response(string msg)
{
LoginData data = JsonSerializer.Deserialize<LoginData>(msg)!;
if (data.success) {
}
else {
//LoginWindow.Instance.LoginMsg.Text = msg;
}
} }
} }

View File

@ -4,9 +4,19 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace chatclient namespace chatapi
{ {
internal class api internal class LoginData
{ {
public bool success { get; set; }
public string? message { get; set; }
public string? token { get; set; }
public int? user_id { get; set; }
public string? username { get; set; }
}
internal class RegisterData
{
public bool success { get; set; }
public string? message { get; set; }
} }
} }

View File

@ -19,4 +19,10 @@
<Resource Include="user.png" /> <Resource Include="user.png" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Update="config\log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project> </Project>