feat: add login

This commit is contained in:
GukSang.Jin
2026-01-26 18:47:27 +08:00
parent 9aa367f34e
commit 2c9861c223
19 changed files with 2800 additions and 15 deletions

View File

@@ -0,0 +1,206 @@
using Dapper;
using MySql.Data.MySqlClient;
using System;
using System.Diagnostics;
namespace .DATA
{
/// <summary>
/// 数据库初始化辅助类
/// 用于创建用户表和初始化默认管理员账户
/// </summary>
public static class DatabaseInitializer
{
private static readonly string _connectionString = "Server=localhost;Database=fullautowaterpressure;User=root;Password=123456;port=3306;charset=utf8;";
/// <summary>
/// 初始化用户表和默认管理员账户
/// </summary>
public static void Initialize()
{
try
{
CreateUsersTable();
CreateDefaultAdminIfNotExists();
}
catch (Exception ex)
{
throw new Exception($"数据库初始化失败:{ex.Message}", ex);
}
}
/// <summary>
/// 强制重置默认用户(删除并重新创建)
/// </summary>
public static void ForceResetDefaultUsers()
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
try
{
// 删除现有的默认用户
connection.Execute("DELETE FROM sys_users WHERE username IN ('admin', 'cgx')");
Debug.WriteLine("已删除现有默认用户");
// 重新创建
CreateUserIfNotExists(connection, "admin", "admin123", 1);
CreateUserIfNotExists(connection, "cgx", "123", 0);
Debug.WriteLine("默认用户重置完成!");
}
catch (Exception ex)
{
Debug.WriteLine($"重置用户失败: {ex.Message}");
throw;
}
}
}
/// <summary>
/// 创建用户表
/// </summary>
private static void CreateUsersTable()
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
// 先检查表是否存在,如果不存在则创建
string checkTableSql = @"SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = @database AND table_name = 'sys_users'";
int tableExists = connection.ExecuteScalar<int>(checkTableSql, new { database = "fullautowaterpressure" });
if (tableExists == 0)
{
string sql = @"
CREATE TABLE `sys_users` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`password_hash` VARCHAR(255) NOT NULL COMMENT '密码哈希值',
`salt` VARCHAR(64) NOT NULL COMMENT '盐值',
`user_role` TINYINT NOT NULL DEFAULT 0 COMMENT '用户角色0=普通用户1=管理员',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态0=禁用1=启用',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`last_login_time` DATETIME DEFAULT NULL COMMENT '最后登录时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表'";
connection.Execute(sql);
}
}
}
/// <summary>
/// 创建默认管理员账户(如果不存在)
/// 默认账户admin / admin123
/// </summary>
private static void CreateDefaultAdminIfNotExists()
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
try
{
// 先检查 sys_users 表是否存在
string checkTableSql = @"SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = @database AND table_name = 'sys_users'";
int tableExists = connection.ExecuteScalar<int>(checkTableSql, new { database = "fullautowaterpressure" });
if (tableExists == 0)
{
Debug.WriteLine("sys_users table does not exist, skipping admin creation");
return;
}
// 创建默认管理员账户 admin / admin123
CreateUserIfNotExists(connection, "admin", "admin123", 1);
// 创建默认普通用户账户 cgx / 123
CreateUserIfNotExists(connection, "cgx", "123", 0);
}
catch (Exception ex)
{
// 捕获其他异常
Debug.WriteLine($"✗ Error creating default users: {ex.GetType().Name} - {ex.Message}");
}
}
}
/// <summary>
/// 创建用户(如果不存在)
/// </summary>
/// <param name="connection">数据库连接</param>
/// <param name="username">用户名</param>
/// <param name="password">密码(明文)</param>
/// <param name="userRole">用户角色0=普通用户1=管理员</param>
private static void CreateUserIfNotExists(MySqlConnection connection, string username, string password, int userRole)
{
try
{
// 检查用户是否已存在
string checkUserSql = "SELECT COUNT(*) FROM `sys_users` WHERE `username` = @username";
int userExists = connection.ExecuteScalar<int>(checkUserSql, new { username });
if (userExists > 0)
{
Debug.WriteLine($"用户 '{username}' 已存在,跳过创建");
return;
}
// 简单明文密码存储
// password_hash 字段存储明文密码
// salt 字段存储空字符串(保持兼容性)
string passwordHash = password; // 直接使用明文
string salt = ""; // 空字符串
// 调试输出
Debug.WriteLine($"\n=== 创建用户: {username} ===");
Debug.WriteLine($" 密码: {password}");
Debug.WriteLine($" 角色: {(userRole == 1 ? "" : "")}");
// 插入用户
string insertSql = @"
INSERT INTO `sys_users`
(`username`, `password_hash`, `salt`, `user_role`, `status`, `create_time`)
VALUES (@username, @passwordHash, @salt, @userRole, @status, NOW())";
int rowsAffected = connection.Execute(insertSql, new
{
username = username,
passwordHash = passwordHash,
salt = salt,
userRole = userRole,
status = 1 // 启用
});
if (rowsAffected > 0)
{
string roleText = userRole == 1 ? "管理员" : "普通用户";
Debug.WriteLine($"✓ 用户创建成功: {username} / {password} ({roleText})");
}
else
{
Debug.WriteLine($"✗ 创建用户失败: {username}");
}
}
catch (MySqlException ex)
{
Debug.WriteLine($"✗ MySQL错误 (创建用户 '{username}'): [{ex.Number}] {ex.Message}");
if (ex.Number == 1062)
{
Debug.WriteLine($"用户 '{username}' 已存在(重复键)");
}
}
catch (Exception ex)
{
Debug.WriteLine($"✗ 异常 (创建用户 '{username}'): {ex.Message}");
}
}
}
}

View File

@@ -1,9 +1,11 @@
namespace
using System;
namespace
{
public class LoginData
{
static string _userName = "";
public string UserName
public static string UserName
{
get { return _userName; }
set { _userName = value; }
@@ -11,11 +13,51 @@
//登陆权限
static int _userPower = 0;//0为普通用户1为管理员
public int UserPower
public static int UserPower
{
get { return _userPower; }
set { _userPower = value; }
}
static int _currentUserId = 0; // 当前登录用户ID
public static int CurrentUserId
{
get { return _currentUserId; }
set { _currentUserId = value; }
}
static DateTime _loginTime = DateTime.Now;
public static DateTime LoginTime
{
get { return _loginTime; }
set { _loginTime = value; }
}
/// <summary>
/// 检查是否为管理员
/// </summary>
public static bool IsAdmin()
{
return _userPower == 1;
}
/// <summary>
/// 检查是否为普通用户
/// </summary>
public static bool IsNormalUser()
{
return _userPower == 0;
}
/// <summary>
/// 退出登录,清空会话信息
/// </summary>
public static void Logout()
{
_userName = "";
_userPower = 0;
_currentUserId = 0;
_loginTime = DateTime.Now;
}
}
}

View File

@@ -0,0 +1,167 @@
using System;
using System.Diagnostics;
using MySql.Data.MySqlClient;
using Dapper;
namespace .DATA
{
/// <summary>
/// 登录调试辅助类
/// 用于测试和调试登录功能
/// </summary>
public static class LoginDebugHelper
{
private static readonly string _connectionString = "Server=localhost;Database=fullautowaterpressure;User=root;Password=123456;port=3306;charset=utf8;";
/// <summary>
/// 测试密码加密和验证
/// </summary>
public static void TestPasswordEncryption()
{
Debug.WriteLine("=== 测试密码加密 ===");
// 测试 admin123
string salt1 = PasswordHelper.GenerateSalt();
string hash1 = PasswordHelper.HashPassword("admin123", salt1);
bool verify1 = PasswordHelper.VerifyPassword("admin123", hash1, salt1);
Debug.WriteLine($"密码: admin123");
Debug.WriteLine($"盐值: {salt1}");
Debug.WriteLine($"哈希: {hash1}");
Debug.WriteLine($"验证: {verify1}");
Debug.WriteLine("");
// 测试 123
string salt2 = PasswordHelper.GenerateSalt();
string hash2 = PasswordHelper.HashPassword("123", salt2);
bool verify2 = PasswordHelper.VerifyPassword("123", hash2, salt2);
Debug.WriteLine($"密码: 123");
Debug.WriteLine($"盐值: {salt2}");
Debug.WriteLine($"哈希: {hash2}");
Debug.WriteLine($"验证: {verify2}");
}
/// <summary>
/// 查看数据库中的用户信息
/// </summary>
public static void ShowDatabaseUsers()
{
try
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
var users = connection.Query<User>("SELECT * FROM sys_users");
Debug.WriteLine("=== 数据库用户列表 ===");
foreach (var user in users)
{
Debug.WriteLine($"ID: {user.Id}");
Debug.WriteLine($"用户名: {user.Username}");
Debug.WriteLine($"角色: {(user.UserRole == 1 ? "" : "")}");
Debug.WriteLine($"状态: {(user.Status == 1 ? "" : "")}");
Debug.WriteLine($"密码哈希: {user.PasswordHash}");
Debug.WriteLine($"盐值: {user.Salt}");
Debug.WriteLine($"创建时间: {user.CreateTime}");
Debug.WriteLine("---");
}
}
}
catch (Exception ex)
{
Debug.WriteLine($"查询用户失败: {ex.Message}");
}
}
/// <summary>
/// 重置所有默认用户
/// </summary>
public static void ResetDefaultUsers()
{
try
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
// 删除现有用户
connection.Execute("DELETE FROM sys_users WHERE username IN ('admin', 'cgx')");
Debug.WriteLine("已删除现有默认用户");
// 重新创建 admin
string salt1 = PasswordHelper.GenerateSalt();
string hash1 = PasswordHelper.HashPassword("admin123", salt1);
connection.Execute(@"
INSERT INTO sys_users (username, password_hash, salt, user_role, status, create_time)
VALUES (@username, @hash, @salt, @role, 1, NOW())",
new { username = "admin", hash = hash1, salt = salt1, role = 1 });
Debug.WriteLine("✓ 创建管理员: admin / admin123");
// 重新创建 cgx
string salt2 = PasswordHelper.GenerateSalt();
string hash2 = PasswordHelper.HashPassword("123", salt2);
connection.Execute(@"
INSERT INTO sys_users (username, password_hash, salt, user_role, status, create_time)
VALUES (@username, @hash, @salt, @role, 1, NOW())",
new { username = "cgx", hash = hash2, salt = salt2, role = 0 });
Debug.WriteLine("✓ 创建普通用户: cgx / 123");
Debug.WriteLine("默认用户重置完成!");
}
}
catch (Exception ex)
{
Debug.WriteLine($"重置用户失败: {ex.Message}");
}
}
/// <summary>
/// 测试登录
/// </summary>
public static void TestLogin(string username, string password)
{
try
{
Debug.WriteLine($"=== 测试登录: {username} ===");
var repository = new UserRepository();
var user = repository.GetUserByUsername(username);
if (user == null)
{
Debug.WriteLine("❌ 用户不存在");
return;
}
Debug.WriteLine($"✓ 找到用户: {user.Username}");
Debug.WriteLine($" 角色: {(user.UserRole == 1 ? "" : "")}");
Debug.WriteLine($" 状态: {(user.Status == 1 ? "" : "")}");
Debug.WriteLine($" 密码哈希: {user.PasswordHash}");
Debug.WriteLine($" 盐值: {user.Salt}");
bool isValid = PasswordHelper.VerifyPassword(password, user.PasswordHash, user.Salt);
if (isValid)
{
Debug.WriteLine("✓ 密码验证成功!");
}
else
{
Debug.WriteLine("❌ 密码验证失败!");
// 测试重新生成哈希
string testHash = PasswordHelper.HashPassword(password, user.Salt);
Debug.WriteLine($" 输入密码的哈希: {testHash}");
Debug.WriteLine($" 数据库的哈希: {user.PasswordHash}");
Debug.WriteLine($" 是否匹配: {testHash == user.PasswordHash}");
}
}
catch (Exception ex)
{
Debug.WriteLine($"测试登录失败: {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,159 @@
using System;
using System.Windows.Forms;
namespace .DATA
{
/// <summary>
/// 密码生成器 - 用于生成正确的密码哈希
/// </summary>
public class PasswordGenerator : Form
{
private TextBox txtPassword;
private TextBox txtSalt;
private TextBox txtHash;
private Button btnGenerate;
private Label lblPassword;
private Label lblSalt;
private Label lblHash;
private Button btnGenerateSalt;
private TextBox txtSqlUpdate;
private Label lblSql;
public PasswordGenerator()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.lblPassword = new Label();
this.txtPassword = new TextBox();
this.lblSalt = new Label();
this.txtSalt = new TextBox();
this.btnGenerateSalt = new Button();
this.lblHash = new Label();
this.txtHash = new TextBox();
this.btnGenerate = new Button();
this.lblSql = new Label();
this.txtSqlUpdate = new TextBox();
this.SuspendLayout();
// lblPassword
this.lblPassword.Location = new System.Drawing.Point(20, 20);
this.lblPassword.Size = new System.Drawing.Size(100, 20);
this.lblPassword.Text = "密码:";
// txtPassword
this.txtPassword.Location = new System.Drawing.Point(120, 20);
this.txtPassword.Size = new System.Drawing.Size(300, 25);
// lblSalt
this.lblSalt.Location = new System.Drawing.Point(20, 60);
this.lblSalt.Size = new System.Drawing.Size(100, 20);
this.lblSalt.Text = "盐值:";
// txtSalt
this.txtSalt.Location = new System.Drawing.Point(120, 60);
this.txtSalt.Size = new System.Drawing.Size(300, 25);
this.txtSalt.ReadOnly = true;
// btnGenerateSalt
this.btnGenerateSalt.Location = new System.Drawing.Point(430, 58);
this.btnGenerateSalt.Size = new System.Drawing.Size(100, 28);
this.btnGenerateSalt.Text = "生成盐值";
this.btnGenerateSalt.Click += BtnGenerateSalt_Click;
// lblHash
this.lblHash.Location = new System.Drawing.Point(20, 100);
this.lblHash.Size = new System.Drawing.Size(100, 20);
this.lblHash.Text = "密码哈希:";
// txtHash
this.txtHash.Location = new System.Drawing.Point(120, 100);
this.txtHash.Size = new System.Drawing.Size(410, 25);
this.txtHash.ReadOnly = true;
// btnGenerate
this.btnGenerate.Location = new System.Drawing.Point(220, 140);
this.btnGenerate.Size = new System.Drawing.Size(120, 35);
this.btnGenerate.Text = "生成哈希";
this.btnGenerate.Click += BtnGenerate_Click;
// lblSql
this.lblSql.Location = new System.Drawing.Point(20, 190);
this.lblSql.Size = new System.Drawing.Size(100, 20);
this.lblSql.Text = "SQL更新语句:";
// txtSqlUpdate
this.txtSqlUpdate.Location = new System.Drawing.Point(20, 220);
this.txtSqlUpdate.Size = new System.Drawing.Size(510, 100);
this.txtSqlUpdate.Multiline = true;
this.txtSqlUpdate.ReadOnly = true;
this.txtSqlUpdate.ScrollBars = ScrollBars.Vertical;
// PasswordGenerator
this.ClientSize = new System.Drawing.Size(560, 350);
this.Controls.Add(this.lblPassword);
this.Controls.Add(this.txtPassword);
this.Controls.Add(this.lblSalt);
this.Controls.Add(this.txtSalt);
this.Controls.Add(this.btnGenerateSalt);
this.Controls.Add(this.lblHash);
this.Controls.Add(this.txtHash);
this.Controls.Add(this.btnGenerate);
this.Controls.Add(this.lblSql);
this.Controls.Add(this.txtSqlUpdate);
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.StartPosition = FormStartPosition.CenterScreen;
this.Text = "密码哈希生成器";
this.ResumeLayout(false);
this.PerformLayout();
}
private void BtnGenerateSalt_Click(object sender, EventArgs e)
{
txtSalt.Text = PasswordHelper.GenerateSalt();
}
private void BtnGenerate_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtPassword.Text))
{
MessageBox.Show("请输入密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (string.IsNullOrEmpty(txtSalt.Text))
{
MessageBox.Show("请先生成盐值!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
string hash = PasswordHelper.HashPassword(txtPassword.Text, txtSalt.Text);
txtHash.Text = hash;
// 生成SQL更新语句
string sql = $@"-- 更新用户密码
UPDATE sys_users
SET password_hash = '{hash}',
salt = '{txtSalt.Text}'
WHERE username = 'admin'; -- 修改为对应的用户名";
txtSqlUpdate.Text = sql;
MessageBox.Show("密码哈希生成成功!\n\n可以复制SQL语句到数据库执行。", "成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new PasswordGenerator());
}
}
}

View File

@@ -0,0 +1,140 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace .DATA
{
/// <summary>
/// 密码加密辅助类
/// 使用 SHA256 + 盐值加密
/// 精确简单的实现确保100%匹配
/// </summary>
public static class PasswordHelper
{
/// <summary>
/// 生成随机盐值16字节
/// </summary>
/// <returns>Base64编码的盐值字符串</returns>
public static string GenerateSalt()
{
byte[] saltBytes = new byte[16];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(saltBytes);
}
return Convert.ToBase64String(saltBytes);
}
/// <summary>
/// 使用 SHA256 哈希密码
/// 精确实现:密码 + 盐值 -> SHA256 -> Base64
/// </summary>
/// <param name="password">明文密码</param>
/// <param name="salt">盐值</param>
/// <returns>Base64编码的密码哈希值</returns>
public static string HashPassword(string password, string salt)
{
if (string.IsNullOrEmpty(password))
throw new ArgumentNullException(nameof(password));
if (string.IsNullOrEmpty(salt))
throw new ArgumentNullException(nameof(salt));
// 拼接密码和盐值
string combined = password + salt;
// 转换为字节数组
byte[] combinedBytes = Encoding.UTF8.GetBytes(combined);
// 计算 SHA256 哈希
using (var sha256 = SHA256.Create())
{
byte[] hashBytes = sha256.ComputeHash(combinedBytes);
// 转换为 Base64 字符串
string hash = Convert.ToBase64String(hashBytes);
return hash;
}
}
/// <summary>
/// 验证密码是否匹配
/// 精确实现:重新计算哈希并比较
/// </summary>
/// <param name="inputPassword">输入的明文密码</param>
/// <param name="storedHash">存储的密码哈希值</param>
/// <param name="salt">盐值</param>
/// <returns>密码是否匹配</returns>
public static bool VerifyPassword(string inputPassword, string storedHash, string salt)
{
if (string.IsNullOrEmpty(inputPassword))
return false;
if (string.IsNullOrEmpty(storedHash))
return false;
if (string.IsNullOrEmpty(salt))
return false;
try
{
// 使用相同的方法计算输入密码的哈希
string inputHash = HashPassword(inputPassword, salt);
// 精确比较(区分大小写)
bool isMatch = string.Equals(inputHash, storedHash, StringComparison.Ordinal);
// 调试输出
System.Diagnostics.Debug.WriteLine($"[密码验证]");
System.Diagnostics.Debug.WriteLine($" 输入密码: {inputPassword}");
System.Diagnostics.Debug.WriteLine($" 盐值: {salt}");
System.Diagnostics.Debug.WriteLine($" 计算的哈希: {inputHash}");
System.Diagnostics.Debug.WriteLine($" 存储的哈希: {storedHash}");
System.Diagnostics.Debug.WriteLine($" 是否匹配: {isMatch}");
return isMatch;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"[密码验证异常] {ex.Message}");
return false;
}
}
/// <summary>
/// 测试密码加密功能
/// </summary>
public static void TestPasswordEncryption()
{
System.Diagnostics.Debug.WriteLine("=== 测试密码加密功能 ===");
// 测试 1: admin123
string salt1 = GenerateSalt();
string hash1 = HashPassword("admin123", salt1);
bool verify1 = VerifyPassword("admin123", hash1, salt1);
System.Diagnostics.Debug.WriteLine($"\n测试 1: admin123");
System.Diagnostics.Debug.WriteLine($" 盐值: {salt1}");
System.Diagnostics.Debug.WriteLine($" 哈希: {hash1}");
System.Diagnostics.Debug.WriteLine($" 验证: {verify1} (应该为 True)");
// 测试 2: 123
string salt2 = GenerateSalt();
string hash2 = HashPassword("123", salt2);
bool verify2 = VerifyPassword("123", hash2, salt2);
System.Diagnostics.Debug.WriteLine($"\n测试 2: 123");
System.Diagnostics.Debug.WriteLine($" 盐值: {salt2}");
System.Diagnostics.Debug.WriteLine($" 哈希: {hash2}");
System.Diagnostics.Debug.WriteLine($" 验证: {verify2} (应该为 True)");
// 测试 3: 错误密码
bool verify3 = VerifyPassword("wrongpassword", hash1, salt1);
System.Diagnostics.Debug.WriteLine($"\n测试 3: 错误密码");
System.Diagnostics.Debug.WriteLine($" 验证: {verify3} (应该为 False)");
System.Diagnostics.Debug.WriteLine("\n=== 测试完成 ===\n");
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
namespace .DATA
{
/// <summary>
/// 用户模型类
/// </summary>
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public string Salt { get; set; }
public int UserRole { get; set; } // 0=普通用户1=管理员
public int Status { get; set; } // 0=禁用1=启用
public DateTime CreateTime { get; set; }
public DateTime? UpdateTime { get; set; }
public DateTime? LastLoginTime { get; set; }
}
/// <summary>
/// 用户角色枚举
/// </summary>
public enum UserRoleEnum
{
Normal = 0, // 普通用户
Admin = 1 // 管理员
}
}

View File

@@ -0,0 +1,290 @@
using Dapper;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
namespace .DATA
{
/// <summary>
/// 用户数据访问层
/// </summary>
public class UserRepository
{
private readonly string _connectionString;
public UserRepository()
{
_connectionString = "Server=localhost;Database=fullautowaterpressure;User=root;Password=123456;port=3306;charset=utf8;";
}
/// <summary>
/// 根据用户名查询用户
/// </summary>
/// <param name="username">用户名</param>
/// <returns>用户对象不存在返回null</returns>
public User GetUserByUsername(string username)
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
// 明确指定字段映射,避免命名差异问题
string sql = @"SELECT
id AS Id,
username AS Username,
password_hash AS PasswordHash,
salt AS Salt,
user_role AS UserRole,
status AS Status,
create_time AS CreateTime,
update_time AS UpdateTime,
last_login_time AS LastLoginTime
FROM sys_users
WHERE username = @username AND status = 1";
var user = connection.QueryFirstOrDefault<User>(sql, new { username });
// 调试输出
if (user != null)
{
System.Diagnostics.Debug.WriteLine($"\n[GetUserByUsername] 查询结果:");
System.Diagnostics.Debug.WriteLine($" 用户名: {user.Username}");
System.Diagnostics.Debug.WriteLine($" PasswordHash: '{user.PasswordHash ?? "(null)"}'");
System.Diagnostics.Debug.WriteLine($" PasswordHash 长度: {user.PasswordHash?.Length ?? 0}");
System.Diagnostics.Debug.WriteLine($" Salt: '{user.Salt ?? "(null)"}'");
System.Diagnostics.Debug.WriteLine($" UserRole: {user.UserRole}");
}
else
{
System.Diagnostics.Debug.WriteLine($"\n[GetUserByUsername] 未找到用户: {username}");
}
return user;
}
}
/// <summary>
/// 根据ID查询用户
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>用户对象不存在返回null</returns>
public User GetUserById(int userId)
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
// 明确指定字段映射
string sql = @"SELECT
id AS Id,
username AS Username,
password_hash AS PasswordHash,
salt AS Salt,
user_role AS UserRole,
status AS Status,
create_time AS CreateTime,
update_time AS UpdateTime,
last_login_time AS LastLoginTime
FROM sys_users
WHERE id = @id";
return connection.QueryFirstOrDefault<User>(sql, new { id = userId });
}
}
/// <summary>
/// 创建用户
/// </summary>
/// <param name="user">用户对象</param>
/// <param name="plainPassword">明文密码</param>
/// <returns>是否创建成功</returns>
public bool CreateUser(User user, string plainPassword)
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
// 简单明文密码存储
string passwordHash = plainPassword; // 直接使用明文
string salt = ""; // 空字符串
string sql = @"INSERT INTO sys_users
(username, password_hash, salt, user_role, status, create_time)
VALUES
(@username, @passwordHash, @salt, @userRole, 1, CURRENT_TIMESTAMP)";
int result = connection.Execute(sql, new
{
username = user.Username,
passwordHash = passwordHash,
salt = salt,
userRole = user.UserRole
});
return result > 0;
}
}
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="user">用户对象</param>
/// <returns>是否更新成功</returns>
public bool UpdateUser(User user)
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
string sql = @"UPDATE sys_users
SET username = @username, user_role = @userRole, status = @status
WHERE id = @id";
int result = connection.Execute(sql, new
{
username = user.Username,
userRole = user.UserRole,
status = user.Status,
id = user.Id
});
return result > 0;
}
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>是否删除成功</returns>
public bool DeleteUser(int userId)
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
string sql = @"DELETE FROM sys_users WHERE id = @id";
int result = connection.Execute(sql, new { id = userId });
return result > 0;
}
}
/// <summary>
/// 获取所有用户
/// </summary>
/// <returns>用户列表</returns>
public List<User> GetAllUsers()
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
// 明确指定字段映射
string sql = @"SELECT
id AS Id,
username AS Username,
password_hash AS PasswordHash,
salt AS Salt,
user_role AS UserRole,
status AS Status,
create_time AS CreateTime,
update_time AS UpdateTime,
last_login_time AS LastLoginTime
FROM sys_users
ORDER BY create_time DESC";
return connection.Query<User>(sql).ToList();
}
}
/// <summary>
/// 用户修改密码
/// </summary>
/// <param name="userId">用户ID</param>
/// <param name="oldPassword">旧密码</param>
/// <param name="newPassword">新密码</param>
/// <returns>是否修改成功</returns>
public bool ChangePassword(int userId, string oldPassword, string newPassword)
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
// 先验证旧密码
User user = GetUserById(userId);
if (user == null)
return false;
// 简单明文密码比较
if (user.PasswordHash != oldPassword)
return false;
// 更新新密码(明文)
string newPasswordHash = newPassword;
string newSalt = "";
string sql = @"UPDATE sys_users
SET password_hash = @passwordHash, salt = @salt, update_time = CURRENT_TIMESTAMP
WHERE id = @id";
int result = connection.Execute(sql, new
{
passwordHash = newPasswordHash,
salt = newSalt,
id = userId
});
return result > 0;
}
}
/// <summary>
/// 管理员重置用户密码
/// </summary>
/// <param name="userId">用户ID</param>
/// <param name="newPassword">新密码</param>
/// <returns>是否重置成功</returns>
public bool ResetPassword(int userId, string newPassword)
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
// 简单明文密码存储
string newPasswordHash = newPassword;
string newSalt = "";
string sql = @"UPDATE sys_users
SET password_hash = @passwordHash, salt = @salt, update_time = CURRENT_TIMESTAMP
WHERE id = @id";
int result = connection.Execute(sql, new
{
passwordHash = newPasswordHash,
salt = newSalt,
id = userId
});
return result > 0;
}
}
/// <summary>
/// 更新最后登录时间
/// </summary>
/// <param name="username">用户名</param>
/// <returns>是否更新成功</returns>
public bool UpdateLastLoginTime(string username)
{
using (var connection = new MySqlConnection(_connectionString))
{
connection.Open();
string sql = @"UPDATE sys_users
SET last_login_time = CURRENT_TIMESTAMP
WHERE username = @username";
int result = connection.Execute(sql, new { username });
return result > 0;
}
}
}
}

View File

@@ -0,0 +1,167 @@
namespace
{
partial class ChangePasswordForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnConfirm = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.txtConfirmPassword = new System.Windows.Forms.TextBox();
this.lblConfirmPassword = new System.Windows.Forms.Label();
this.txtNewPassword = new System.Windows.Forms.TextBox();
this.lblNewPassword = new System.Windows.Forms.Label();
this.txtOldPassword = new System.Windows.Forms.TextBox();
this.lblOldPassword = new System.Windows.Forms.Label();
this.panelMain = new System.Windows.Forms.Panel();
this.panelMain.SuspendLayout();
this.SuspendLayout();
//
// btnConfirm
//
this.btnConfirm.Location = new System.Drawing.Point(120, 250);
this.btnConfirm.Name = "btnConfirm";
this.btnConfirm.Size = new System.Drawing.Size(90, 35);
this.btnConfirm.TabIndex = 6;
this.btnConfirm.Text = "确定";
this.btnConfirm.UseVisualStyleBackColor = true;
this.btnConfirm.Click += new System.EventHandler(this.btnConfirm_Click);
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(230, 250);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(90, 35);
this.btnCancel.TabIndex = 7;
this.btnCancel.Text = "取消";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// txtConfirmPassword
//
this.txtConfirmPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.txtConfirmPassword.Location = new System.Drawing.Point(120, 200);
this.txtConfirmPassword.Name = "txtConfirmPassword";
this.txtConfirmPassword.PasswordChar = '*';
this.txtConfirmPassword.Size = new System.Drawing.Size(200, 25);
this.txtConfirmPassword.TabIndex = 2;
//
// lblConfirmPassword
//
this.lblConfirmPassword.AutoSize = true;
this.lblConfirmPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.lblConfirmPassword.Location = new System.Drawing.Point(30, 205);
this.lblConfirmPassword.Name = "lblConfirmPassword";
this.lblConfirmPassword.Size = new System.Drawing.Size(88, 20);
this.lblConfirmPassword.TabIndex = 5;
this.lblConfirmPassword.Text = "确认密码:";
//
// txtNewPassword
//
this.txtNewPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.txtNewPassword.Location = new System.Drawing.Point(120, 155);
this.txtNewPassword.Name = "txtNewPassword";
this.txtNewPassword.PasswordChar = '*';
this.txtNewPassword.Size = new System.Drawing.Size(200, 25);
this.txtNewPassword.TabIndex = 1;
//
// lblNewPassword
//
this.lblNewPassword.AutoSize = true;
this.lblNewPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.lblNewPassword.Location = new System.Drawing.Point(30, 160);
this.lblNewPassword.Name = "lblNewPassword";
this.lblNewPassword.Size = new System.Drawing.Size(88, 20);
this.lblNewPassword.TabIndex = 3;
this.lblNewPassword.Text = "新密码:";
//
// txtOldPassword
//
this.txtOldPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.txtOldPassword.Location = new System.Drawing.Point(120, 110);
this.txtOldPassword.Name = "txtOldPassword";
this.txtOldPassword.PasswordChar = '*';
this.txtOldPassword.Size = new System.Drawing.Size(200, 25);
this.txtOldPassword.TabIndex = 0;
//
// lblOldPassword
//
this.lblOldPassword.AutoSize = true;
this.lblOldPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.lblOldPassword.Location = new System.Drawing.Point(30, 115);
this.lblOldPassword.Name = "lblOldPassword";
this.lblOldPassword.Size = new System.Drawing.Size(88, 20);
this.lblOldPassword.TabIndex = 4;
this.lblOldPassword.Text = "旧密码:";
//
// panelMain
//
this.panelMain.BackColor = System.Drawing.Color.White;
this.panelMain.Controls.Add(this.txtConfirmPassword);
this.panelMain.Controls.Add(this.lblConfirmPassword);
this.panelMain.Controls.Add(this.txtNewPassword);
this.panelMain.Controls.Add(this.lblNewPassword);
this.panelMain.Controls.Add(this.txtOldPassword);
this.panelMain.Controls.Add(this.lblOldPassword);
this.panelMain.Location = new System.Drawing.Point(60, 50);
this.panelMain.Name = "panelMain";
this.panelMain.Size = new System.Drawing.Size(380, 320);
this.panelMain.TabIndex = 0;
//
// ChangePasswordForm
//
this.AcceptButton = this.btnConfirm;
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(500, 400);
this.Controls.Add(this.btnConfirm);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.panelMain);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ChangePasswordForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "修改密码";
this.panelMain.ResumeLayout(false);
this.panelMain.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TextBox txtOldPassword;
private System.Windows.Forms.Label lblOldPassword;
private System.Windows.Forms.TextBox txtNewPassword;
private System.Windows.Forms.Label lblNewPassword;
private System.Windows.Forms.TextBox txtConfirmPassword;
private System.Windows.Forms.Label lblConfirmPassword;
private System.Windows.Forms.Button btnConfirm;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Panel panelMain;
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Windows.Forms;
using .DATA;
namespace
{
public partial class ChangePasswordForm : Form
{
private UserRepository _userRepository;
public ChangePasswordForm()
{
InitializeComponent();
_userRepository = new UserRepository();
}
/// <summary>
/// 确定按钮
/// </summary>
private void btnConfirm_Click(object sender, EventArgs e)
{
string oldPassword = txtOldPassword.Text;
string newPassword = txtNewPassword.Text;
string confirmPassword = txtConfirmPassword.Text;
// 验证
if (string.IsNullOrEmpty(oldPassword))
{
MessageBox.Show("请输入旧密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtOldPassword.Focus();
return;
}
if (string.IsNullOrEmpty(newPassword))
{
MessageBox.Show("请输入新密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtNewPassword.Focus();
return;
}
if (newPassword.Length < 6)
{
MessageBox.Show("新密码长度不能少于6位", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtNewPassword.Focus();
return;
}
if (string.IsNullOrEmpty(confirmPassword))
{
MessageBox.Show("请输入确认密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtConfirmPassword.Focus();
return;
}
if (newPassword != confirmPassword)
{
MessageBox.Show("两次输入的密码不一致!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtConfirmPassword.Focus();
return;
}
try
{
if (_userRepository.ChangePassword(LoginData.CurrentUserId, oldPassword, newPassword))
{
MessageBox.Show("密码修改成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
MessageBox.Show("旧密码错误,请重新输入!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtOldPassword.Clear();
txtOldPassword.Focus();
}
}
catch (Exception ex)
{
MessageBox.Show($"修改密码失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 取消按钮
/// </summary>
private void btnCancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
}
}

View File

@@ -0,0 +1,203 @@
namespace
{
partial class LoginForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lblUsername = new System.Windows.Forms.Label();
this.lblPassword = new System.Windows.Forms.Label();
this.txtUsername = new System.Windows.Forms.TextBox();
this.txtPassword = new System.Windows.Forms.TextBox();
this.btnLogin = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.panelMain = new System.Windows.Forms.Panel();
this.rbNormalUser = new System.Windows.Forms.RadioButton();
this.rbAdmin = new System.Windows.Forms.RadioButton();
this.lblUserType = new System.Windows.Forms.Label();
this.panelMain.SuspendLayout();
this.SuspendLayout();
//
// lblUsername
//
this.lblUsername.AutoSize = true;
this.lblUsername.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F);
this.lblUsername.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.lblUsername.Location = new System.Drawing.Point(91, 97);
this.lblUsername.Name = "lblUsername";
this.lblUsername.Size = new System.Drawing.Size(88, 25);
this.lblUsername.TabIndex = 1;
this.lblUsername.Text = "用户名:";
//
// lblPassword
//
this.lblPassword.AutoSize = true;
this.lblPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F);
this.lblPassword.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.lblPassword.Location = new System.Drawing.Point(91, 150);
this.lblPassword.Name = "lblPassword";
this.lblPassword.Size = new System.Drawing.Size(69, 25);
this.lblPassword.TabIndex = 2;
this.lblPassword.Text = "密码:";
//
// txtUsername
//
this.txtUsername.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F);
this.txtUsername.Location = new System.Drawing.Point(194, 94);
this.txtUsername.Name = "txtUsername";
this.txtUsername.Size = new System.Drawing.Size(285, 31);
this.txtUsername.TabIndex = 2;
//
// txtPassword
//
this.txtPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F);
this.txtPassword.Location = new System.Drawing.Point(194, 147);
this.txtPassword.Name = "txtPassword";
this.txtPassword.PasswordChar = '●';
this.txtPassword.Size = new System.Drawing.Size(285, 31);
this.txtPassword.TabIndex = 3;
this.txtPassword.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtPassword_KeyDown);
//
// btnLogin
//
this.btnLogin.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(80)))), ((int)(((byte)(160)))), ((int)(((byte)(255)))));
this.btnLogin.FlatAppearance.BorderSize = 0;
this.btnLogin.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnLogin.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F, System.Drawing.FontStyle.Bold);
this.btnLogin.ForeColor = System.Drawing.Color.White;
this.btnLogin.Location = new System.Drawing.Point(194, 199);
this.btnLogin.Name = "btnLogin";
this.btnLogin.Size = new System.Drawing.Size(126, 35);
this.btnLogin.TabIndex = 4;
this.btnLogin.Text = "登录";
this.btnLogin.UseVisualStyleBackColor = false;
this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
//
// btnCancel
//
this.btnCancel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
this.btnCancel.FlatAppearance.BorderSize = 0;
this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnCancel.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F);
this.btnCancel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.btnCancel.Location = new System.Drawing.Point(354, 199);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(126, 35);
this.btnCancel.TabIndex = 5;
this.btnCancel.Text = "退出";
this.btnCancel.UseVisualStyleBackColor = false;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// panelMain
//
this.panelMain.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(235)))), ((int)(((byte)(240)))));
this.panelMain.Controls.Add(this.rbNormalUser);
this.panelMain.Controls.Add(this.rbAdmin);
this.panelMain.Controls.Add(this.lblUserType);
this.panelMain.Controls.Add(this.btnCancel);
this.panelMain.Controls.Add(this.btnLogin);
this.panelMain.Controls.Add(this.txtPassword);
this.panelMain.Controls.Add(this.lblPassword);
this.panelMain.Controls.Add(this.lblUsername);
this.panelMain.Controls.Add(this.txtUsername);
this.panelMain.Location = new System.Drawing.Point(91, 53);
this.panelMain.Name = "panelMain";
this.panelMain.Size = new System.Drawing.Size(571, 265);
this.panelMain.TabIndex = 4;
this.panelMain.Paint += new System.Windows.Forms.PaintEventHandler(this.panelMain_Paint);
//
// rbNormalUser
//
this.rbNormalUser.AutoSize = true;
this.rbNormalUser.Checked = true;
this.rbNormalUser.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F);
this.rbNormalUser.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.rbNormalUser.Location = new System.Drawing.Point(354, 42);
this.rbNormalUser.Name = "rbNormalUser";
this.rbNormalUser.Size = new System.Drawing.Size(109, 29);
this.rbNormalUser.TabIndex = 1;
this.rbNormalUser.TabStop = true;
this.rbNormalUser.Text = "普通用户";
this.rbNormalUser.UseVisualStyleBackColor = true;
this.rbNormalUser.CheckedChanged += new System.EventHandler(this.rbUserType_CheckedChanged);
//
// rbAdmin
//
this.rbAdmin.AutoSize = true;
this.rbAdmin.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F);
this.rbAdmin.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.rbAdmin.Location = new System.Drawing.Point(211, 42);
this.rbAdmin.Name = "rbAdmin";
this.rbAdmin.Size = new System.Drawing.Size(90, 29);
this.rbAdmin.TabIndex = 0;
this.rbAdmin.Text = "管理员";
this.rbAdmin.UseVisualStyleBackColor = true;
this.rbAdmin.CheckedChanged += new System.EventHandler(this.rbUserType_CheckedChanged);
//
// lblUserType
//
this.lblUserType.AutoSize = true;
this.lblUserType.Font = new System.Drawing.Font("Microsoft YaHei UI", 11F);
this.lblUserType.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.lblUserType.Location = new System.Drawing.Point(91, 44);
this.lblUserType.Name = "lblUserType";
this.lblUserType.Size = new System.Drawing.Size(107, 25);
this.lblUserType.TabIndex = 6;
this.lblUserType.Text = "用户类型:";
//
// LoginForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(235)))), ((int)(((byte)(240)))));
this.ClientSize = new System.Drawing.Size(754, 371);
this.Controls.Add(this.panelMain);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "LoginForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "用户登录";
this.panelMain.ResumeLayout(false);
this.panelMain.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Label lblUsername;
private System.Windows.Forms.Label lblPassword;
private System.Windows.Forms.TextBox txtUsername;
private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.Button btnLogin;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Panel panelMain;
private System.Windows.Forms.Label lblUserType;
private System.Windows.Forms.RadioButton rbAdmin;
private System.Windows.Forms.RadioButton rbNormalUser;
}
}

View File

@@ -0,0 +1,186 @@
using System;
using System.Windows.Forms;
using .DATA;
namespace
{
public partial class LoginForm : Form
{
private UserRepository _userRepository;
private int _selectedUserType = 0; // 0=普通用户, 1=管理员
public LoginForm()
{
InitializeComponent();
_userRepository = new UserRepository();
}
/// <summary>
/// 用户类型切换事件
/// </summary>
private void rbUserType_CheckedChanged(object sender, EventArgs e)
{
if (rbAdmin.Checked)
{
_selectedUserType = 1; // 管理员
}
else if (rbNormalUser.Checked)
{
_selectedUserType = 0; // 普通用户
}
// 切换用户类型时自动清空用户名和密码
txtUsername.Clear();
txtPassword.Clear();
txtUsername.Focus();
}
/// <summary>
/// 登录按钮点击事件
/// </summary>
private void btnLogin_Click(object sender, EventArgs e)
{
string username = txtUsername.Text.Trim();
string password = txtPassword.Text;
// 输入验证
if (string.IsNullOrEmpty(username))
{
MessageBox.Show("请输入用户名!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtUsername.Focus();
return;
}
if (string.IsNullOrEmpty(password))
{
MessageBox.Show("请输入密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtPassword.Focus();
return;
}
try
{
// 查询用户
User user = _userRepository.GetUserByUsername(username);
if (user == null)
{
MessageBox.Show("用户名或密码错误!", "登录失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtPassword.Clear();
txtPassword.Focus();
return;
}
// 获取数据库中存储的密码
string storedPassword = user.PasswordHash ?? "";
// 详细调试输出
System.Diagnostics.Debug.WriteLine($"\n========== 登录验证详细信息 ==========");
System.Diagnostics.Debug.WriteLine($"用户名: {username}");
System.Diagnostics.Debug.WriteLine($"输入密码: '{password}'");
System.Diagnostics.Debug.WriteLine($"输入密码长度: {password.Length}");
System.Diagnostics.Debug.WriteLine($"数据库密码: '{storedPassword}'");
System.Diagnostics.Debug.WriteLine($"数据库密码长度: {storedPassword.Length}");
System.Diagnostics.Debug.WriteLine($"盐值: '{user.Salt ?? "(null)"}'");
// 检查是否是旧的加密格式Base64 编码的哈希值)
bool isOldFormat = storedPassword.Length > 20 && (storedPassword.Contains("+") || storedPassword.Contains("/") || storedPassword.Contains("="));
System.Diagnostics.Debug.WriteLine($"是否旧格式: {isOldFormat}");
bool passwordValid = false;
if (isOldFormat)
{
// 旧格式:需要重置
System.Diagnostics.Debug.WriteLine($"检测到旧的加密格式,需要重置密码");
MessageBox.Show("检测到旧的密码格式!\n\n请重启程序系统会自动修复密码。\n\n或者手动运行 SQL 脚本:\n查询并修复密码.sql",
"需要重置密码", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtPassword.Clear();
txtPassword.Focus();
return;
}
else
{
// 新格式:明文比较
passwordValid = (password == storedPassword);
System.Diagnostics.Debug.WriteLine($"明文比较结果: {passwordValid}");
// 逐字符比较(用于调试)
if (!passwordValid && password.Length == storedPassword.Length)
{
System.Diagnostics.Debug.WriteLine($"逐字符比较:");
for (int i = 0; i < password.Length; i++)
{
char c1 = password[i];
char c2 = storedPassword[i];
System.Diagnostics.Debug.WriteLine($" 位置 {i}: 输入='{c1}'({(int)c1}) 数据库='{c2}'({(int)c2}) 相同={c1 == c2}");
}
}
}
System.Diagnostics.Debug.WriteLine($"最终验证结果: {passwordValid}");
System.Diagnostics.Debug.WriteLine($"======================================\n");
if (!passwordValid)
{
MessageBox.Show("用户名或密码错误!", "登录失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtPassword.Clear();
txtPassword.Focus();
return;
}
// 验证用户类型是否匹配
if (user.UserRole != _selectedUserType)
{
string expectedType = _selectedUserType == 1 ? "管理员" : "普通用户";
string actualType = user.UserRole == 1 ? "管理员" : "普通用户";
MessageBox.Show($"用户类型不匹配!\n\n该账户是【{actualType}】\n请选择正确的用户类型后重新登录。",
"登录失败", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
// 登录成功
_userRepository.UpdateLastLoginTime(username);
// 保存登录信息到LoginData
LoginData.UserName = username;
LoginData.UserPower = user.UserRole;
LoginData.CurrentUserId = user.Id;
LoginData.LoginTime = DateTime.Now;
// 关闭登录窗体,返回 DialogResult.OK
this.DialogResult = DialogResult.OK;
this.Close();
}
catch (Exception ex)
{
MessageBox.Show($"登录失败:{ex.Message}\n\n请检查数据库连接是否正常。", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 退出按钮点击事件
/// </summary>
private void btnCancel_Click(object sender, EventArgs e)
{
Application.Exit();
}
/// <summary>
/// 回车键快速登录
/// </summary>
private void txtPassword_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
btnLogin_Click(sender, e);
}
}
private void panelMain_Paint(object sender, PaintEventArgs e)
{
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,185 @@
namespace
{
partial class UserEditForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnSave = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.chkStatus = new System.Windows.Forms.CheckBox();
this.cmbUserRole = new System.Windows.Forms.ComboBox();
this.lblUserRole = new System.Windows.Forms.Label();
this.lblPassword = new System.Windows.Forms.Label();
this.lblUsername = new System.Windows.Forms.Label();
this.txtPassword = new System.Windows.Forms.TextBox();
this.txtUsername = new System.Windows.Forms.TextBox();
this.panelMain = new System.Windows.Forms.Panel();
this.panelMain.SuspendLayout();
this.SuspendLayout();
//
// btnSave
//
this.btnSave.Location = new System.Drawing.Point(150, 230);
this.btnSave.Name = "btnSave";
this.btnSave.Size = new System.Drawing.Size(90, 35);
this.btnSave.TabIndex = 6;
this.btnSave.Text = "保存";
this.btnSave.UseVisualStyleBackColor = true;
this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(260, 230);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(90, 35);
this.btnCancel.TabIndex = 7;
this.btnCancel.Text = "取消";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// chkStatus
//
this.chkStatus.AutoSize = true;
this.chkStatus.Checked = true;
this.chkStatus.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkStatus.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.chkStatus.Location = new System.Drawing.Point(150, 190);
this.chkStatus.Name = "chkStatus";
this.chkStatus.Size = new System.Drawing.Size(78, 24);
this.chkStatus.TabIndex = 5;
this.chkStatus.Text = "启用";
//
// cmbUserRole
//
this.cmbUserRole.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbUserRole.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.cmbUserRole.FormattingEnabled = true;
this.cmbUserRole.Items.AddRange(new object[] {
"普通用户",
"管理员"});
this.cmbUserRole.Location = new System.Drawing.Point(150, 155);
this.cmbUserRole.Name = "cmbUserRole";
this.cmbUserRole.Size = new System.Drawing.Size(200, 28);
this.cmbUserRole.TabIndex = 4;
//
// lblUserRole
//
this.lblUserRole.AutoSize = true;
this.lblUserRole.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.lblUserRole.Location = new System.Drawing.Point(60, 160);
this.lblUserRole.Name = "lblUserRole";
this.lblUserRole.Size = new System.Drawing.Size(68, 20);
this.lblUserRole.TabIndex = 3;
this.lblUserRole.Text = "用户角色:";
//
// lblPassword
//
this.lblPassword.AutoSize = true;
this.lblPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.lblPassword.Location = new System.Drawing.Point(60, 120);
this.lblPassword.Name = "lblPassword";
this.lblPassword.Size = new System.Drawing.Size(68, 20);
this.lblPassword.TabIndex = 2;
this.lblPassword.Text = "密码:";
//
// lblUsername
//
this.lblUsername.AutoSize = true;
this.lblUsername.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.lblUsername.Location = new System.Drawing.Point(60, 80);
this.lblUsername.Name = "lblUsername";
this.lblUsername.Size = new System.Drawing.Size(68, 20);
this.lblUsername.TabIndex = 1;
this.lblUsername.Text = "用户名:";
//
// txtPassword
//
this.txtPassword.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.txtPassword.Location = new System.Drawing.Point(150, 117);
this.txtPassword.Name = "txtPassword";
this.txtPassword.PasswordChar = '*';
this.txtPassword.Size = new System.Drawing.Size(200, 25);
this.txtPassword.TabIndex = 1;
//
// txtUsername
//
this.txtUsername.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F);
this.txtUsername.Location = new System.Drawing.Point(150, 77);
this.txtUsername.Name = "txtUsername";
this.txtUsername.Size = new System.Drawing.Size(200, 25);
this.txtUsername.TabIndex = 0;
//
// panelMain
//
this.panelMain.BackColor = System.Drawing.Color.White;
this.panelMain.Controls.Add(this.chkStatus);
this.panelMain.Controls.Add(this.cmbUserRole);
this.panelMain.Controls.Add(this.lblUserRole);
this.panelMain.Controls.Add(this.lblPassword);
this.panelMain.Controls.Add(this.lblUsername);
this.panelMain.Controls.Add(this.txtPassword);
this.panelMain.Controls.Add(this.txtUsername);
this.panelMain.Location = new System.Drawing.Point(60, 50);
this.panelMain.Name = "panelMain";
this.panelMain.Size = new System.Drawing.Size(400, 300);
this.panelMain.TabIndex = 0;
//
// UserEditForm
//
this.AcceptButton = this.btnSave;
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(520, 380);
this.Controls.Add(this.btnSave);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.panelMain);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "UserEditForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "UserEditForm";
this.panelMain.ResumeLayout(false);
this.panelMain.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TextBox txtUsername;
private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.Label lblUsername;
private System.Windows.Forms.Label lblPassword;
private System.Windows.Forms.Label lblUserRole;
private System.Windows.Forms.ComboBox cmbUserRole;
private System.Windows.Forms.CheckBox chkStatus;
private System.Windows.Forms.Button btnSave;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Panel panelMain;
}
}

View File

@@ -0,0 +1,137 @@
using System;
using System.Windows.Forms;
using .DATA;
namespace
{
public partial class UserEditForm : Form
{
private UserRepository _userRepository;
private User _user;
private bool _isEditMode;
public UserEditForm() : this(null) { }
public UserEditForm(User user)
{
InitializeComponent();
_userRepository = new UserRepository();
_user = user;
_isEditMode = user != null;
InitializeFormData();
}
/// <summary>
/// 初始化表单数据
/// </summary>
private void InitializeFormData()
{
if (_isEditMode)
{
this.Text = "编辑用户";
txtUsername.Text = _user.Username;
txtUsername.ReadOnly = true; // 编辑模式不能修改用户名
txtPassword.Visible = false;
lblPassword.Visible = false;
cmbUserRole.SelectedIndex = _user.UserRole;
chkStatus.Checked = _user.Status == 1;
}
else
{
this.Text = "添加用户";
cmbUserRole.SelectedIndex = 0; // 默认为普通用户
chkStatus.Checked = true;
}
}
/// <summary>
/// 保存按钮
/// </summary>
private void btnSave_Click(object sender, EventArgs e)
{
string username = txtUsername.Text.Trim();
string password = txtPassword.Text;
int userRole = cmbUserRole.SelectedIndex;
int status = chkStatus.Checked ? 1 : 0;
// 验证
if (string.IsNullOrEmpty(username))
{
MessageBox.Show("请输入用户名!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtUsername.Focus();
return;
}
if (!_isEditMode && string.IsNullOrEmpty(password))
{
MessageBox.Show("请输入密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtPassword.Focus();
return;
}
if (!_isEditMode && password.Length < 6)
{
MessageBox.Show("密码长度不能少于6位", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtPassword.Focus();
return;
}
try
{
if (_isEditMode)
{
// 编辑模式:更新用户信息
_user.Username = username;
_user.UserRole = userRole;
_user.Status = status;
if (_userRepository.UpdateUser(_user))
{
MessageBox.Show("用户信息更新成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
MessageBox.Show("用户信息更新失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
// 添加模式:创建新用户
var newUser = new User
{
Username = username,
UserRole = userRole,
Status = status
};
if (_userRepository.CreateUser(newUser, password))
{
MessageBox.Show("用户创建成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
MessageBox.Show("用户创建失败,用户名可能已存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
catch (Exception ex)
{
MessageBox.Show($"操作失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 取消按钮
/// </summary>
private void btnCancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
}
}

View File

@@ -0,0 +1,190 @@
namespace
{
partial class UserManagerForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dgvUsers = new System.Windows.Forms.DataGridView();
this.btnRefresh = new System.Windows.Forms.Button();
this.btnResetPassword = new System.Windows.Forms.Button();
this.btnDeleteUser = new System.Windows.Forms.Button();
this.btnEditUser = new System.Windows.Forms.Button();
this.btnAddUser = new System.Windows.Forms.Button();
this.panelTop = new System.Windows.Forms.Panel();
this.lblTitle = new System.Windows.Forms.Label();
this.panelBottom = new System.Windows.Forms.Panel();
this.panelMain = new System.Windows.Forms.Panel();
((System.ComponentModel.ISupportInitialize)(this.dgvUsers)).BeginInit();
this.panelTop.SuspendLayout();
this.panelBottom.SuspendLayout();
this.panelMain.SuspendLayout();
this.SuspendLayout();
//
// dgvUsers
//
this.dgvUsers.AllowUserToAddRows = false;
this.dgvUsers.AllowUserToDeleteRows = false;
this.dgvUsers.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgvUsers.BackgroundColor = System.Drawing.Color.White;
this.dgvUsers.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgvUsers.Location = new System.Drawing.Point(10, 10);
this.dgvUsers.Name = "dgvUsers";
this.dgvUsers.ReadOnly = true;
this.dgvUsers.RowHeadersVisible = false;
this.dgvUsers.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgvUsers.Size = new System.Drawing.Size(780, 350);
this.dgvUsers.TabIndex = 0;
this.dgvUsers.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvUsers_CellClick);
//
// btnRefresh
//
this.btnRefresh.Location = new System.Drawing.Point(450, 10);
this.btnRefresh.Name = "btnRefresh";
this.btnRefresh.Size = new System.Drawing.Size(90, 35);
this.btnRefresh.TabIndex = 4;
this.btnRefresh.Text = "刷新";
this.btnRefresh.UseVisualStyleBackColor = true;
this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
//
// btnResetPassword
//
this.btnResetPassword.Location = new System.Drawing.Point(340, 10);
this.btnResetPassword.Name = "btnResetPassword";
this.btnResetPassword.Size = new System.Drawing.Size(90, 35);
this.btnResetPassword.TabIndex = 3;
this.btnResetPassword.Text = "重置密码";
this.btnResetPassword.UseVisualStyleBackColor = true;
this.btnResetPassword.Click += new System.EventHandler(this.btnResetPassword_Click);
//
// btnDeleteUser
//
this.btnDeleteUser.Location = new System.Drawing.Point(230, 10);
this.btnDeleteUser.Name = "btnDeleteUser";
this.btnDeleteUser.Size = new System.Drawing.Size(90, 35);
this.btnDeleteUser.TabIndex = 2;
this.btnDeleteUser.Text = "删除用户";
this.btnDeleteUser.UseVisualStyleBackColor = true;
this.btnDeleteUser.Click += new System.EventHandler(this.btnDeleteUser_Click);
//
// btnEditUser
//
this.btnEditUser.Location = new System.Drawing.Point(120, 10);
this.btnEditUser.Name = "btnEditUser";
this.btnEditUser.Size = new System.Drawing.Size(90, 35);
this.btnEditUser.TabIndex = 1;
this.btnEditUser.Text = "编辑用户";
this.btnEditUser.UseVisualStyleBackColor = true;
this.btnEditUser.Click += new System.EventHandler(this.btnEditUser_Click);
//
// btnAddUser
//
this.btnAddUser.Location = new System.Drawing.Point(10, 10);
this.btnAddUser.Name = "btnAddUser";
this.btnAddUser.Size = new System.Drawing.Size(90, 35);
this.btnAddUser.TabIndex = 0;
this.btnAddUser.Text = "添加用户";
this.btnAddUser.UseVisualStyleBackColor = true;
this.btnAddUser.Click += new System.EventHandler(this.btnAddUser_Click);
//
// panelTop
//
this.panelTop.Controls.Add(this.lblTitle);
this.panelTop.Dock = System.Windows.Forms.DockStyle.Top;
this.panelTop.Location = new System.Drawing.Point(0, 0);
this.panelTop.Name = "panelTop";
this.panelTop.Size = new System.Drawing.Size(800, 50);
this.panelTop.TabIndex = 1;
//
// lblTitle
//
this.lblTitle.AutoSize = true;
this.lblTitle.Font = new System.Drawing.Font("Microsoft YaHei UI", 16F, System.Drawing.FontStyle.Bold);
this.lblTitle.Location = new System.Drawing.Point(15, 10);
this.lblTitle.Name = "lblTitle";
this.lblTitle.Size = new System.Drawing.Size(108, 31);
this.lblTitle.TabIndex = 0;
this.lblTitle.Text = "用户管理";
//
// panelBottom
//
this.panelBottom.Controls.Add(this.btnRefresh);
this.panelBottom.Controls.Add(this.btnResetPassword);
this.panelBottom.Controls.Add(this.btnDeleteUser);
this.panelBottom.Controls.Add(this.btnEditUser);
this.panelBottom.Controls.Add(this.btnAddUser);
this.panelBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panelBottom.Location = new System.Drawing.Point(0, 420);
this.panelBottom.Name = "panelBottom";
this.panelBottom.Size = new System.Drawing.Size(800, 60);
this.panelBottom.TabIndex = 2;
//
// panelMain
//
this.panelMain.Controls.Add(this.dgvUsers);
this.panelMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.panelMain.Location = new System.Drawing.Point(0, 50);
this.panelMain.Name = "panelMain";
this.panelMain.Size = new System.Drawing.Size(800, 370);
this.panelMain.TabIndex = 3;
//
// UserManagerForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 480);
this.Controls.Add(this.panelMain);
this.Controls.Add(this.panelBottom);
this.Controls.Add(this.panelTop);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.Name = "UserManagerForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "用户管理";
this.Load += new System.EventHandler(this.UserManagerForm_Load);
((System.ComponentModel.ISupportInitialize)(this.dgvUsers)).EndInit();
this.panelTop.ResumeLayout(false);
this.panelTop.PerformLayout();
this.panelBottom.ResumeLayout(false);
this.panelMain.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dgvUsers;
private System.Windows.Forms.Button btnRefresh;
private System.Windows.Forms.Button btnResetPassword;
private System.Windows.Forms.Button btnDeleteUser;
private System.Windows.Forms.Button btnEditUser;
private System.Windows.Forms.Button btnAddUser;
private System.Windows.Forms.Panel panelTop;
private System.Windows.Forms.Label lblTitle;
private System.Windows.Forms.Panel panelBottom;
private System.Windows.Forms.Panel panelMain;
}
}

View File

@@ -0,0 +1,287 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using .DATA;
namespace
{
public partial class UserManagerForm : Form
{
private UserRepository _userRepository;
private List<User> _users;
public UserManagerForm()
{
InitializeComponent();
_userRepository = new UserRepository();
}
/// <summary>
/// 窗体加载事件
/// </summary>
private void UserManagerForm_Load(object sender, EventArgs e)
{
LoadUsers();
}
/// <summary>
/// 加载用户列表
/// </summary>
private void LoadUsers()
{
try
{
_users = _userRepository.GetAllUsers();
// 配置 DataGridView 列
dgvUsers.Columns.Clear();
dgvUsers.AutoGenerateColumns = false;
dgvUsers.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "Id",
HeaderText = "ID",
Visible = false
});
dgvUsers.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "Username",
HeaderText = "用户名"
});
dgvUsers.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "UserRole",
HeaderText = "角色"
});
dgvUsers.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "Status",
HeaderText = "状态"
});
dgvUsers.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "CreateTime",
HeaderText = "创建时间",
DefaultCellStyle = new DataGridViewCellStyle { Format = "yyyy-MM-dd HH:mm:ss" }
});
dgvUsers.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "LastLoginTime",
HeaderText = "最后登录时间",
DefaultCellStyle = new DataGridViewCellStyle { Format = "yyyy-MM-dd HH:mm:ss", NullValue = "" }
});
// 绑定数据
var displayData = _users.Select(u => new
{
u.Id,
u.Username,
UserRole = u.UserRole == 1 ? "管理员" : "普通用户",
Status = u.Status == 1 ? "启用" : "禁用",
u.CreateTime,
LastLoginTime = u.LastLoginTime.HasValue ? u.LastLoginTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : ""
}).ToList();
dgvUsers.DataSource = displayData;
}
catch (Exception ex)
{
MessageBox.Show($"加载用户列表失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 添加用户按钮
/// </summary>
private void btnAddUser_Click(object sender, EventArgs e)
{
var addUserForm = new UserEditForm();
if (addUserForm.ShowDialog() == DialogResult.OK)
{
LoadUsers();
MessageBox.Show("用户添加成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
/// <summary>
/// 编辑用户按钮
/// </summary>
private void btnEditUser_Click(object sender, EventArgs e)
{
if (dgvUsers.CurrentRow == null)
{
MessageBox.Show("请先选择要编辑的用户!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
int userId = Convert.ToInt32(dgvUsers.CurrentRow.Cells[0].Value);
User selectedUser = _userRepository.GetUserById(userId);
if (selectedUser == null)
{
MessageBox.Show("未找到用户信息!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var editUserForm = new UserEditForm(selectedUser);
if (editUserForm.ShowDialog() == DialogResult.OK)
{
LoadUsers();
MessageBox.Show("用户信息更新成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
/// <summary>
/// 删除用户按钮
/// </summary>
private void btnDeleteUser_Click(object sender, EventArgs e)
{
if (dgvUsers.CurrentRow == null)
{
MessageBox.Show("请先选择要删除的用户!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
int userId = Convert.ToInt32(dgvUsers.CurrentRow.Cells[0].Value);
string username = dgvUsers.CurrentRow.Cells[1].Value.ToString();
if (userId == LoginData.CurrentUserId)
{
MessageBox.Show("不能删除当前登录的用户!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (MessageBox.Show($"确定要删除用户 {username} 吗?", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
try
{
if (_userRepository.DeleteUser(userId))
{
LoadUsers();
MessageBox.Show("用户删除成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("用户删除失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception ex)
{
MessageBox.Show($"删除用户失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
/// <summary>
/// 重置密码按钮
/// </summary>
private void btnResetPassword_Click(object sender, EventArgs e)
{
if (dgvUsers.CurrentRow == null)
{
MessageBox.Show("请先选择要重置密码的用户!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
int userId = Convert.ToInt32(dgvUsers.CurrentRow.Cells[0].Value);
string username = dgvUsers.CurrentRow.Cells[1].Value.ToString();
string newPassword = string.Empty;
using (var inputForm = new Form())
{
inputForm.Text = "重置密码";
inputForm.FormBorderStyle = FormBorderStyle.FixedDialog;
inputForm.StartPosition = FormStartPosition.CenterScreen;
inputForm.Size = new System.Drawing.Size(300, 150);
var label = new Label
{
Text = $"请输入 {username} 的新密码:",
Location = new System.Drawing.Point(10, 10),
Size = new System.Drawing.Size(280, 20)
};
var textBox = new TextBox
{
Location = new System.Drawing.Point(10, 35),
Size = new System.Drawing.Size(260, 25),
PasswordChar = '*'
};
var btnOk = new Button
{
Text = "确定",
DialogResult = DialogResult.OK,
Location = new System.Drawing.Point(70, 70),
Size = new System.Drawing.Size(80, 30)
};
var btnCancel = new Button
{
Text = "取消",
DialogResult = DialogResult.Cancel,
Location = new System.Drawing.Point(160, 70),
Size = new System.Drawing.Size(80, 30)
};
inputForm.Controls.AddRange(new Control[] { label, textBox, btnOk, btnCancel });
inputForm.AcceptButton = btnOk;
inputForm.CancelButton = btnCancel;
if (inputForm.ShowDialog() == DialogResult.OK)
{
newPassword = textBox.Text.Trim();
}
}
if (string.IsNullOrEmpty(newPassword) || newPassword.Length < 6)
{
MessageBox.Show("密码长度不能少于6位", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
try
{
if (_userRepository.ResetPassword(userId, newPassword))
{
MessageBox.Show("密码重置成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("密码重置失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception ex)
{
MessageBox.Show($"重置密码失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 刷新按钮
/// </summary>
private void btnRefresh_Click(object sender, EventArgs e)
{
LoadUsers();
}
/// <summary>
/// 表格行点击事件
/// </summary>
private void dgvUsers_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.RowIndex < dgvUsers.Rows.Count)
{
dgvUsers.Rows[e.RowIndex].Selected = true;
}
}
}
}

View File

@@ -708,6 +708,24 @@ namespace 全自动水压检测仪
private void NormalTemperatureMode_Load(object sender, EventArgs e)
{
// 权限检查:只有管理员才能看到"录入系统"按钮
if (!LoginData.IsAdmin())
{
// 普通用户隐藏"录入系统"按钮
uiButton7.Visible = false;
// 调试输出
System.Diagnostics.Debug.WriteLine($"[NormalTemperatureMode] 普通用户登录,隐藏录入系统按钮");
}
else
{
// 管理员显示"录入系统"按钮
uiButton7.Visible = true;
// 调试输出
System.Diagnostics.Debug.WriteLine($"[NormalTemperatureMode] 管理员登录,显示录入系统按钮");
}
string plcIp = "192.168.1.10";
//string plcIp = "127.0.0.1";
bool initSuccess = Data.ModbusResourceManager.Instance.Init(plcIp, 502);

View File

@@ -16,23 +16,187 @@ namespace 全自动水压检测仪
/// </summary>
[STAThread]
static void Main()
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Coeffiicientsetting coeffiicientsetting = new Coeffiicientsetting();
//HighTemperatureMode highTemperatureMode = new HighTemperatureMode();
//NormalTemperatureMode normalTemperatureMode = new NormalTemperatureMode();
try
{
// 测试密码加密功能
System.Diagnostics.Debug.WriteLine("\n========================================");
System.Diagnostics.Debug.WriteLine("程序启动 - 密码加密测试");
System.Diagnostics.Debug.WriteLine("========================================");
PasswordHelper.TestPasswordEncryption();
//FormManager.Instance
// .RegisterForm(coeffiicientsetting)
// .RegisterForm(highTemperatureMode)
// .RegisterForm(normalTemperatureMode);
// 检查是否有重置参数
bool forceReset = args.Length > 0 && args[0].ToLower() == "--reset-users";
if (forceReset)
{
var result = MessageBox.Show(
"确定要重置默认用户吗?\n\n这将删除并重新创建\n• admin / admin123 (管理员)\n• cgx / 123 (普通用户)\n\n其他用户不受影响。",
"重置默认用户",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
//Application.Run(normalTemperatureMode);
Application.Run(new ScanImport());
if (result == DialogResult.Yes)
{
DatabaseInitializer.Initialize();
DatabaseInitializer.ForceResetDefaultUsers();
MessageBox.Show("默认用户已重置!\n\n管理员: admin / admin123\n普通用户: cgx / 123",
"重置成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
return;
}
// 初始化数据库表和默认管理员账户
System.Diagnostics.Debug.WriteLine("\n========================================");
System.Diagnostics.Debug.WriteLine("初始化数据库");
System.Diagnostics.Debug.WriteLine("========================================");
DatabaseInitializer.Initialize();
// 检查并修复损坏的密码数据
System.Diagnostics.Debug.WriteLine("\n========================================");
System.Diagnostics.Debug.WriteLine("检查密码数据完整性");
System.Diagnostics.Debug.WriteLine("========================================");
CheckAndFixPasswordData();
}
catch (Exception ex)
{
MessageBox.Show($"数据库初始化失败:{ex.Message}\n\n请检查\n1. MySQL服务是否启动\n2. 数据库连接配置是否正确\n3. 数据库 fullautowaterpressure 是否存在\n\n应用程序将退出。",
"初始化错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 显示登录窗体
using (var loginForm = new LoginForm())
{
if (loginForm.ShowDialog() == DialogResult.OK)
{
// 登录成功,根据用户权限显示对应窗体
if (LoginData.IsAdmin())
{
// 管理员登录,显示 ScanImport 页面
Application.Run(new ScanImport());
}
else
{
// 普通用户登录,显示 NormalTemperatureMode 页面
Application.Run(new NormalTemperatureMode());
}
}
// 登录失败或取消,直接退出
}
}
/// <summary>
/// 检查并修复损坏的密码数据
/// </summary>
private static void CheckAndFixPasswordData()
{
try
{
var userRepo = new UserRepository();
// 检查默认用户
var adminUser = userRepo.GetUserByUsername("admin");
var cgxUser = userRepo.GetUserByUsername("cgx");
bool needsReset = false;
// 检查 admin 用户
if (adminUser != null)
{
string storedPassword = adminUser.PasswordHash ?? "";
System.Diagnostics.Debug.WriteLine($"\n检查 admin 用户:");
System.Diagnostics.Debug.WriteLine($" 当前密码值: '{storedPassword}'");
System.Diagnostics.Debug.WriteLine($" 密码长度: {storedPassword.Length}");
// 检查是否为空
if (string.IsNullOrEmpty(storedPassword))
{
System.Diagnostics.Debug.WriteLine($" 状态: 密码为空");
needsReset = true;
}
// 检查是否是旧的加密格式(包含 Base64 特殊字符)
else if (storedPassword.Length > 20 && (storedPassword.Contains("+") || storedPassword.Contains("/") || storedPassword.Contains("=")))
{
System.Diagnostics.Debug.WriteLine($" 状态: 旧的加密格式");
needsReset = true;
}
// 检查是否是正确的明文密码
else if (storedPassword != "admin123")
{
System.Diagnostics.Debug.WriteLine($" 状态: 密码不正确(应该是 'admin123'");
needsReset = true;
}
else
{
System.Diagnostics.Debug.WriteLine($" 状态: ✓ 正确");
}
}
else
{
System.Diagnostics.Debug.WriteLine($"\nadmin 用户不存在");
needsReset = true;
}
// 检查 cgx 用户
if (cgxUser != null)
{
string storedPassword = cgxUser.PasswordHash ?? "";
System.Diagnostics.Debug.WriteLine($"\n检查 cgx 用户:");
System.Diagnostics.Debug.WriteLine($" 当前密码值: '{storedPassword}'");
System.Diagnostics.Debug.WriteLine($" 密码长度: {storedPassword.Length}");
if (string.IsNullOrEmpty(storedPassword))
{
System.Diagnostics.Debug.WriteLine($" 状态: 密码为空");
needsReset = true;
}
else if (storedPassword.Length > 20 && (storedPassword.Contains("+") || storedPassword.Contains("/") || storedPassword.Contains("=")))
{
System.Diagnostics.Debug.WriteLine($" 状态: 旧的加密格式");
needsReset = true;
}
else if (storedPassword != "123")
{
System.Diagnostics.Debug.WriteLine($" 状态: 密码不正确(应该是 '123'");
needsReset = true;
}
else
{
System.Diagnostics.Debug.WriteLine($" 状态: ✓ 正确");
}
}
else
{
System.Diagnostics.Debug.WriteLine($"\ncgx 用户不存在");
needsReset = true;
}
if (needsReset)
{
System.Diagnostics.Debug.WriteLine("\n检测到密码数据异常自动重置默认用户...");
DatabaseInitializer.ForceResetDefaultUsers();
System.Diagnostics.Debug.WriteLine("密码数据已修复!");
System.Diagnostics.Debug.WriteLine(" admin 密码: admin123");
System.Diagnostics.Debug.WriteLine(" cgx 密码: 123");
}
else
{
System.Diagnostics.Debug.WriteLine("\n密码数据检查通过 ✓");
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"密码数据检查失败: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"详细信息: {ex}");
// 不影响程序启动,继续运行
}
}
}
}

View File

@@ -9,6 +9,9 @@
<package id="K4os.Hash.xxHash" version="1.0.8" targetFramework="net472" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="9.0.1" targetFramework="net472" />
<package id="MySql.Data" version="9.5.0" targetFramework="net472" />
<package id="NModbus4" version="2.1.0" targetFramework="net472" />
<package id="SunnyUI" version="3.9.1" targetFramework="net472" />
<package id="SunnyUI.Common" version="3.9.1" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Configuration.ConfigurationManager" version="8.0.0" targetFramework="net472" />
<package id="System.IO.Pipelines" version="5.0.2" targetFramework="net472" />