在 `MaterialTrayMenuItem.xaml` 中添加命名空间,更新菜单项样式,增加悬停和点击动画效果,提升用户交互体验。新增上下文菜单样式,包含透明度和缩放动画。 在 `LoginWindow.xaml.cs` 中将 `Window_Loaded` 方法改为异步,增强窗口加载时的连接稳定性,并添加连接服务器的逻辑及错误处理。 在 `MainWindow.xaml` 中移除 `TextBox` 控件的 `Foreground` 属性设置,简化样式,保持界面整洁。
349 lines
13 KiB
C#
349 lines
13 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Net.Sockets;
|
|
using log4net;
|
|
using System.Net.Http;
|
|
using Microsoft.Win32;
|
|
using chatclient.Data;
|
|
using System.Net;
|
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
|
|
using Microsoft.VisualBasic.ApplicationServices;
|
|
using MaterialDesignThemes.Wpf;
|
|
|
|
|
|
namespace chatclient
|
|
{
|
|
/// <summary>
|
|
/// LoginWindow.xaml 的交互逻辑
|
|
/// </summary>
|
|
public partial class LoginWindow : Window, INotifyPropertyChanged
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(LoginWindow));
|
|
public LoginWindow()
|
|
{
|
|
InitializeComponent();
|
|
this.DataContext = this;
|
|
}
|
|
public event PropertyChangedEventHandler? PropertyChanged;
|
|
private void Update(string UpdateName)
|
|
{
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(UpdateName));
|
|
}
|
|
public static string UserName { get; set; } = "";
|
|
public static string UserPassword { get; set; } = "";
|
|
public static string SignName { get; set; } = "";
|
|
public static string SignPassword1 { get; set; } = "";
|
|
public static string SignPassword2 { get; set; } = "";
|
|
private string? _LoginMsg;
|
|
public string? LoginMsg
|
|
{
|
|
get { return _LoginMsg; }
|
|
set
|
|
{
|
|
_LoginMsg = value;
|
|
Update("LoginMsg");
|
|
}
|
|
}
|
|
private string? _SignMsg;
|
|
public string? SignMsg
|
|
{
|
|
get { return _SignMsg; }
|
|
set
|
|
{
|
|
_SignMsg = value;
|
|
Update("SignMsg");
|
|
}
|
|
}
|
|
private bool _SaveAccount;
|
|
public bool SaveAccount
|
|
{
|
|
get { return _SaveAccount; }
|
|
set
|
|
{
|
|
_SaveAccount = value;
|
|
Update("SaveAccount");
|
|
}
|
|
}
|
|
private async void Login_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (UserName == "")
|
|
{
|
|
LoginMsg = "用户名不能为空";
|
|
}
|
|
else if (UserPassword == "")
|
|
{
|
|
LoginMsg = "密码不能为空";
|
|
}
|
|
else
|
|
{
|
|
await Login(false, UserName, UserPassword);
|
|
}
|
|
}
|
|
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
|
|
{
|
|
SignRegistryUser(SignName, SignPassword1).ContinueWith(Task =>
|
|
{
|
|
if (Task.IsCompletedSuccessfully)
|
|
{
|
|
log.Info("注册请求发送成功");
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
|
|
if (loginWindow != null)
|
|
{
|
|
loginWindow.SignMsg = "注册请求已发送,请等待服务器响应";
|
|
}
|
|
});
|
|
}
|
|
else
|
|
{
|
|
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)
|
|
{
|
|
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
|
|
{
|
|
var SignData = new
|
|
{
|
|
type = "register",
|
|
username = Username,
|
|
password = Userpassword
|
|
};
|
|
string SignJsonData = JsonSerializer.Serialize(SignData);
|
|
byte[] dataBytes = Encoding.UTF8.GetBytes(SignJsonData);
|
|
var content = new StringContent(SignJsonData, Encoding.UTF8, "application/json");
|
|
var response = await MainWindow.HttpClient.PostAsync($"{Server.ServerUrl}/api/register", content);
|
|
var responseBody = await response.Content.ReadAsStringAsync();
|
|
log.Info($"注册请求已发送,响应内容: {responseBody}");
|
|
var signresponse = JsonSerializer.Deserialize<SignResultData>(responseBody);
|
|
if (signresponse!.success)
|
|
{
|
|
log.Info($"注册成功: {signresponse.message}");
|
|
await Login(true, Username, Userpassword);
|
|
}
|
|
else
|
|
{
|
|
log.Error($"注册失败: {signresponse.message}");
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
|
|
loginWindow!.SignMsg = signresponse.message;
|
|
});
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Error("注册请求发送失败", ex);
|
|
}
|
|
finally
|
|
{
|
|
log.Info("注册请求已完成");
|
|
}
|
|
}
|
|
public static async Task Login(bool Sign, string Username, string Userpassword)
|
|
{
|
|
// 公共的登录数据准备
|
|
var LoginData = new
|
|
{
|
|
type = "login",
|
|
username = Username,
|
|
password = Userpassword
|
|
};
|
|
string LoginJsonData = JsonSerializer.Serialize(LoginData);
|
|
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();
|
|
// 根据Sign类型更新UI
|
|
string errorMsg = Sign ?
|
|
"在完成注册后与服务器断开连接\n请尝试在登录窗口重新登录" :
|
|
"服务器连接失败";
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
var loginWindow = Application.Current.Windows.OfType<LoginWindow>().FirstOrDefault();
|
|
if (loginWindow != null)
|
|
{
|
|
if (Sign) loginWindow.SignMsg = errorMsg;
|
|
else loginWindow.LoginMsg = errorMsg;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
public async void Window_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
log.Info("登录窗口已加载");
|
|
if (MainWindow.Client?.Connected == false)
|
|
{
|
|
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();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Error($"连接失败: {ex.Message}");
|
|
MainWindow.Client?.Close();
|
|
}
|
|
});
|
|
}
|
|
try
|
|
{
|
|
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)
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
|