2025/12/17 每日总结 核心业务模块(一):客户与员工全流程管理

核心业务模块(一):客户与员工全流程管理

承接上一篇的系统基础架构搭建,本篇聚焦MoonMIS系统的“人”管理核心——客户(老板池)与员工(打手)全流程管理。将详细拆解客户信息的增删改查、员工绩效统计、搜索筛选等核心功能,提供可直接复用的数据库交互代码和界面实现逻辑,帮大家搞定业务系统中“用户管理”的核心场景。

一、模块设计核心目标:为什么要做“人”的管理?

1. 模块定位

客户与员工是工作室业务的核心载体:老板池模块负责管理付费客户资源,记录客户偏好、消费记录等关键信息,支撑复购转化;员工管理模块负责维护服务提供方信息,跟踪工作状态与绩效,保障服务效率。两个模块共同构成“需求方-供给方”的连接桥梁,是订单流转的基础。

2. 核心功能清单

模块 核心功能 涉及控件/技术
老板池管理 客户信息增删改查、搜索筛选、标签分类、复购预警、黑名单管理 DataGridView、TextBox、Button、MySQL CRUD、SQL聚合查询
员工管理 员工信息维护、状态管理(在线/忙碌/休息)、绩效统计(订单数/成功率)、搜索查询 DataGridView、ComboBox、Label、SQL条件查询

3. 数据库表设计(核心表结构)

(1)客户表(Bosses)

CREATE TABLE Bosses (
 BossId VARCHAR(50) PRIMARY KEY, -- 客户唯一ID(如BOS000001)
 BossName VARCHAR(50) NOT NULL, -- 微信昵称/客户名称
 Source VARCHAR(30), -- 来源渠道(QQ/微信/网站/推荐)
 ContactInfo VARCHAR(100), -- 联系方式
 AvgOrderAmount DECIMAL(10,2), -- 平均订单金额
 Last30DaysSpend DECIMAL(10,2), -- 近30天消费
 Tags VARCHAR(100), -- 用户标签(如高消费、稳定客户)
 IsBlacklisted TINYINT(1) DEFAULT 0, -- 是否黑名单(0否1是)
 ComplaintCount INT DEFAULT 0, -- 投诉次数
 BanCount INT DEFAULT 0, -- 封禁次数
 LastOrderDate DATETIME, -- 最后订单日期
 CreatedAt DATETIME DEFAULT NOW() -- 创建时间
);

(2)员工表(Workers)

CREATE TABLE Workers (
 WorkerId VARCHAR(50) PRIMARY KEY, -- 员工唯一ID(如WRK000001)
 WorkerName VARCHAR(50) NOT NULL, -- 姓名
 Contact VARCHAR(20), -- 联系方式
 GameAccount VARCHAR(100), -- 游戏账号(业务相关账号)
 Status VARCHAR(20) DEFAULT '空闲', -- 状态(在线/忙碌/休息/离线)
 RegisterTime DATETIME DEFAULT NOW(), -- 注册时间
 TotalOrders INT DEFAULT 0, -- 总订单数
 CompletedOrders INT DEFAULT 0, -- 已完成订单数
 SuccessRate DECIMAL(5,2) DEFAULT 0 -- 成功率(CompletedOrders/TotalOrders)
);

二、老板池模块开发:客户全生命周期管理

1. 界面布局设计

老板池界面核心分为三部分:

  • 顶部统计区:展示总老板数、活跃老板、复购率、VIP老板等核心指标

  • 功能操作区:包含搜索框、刷新、自动标签、复购预警、黑名单检查等按钮

  • 数据展示区:用DataGridView展示客户列表,支持分页、选中编辑/删除

    2. 核心功能实现

    (1)客户列表加载:DataGridView绑定数据库数据

    DataGridView是展示列表数据的核心控件,通过MySQL查询结果动态填充,实现客户信息的可视化展示:

    // 加载客户列表(核心方法)
    private void LoadBossList()
    {
    // 清空现有数据
    bossDataGridView.Rows.Clear();
    // 数据库连接(使用上一篇封装的DatabaseHelper)
    using (var conn = DatabaseHelper.GetConnection())
    {
    conn.Open();
    // 查询客户列表(按创建时间倒序)
    string query = "SELECT BossId, BossName, Source, AvgOrderAmount, Last30DaysSpend, " +
    "Tags, IsBlacklisted, ComplaintCount, BanCount, LastOrderDate " +
    "FROM Bosses ORDER BY CreatedAt DESC";
    

using (var cmd = new MySqlCommand(query, conn))
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// 逐行添加数据到DataGridView
bossDataGridView.Rows.Add(
reader["BossId"],
reader["BossName"],
reader["Source"],
Convert.ToDecimal(reader["AvgOrderAmount"]).ToString("C2"), // 金额格式化
Convert.ToDecimal(reader["Last30DaysSpend"]).ToString("C2"),
reader["Tags"],
reader["IsBlacklisted"].ToString() == "1" ? "是" : "否", // 布尔值转文字
reader["ComplaintCount"],
reader["BanCount"],
Convert.ToDateTime(reader["LastOrderDate"]).ToString("yyyy/MM/dd HH:mm") // 日期格式化
);
}
}
}
}

#### (2)客户添加:表单录入+数据验证
通过弹出表单窗口收集客户信息,验证数据合法性后插入数据库:
```csharp
// 添加客户按钮点击事件
private void btnAddBoss_Click(object sender, EventArgs e)
{
 // 弹出添加客户表单(自定义窗口AddBossForm)
 AddBossForm addForm = new AddBossForm();
 if (addForm.ShowDialog() == DialogResult.OK)
 {
 // 获取表单输入数据
 string bossId = GenerateBossId(); // 生成唯一ID(如BOS000011)
 string bossName = addForm.txtBossName.Text;
 string source = addForm.cmbSource.SelectedItem.ToString();
 string tags = addForm.txtTags.Text;
 // ... 其他字段获取

// 插入数据库
 using (var conn = DatabaseHelper.GetConnection())
 {
 conn.Open();
 string insertQuery = "INSERT INTO Bosses (BossId, BossName, Source, Tags, Last30DaysSpend, AvgOrderAmount) " +
 "VALUES (@BossId, @BossName, @Source, @Tags, 0, 0)";

using (var cmd = new MySqlCommand(insertQuery, conn))
 {
 // 参数化查询(避免SQL注入)
 cmd.Parameters.AddWithValue("@BossId", bossId);
 cmd.Parameters.AddWithValue("@BossName", bossName);
 cmd.Parameters.AddWithValue("@Source", source);
 cmd.Parameters.AddWithValue("@Tags", tags);
 cmd.ExecuteNonQuery();
 }
 }
 // 重新加载列表
 LoadBossList();
 MessageBox.Show("客户添加成功!");
 }
}
// 生成唯一客户ID(BOS+6位数字)
private string GenerateBossId()
{
 using (var conn = DatabaseHelper.GetConnection())
 {
 conn.Open();
 string query = "SELECT MAX(BossId) FROM Bosses";
 object maxId = new MySqlCommand(query, conn).ExecuteScalar();
 if (maxId == DBNull.Value)
 return "BOS000001";
 // 截取数字部分自增
 int idNum = int.Parse(maxId.ToString().Substring(3)) + 1;
 return $"BOS{idNum:D6}"; // 格式化为6位数字
 }
}

(3)客户搜索筛选:文本输入+条件查询

支持按客户ID、微信昵称模糊搜索,核心是动态拼接SQL查询条件:

private void btnSearchBoss_Click(object sender, EventArgs e)
{
 string keyWord = txtSearchBoss.Text.Trim();
 bossDataGridView.Rows.Clear();

using (var conn = DatabaseHelper.GetConnection())
 {
 conn.Open();
 // 动态拼接查询条件(模糊匹配BossId或BossName)
 string query = "SELECT BossId, BossName, Source, AvgOrderAmount, Last30DaysSpend, " +
 "Tags, IsBlacklisted, ComplaintCount, BanCount, LastOrderDate " +
 "FROM Bosses WHERE BossId LIKE @KeyWord OR BossName LIKE @KeyWord " +
 "ORDER BY CreatedAt DESC";

using (var cmd = new MySqlCommand(query, conn))
 {
 // 模糊查询参数(%表示任意字符)
 cmd.Parameters.AddWithValue("@KeyWord", $"%{keyWord}%");
 using (var reader = cmd.ExecuteReader())
 {
 // 同LoadBossList逻辑,填充DataGridView
 while (reader.Read())
 {
 // 数据添加逻辑...(与LoadBossList一致)
 }
 }
 }
 }
}

(4)复购预警功能:SQL聚合查询筛选

筛选近30天无消费但历史有订单的客户,实现复购提醒:

private void btnRepurchaseAlert_Click(object sender, EventArgs e)
{
 List<string> alertBosses = new List<string>();
 using (var conn = DatabaseHelper.GetConnection())
 {
 conn.Open();
 // 查询条件:近30天消费为0 + 总订单数≥1
 string query = "SELECT BossName, LastOrderDate FROM Bosses " +
 "WHERE Last30DaysSpend = 0 AND " +
 "EXISTS (SELECT 1 FROM Orders WHERE Orders.BossId = Bosses.BossId)";

using (var cmd = new MySqlCommand(query, conn))
 using (var reader = cmd.ExecuteReader())
 {
 while (reader.Read())
 {
 string bossName = reader["BossName"].ToString();
 string lastOrderDate = Convert.ToDateTime(reader["LastOrderDate"]).ToString("yyyy/MM/dd");
 alertBosses.Add($"{bossName}(最后消费:{lastOrderDate})");
 }
 }
 }

// 显示预警信息
 if (alertBosses.Count > 0)
 MessageBox.Show("复购预警客户:\n" + string.Join("\n", alertBosses), "复购提醒");
 else
 MessageBox.Show("暂无需要复购预警的客户");
}

3. 界面样式优化

  • DataGridView设置:启用行选中、禁止编辑(通过代码控制修改)、列宽自适应

  • 标签展示:用不同颜色标注客户标签(如“高消费”标红色、“稳定客户”标绿色)

  • 操作按钮:添加/编辑/删除按钮按功能分组,hover时变色,提升交互体验

    三、员工管理模块开发:从信息维护到绩效统计

    1. 界面布局设计

    与老板池模块布局逻辑一致,保持系统界面统一性:

  • 顶部统计区:展示总打手数、活跃打手、暂停打手、平均成功率

  • 功能操作区:搜索框、添加/编辑/删除按钮

  • 数据展示区:DataGridView展示员工列表,包含基本信息、状态、绩效数据

    2. 核心功能实现

    (1)员工状态管理:ComboBox下拉选择

    员工状态(在线/忙碌/休息/离线)直接影响订单分配,通过ComboBox实现状态快速切换:

    // 初始化员工状态下拉框(在DataGridView编辑模式中)
    private void bossDataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
    {
    // 假设第5列是状态列
    if (e.ColumnIndex == 5)
    {
    DataGridViewComboBoxCell comboCell = new DataGridViewComboBoxCell();
    comboCell.Items.AddRange("在线", "忙碌", "休息", "离线");
    bossDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex] = comboCell;
    // 选中当前状态
    comboCell.Value = bossDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
    }
    }
    // 状态修改后同步到数据库
    private void bossDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
    if (e.ColumnIndex == 5)
    {
    string workerId = bossDataGridView.Rows[e.RowIndex].Cells[0].Value.ToString();
    string newStatus = bossDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
    

using (var conn = DatabaseHelper.GetConnection())
{
conn.Open();
string updateQuery = "UPDATE Workers SET Status = @Status WHERE WorkerId = @WorkerId";
using (var cmd = new MySqlCommand(updateQuery, conn))
{
cmd.Parameters.AddWithValue("@Status", newStatus);
cmd.Parameters.AddWithValue("@WorkerId", workerId);
cmd.ExecuteNonQuery();
}
}
}
}

#### (2)员工绩效统计:SQL聚合查询
自动计算员工总订单数、已完成订单数、成功率,核心是通过SQL聚合函数统计数据:
```csharp
// 更新员工绩效统计(传入员工ID)
private void UpdateWorkerStats(string workerId)
{
 using (var conn = DatabaseHelper.GetConnection())
 {
 conn.Open();
 // 统计该员工的订单数据
 string statsQuery = "SELECT " +
 "COUNT(*) as TotalOrders, " +
 "SUM(CASE WHEN Status = '已完成' THEN 1 ELSE 0 END) as CompletedOrders, " +
 "IF(COUNT(*) = 0, 0, SUM(CASE WHEN Status = '已完成' THEN 1 ELSE 0 END) / COUNT(*) * 100) as SuccessRate " +
 "FROM Orders WHERE WorkerId = @WorkerId";

using (var cmd = new MySqlCommand(statsQuery, conn))
 {
 cmd.Parameters.AddWithValue("@WorkerId", workerId);
 using (var reader = cmd.ExecuteReader())
 {
 if (reader.Read())
 {
 int totalOrders = Convert.ToInt32(reader["TotalOrders"]);
 int completedOrders = Convert.ToInt32(reader["CompletedOrders"]);
 decimal successRate = Convert.ToDecimal(reader["SuccessRate"]);

// 更新员工表中的绩效数据
 UpdateWorkerStatsToDB(workerId, totalOrders, completedOrders, successRate);
 // 更新界面显示
 UpdateWorkerStatsUI(workerId, totalOrders, completedOrders, successRate.ToString("F2") + "%");
 }
 }
 }
 }
}
// 将绩效数据写入员工表
private void UpdateWorkerStatsToDB(string workerId, int totalOrders, int completedOrders, decimal successRate)
{
 using (var conn = DatabaseHelper.GetConnection())
 {
 conn.Open();
 string updateQuery = "UPDATE Workers SET TotalOrders = @TotalOrders, " +
 "CompletedOrders = @CompletedOrders, SuccessRate = @SuccessRate " +
 "WHERE WorkerId = @WorkerId";

using (var cmd = new MySqlCommand(updateQuery, conn))
 {
 cmd.Parameters.AddWithValue("@TotalOrders", totalOrders);
 cmd.Parameters.AddWithValue("@CompletedOrders", completedOrders);
 cmd.Parameters.AddWithValue("@SuccessRate", successRate);
 cmd.Parameters.AddWithValue("@WorkerId", workerId);
 cmd.ExecuteNonQuery();
 }
 }
}

(3)员工搜索:多条件模糊匹配

支持按员工ID、姓名、联系方式搜索,逻辑与客户搜索一致,动态拼接查询条件:

private void btnSearchWorker_Click(object sender, EventArgs e)
{
 string keyWord = txtSearchWorker.Text.Trim();
 workerDataGridView.Rows.Clear();

using (var conn = DatabaseHelper.GetConnection())
 {
 conn.Open();
 string query = "SELECT WorkerId, WorkerName, Contact, GameAccount, Status, TotalOrders, SuccessRate, RegisterTime " +
 "FROM Workers WHERE WorkerId LIKE @KeyWord OR WorkerName LIKE @KeyWord OR Contact LIKE @KeyWord " +
 "ORDER BY RegisterTime DESC";

using (var cmd = new MySqlCommand(query, conn))
 {
 cmd.Parameters.AddWithValue("@KeyWord", $"%{keyWord}%");
 using (var reader = cmd.ExecuteReader())
 {
 while (reader.Read())
 {
 // 填充DataGridView逻辑...
 }
 }
 }
 }
}

3. 批量操作与数据导出

支持员工信息批量导出为CSV文件,方便离线统计:

private void btnExportWorkers_Click(object sender, EventArgs e)
{
 SaveFileDialog saveDialog = new SaveFileDialog();
 saveDialog.Filter = "CSV文件|*.csv";
 saveDialog.Title = "导出员工数据";
 if (saveDialog.ShowDialog() == DialogResult.OK)
 {
 // 写入CSV文件
 using (StreamWriter sw = new StreamWriter(saveDialog.FileName, false, Encoding.UTF8))
 {
 // 写入表头
 sw.WriteLine("员工ID,姓名,联系方式,游戏账号,状态,总订单数,成功率,注册时间");

// 写入数据行
 foreach (DataGridViewRow row in workerDataGridView.Rows)
 {
 if (!row.IsNewRow)
 {
 string line = string.Join(",",
 row.Cells["WorkerId"].Value.ToString(),
 row.Cells["WorkerName"].Value.ToString(),
 row.Cells["Contact"].Value.ToString(),
 row.Cells["GameAccount"].Value.ToString(),
 row.Cells["Status"].Value.ToString(),
 row.Cells["TotalOrders"].Value.ToString(),
 row.Cells["SuccessRate"].Value.ToString(),
 row.Cells["RegisterTime"].Value.ToString()
 );
 sw.WriteLine(line);
 }
 }
 }
 MessageBox.Show("导出成功!");
 }
}

四、开发避坑指南:这些问题一定要注意

  1. 数据重复加载:每次查询前清空DataGridView的Rows,避免重复添加;使用using语句自动释放数据库连接,防止连接泄露。
  2. SQL注入风险:所有用户输入(如搜索关键词、表单数据)必须使用参数化查询(cmd.Parameters.AddWithValue),禁止直接拼接SQL字符串。
  3. 金额/日期格式化:从数据库读取的金额、日期需统一格式化(如金额转货币格式、日期转“yyyy/MM/dd”),保证界面显示一致性。
  4. 空值处理:数据库查询结果可能为DBNull,需先判断(reader.IsDBNull(index)),再转换类型,避免空引用异常。
  5. 界面卡顿:数据量较大时(如百级以上客户/员工),可添加分页功能(SQL LIMIT),或在后台线程加载数据,避免界面卡死。
posted @ 2026-01-06 05:31  Moonbeamsc  阅读(5)  评论(0)    收藏  举报
返回顶端