<think>设计抽检频次规则配置界面需要考虑以下几个方面:
1. 界面布局:直观易用,通常采用表格形式展示规则
2. 数据绑定:将规则数据与界面控件绑定
3. 操作功能:添加、删除、修改规则,保存配置
4. 数据验证:确保输入的有效性
以下是一个使用C# WinForms实现的抽检频次规则配置界面示例:
### 解决方案设计
1. **数据结构**:定义规则类(ProductInspectionRule)
2. **界面组件**:
- DataGridView:显示和编辑规则列表
- 按钮:添加、删除、保存
- 状态栏:显示操作状态
3. **数据持久化**:使用JSON文件保存规则
### 完整代码实现
```csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace InspectionRuleConfigurator
{
public partial class RuleConfigForm : Form
{
private BindingList<ProductInspectionRule> rules;
private string configFilePath = "InspectionRules.json";
public RuleConfigForm()
{
InitializeComponent();
InitializeDataGridView();
LoadRules();
}
private void InitializeDataGridView()
{
// 设置DataGridView属性
dataGridView.AutoGenerateColumns = false;
dataGridView.AllowUserToAddRows = false;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
// 添加列
dataGridView.Columns.Add(new DataGridViewTextBoxColumn()
{
DataPropertyName = "ProductType",
HeaderText = "产品类型",
Width = 150
});
dataGridView.Columns.Add(new DataGridViewTextBoxColumn()
{
DataPropertyName = "Description",
HeaderText = "描述",
Width = 200
});
dataGridView.Columns.Add(new DataGridViewTextBoxColumn()
{
DataPropertyName = "InspectionRate",
HeaderText = "抽检频次",
Width = 100
});
dataGridView.Columns.Add(new DataGridViewCheckBoxColumn()
{
DataPropertyName = "IsEnabled",
HeaderText = "启用",
Width = 60
});
}
private void LoadRules()
{
try
{
if (File.Exists(configFilePath))
{
var json = File.ReadAllText(configFilePath);
rules = JsonConvert.DeserializeObject<BindingList<ProductInspectionRule>>(json);
}
else
{
rules = new BindingList<ProductInspectionRule>();
}
dataGridView.DataSource = rules;
statusLabel.Text = $"已加载 {rules.Count} 条规则";
}
catch (Exception ex)
{
MessageBox.Show($"加载规则失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
rules = new BindingList<ProductInspectionRule>();
dataGridView.DataSource = rules;
}
}
private void btnAdd_Click(object sender, EventArgs e)
{
var newRule = new ProductInspectionRule
{
ProductType = "NEW_TYPE",
Description = "新规则",
InspectionRate = 10,
IsEnabled = true
};
rules.Add(newRule);
statusLabel.Text = "已添加新规则";
}
private void btnDelete_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count > 0)
{
var selectedRule = dataGridView.SelectedRows[0].DataBoundItem as ProductInspectionRule;
rules.Remove(selectedRule);
statusLabel.Text = "已删除选定规则";
}
else
{
MessageBox.Show("请先选择一条规则", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void btnSave_Click(object sender, EventArgs e)
{
try
{
// 验证数据
foreach (var rule in rules)
{
if (rule.InspectionRate <= 0)
throw new Exception($"产品类型 {rule.ProductType} 的抽检频次必须大于0");
}
var json = JsonConvert.SerializeObject(rules, Formatting.Indented);
File.WriteAllText(configFilePath, json);
statusLabel.Text = $"规则保存成功,共 {rules.Count} 条";
}
catch (Exception ex)
{
MessageBox.Show($"保存失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
// 抽检规则数据模型
public class ProductInspectionRule
{
public string ProductType { get; set; } // 产品类型代码
public string Description { get; set; } // 产品描述
public int InspectionRate { get; set; } // 抽检频次(每N个抽检1个)
public bool IsEnabled { get; set; } // 是否启用该规则
}
}
```
### 关键代码解释
1. **数据结构定义**:
```csharp
public class ProductInspectionRule
{
public string ProductType { get; set; }
public string Description { get; set; }
public int InspectionRate { get; set; }
public bool IsEnabled { get; set; }
}
```
- `ProductType`:唯一标识产品类型(如"A"、"B")
- `InspectionRate`:抽检频次(数值表示每多少个产品抽检一个)
2. **数据绑定**:
```csharp
dataGridView.DataSource = rules;
```
- 使用`BindingList<T>`作为数据源,支持自动更新
- 通过`DataPropertyName`将列绑定到对象属性
3. **持久化实现**:
```csharp
// 保存
var json = JsonConvert.SerializeObject(rules, Formatting.Indented);
File.WriteAllText(configFilePath, json);
// 加载
var json = File.ReadAllText(configFilePath);
rules = JsonConvert.DeserializeObject<BindingList<ProductInspectionRule>>(json);
```
- 使用Newtonsoft.Json库进行序列化
- 以JSON格式保存到本地文件
4. **数据验证**:
```csharp
foreach (var rule in rules)
{
if (rule.InspectionRate <= 0)
throw new Exception($"产品类型 {rule.ProductType} 的抽检频次必须大于0");
}
```
- 在保存前验证关键字段有效性
- 可扩展其他验证规则(如产品类型唯一性)
### 界面效果优化建议
1. **添加编辑验证**:
- 在DataGridView的`CellValidating`事件中添加验证
- 确保产品类型不为空且频次为大于0的整数
2. **搜索/过滤功能**:
- 添加文本框实时过滤规则列表
- 实现按产品类型或描述搜索
3. **导入导出**:
- 添加Excel导入导出功能
- 支持CSV格式批量操作
4. **规则优先级**:
- 添加优先级字段(当产品匹配多条规则时使用)
- 实现拖拽排序功能
### 扩展功能代码示例(数据验证)
```csharp
private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if (e.RowIndex < 0 || e.RowIndex >= rules.Count) return;
string headerText = dataGridView.Columns[e.ColumnIndex].HeaderText;
// 验证产品类型
if (headerText.Equals("产品类型"))
{
if (string.IsNullOrWhiteSpace(e.FormattedValue.ToString()))
{
MessageBox.Show("产品类型不能为空", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
e.Cancel = true;
}
}
// 验证抽检频次
else if (headerText.Equals("抽检频次"))
{
if (!int.TryParse(e.FormattedValue.ToString(), out int rate) || rate <= 0)
{
MessageBox.Show("抽检频次必须是大于0的整数", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
e.Cancel = true;
}
}
}
```
### 相关配置建议
1. 将配置文件路径改为可配置项(通过App.config)
2. 添加默认规则初始化功能
3. 实现规则复制功能(减少重复输入)
§§相关问题§§:
1. 如何实现规则的导入导出功能(Excel/CSV)?
2. 如何在WinForms中实现实时搜索过滤DataGridView数据?
3. 如何添加规则优先级和冲突解决机制?
4. 如何实现规则启用/停用的批量操作?</think># 抽检频次规则配置界面设计
我将设计一个直观、易用的抽检频次规则配置界面,使用C# WinForms实现,支持产品类型、抽检频次、生效时间等配置项的灵活设置。
## 解决方案设计
### 核心功能需求:
1. 支持按产品类型配置抽检频次
2. 支持时间段配置(如特定时间段应用不同规则)
3. 支持批量导入/导出规则
4. 规则优先级管理(当多个规则冲突时)
5. 历史规则版本管理
### 界面设计:
- 左侧:规则列表(树形结构)
- 右侧:规则详情编辑区域
- 底部:操作按钮(保存、删除、导入、导出等)
## 完整代码实现
```csharp
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace InspectionRuleConfigurator
{
public partial class RuleConfigForm : Form
{
private BindingList<InspectionRule> rules = new BindingList<InspectionRule>();
private string configFilePath = "InspectionRules.json";
public RuleConfigForm()
{
InitializeComponent();
InitializeUI();
LoadRules();
}
private void InitializeUI()
{
// 主布局
this.Text = "抽检频次规则配置";
this.Size = new Size(900, 600);
// 分割容器
SplitContainer splitContainer = new SplitContainer
{
Dock = DockStyle.Fill,
Orientation = Orientation.Horizontal,
SplitterDistance = 300
};
this.Controls.Add(splitContainer);
// 规则列表区域
Panel listPanel = new Panel { Dock = DockStyle.Fill };
splitContainer.Panel1.Controls.Add(listPanel);
// 规则列表
dataGridViewRules.DataSource = rules;
dataGridViewRules.Dock = DockStyle.Fill;
dataGridViewRules.AutoGenerateColumns = false;
dataGridViewRules.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
// 添加列
dataGridViewRules.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "ProductType",
HeaderText = "产品类型",
Width = 150
});
dataGridViewRules.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "InspectionRate",
HeaderText = "抽检频次",
Width = 100
});
dataGridViewRules.Columns.Add(new DataGridViewCheckBoxColumn
{
DataPropertyName = "IsEnabled",
HeaderText = "启用",
Width = 60
});
dataGridViewRules.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "EffectiveDateRange",
HeaderText = "生效时间",
Width = 200
});
dataGridViewRules.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = "Priority",
HeaderText = "优先级",
Width = 80
});
listPanel.Controls.Add(dataGridViewRules);
// 规则编辑区域
Panel editPanel = new Panel { Dock = DockStyle.Fill };
splitContainer.Panel2.Controls.Add(editPanel);
TableLayoutPanel editLayout = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 2,
RowCount = 6
};
editLayout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 30));
editLayout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 70));
editPanel.Controls.Add(editLayout);
// 添加编辑控件
int row = 0;
editLayout.Controls.Add(new Label { Text = "产品类型:", Anchor = AnchorStyles.Right }, 0, row);
editLayout.Controls.Add(txtProductType, 1, row++);
editLayout.Controls.Add(new Label { Text = "抽检频次:", Anchor = AnchorStyles.Right }, 0, row);
editLayout.Controls.Add(numInspectionRate, 1, row++);
editLayout.Controls.Add(new Label { Text = "生效时间:", Anchor = AnchorStyles.Right }, 0, row);
editLayout.Controls.Add(dateTimeEffectiveFrom, 1, row);
editLayout.Controls.Add(new Label { Text = "至", Anchor = AnchorStyles.Left }, 1, row);
editLayout.Controls.Add(dateTimeEffectiveTo, 1, row);
editLayout.SetColumnSpan(dateTimeEffectiveTo, 1);
row++;
editLayout.Controls.Add(new Label { Text = "优先级:", Anchor = AnchorStyles.Right }, 0, row);
editLayout.Controls.Add(numPriority, 1, row++);
editLayout.Controls.Add(new Label { Text = "启用规则:", Anchor = AnchorStyles.Right }, 0, row);
editLayout.Controls.Add(chkEnabled, 1, row++);
// 按钮区域
Panel buttonPanel = new Panel { Dock = DockStyle.Bottom, Height = 50 };
this.Controls.Add(buttonPanel);
Button btnSave = new Button { Text = "保存规则", Dock = DockStyle.Right, Width = 100 };
Button btnDelete = new Button { Text = "删除规则", Dock = DockStyle.Right, Width = 100 };
Button btnImport = new Button { Text = "导入规则", Dock = DockStyle.Right, Width = 100 };
Button btnExport = new Button { Text = "导出规则", Dock = DockStyle.Right, Width = 100 };
btnSave.Click += (s, e) => SaveRules();
btnDelete.Click += (s, e) => DeleteSelectedRule();
btnImport.Click += (s, e) => ImportRules();
btnExport.Click += (s, e) => ExportRules();
buttonPanel.Controls.Add(btnSave);
buttonPanel.Controls.Add(btnDelete);
buttonPanel.Controls.Add(btnImport);
buttonPanel.Controls.Add(btnExport);
// 数据绑定
dataGridViewRules.SelectionChanged += (s, e) =>
{
if (dataGridViewRules.CurrentRow != null && dataGridViewRules.CurrentRow.DataBoundItem is InspectionRule rule)
{
BindRuleToForm(rule);
}
};
}
private void LoadRules()
{
try
{
if (File.Exists(configFilePath))
{
string json = File.ReadAllText(configFilePath);
rules = new BindingList<InspectionRule>(
JsonConvert.DeserializeObject<List<InspectionRule>>(json));
}
else
{
// 添加示例规则
rules.Add(new InspectionRule
{
ProductType = "A",
InspectionRate = 10,
EffectiveFrom = DateTime.Today,
EffectiveTo = DateTime.Today.AddYears(1),
Priority = 1,
IsEnabled = true
});
}
dataGridViewRules.DataSource = rules;
}
catch (Exception ex)
{
MessageBox.Show($"加载规则失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void SaveRules()
{
try
{
string json = JsonConvert.SerializeObject(rules.ToList(), Formatting.Indented);
File.WriteAllText(configFilePath, json);
MessageBox.Show("规则保存成功!", "成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"保存规则失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DeleteSelectedRule()
{
if (dataGridViewRules.CurrentRow != null &&
dataGridViewRules.CurrentRow.DataBoundItem is InspectionRule rule)
{
if (MessageBox.Show($"确定要删除产品类型 '{rule.ProductType}' 的规则吗?",
"确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
rules.Remove(rule);
}
}
}
private void ImportRules()
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "JSON 文件 (*.json)|*.json|所有文件 (*.*)|*.*";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
string json = File.ReadAllText(openFileDialog.FileName);
var importedRules = JsonConvert.DeserializeObject<List<InspectionRule>>(json);
foreach (var rule in importedRules)
{
rules.Add(rule);
}
MessageBox.Show($"成功导入 {importedRules.Count} 条规则", "导入成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"导入失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
private void ExportRules()
{
using (SaveFileDialog saveFileDialog = new SaveFileDialog())
{
saveFileDialog.Filter = "JSON 文件 (*.json)|*.json";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
string json = JsonConvert.SerializeObject(rules.ToList(), Formatting.Indented);
File.WriteAllText(saveFileDialog.FileName, json);
MessageBox.Show("规则导出成功!", "成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"导出失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
private void BindRuleToForm(InspectionRule rule)
{
txtProductType.Text = rule.ProductType;
numInspectionRate.Value = rule.InspectionRate;
dateTimeEffectiveFrom.Value = rule.EffectiveFrom;
dateTimeEffectiveTo.Value = rule.EffectiveTo;
numPriority.Value = rule.Priority;
chkEnabled.Checked = rule.IsEnabled;
}
private void UpdateRuleFromForm(InspectionRule rule)
{
rule.ProductType = txtProductType.Text;
rule.InspectionRate = (int)numInspectionRate.Value;
rule.EffectiveFrom = dateTimeEffectiveFrom.Value;
rule.EffectiveTo = dateTimeEffectiveTo.Value;
rule.Priority = (int)numPriority.Value;
rule.IsEnabled = chkEnabled.Checked;
}
}
// 抽检规则类
public class InspectionRule
{
public string ProductType { get; set; } // 产品类型
public int InspectionRate { get; set; } // 抽检频次(每N个抽检1个)
public DateTime EffectiveFrom { get; set; } // 规则生效起始时间
public DateTime EffectiveTo { get; set; } // 规则生效结束时间
public int Priority { get; set; } // 规则优先级(数值越大优先级越高)
public bool IsEnabled { get; set; } // 是否启用
// 格式化显示生效时间范围
public string EffectiveDateRange =>
$"{EffectiveFrom:yyyy-MM-dd} 至 {EffectiveTo:yyyy-MM-dd}";
}
}
```
## 关键功能说明
### 1. 规则数据结构
```csharp
public class InspectionRule
{
public string ProductType { get; set; } // 产品类型
public int InspectionRate { get; set; } // 抽检频次(每N个抽检1个)
public DateTime EffectiveFrom { get; set; } // 规则生效起始时间
public DateTime EffectiveTo { get; set; } // 规则生效结束时间
public int Priority { get; set; } // 规则优先级(数值越大优先级越高)
public bool IsEnabled { get; set; } // 是否启用
}
```
- **ProductType**:唯一标识产品类型
- **InspectionRate**:抽检频次(如10表示每10个产品抽检1个)
- **EffectiveFrom/To**:规则生效时间范围
- **Priority**:解决规则冲突(当多个规则匹配时,使用优先级最高的)
- **IsEnabled**:快速启用/禁用规则
### 2. 数据绑定与展示
```csharp
dataGridViewRules.DataSource = rules;
dataGridViewRules.AutoGenerateColumns = false;
// 手动配置列与属性的映射关系
```
- 使用DataGridView展示规则列表
- 手动配置列映射确保显示格式符合要求
- 绑定生效时间范围显示为格式化字符串
### 3. 持久化存储
```csharp
// 保存规则
string json = JsonConvert.SerializeObject(rules.ToList(), Formatting.Indented);
File.WriteAllText(configFilePath, json);
// 加载规则
string json = File.ReadAllText(configFilePath);
rules = new BindingList<InspectionRule>(
JsonConvert.DeserializeObject<List<InspectionRule>>(json));
```
- 使用JSON格式存储规则
- Newtonsoft.Json库处理序列化/反序列化
- 支持导入/导出功能实现规则迁移
### 4. 规则编辑流程
```csharp
// 选择规则时绑定到表单
dataGridViewRules.SelectionChanged += (s, e) =>
{
if (dataGridViewRules.CurrentRow != null &&
dataGridViewRules.CurrentRow.DataBoundItem is InspectionRule rule)
{
BindRuleToForm(rule);
}
};
// 保存时更新规则
private void UpdateRuleFromForm(InspectionRule rule)
{
rule.ProductType = txtProductType.Text;
rule.InspectionRate = (int)numInspectionRate.Value;
// ...其他属性更新
}
```
- 选择规则时自动加载到编辑表单
- 修改后自动更新绑定对象
- 提供保存按钮持久化所有更改
## 界面优化建议
1. **添加验证逻辑**:
```csharp
private bool ValidateRule(InspectionRule rule)
{
if (string.IsNullOrWhiteSpace(rule.ProductType))
{
MessageBox.Show("产品类型不能为空");
return false;
}
if (rule.InspectionRate <= 0)
{
MessageBox.Show("抽检频次必须大于0");
return false;
}
if (rule.EffectiveFrom > rule.EffectiveTo)
{
MessageBox.Show("生效结束时间不能早于开始时间");
return false;
}
return true;
}
```
2. **添加规则冲突检测**:
```csharp
private bool CheckRuleConflict(InspectionRule newRule)
{
return rules.Any(r =>
r.ProductType == newRule.ProductType &&
r.IsEnabled &&
r.EffectiveFrom <= newRule.EffectiveTo &&
r.EffectiveTo >= newRule.EffectiveFrom);
}
```
3. **添加搜索/过滤功能**:
```csharp
private void FilterRules(string keyword)
{
var filtered = rules.Where(r =>
r.ProductType.Contains(keyword) ||
r.InspectionRate.ToString().Contains(keyword)).ToList();
dataGridViewRules.DataSource = new BindingList<InspectionRule>(filtered);
}
```
4. **添加规则复制功能**:
```csharp
private void DuplicateRule(InspectionRule source)
{
var newRule = new InspectionRule
{
ProductType = $"{source.ProductType}_复制",
InspectionRate = source.InspectionRate,
EffectiveFrom = source.EffectiveFrom,
EffectiveTo = source.EffectiveTo,
Priority = source.Priority - 1, // 降低优先级避免冲突
IsEnabled = false // 默认禁用复制的规则
};
rules.Add(newRule);
}
```
## 使用建议
1. **产品类型管理**:
- 建议与MES系统中的产品类型保持一致
- 可添加产品类型下拉选择框避免输入错误
2. **频次规则扩展**:
- 可添加最小/最大抽检量限制
- 支持按批次大小动态计算抽检量
3. **规则生效策略**:
- 添加基于班次、设备或产线的规则
- 支持节假日特殊抽检规则
4. **审计跟踪**:
- 记录规则修改历史
- 添加修改人、修改时间信息