LanBMes MES Client 是基于 .NET Framework 4.8 和 DevExpress WinForms 构建的企业级制造执行系统(MES)桌面应用程序,为制造车间提供全面的生产执行、仓储管理、质量控制和报表分析能力。
| 项目 | 说明 |
|---|---|
| 解决方案名称 | GsDevSolution.sln |
| 产品名称 | G-MES V2.0 |
| 主要用途 | 面向制造现场的 MES Windows 客户端 |
| 核心应用 | Gs.DevApp (主客户端) |
| 辅助应用 | Gs.WeightIqc (IQC称重), Gs.WeightLine (产线称重) |
| 开发环境 | Visual Studio 2022+ |
| 目标框架 | .NET Framework 4.8 |
| 构建平台 | Any CPU |
基础数据管理 → 生产计划 → 工单管理 → 生产执行 → 质量检验 → 仓储物流 → 报表分析
↓ ↓ ↓ ↓ ↓ ↓ ↓
客户/供应商 排产调整 任务下达 工序开工 多级质检 出入库管理 FastReport
物料主数据 产线分配 流程卡 数据采集 缺陷追踪 库存调拨 统计分析
工装设备 资源协调 进度追踪 返工维修 AQL抽样 条码管理 自定义报表
GsDevSolution/
├── Gs.DevApp/ 【主客户端项目】
│ ├── DevFrm/ - 18个业务领域模块 (150+ 窗体)
│ │ ├── BasicData/ - 基础数据 (客户/供应商/物料/产线)
│ │ ├── Work/ - 生产执行 (开工/数据采集/返工)
│ │ ├── WOM/ - 工单管理 (任务下达/排产)
│ │ ├── QC/ - 质量管理通用模块
│ │ ├── IPQC/ - 制程检验 (首件/巡检)
│ │ ├── FQC/ - 成品终检
│ │ ├── RkQC/ - 来料质检
│ │ ├── Ck/ - 出库管理 (领料/补料/退货)
│ │ ├── Rk/ - 入库管理 (来料/退库/其他)
│ │ ├── Warehouse/ - 仓库操作 (调拨/盘点/条码)
│ │ ├── Sales/ - 销售订单与发货
│ │ ├── WW/ - 委外管理
│ │ ├── Rpt/ - 报表设计与执行
│ │ ├── Sys/ - 系统设置 (菜单/组织/单号规则)
│ │ ├── User/ - 用户与权限管理
│ │ ├── JJGZ/ - 夹具工装与设备台账
│ │ ├── BarCode/ - 条码生成与打印
│ │ └── PDA/ - 手持终端界面
│ ├── Entity/ - 数据传输对象 (DTO)
│ ├── ToolBox/ - 公共工具类
│ ├── UserControl/ - 可复用控件库 (150+)
│ ├── Resources/ - 资源文件 (图标/图片)
│ ├── App.config - 应用配置文件
│ └── Program.cs - 应用程序入口
├── Gs.WeightIqc/ 【IQC 称重客户端】
├── Gs.WeightLine/ 【产线称重客户端】
├── Gs.Setup/ 【安装程序项目】(.vdproj)
└── packages/ 【NuGet 包目录】
所有业务窗体按领域划分,每个子目录包含该领域的所有表单和对话框。
命名规范: Frm_{业务名称}.cs 或 Frm_{业务名称}_{子类型}.cs
| 文件 | 说明 |
|---|---|
LoginInfoModel.cs |
登录用户信息模型 |
PageQueryModel.cs |
分页查询通用模型 |
ReturnModel.cs |
API 返回结果封装 |
| 文件 | 说明 |
|---|---|
UtilityHelper.cs |
核心工具类: HTTP请求、JSON解析、Grid初始化等 |
LogHelper.cs |
日志记录工具 (写入 logs/{yyyy-MM-dd}.log) |
MsgHelper.cs |
统一消息提示封装 (基于 DevExpress) |
UpdateParentEventArgs.cs |
窗体间事件通信机制 |
ModbusHelper.cs |
Modbus 设备通信封装 |
| 控件类型 | 示例 | 说明 |
|---|---|---|
| 工具栏 | UcToolBarMenu.cs |
标准CRUD操作栏 |
| 分页 | UcPageBar.cs |
分页控件 |
| 选择器 | UcDictionarySelect.cs |
数据字典下拉框 |
| 查找控件 | UcLookCustomer.csUcLookItems.csUcLookWarehouse.cs |
60+ 数据查找对话框 (客户/物料/仓库等) |
| 通知 | Toast.cs |
轻量级提示框 |
| 技术/库 | 版本 | 用途 |
|---|---|---|
| .NET Framework | 4.8 | 应用基础框架 |
| DevExpress | v22.2.3 | UI 组件库 (FluentDesign, XtraGrid, XtraTab, XtraBars) |
| CefSharp | 109.1.110 | 嵌入式 Chromium 浏览器 |
| AutoUpdater.NET | 1.9.2 | 自动软件更新 |
| NModbus | 3.0.81 | 工业设备通信 (Modbus TCP/RTU) |
| Newtonsoft.Json | 13.0.3 | JSON 序列化 |
| System.Text.Json | 8.0.4 | 现代 JSON 支持 |
| Oracle.ManagedDataAccess | 最新 | Oracle 数据库访问 |
| System.Data.SqlClient | 最新 | SQL Server 数据库访问 |
// FluentDesign 主界面
DevExpress.XtraBars.FluentDesignSystem.FluentDesignForm
// 数据表格
DevExpress.XtraGrid.GridControl
DevExpress.XtraGrid.Views.Grid.GridView
// 标签页
DevExpress.XtraTab.XtraTabControl
// 导航菜单
DevExpress.XtraNavBar.NavBarControl
// 等待对话框
DevExpress.XtraWaitForm.WaitDialogForm
# 克隆代码库
cd E:\LanBMes
git clone <repository_url> LB_MesClient
# 进入解决方案目录
cd LB_MesClient\DevApp
# 还原 NuGet 包
nuget restore GsDevSolution.sln
# 或在 Visual Studio 中:
# 右键解决方案 → 还原 NuGet 程序包
确保已安装 DevExpress v22.2 并配置 NuGet 源:
工具 → NuGet 包管理器 → 程序包管理器设置 → 程序包源
添加源: https://nuget.devexpress.com/<your_feed_key>/api
编辑 Gs.DevApp\App.config:
<add key="WebApiUrl" value="http://192.168.0.51:8081/" />
修改为实际的后端 API 地址。
# Debug 构建 (推荐开发使用)
cd E:\LanBMes\LB_MesClient\DevApp
msbuild GsDevSolution.sln /p:Configuration=Debug /p:Platform="Any CPU"
# Release 构建 (用于发布)
msbuild GsDevSolution.sln /p:Configuration=Release /p:Platform="Any CPU"
# 仅构建主项目
msbuild Gs.DevApp\Gs.DevApp.csproj /t:Rebuild /p:Configuration=Debug
GsDevSolution.slnGs.DevApp → 设为启动项目F5 或点击 "开始调试"# Debug 版本
Gs.DevApp\bin\Debug\Gs.DevApp.exe
# Release 版本
Gs.DevApp\bin\Release\Gs.DevApp.exe
禁用单实例限制 (允许同时运行多个实例用于测试):
在 Program.cs 中注释以下代码:
// Process[] MyProcesses = Process.GetProcessesByName("Gs.DevApp");
// if (MyProcesses.Length > 1)
// {
// MyProcesses[0].Kill();
// }
[STAThread]
static void Main()
{
// 1. 单实例检查 (防止重复运行)
Process[] MyProcesses = Process.GetProcessesByName("Gs.DevApp");
if (MyProcesses.Length > 1) {
MyProcesses[0].Kill();
}
// 2. 启用视觉样式
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// 3. 启动登录流程
_startLogin();
}
核心功能:
- 自动更新检查 (AutoUpdater.NET)
- 用户身份验证 (调用 User/UserLogin API)
- 记住用户名/密码
- 字体设置持久化 (注册表)
关键代码:
// 登录验证
string result = UtilityHelper.HttpPost("User/UserLogin", "UserLogin", jsonParam);
dynamic dy = UtilityHelper.ReturnToDynamic(result);
if (dy.code == 200) {
LoginInfoModel.CurrentUser = JsonConvert.DeserializeObject<LoginInfoModel>(dy.data.ToString());
this.DialogResult = DialogResult.OK;
}
核心职责:
1. 加载用户菜单结构 (User/GetUserLoginInfo)
2. 构建 AccordionControl 导航菜单
3. 动态加载窗体 (通过反射)
4. 管理 TabPage 生命周期
5. 组织切换
6. 全局事件处理
动态窗体加载:
// 通过命名空间动态创建窗体实例
Form newForm = (Form)Assembly.GetExecutingAssembly()
.CreateInstance("Gs.DevApp.DevFrm.BasicData.Frm_Customer");
// 嵌入到 TabPage
newForm.FormBorderStyle = FormBorderStyle.None;
newForm.TopLevel = false;
newForm.Dock = DockStyle.Fill;
xtraTabPage.Controls.Add(newForm);
newForm.Show();
TabPage 缓存 (防止重复打开):
if (tabPageDict.ContainsKey(formName)) {
xtraTabControl.SelectedTabPage = tabPageDict[formName];
return;
}
UcToolBarMenu 实现增删改查UcPageBar 实现分页Frm_Supplier.cs - 供应商基础信息Frm_SupplierSrm.cs - SRM 供应商关系管理Frm_MesItems.cs - 物料主数据维护Frm_MesItemsShow.cs - 物料信息展示Frm_Staff.cs - 员工信息Frm_Department.cs - 部门组织| 窗体 | 功能 |
|---|---|
Frm_MesInvItemOut_SCLL.cs |
生产领料出库 |
Frm_MesItemBl.cs |
补料出库 |
Frm_MesCgthSq.cs |
采购退货申请 |
Frm_MesItemQtck.cs |
其他出库 |
| 窗体 | 功能 |
|---|---|
Frm_MesInvItemArn.cs |
到货入库 |
Frm_MesItemTbl.cs |
材料入库台账 |
Frm_MesItemQtrk.cs |
其他入库 |
| 窗体 | 功能 |
|---|---|
Frm_MesDbck.cs |
调拨出库 |
Frm_MesRohIn.cs |
原材入库 |
Frm_ArrivalBarcode.cs |
到货条码生成 |
Frm_InitialBarcode.cs |
初始条码维护 |
提供简化的扫码作业界面,用于:
- 快速理货
- 库存盘点
- 条码扫描
- 移动作业
DefectCode*.cs)Frm_MesQaItemsDetect01.cs)Frm_MesQmAql1.cs)| 窗体 | 功能 |
|---|---|
Frm_ShouJian.cs |
首件检验 |
Frm_XunJian.cs |
巡检作业 |
| H5 检验界面 | 移动端检验 |
| 窗体 | 功能 |
|---|---|
Frm_Fqc.cs |
成品检验主界面 |
Frm_FqcDetect01.cs |
检验数据录入 |
MesFqcExceptional.cs |
异常处理 |
| 窗体 | 功能 |
|---|---|
Frm_Cqfa.cs |
抽检方案 |
Frm_CqfaItems.cs |
检验项配置 |
Frm_QtrkDetect01.cs |
来料检验 |
Frm_WwrkDetect01.cs |
委外来料检验 |
| 窗体 | 功能 |
|---|---|
Frm_WorkStart.cs |
工序开工 |
Frm_WorkProcesses.cs |
流程卡管理 |
Frm_Work01.cs ~ Frm_Work09.cs |
各工站数据采集 |
Frm_Repair.cs |
返工维修 |
| 窗体 | 功能 |
|---|---|
EasyRptDesign.cs |
报表设计器 |
EasyRptEdt.cs |
报表编辑 |
SysHelp.cs |
报表帮助 |
支持技术:
- FastReport
- DevExpress Reports
- 自定义报表引擎
| 窗体 | 功能 |
|---|---|
SysMenu.cs |
菜单结构维护 |
Organization.cs |
组织架构管理 |
DocNoRule.cs |
单号规则配置 |
SysLog.cs |
系统日志查询 |
Frm_Config.cs |
系统配置 |
| 窗体 | 功能 |
|---|---|
User.cs |
用户管理 |
Role.cs |
角色管理 |
RoleSelectAction.cs |
角色授权 |
UserSetPwd.cs |
密码变更 |
权限模型: 用户 → 角色 → 菜单权限 + 操作权限
| 窗体 | 功能 |
|---|---|
Frm_BarcodePrint.cs |
条码批量打印 |
Frm_BarcodeTemplate.cs |
打印模板设置 |
┌─────────────────────────────────────────┐
│ UI Layer (WinForms) │
│ DevExpress FluentDesign + 150+ 控件 │
└─────────────────┬───────────────────────┘
│ HTTP/JSON REST API
┌─────────────────▼───────────────────────┐
│ Business Logic Layer (Client) │
│ 窗体逻辑 + ToolBox 工具类 + 动态加载 │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ Backend REST API (别处项目) │
│ 身份验证 + 菜单 + 业务逻辑 + 数据访问 │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ Data Layer │
│ Oracle / SQL Server │
└─────────────────────────────────────────┘
所有 API 调用统一使用 UtilityHelper.HttpPost():
public static string HttpPost(string url, string method, string param, bool isLoading = true)
{
// 1. 拼接完整 URL (WebApiUrl + url)
// 2. 添加 Bearer Token 认证头
// 3. 显示 Loading 对话框 (可选)
// 4. 发送 POST 请求
// 5. 返回 JSON 字符串
// 6. 超时时间: 150 秒
}
使用示例:
string jsonParam = JsonConvert.SerializeObject(new {
pageIndex = 1,
pageSize = 50
});
string result = UtilityHelper.HttpPost(
"BasicData/Customer/GetListPage", // 相对路径
"GetListPage", // 方法名
jsonParam, // JSON 参数
true // 显示加载框
);
dynamic dy = UtilityHelper.ReturnToDynamic(result);
if (dy.code == 200) {
// 处理数据
}
// 在 FrmMain.cs 中
private void LoadForm(string namespacePath)
{
// 通过命名空间路径创建窗体实例
string fullName = $"Gs.DevApp.DevFrm.{namespacePath}";
Form form = (Form)Assembly.GetExecutingAssembly().CreateInstance(fullName);
if (form != null)
{
// 配置为子窗体
form.FormBorderStyle = FormBorderStyle.None;
form.TopLevel = false;
form.Dock = DockStyle.Fill;
// 添加到 TabPage
XtraTabPage tabPage = new XtraTabPage();
tabPage.Text = form.Text;
tabPage.Controls.Add(form);
xtraTabControl.TabPages.Add(tabPage);
xtraTabControl.SelectedTabPage = tabPage;
form.Show();
}
}
好处:
- 菜单结构完全由后端控制
- 无需修改代码即可调整菜单
- 支持动态权限控制
// 防止重复打开同一窗体
private Dictionary<string, XtraTabPage> tabPageDict = new Dictionary<string, XtraTabPage>();
private void OpenForm(string formName)
{
if (tabPageDict.ContainsKey(formName))
{
// 已存在,激活现有 Tab
xtraTabControl.SelectedTabPage = tabPageDict[formName];
}
else
{
// 新建 Tab
XtraTabPage newPage = CreateNewTabPage(formName);
tabPageDict[formName] = newPage;
}
}
子窗体触发父窗体刷新:
// 在子窗体中
UpdateParentEventArgs args = new UpdateParentEventArgs(this, "Refresh");
// 触发事件,通知父窗体
// 在父窗体中
private void ChildForm_UpdateParent(object sender, UpdateParentEventArgs e)
{
if (e.Action == "Refresh")
{
LoadData(); // 刷新数据
}
}
典型窗体结构:
public partial class Frm_Customer : DevExpress.XtraEditors.XtraForm
{
private UcToolBarMenu ucToolBar; // 工具栏 (增删改查)
private UcPageBar ucPageBar; // 分页控件
private GridControl gridControl; // 数据表格
private void InitializeForm()
{
// 1. 初始化工具栏
ucToolBar.AddClick += BtnAdd_Click;
ucToolBar.EditClick += BtnEdit_Click;
ucToolBar.DeleteClick += BtnDelete_Click;
ucToolBar.RefreshClick += BtnRefresh_Click;
// 2. 初始化分页
ucPageBar.PageChanged += LoadData;
// 3. 加载数据
LoadData();
}
private void LoadData()
{
string jsonParam = JsonConvert.SerializeObject(new {
pageIndex = ucPageBar.CurrentPage,
pageSize = ucPageBar.PageSize
});
string result = UtilityHelper.HttpPost(
"BasicData/Customer/GetListPage",
"GetListPage",
jsonParam
);
dynamic dy = UtilityHelper.ReturnToDynamic(result);
if (dy.code == 200)
{
gridControl.DataSource = dy.data;
ucPageBar.TotalRecords = dy.totalCount;
}
}
}
// 标准 POST 请求
string result = UtilityHelper.HttpPost(
"User/UserLogin", // 相对路径
"UserLogin", // 方法名
jsonParam, // JSON 参数
true // 显示加载框
);
// 解析为 dynamic 对象
dynamic dy = UtilityHelper.ReturnToDynamic(result);
// 解析为分页数据表
DataTable dt = UtilityHelper.ReturnToTablePage(result);
// 初始化表格控件
UtilityHelper.InitGridControl(
gridControl,
gridView,
columns, // 列定义
dataSource, // 数据源
allowEdit: false,
allowDelete: false
);
// 记录信息日志
LogHelper.WriteLog("用户登录成功", LogHelper.LogType.Info);
// 记录错误日志
LogHelper.WriteLog($"API 调用失败: {ex.Message}", LogHelper.LogType.Error);
// 记录警告
LogHelper.WriteLog("数据异常,使用默认值", LogHelper.LogType.Warning);
日志文件位置: logs/{yyyy-MM-dd}.log
// 成功提示
MsgHelper.ShowSuccess("操作成功!");
// 错误提示
MsgHelper.ShowError("操作失败,请重试!");
// 警告提示
MsgHelper.ShowWarning("数据不完整!");
// 确认对话框
if (MsgHelper.ShowConfirm("确定要删除吗?") == DialogResult.Yes)
{
// 执行删除
}
// 显示 3 秒提示
Toast.Show("保存成功", 3);
// 显示自定义时长
Toast.Show("数据已更新", 5); // 5 秒
UcToolBarMenu toolBar = new UcToolBarMenu();
toolBar.AddClick += (s, e) => { /* 新增 */ };
toolBar.EditClick += (s, e) => { /* 编辑 */ };
toolBar.DeleteClick += (s, e) => { /* 删除 */ };
toolBar.RefreshClick += (s, e) => { /* 刷新 */ };
toolBar.ExportClick += (s, e) => { /* 导出 */ };
UcPageBar pageBar = new UcPageBar();
pageBar.PageSize = 50;
pageBar.TotalRecords = 1000;
pageBar.PageChanged += (s, e) => {
LoadData(pageBar.CurrentPage, pageBar.PageSize);
};
UcDictionarySelect cmbStatus = new UcDictionarySelect();
cmbStatus.DictionaryType = "OrderStatus"; // 字典类型
cmbStatus.LoadData();
60+ 查找控件,覆盖所有主数据:
// 客户查找
UcLookCustomer lookCustomer = new UcLookCustomer();
lookCustomer.ShowDialog();
string customerId = lookCustomer.SelectedId;
string customerName = lookCustomer.SelectedName;
// 物料查找
UcLookItems lookItems = new UcLookItems();
lookItems.ShowDialog();
string itemId = lookItems.SelectedId;
// 仓库查找
UcLookWarehouse lookWarehouse = new UcLookWarehouse();
lookWarehouse.ShowDialog();
位置: Gs.DevApp\App.config (运行时为 Gs.DevApp.exe.config)
<appSettings>
<!-- 后端 API 地址 (必须配置) -->
<add key="WebApiUrl" value="http://192.168.0.51:8081/" />
<!-- 产品名称 -->
<add key="ProductName" value="G-MES V2.0" />
<!-- 版本号 -->
<add key="Version" value="0.1" />
<!-- 日志目录 (相对路径或绝对路径) -->
<add key="LogPath" value="logs" />
<!-- 分页大小 -->
<add key="PageSize" value="50" />
<!-- 启用自动更新 (0=禁用, 1=启用) -->
<add key="IsAutoUpdater" value="0" />
<!-- 自动更新配置文件 URL -->
<add key="AutoUpdaterXml" value="http://192.168.0.51:8086/AutoUpdater/AutoUpdater.xml" />
<!-- Toast 提示框显示时长 (秒) -->
<add key="ToastSeconds" value="5" />
<!-- 水检超时时间 (秒) -->
<add key="AsyncSeconds" value="2" />
<!-- 是否启用水检及工位码功能 (0=禁用, 1=启用) -->
<add key="IsWater" value="0" />
<!-- IQC 称重读取超时 (毫秒) -->
<add key="IqcGetWeight" value="3000" />
<!-- 定时邮件发送间隔 (毫秒) -->
<add key="TimingMailInterval" value="10000" />
</appSettings>
<userSettings>
<Gs.DevApp.Properties.Settings>
<!-- 用户名 (记住密码功能) -->
<setting name="userName" serializeAs="String">
<value />
</setting>
<!-- 密码 (加密存储) -->
<setting name="userPwd" serializeAs="String">
<value />
</setting>
<!-- 记住密码 -->
<setting name="remember" serializeAs="String">
<value>False</value>
</setting>
<!-- 字体设置 -->
<setting name="fontSizeName" serializeAs="String">
<value>宋体,10</value>
</setting>
<!-- 是否启用称重功能 -->
<setting name="isWeight" serializeAs="String">
<value>False</value>
</setting>
</Gs.DevApp.Properties.Settings>
</userSettings>
开发环境 → 生产环境:
| 配置项 | 开发环境 | 生产环境 |
|---|---|---|
WebApiUrl |
http://192.168.0.51:8081/ |
http://your-server:port/ |
IsAutoUpdater |
0 (禁用) |
1 (启用) |
AutoUpdaterXml |
内网地址 | 生产环境 URL |
LogPath |
logs |
建议使用公共目录 |
# 清理并重新构建
msbuild Gs.DevApp\Gs.DevApp.csproj /t:Clean
msbuild Gs.DevApp\Gs.DevApp.csproj /t:Rebuild /p:Configuration=Release /p:Platform="Any CPU"
Gs.DevApp.exe # 主程序
Gs.DevApp.exe.config # 配置文件 (必须修改)
DevExpress.*.dll # DevExpress 组件
CefSharp.*.dll # CefSharp 组件
AutoUpdater.NET.dll # 自动更新组件
Newtonsoft.Json.dll # JSON 库
Oracle.ManagedDataAccess.dll # Oracle 驱动
x86/ # CefSharp x86 本地库 (必须)
x64/ # CefSharp x64 本地库 (必须)
locales/ # CefSharp 语言包
logs/ # 日志目录 (运行时创建)
Gs.Setup\Gs.Setup.vdprojGs.Setup\Release\Gs.Setup.msi<?xml version="1.0" encoding="utf-8"?>
<update>
<version>0.2.0.0</version>
<url>http://your-server/updates/Gs.DevApp_v0.2.0.0.zip</url>
<changelog>
<![CDATA[
<h3>版本 0.2.0.0 更新内容</h3>
<ul>
<li>新增:条码批量打印功能</li>
<li>优化:仓库出入库流程</li>
<li>修复:质检数据保存失败问题</li>
</ul>
]]>
</changelog>
<mandatory>false</mandatory>
</update>
在 App.config 中:
<add key="IsAutoUpdater" value="1" />
<add key="AutoUpdaterXml" value="http://your-server/updates/AutoUpdater.xml" />
WebApiUrl 为生产环境地址IsAutoUpdater 配置x86/ 和 x64/ 目录完整DevFrm/
└── YourModule/ # 新模块目录
├── Frm_Main.cs # 主窗体
├── Frm_Edit.cs # 编辑窗体
├── Dlg_Select.cs # 选择对话框
└── Models/ # 本地模型 (可选)
| 类型 | 命名规则 | 示例 |
|---|---|---|
| 主窗体 | Frm_{业务名} |
Frm_Customer.cs |
| 编辑窗体 | Frm_{业务名}Edit |
Frm_CustomerEdit.cs |
| 对话框 | Dlg_{业务名} |
Dlg_SelectCustomer.cs |
| 用户控件 | Uc{功能名} |
UcToolBarMenu.cs |
// 使用 UtilityHelper.HttpPost
string jsonParam = JsonConvert.SerializeObject(new {
id = customerId
});
string result = UtilityHelper.HttpPost(
"BasicData/Customer/GetById",
"GetById",
jsonParam
);
dynamic dy = UtilityHelper.ReturnToDynamic(result);
if (dy.code == 200)
{
// 处理数据
}
else
{
MsgHelper.ShowError(dy.msg.ToString());
LogHelper.WriteLog($"API Error: {dy.msg}", LogHelper.LogType.Error);
}
// 不要直接使用 HttpClient、WebRequest 等
// 不要跳过错误处理
// 不要忽略日志记录
try
{
// 业务逻辑
string result = UtilityHelper.HttpPost(...);
dynamic dy = UtilityHelper.ReturnToDynamic(result);
if (dy.code == 200)
{
// 成功处理
}
else
{
// API 返回错误
MsgHelper.ShowError(dy.msg.ToString());
LogHelper.WriteLog($"API Error: {dy.msg}", LogHelper.LogType.Error);
}
}
catch (Exception ex)
{
// 捕获异常
MsgHelper.ShowError($"操作失败: {ex.Message}");
LogHelper.WriteLog($"Exception in {MethodName}: {ex}", LogHelper.LogType.Error);
}
// 使用 BackgroundWorker
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) => {
// 耗时操作
e.Result = PerformLongOperation();
};
worker.RunWorkerCompleted += (s, e) => {
// UI 更新
UpdateUI(e.Result);
};
worker.RunWorkerAsync();
// ❌ 阻塞 UI 线程
Thread.Sleep(5000);
// ✅ 使用定时器或异步
Timer timer = new Timer();
timer.Interval = 5000;
timer.Tick += (s, e) => {
timer.Stop();
// 执行操作
};
timer.Start();
// ✅ 使用 UcLookCustomer
UcLookCustomer lookCustomer = new UcLookCustomer();
if (lookCustomer.ShowDialog() == DialogResult.OK)
{
txtCustomerId.Text = lookCustomer.SelectedId;
txtCustomerName.Text = lookCustomer.SelectedName;
}
// ❌ 不要自己写选择对话框
// 已有 60+ UcLook* 控件可用
// 关键操作前后记录日志
LogHelper.WriteLog($"开始保存客户数据: {customerId}", LogHelper.LogType.Info);
try
{
string result = UtilityHelper.HttpPost(...);
LogHelper.WriteLog($"保存成功: {customerId}", LogHelper.LogType.Info);
}
catch (Exception ex)
{
LogHelper.WriteLog($"保存失败: {ex.Message}", LogHelper.LogType.Error);
}
// ✅ 从配置文件读取
string apiUrl = ConfigurationManager.AppSettings["WebApiUrl"];
int pageSize = int.Parse(ConfigurationManager.AppSettings["PageSize"]);
// ❌ 不要硬编码
// string apiUrl = "http://192.168.0.51:8081/";
原因: DevExpress 未安装或 NuGet 源未配置
解决方案:
工具 → NuGet 包管理器 → 程序包管理器设置 → 程序包源 添加: https://nuget.devexpress.com/<your_feed_key>/api bash nuget restore GsDevSolution.sln 原因: x86/ 或 x64/ 目录缺失
解决方案:
确保输出目录包含: x86/ libcef.dll chrome_elf.dll ... x64/ libcef.dll chrome_elf.dll ...
排查步骤:
App.config 中的 WebApiUrllogs/{yyyy-MM-dd}.log排查步骤:
原因: 反射创建窗体失败
排查步骤:
优化方案:
UcPageBar)gridView.OptionsView.ColumnAutoWidth = false;
gridView.BestFitColumns();
解决方案:
UtilityHelper.cs 中的超时设置)位置: logs/{yyyy-MM-dd}.log
日志级别:
- [Info] - 信息
- [Warning] - 警告
- [Error] - 错误
原因: 无写权限
解决方案:
LogPath 为公共目录检查:
- Oracle.ManagedDataAccess.dll 是否存在
- 连接字符串是否正确
- 网络是否可达
检查:
- SQL Server 是否启用 TCP/IP
- 端口是否开放 (默认 1433)
- 防火墙规则
排查:
AutoUpdaterXml URL 是否可访问排查:
| 端点 | 说明 |
|---|---|
User/UserLogin |
用户登录 |
User/GetUserLoginInfo |
获取用户信息和菜单 |
User/SetUserOrg |
切换组织 |
| 端点 | 说明 |
|---|---|
Organization/GetListPage |
获取组织列表 |
MenuAction/GetModelByNameSpace |
根据命名空间获取窗体信息 |
模式: {Module}/{Entity}/GetListPage
示例:
- BasicData/Customer/GetListPage - 客户列表
- BasicData/Items/GetListPage - 物料列表
- Warehouse/Inventory/GetListPage - 库存列表
# 还原 NuGet 包
nuget restore GsDevSolution.sln
# Debug 构建
msbuild GsDevSolution.sln /p:Configuration=Debug
# Release 构建
msbuild GsDevSolution.sln /p:Configuration=Release
# 运行程序
Gs.DevApp\bin\Debug\Gs.DevApp.exe
// API 调用
string result = UtilityHelper.HttpPost("Module/Action", "Action", jsonParam);
dynamic dy = UtilityHelper.ReturnToDynamic(result);
// 消息提示
MsgHelper.ShowSuccess("操作成功");
MsgHelper.ShowError("操作失败");
// 日志记录
LogHelper.WriteLog("消息内容", LogHelper.LogType.Info);
// Toast 提示
Toast.Show("提示内容", 3);
如需技术支持或报告问题,请联系开发团队。
最后更新: 2025-10-16
本文档随项目持续更新,建议定期查看最新版本。