添加账户管理和界面优化

在 `ChatDataModel.cs` 中添加 `Account` 类以存储临时账户信息。
修改 `TrayIconManager.cs` 的窗口关闭事件处理,移除通知显示并优化设置逻辑。
更新 `chatapi.cs` 中的服务器 URL 和 IP 地址。
调整 `LoginWindow.xaml` 的尺寸并添加 `Loaded` 事件处理,确保用户名和密码输入框正确绑定。
在 `LoginWindow.xaml.cs` 中实现读取和保存临时登录信息的功能。
修改 `MainWindow.xaml` 的选项卡定义,确保用户信息和设置选项卡正确显示。
更新 `MainWindow.xaml.cs` 中的登录和注册处理逻辑,确保正确处理服务器返回消息并清理资源。
This commit is contained in:
绪山七寻 2025-06-08 07:34:58 +08:00
parent f4de02ec38
commit f4e2d0be38
7 changed files with 176 additions and 29 deletions

View File

@ -52,4 +52,12 @@ namespace chatclient.Data
File,//文件 File,//文件
System//系统信息 System//系统信息
} }
/// <summary>
/// 临时账户信息类,包含用户名和密码
/// </summary>
public class Account
{
public string? UserName { get; set; }
public string? UserPassword { get; set; }
}
} }

View File

@ -35,11 +35,6 @@ namespace chatclient.Data
// 取消关闭操作,改为最小化到托盘 // 取消关闭操作,改为最小化到托盘
e.Cancel = true; e.Cancel = true;
_mainWindow.Hide(); _mainWindow.Hide();
// 显示通知
//_trayIcon.ShowBalloonTip("Application minimized",
// "The application is running in the system tray",
// BalloonIcon.Info);
} }
private ContextMenu CreateContextMenu() private ContextMenu CreateContextMenu()
@ -70,7 +65,6 @@ namespace chatclient.Data
Style = (Style)Application.Current.Resources["MaterialTrayMenuItem"], Style = (Style)Application.Current.Resources["MaterialTrayMenuItem"],
Icon = new PackIcon { Kind = iconKind, Width = 20, Height = 20 } Icon = new PackIcon { Kind = iconKind, Width = 20, Height = 20 }
}; };
menuItem.Click += clickHandler; menuItem.Click += clickHandler;
return menuItem; return menuItem;
} }
@ -94,7 +88,15 @@ namespace chatclient.Data
private void Settings_Click(object sender, RoutedEventArgs e) private void Settings_Click(object sender, RoutedEventArgs e)
{ {
// 实现设置逻辑 RestoreApplication();
Application.Current.Dispatcher.Invoke(() =>
{
var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (mainWindow != null)
{
mainWindow.TabControl.SelectedItem = mainWindow.Settings;
}
});
} }
private void Updates_Click(object sender, RoutedEventArgs e) private void Updates_Click(object sender, RoutedEventArgs e)

View File

@ -4,8 +4,8 @@ namespace chatclient.Data
{ {
internal class Server internal class Server
{ {
public const string ServerUrl = "http://127.0.0.1:5001"; public const string ServerUrl = "http://175.24.191.172:5001";
public const string ServerIP = "127.0.0.1"; public const string ServerIP = "175.24.191.172";
public const int ServerPort = 8889; public const int ServerPort = 8889;
} }
internal class LoginData internal class LoginData

View File

@ -7,8 +7,8 @@
xmlns:local="clr-namespace:chatclient" xmlns:local="clr-namespace:chatclient"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" x:Class="chatclient.LoginWindow" xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" x:Class="chatclient.LoginWindow"
mc:Ignorable="d" mc:Ignorable="d"
Title="LoginWindow" Height="590" Width="330" MinHeight="590" MinWidth="330" MaxHeight="590" MaxWidth="330" Title="LoginWindow" Height="540" Width="330" MinHeight="540" MinWidth="330" MaxHeight="540" MaxWidth="330"
ResizeMode="NoResize" Closing="Window_Closing"> ResizeMode="NoResize" Closing="Window_Closing" Loaded="Window_Loaded">
<TabControl> <TabControl>
<TabItem Header="登录账号" Cursor="Hand" Height="40"> <TabItem Header="登录账号" Cursor="Hand" Height="40">
@ -26,8 +26,8 @@
</Grid> </Grid>
<Grid Width="280"> <Grid Width="280">
<StackPanel> <StackPanel>
<TextBox VerticalAlignment="Top" materialDesign:HintAssist.Hint="用户名" Text="{Binding UserName}" Style="{StaticResource MaterialDesignOutlinedTextBox}" Margin="0,2,0,5"/> <TextBox x:Name="NameBox" VerticalAlignment="Top" materialDesign:HintAssist.Hint="用户名" Text="{Binding UserName}" Style="{StaticResource MaterialDesignOutlinedTextBox}" Margin="0,2,0,5"/>
<PasswordBox VerticalContentAlignment="Bottom" materialDesign:HintAssist.Hint="密码" <PasswordBox x:Name="PasswoedBox" VerticalContentAlignment="Bottom" materialDesign:HintAssist.Hint="密码"
materialDesign:TextFieldAssist.HasClearButton="False" Margin="0,10,0,5" materialDesign:TextFieldAssist.HasClearButton="False" Margin="0,10,0,5"
materialDesign:PasswordBoxAssist.Password="{Binding UserPassword}" materialDesign:PasswordBoxAssist.Password="{Binding UserPassword}"
Style="{StaticResource MaterialDesignOutlinedRevealPasswordBox}"/> Style="{StaticResource MaterialDesignOutlinedRevealPasswordBox}"/>

View File

@ -11,6 +11,8 @@ using Microsoft.Win32;
using chatclient.Data; using chatclient.Data;
using System.Net; using System.Net;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel; using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
using Microsoft.VisualBasic.ApplicationServices;
using MaterialDesignThemes.Wpf;
namespace chatclient namespace chatclient
@ -101,21 +103,91 @@ namespace chatclient
} }
else else
{ {
log.Info($"向服务器发送注册HttpAPI请求(UserName:{SignName})"); SignRegistryUser(SignName, SignPassword1).ContinueWith(Task =>
SignRegistryUser(SignName, SignPassword1).ContinueWith(task =>
{ {
if (task.IsCompletedSuccessfully) if (Task.IsCompletedSuccessfully)
{ {
log.Info("注册请求发送成功"); log.Info("注册请求发送成功");
Application.Current.Dispatcher.Invoke(() =>
{
var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
if (loginWindow != null)
{
loginWindow.SignMsg = "注册请求已发送,请等待服务器响应";
}
});
} }
else else
{ {
log.Error("注册请求发送失败", task.Exception); log.Error("注册请求发送失败", Task.Exception);
Application.Current.Dispatcher.Invoke(() =>
{
var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
if (loginWindow != null)
{
loginWindow.SignMsg = "注册请求发送失败,请检查网络连接";
}
});
} }
}); });
//log.Info($"向服务器发送注册HttpAPI请求(UserName:{SignName})");
//SignRegistryUser(SignName, SignPassword1).ContinueWith(task =>
//{
// if (task.IsCompletedSuccessfully)
// {
// log.Info("注册请求发送成功");
// }
// else
// {
// log.Error("注册请求发送失败", task.Exception);
// }
//});
} }
} }
public static async Task SignRegistryUser(string Username, string Userpassword) public static async Task SignRegistryUser(string Username, string Userpassword)
{
var SignData = new
{
type = "register",
username = Username,
password = Userpassword
};
string LoginJsonData = JsonSerializer.Serialize(SignData);
byte[] dataBytes = Encoding.UTF8.GetBytes(LoginJsonData);
log.Info($"向服务器发送注册请求(UserName:{Username})");
// 检查Socket是否可用
if (MainWindow.Client?.Connected == true)
{
MainWindow.Client.Send(dataBytes);
return;
}
log.Info("未连接服务器,尝试异步连接");
// 异步连接操作
await Task.Run(() =>
{
try
{
MainWindow.Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
MainWindow.Client?.Connect(IPAddress.Parse(Server.ServerIP), Server.ServerPort);
MainWindow.StartReceive();
MainWindow.Client?.Send(dataBytes);
}
catch (Exception ex)
{
log.Error($"连接失败: {ex.Message}");
MainWindow.Client?.Close();
Application.Current.Dispatcher.Invoke(() =>
{
var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
if (loginWindow != null)
{
loginWindow.SignMsg = "服务器连接失败";
}
});
}
});
}
public static async Task HttpSignRegistryUser(string Username, string Userpassword)
{ {
try try
{ {
@ -207,15 +279,51 @@ namespace chatclient
} }
public void Window_Loaded(object sender, RoutedEventArgs e) public void Window_Loaded(object sender, RoutedEventArgs e)
{ {
// 窗口加载时可以进行一些初始化操作
log.Info("登录窗口已加载"); log.Info("登录窗口已加载");
// 如果需要从配置文件或其他地方加载保存的账号信息,可以在这里实现
// 例如UserName = LoadSavedUsername(); try
// Update("UserName"); {
string tempPath = System.IO.Path.GetTempPath();
string filePath = System.IO.Path.Combine(tempPath, "chatclient_login.tmp");
if (System.IO.File.Exists(filePath))
{
string json = System.IO.File.ReadAllText(filePath, Encoding.UTF8);
var loginInfo = JsonSerializer.Deserialize <Account> (json);
if (loginInfo != null)
{
UserName = loginInfo.UserName!;
NameBox.Text = loginInfo.UserName;
UserPassword = loginInfo.UserPassword!;
PasswoedBox.Password = loginInfo.UserPassword;
SaveAccount = true;
}
}
}
catch (Exception ex)
{
log.Error("读取临时登录信息失败", ex);
}
} }
public void Window_Closing(object sender, CancelEventArgs e) public void Window_Closing(object sender, CancelEventArgs e)
{ {
if(MainWindow.token == null) Application.Current.Shutdown(); if (SaveAccount && !string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(UserPassword))
{
try
{
string tempPath = System.IO.Path.GetTempPath();
string filePath = System.IO.Path.Combine(tempPath, "chatclient_login.tmp");
var loginInfo = new { UserName, UserPassword };
string json = JsonSerializer.Serialize(loginInfo);
System.IO.File.WriteAllText(filePath, json, Encoding.UTF8);
}
catch (Exception ex)
{
log.Error("保存登录信息到临时文件失败", ex);
}
}
if (MainWindow.token == null) Application.Current.Shutdown();
} }
} }
} }

View File

@ -11,7 +11,7 @@
Style="{StaticResource MaterialDesignWindow}" Closed="MainWindow_Closed" Loaded="MainWindow_Loaded"> Style="{StaticResource MaterialDesignWindow}" Closed="MainWindow_Closed" Loaded="MainWindow_Loaded">
<Grid> <Grid>
<materialDesign:Card> <materialDesign:Card>
<TabControl VerticalContentAlignment="Bottom" materialDesign:ColorZoneAssist.Mode="PrimaryMid" Style="{StaticResource MaterialDesignNavigationRailTabControl}"> <TabControl x:Name="TabControl" VerticalContentAlignment="Bottom" materialDesign:ColorZoneAssist.Mode="PrimaryMid" Style="{StaticResource MaterialDesignNavigationRailTabControl}">
<materialDesign:NavigationRailAssist.FloatingContent> <materialDesign:NavigationRailAssist.FloatingContent>
<StackPanel> <StackPanel>
<Button Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}" Margin="12"> <Button Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}" Margin="12">
@ -20,7 +20,7 @@
<TextBlock Text="{Binding UserName}" TextAlignment="Center" MaxWidth="64" MaxHeight="64" TextWrapping="Wrap"/> <TextBlock Text="{Binding UserName}" TextAlignment="Center" MaxWidth="64" MaxHeight="64" TextWrapping="Wrap"/>
</StackPanel> </StackPanel>
</materialDesign:NavigationRailAssist.FloatingContent> </materialDesign:NavigationRailAssist.FloatingContent>
<TabItem> <TabItem x:Name="ChatMsg">
<TabItem.Header> <TabItem.Header>
<StackPanel Width="auto" Height="auto"> <StackPanel Width="auto" Height="auto">
<materialDesign:PackIcon Width="24" Height="24" HorizontalAlignment="Center" Kind="Message" /> <materialDesign:PackIcon Width="24" Height="24" HorizontalAlignment="Center" Kind="Message" />
@ -133,7 +133,7 @@
</Grid> </Grid>
</Grid> </Grid>
</TabItem> </TabItem>
<TabItem> <TabItem x:Name="Settings">
<TabItem.Header> <TabItem.Header>
<StackPanel Width="auto" Height="auto"> <StackPanel Width="auto" Height="auto">
<materialDesign:PackIcon Width="24" Height="24" HorizontalAlignment="Center" Kind="Cog" /> <materialDesign:PackIcon Width="24" Height="24" HorizontalAlignment="Center" Kind="Cog" />

View File

@ -21,6 +21,7 @@ using System.ComponentModel;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Windows.Threading; using System.Windows.Threading;
using System.Collections.Specialized; using System.Collections.Specialized;
using Hardcodet.Wpf.TaskbarNotification;
[assembly: XmlConfigurator(ConfigFile = "config/log4net.config", Watch = true)] [assembly: XmlConfigurator(ConfigFile = "config/log4net.config", Watch = true)]
namespace chatclient namespace chatclient
@ -132,9 +133,9 @@ namespace chatclient
var Type = JsonSerializer.Deserialize<RegisterData>(msg); var Type = JsonSerializer.Deserialize<RegisterData>(msg);
if (Type != null) if (Type != null)
{ {
var LoginResponse = JsonSerializer.Deserialize<LoginResultData>(msg);
if (Type.type == "login_1") if (Type.type == "login_1")
{ {
var LoginResponse = JsonSerializer.Deserialize<LoginResultData>(msg);
if (LoginResponse!.status == "success" && LoginResponse != null) if (LoginResponse!.status == "success" && LoginResponse != null)
{ {
token = LoginResponse.token; token = LoginResponse.token;
@ -176,9 +177,10 @@ namespace chatclient
}); });
} }
} }
else if (Type.type == "login_0" && LoginResponse != null) else if (Type.type == "login_0")
{ {
log.Warn($"登录失败: {LoginResponse.message}\nMsg:{msg}"); var LoginResponse = JsonSerializer.Deserialize<LoginResultData>(msg);
log.Warn($"登录失败: {LoginResponse!.message}\nMsg:{msg}");
Application.Current.Dispatcher.Invoke(() => Application.Current.Dispatcher.Invoke(() =>
{ {
var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault(); var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
@ -188,6 +190,29 @@ namespace chatclient
} }
}); });
} }
else if (Type.type == "register_1")
{
var SignResponse = JsonSerializer.Deserialize<SignResultData>(msg);
log.Warn($"注册成功\nMsg:{msg}");
Application.Current.Dispatcher.Invoke(async () =>
{
//var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
await LoginWindow.Login(true,LoginWindow.SignName, LoginWindow.SignPassword1);
});
}
else if (Type.type == "register_0")
{
var SignResponse = JsonSerializer.Deserialize<SignResultData>(msg);
log.Warn($"注册失败: {SignResponse!.message}\nMsg:{msg}");
Application.Current.Dispatcher.Invoke(() =>
{
var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
if (loginWindow != null)
{
loginWindow.SignMsg = "用户名已存在";
}
});
}
else if (Type.type == "chat") else if (Type.type == "chat")
{ {
var chat = JsonSerializer.Deserialize<ChatRegisterData>(msg); var chat = JsonSerializer.Deserialize<ChatRegisterData>(msg);
@ -345,12 +370,16 @@ namespace chatclient
} }
private void MainWindow_Closed(object sender, System.EventArgs e) private void MainWindow_Closed(object sender, System.EventArgs e)
{ {
log.Info("MainWindow 关闭事件触发,清理资源");
// 清理资源 // 清理资源
Client?.Shutdown(SocketShutdown.Both); Client?.Shutdown(SocketShutdown.Both);
Client?.Close(); Client?.Close();
log.Info("关闭Socket连接");
Client?.Dispose(); Client?.Dispose();
token = null; token = null;
_trayManager?.Dispose(); _trayManager?.Dispose();
log.Info("托盘图标管理器已释放资源");
log.Info("Bye!");
} }
} }
} }