编辑 | blame | 历史 | 原始文档

蓝宝 MES 客户端帮助指南 (G-MES V2.0)

LanBMes MES Client 是基于 .NET Framework 4.8 和 DevExpress WinForms 构建的企业级制造执行系统(MES)桌面应用程序,为制造车间提供全面的生产执行、仓储管理、质量控制和报表分析能力。

目录


1. 项目概览

1.1 基本信息

项目 说明
解决方案名称 GsDevSolution.sln
产品名称 G-MES V2.0
主要用途 面向制造现场的 MES Windows 客户端
核心应用 Gs.DevApp (主客户端)
辅助应用 Gs.WeightIqc (IQC称重), Gs.WeightLine (产线称重)
开发环境 Visual Studio 2022+
目标框架 .NET Framework 4.8
构建平台 Any CPU

1.2 核心特性

  • 现代化 UI: 基于 DevExpress v22.2 的 FluentDesign 界面
  • 动态加载: 通过反射机制实现菜单和窗体的动态加载
  • 权限控制: 基于角色的菜单权限和操作权限管理
  • 可复用组件: 150+ 业务控件,提高开发效率
  • 多数据库支持: 兼容 Oracle 和 SQL Server
  • 自动更新: 集成 AutoUpdater.NET 实现自动升级
  • 嵌入式浏览器: CefSharp 支持 H5 页面集成
  • 工业通信: NModbus 支持 Modbus TCP/RTU 设备通信
  • 集中式日志: 统一的日志记录和错误追踪机制

1.3 业务覆盖范围

基础数据管理 → 生产计划 → 工单管理 → 生产执行 → 质量检验 → 仓储物流 → 报表分析
     ↓            ↓          ↓          ↓          ↓          ↓          ↓
  客户/供应商   排产调整   任务下达   工序开工   多级质检   出入库管理   FastReport
  物料主数据   产线分配   流程卡     数据采集   缺陷追踪   库存调拨   统计分析
  工装设备     资源协调   进度追踪   返工维修   AQL抽样   条码管理   自定义报表

2. 解决方案结构

2.1 项目组成

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 包目录】

2.2 核心目录详解

DevFrm/ - 业务窗体

所有业务窗体按领域划分,每个子目录包含该领域的所有表单和对话框。

命名规范: Frm_{业务名称}.csFrm_{业务名称}_{子类型}.cs

Entity/ - 数据模型

文件 说明
LoginInfoModel.cs 登录用户信息模型
PageQueryModel.cs 分页查询通用模型
ReturnModel.cs API 返回结果封装

ToolBox/ - 工具类库

文件 说明
UtilityHelper.cs 核心工具类: HTTP请求、JSON解析、Grid初始化等
LogHelper.cs 日志记录工具 (写入 logs/{yyyy-MM-dd}.log)
MsgHelper.cs 统一消息提示封装 (基于 DevExpress)
UpdateParentEventArgs.cs 窗体间事件通信机制
ModbusHelper.cs Modbus 设备通信封装

UserControl/ - 可复用控件

控件类型 示例 说明
工具栏 UcToolBarMenu.cs 标准CRUD操作栏
分页 UcPageBar.cs 分页控件
选择器 UcDictionarySelect.cs 数据字典下拉框
查找控件 UcLookCustomer.cs
UcLookItems.cs
UcLookWarehouse.cs
60+ 数据查找对话框
(客户/物料/仓库等)
通知 Toast.cs 轻量级提示框

3. 核心技术栈

3.1 主要依赖

技术/库 版本 用途
.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 数据库访问

3.2 DevExpress 核心组件

// FluentDesign 主界面
DevExpress.XtraBars.FluentDesignSystem.FluentDesignForm

// 数据表格
DevExpress.XtraGrid.GridControl
DevExpress.XtraGrid.Views.Grid.GridView

// 标签页
DevExpress.XtraTab.XtraTabControl

// 导航菜单
DevExpress.XtraNavBar.NavBarControl

// 等待对话框
DevExpress.XtraWaitForm.WaitDialogForm

4. 开发环境配置

4.1 前置要求

  • ✅ Windows 10/11 或 Windows Server 2016+
  • ✅ Visual Studio 2022 (推荐) 或 Visual Studio 2019
  • ✅ .NET Framework 4.8 SDK
  • ✅ DevExpress v22.2+ 许可证 (需配置 NuGet 源)
  • ✅ Git (版本控制)

4.2 克隆与还原

# 克隆代码库
cd E:\LanBMes
git clone <repository_url> LB_MesClient

# 进入解决方案目录
cd LB_MesClient\DevApp

# 还原 NuGet 包
nuget restore GsDevSolution.sln

# 或在 Visual Studio 中:
# 右键解决方案 → 还原 NuGet 程序包

4.3 配置 DevExpress

确保已安装 DevExpress v22.2 并配置 NuGet 源:

工具 → NuGet 包管理器 → 程序包管理器设置 → 程序包源
添加源: https://nuget.devexpress.com/<your_feed_key>/api

4.4 配置后端 API

编辑 Gs.DevApp\App.config:

<add key="WebApiUrl" value="http://192.168.0.51:8081/" />

修改为实际的后端 API 地址。


5. 构建与运行

5.1 命令行构建

# 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

5.2 Visual Studio 运行

  1. 打开解决方案: 双击 GsDevSolution.sln
  2. 设置启动项目: 右键 Gs.DevApp → 设为启动项目
  3. 运行: 按 F5 或点击 "开始调试"

5.3 直接运行

# Debug 版本
Gs.DevApp\bin\Debug\Gs.DevApp.exe

# Release 版本
Gs.DevApp\bin\Release\Gs.DevApp.exe

5.4 调试技巧

禁用单实例限制 (允许同时运行多个实例用于测试):

Program.cs 中注释以下代码:

// Process[] MyProcesses = Process.GetProcessesByName("Gs.DevApp");
// if (MyProcesses.Length > 1)
// {
//     MyProcesses[0].Kill();
// }

6. DevFrm 功能模块详解

6.1 登录与主框架

Program.cs - 应用程序入口

[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();
}

FrmLogin.cs - 登录窗体

核心功能:
- 自动更新检查 (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;
}

FrmMain.cs - 主窗体

核心职责:
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;
}

6.2 基础数据域 (BasicData/)

客户管理 - Frm_Customer.cs

  • 客户主数据维护
  • 支持分页查询
  • 使用 UcToolBarMenu 实现增删改查
  • 使用 UcPageBar 实现分页

供应商管理

  • Frm_Supplier.cs - 供应商基础信息
  • Frm_SupplierSrm.cs - SRM 供应商关系管理

物料管理

  • Frm_MesItems.cs - 物料主数据维护
  • Frm_MesItemsShow.cs - 物料信息展示

产线管理 - Frm_MesWorkshopLine.cs

  • 车间产线配置
  • 工作中心定义

其他主数据

  • Frm_Staff.cs - 员工信息
  • Frm_Department.cs - 部门组织

6.3 仓储管理域

出库管理 (Ck/)

窗体 功能
Frm_MesInvItemOut_SCLL.cs 生产领料出库
Frm_MesItemBl.cs 补料出库
Frm_MesCgthSq.cs 采购退货申请
Frm_MesItemQtck.cs 其他出库

入库管理 (Rk/)

窗体 功能
Frm_MesInvItemArn.cs 到货入库
Frm_MesItemTbl.cs 材料入库台账
Frm_MesItemQtrk.cs 其他入库

仓库操作 (Warehouse/)

窗体 功能
Frm_MesDbck.cs 调拨出库
Frm_MesRohIn.cs 原材入库
Frm_ArrivalBarcode.cs 到货条码生成
Frm_InitialBarcode.cs 初始条码维护

手持终端 (PDA/)

提供简化的扫码作业界面,用于:
- 快速理货
- 库存盘点
- 条码扫描
- 移动作业


6.4 质量管理域

QC/ - 质量通用模块

  • 缺陷代码维护 (DefectCode*.cs)
  • 检验项目设置 (Frm_MesQaItemsDetect01.cs)
  • AQL 抽样方案 (Frm_MesQmAql1.cs)
  • 质量标准定义

IPQC/ - 制程检验

窗体 功能
Frm_ShouJian.cs 首件检验
Frm_XunJian.cs 巡检作业
H5 检验界面 移动端检验

FQC/ - 成品终检

窗体 功能
Frm_Fqc.cs 成品检验主界面
Frm_FqcDetect01.cs 检验数据录入
MesFqcExceptional.cs 异常处理

RkQC/ - 来料质检

窗体 功能
Frm_Cqfa.cs 抽检方案
Frm_CqfaItems.cs 检验项配置
Frm_QtrkDetect01.cs 来料检验
Frm_WwrkDetect01.cs 委外来料检验

6.5 制造执行域 (Work/)

工序作业

窗体 功能
Frm_WorkStart.cs 工序开工
Frm_WorkProcesses.cs 流程卡管理
Frm_Work01.cs ~ Frm_Work09.cs 各工站数据采集
Frm_Repair.cs 返工维修

特殊功能

  • Modbus 设备通信: 支持实时读取工业设备数据
  • SQL Server 直连: 部分工站直接与 SQL Server 交互
  • 实时监控: 工站状态实时展示

6.6 工单管理域 (WOM/)

  • 生产任务下达
  • 工单排产调整
  • 工单进度追踪
  • 工单状态管理

6.7 销售管理域 (Sales/)

  • 销售订单管理
  • 发货单处理
  • 退货管理
  • 客户对账

6.8 委外管理域 (WW/)

  • 委外订单管理
  • 委外来料检验
  • 委外质量异常处理
  • 外协流程闭环

6.9 报表域 (Rpt/)

窗体 功能
EasyRptDesign.cs 报表设计器
EasyRptEdt.cs 报表编辑
SysHelp.cs 报表帮助

支持技术:
- FastReport
- DevExpress Reports
- 自定义报表引擎


6.10 系统管理域 (Sys/)

窗体 功能
SysMenu.cs 菜单结构维护
Organization.cs 组织架构管理
DocNoRule.cs 单号规则配置
SysLog.cs 系统日志查询
Frm_Config.cs 系统配置

6.11 用户与权限域 (User/)

窗体 功能
User.cs 用户管理
Role.cs 角色管理
RoleSelectAction.cs 角色授权
UserSetPwd.cs 密码变更

权限模型:
用户 → 角色 → 菜单权限 + 操作权限


6.12 夹具工装域 (JJGZ/)

  • 夹具工装台账
  • 计量设备管理
  • 点检任务与记录
  • 设备维护计划

6.13 条码管理域 (BarCode/)

窗体 功能
Frm_BarcodePrint.cs 条码批量打印
Frm_BarcodeTemplate.cs 打印模板设置

7. 架构与设计模式

7.1 多层架构

┌─────────────────────────────────────────┐
│         UI Layer (WinForms)             │
│  DevExpress FluentDesign + 150+ 控件    │
└─────────────────┬───────────────────────┘
                  │ HTTP/JSON REST API
┌─────────────────▼───────────────────────┐
│      Business Logic Layer (Client)      │
│  窗体逻辑 + ToolBox 工具类 + 动态加载    │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│     Backend REST API (别处项目)         │
│  身份验证 + 菜单 + 业务逻辑 + 数据访问   │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│          Data Layer                     │
│     Oracle / SQL Server                 │
└─────────────────────────────────────────┘

7.2 核心设计模式

模式 1: HTTP 请求集中化

所有 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) {
    // 处理数据
}

模式 2: 动态窗体加载 (反射)

// 在 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();
    }
}

好处:
- 菜单结构完全由后端控制
- 无需修改代码即可调整菜单
- 支持动态权限控制

模式 3: TabPage 缓存机制

// 防止重复打开同一窗体
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;
    }
}

模式 4: 父子窗体事件通信

子窗体触发父窗体刷新:

// 在子窗体中
UpdateParentEventArgs args = new UpdateParentEventArgs(this, "Refresh");
// 触发事件,通知父窗体

// 在父窗体中
private void ChildForm_UpdateParent(object sender, UpdateParentEventArgs e)
{
    if (e.Action == "Refresh")
    {
        LoadData(); // 刷新数据
    }
}

模式 5: 标准 CRUD 窗体模板

典型窗体结构:

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;
        }
    }
}

8. 工具类与公共组件

8.1 UtilityHelper.cs - 核心工具类

HTTP 请求

// 标准 POST 请求
string result = UtilityHelper.HttpPost(
    "User/UserLogin",       // 相对路径
    "UserLogin",            // 方法名
    jsonParam,              // JSON 参数
    true                    // 显示加载框
);

JSON 解析

// 解析为 dynamic 对象
dynamic dy = UtilityHelper.ReturnToDynamic(result);

// 解析为分页数据表
DataTable dt = UtilityHelper.ReturnToTablePage(result);

Grid 初始化

// 初始化表格控件
UtilityHelper.InitGridControl(
    gridControl,
    gridView,
    columns,        // 列定义
    dataSource,     // 数据源
    allowEdit: false,
    allowDelete: false
);

8.2 LogHelper.cs - 日志工具

// 记录信息日志
LogHelper.WriteLog("用户登录成功", LogHelper.LogType.Info);

// 记录错误日志
LogHelper.WriteLog($"API 调用失败: {ex.Message}", LogHelper.LogType.Error);

// 记录警告
LogHelper.WriteLog("数据异常,使用默认值", LogHelper.LogType.Warning);

日志文件位置: logs/{yyyy-MM-dd}.log

8.3 MsgHelper.cs - 消息提示

// 成功提示
MsgHelper.ShowSuccess("操作成功!");

// 错误提示
MsgHelper.ShowError("操作失败,请重试!");

// 警告提示
MsgHelper.ShowWarning("数据不完整!");

// 确认对话框
if (MsgHelper.ShowConfirm("确定要删除吗?") == DialogResult.Yes)
{
    // 执行删除
}

8.4 Toast.cs - 轻量提示

// 显示 3 秒提示
Toast.Show("保存成功", 3);

// 显示自定义时长
Toast.Show("数据已更新", 5); // 5 秒

8.5 可复用控件

UcToolBarMenu - 工具栏控件

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 - 分页控件

UcPageBar pageBar = new UcPageBar();
pageBar.PageSize = 50;
pageBar.TotalRecords = 1000;
pageBar.PageChanged += (s, e) => {
    LoadData(pageBar.CurrentPage, pageBar.PageSize);
};

UcDictionarySelect - 数据字典下拉

UcDictionarySelect cmbStatus = new UcDictionarySelect();
cmbStatus.DictionaryType = "OrderStatus"; // 字典类型
cmbStatus.LoadData();

UcLook* - 数据查找控件

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();

9. 配置说明

9.1 App.config 关键配置

位置: 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>

9.2 用户设置 (自动保存)

<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>

9.3 部署前必改配置

开发环境 → 生产环境:

配置项 开发环境 生产环境
WebApiUrl http://192.168.0.51:8081/ http://your-server:port/
IsAutoUpdater 0 (禁用) 1 (启用)
AutoUpdaterXml 内网地址 生产环境 URL
LogPath logs 建议使用公共目录

10. 部署指南

10.1 构建 Release 版本

# 清理并重新构建
msbuild Gs.DevApp\Gs.DevApp.csproj /t:Clean
msbuild Gs.DevApp\Gs.DevApp.csproj /t:Rebuild /p:Configuration=Release /p:Platform="Any CPU"

10.2 发布目录结构

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/                           # 日志目录 (运行时创建)

10.3 使用安装程序

  1. 打开 Gs.Setup\Gs.Setup.vdproj
  2. 配置安装程序属性:
  • ProductName: G-MES V2.0
  • Manufacturer: 蓝宝
  • Version: 与 App.config 保持一致
  1. 右键项目 → 生成
  2. 输出: Gs.Setup\Release\Gs.Setup.msi

10.4 自动更新配置

AutoUpdater.xml 示例

<?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" />

10.5 部署检查清单

  • [ ] 修改 WebApiUrl 为生产环境地址
  • [ ] 检查 IsAutoUpdater 配置
  • [ ] 确保 x86/x64/ 目录完整
  • [ ] 测试数据库连接
  • [ ] 验证日志目录写权限
  • [ ] 测试自动更新功能
  • [ ] 检查 DevExpress 许可证
  • [ ] 备份配置文件

11. 开发规范与最佳实践

11.1 代码组织规范

新增模块

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

11.2 API 调用规范

✅ 正确做法

// 使用 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 等
// 不要跳过错误处理
// 不要忽略日志记录

11.3 异常处理规范

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);
}

11.4 UI 更新规范

长时间操作使用后台线程

// 使用 BackgroundWorker
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) => {
    // 耗时操作
    e.Result = PerformLongOperation();
};
worker.RunWorkerCompleted += (s, e) => {
    // UI 更新
    UpdateUI(e.Result);
};
worker.RunWorkerAsync();

避免 UI 阻塞

// ❌ 阻塞 UI 线程
Thread.Sleep(5000);

// ✅ 使用定时器或异步
Timer timer = new Timer();
timer.Interval = 5000;
timer.Tick += (s, e) => {
    timer.Stop();
    // 执行操作
};
timer.Start();

11.5 控件复用规范

优先使用现有控件

// ✅ 使用 UcLookCustomer
UcLookCustomer lookCustomer = new UcLookCustomer();
if (lookCustomer.ShowDialog() == DialogResult.OK)
{
    txtCustomerId.Text = lookCustomer.SelectedId;
    txtCustomerName.Text = lookCustomer.SelectedName;
}

// ❌ 不要自己写选择对话框
// 已有 60+ UcLook* 控件可用

11.6 日志记录规范

// 关键操作前后记录日志
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);
}

11.7 配置管理规范

// ✅ 从配置文件读取
string apiUrl = ConfigurationManager.AppSettings["WebApiUrl"];
int pageSize = int.Parse(ConfigurationManager.AppSettings["PageSize"]);

// ❌ 不要硬编码
// string apiUrl = "http://192.168.0.51:8081/";

12. 常见问题与故障排查

12.1 构建失败

问题: DevExpress 组件找不到

原因: DevExpress 未安装或 NuGet 源未配置

解决方案:

  1. 安装 DevExpress v22.2
  2. 配置 NuGet 源:
    工具 → NuGet 包管理器 → 程序包管理器设置 → 程序包源 添加: https://nuget.devexpress.com/<your_feed_key>/api
  3. 还原 NuGet 包:
    bash nuget restore GsDevSolution.sln

问题: CefSharp 本地库加载失败

原因: x86/x64/ 目录缺失

解决方案:

确保输出目录包含:
x86/ libcef.dll chrome_elf.dll ... x64/ libcef.dll chrome_elf.dll ...

12.2 运行时错误

问题: "无法连接到 API 服务器"

排查步骤:

  1. 检查 App.config 中的 WebApiUrl
  2. 使用浏览器访问 API 地址
  3. 检查网络连接
  4. 查看日志文件 logs/{yyyy-MM-dd}.log

问题: "登录失败"

排查步骤:

  1. 检查用户名密码是否正确
  2. 检查后端 API 是否正常
  3. 查看日志文件中的错误信息
  4. 检查数据库连接

问题: "窗体加载失败"

原因: 反射创建窗体失败

排查步骤:

  1. 检查命名空间是否正确
  2. 检查窗体类是否为 public
  3. 检查窗体是否有无参构造函数
  4. 查看日志中的异常堆栈

12.3 性能问题

问题: Grid 加载慢

优化方案:

  1. 启用分页 (使用 UcPageBar)
  2. 减少列数
  3. 禁用不必要的 Grid 特性
  4. 使用虚拟模式 (大数据量时)
gridView.OptionsView.ColumnAutoWidth = false;
gridView.BestFitColumns();

问题: API 请求超时

解决方案:

  1. 检查网络状况
  2. 优化后端查询
  3. 增加超时时间 (修改 UtilityHelper.cs 中的超时设置)

12.4 日志相关

查看日志

位置: logs/{yyyy-MM-dd}.log

日志级别:
- [Info] - 信息
- [Warning] - 警告
- [Error] - 错误

日志写入失败

原因: 无写权限

解决方案:

  1. 以管理员身份运行
  2. 修改 LogPath 为公共目录
  3. 赋予应用目录写权限

12.5 数据库连接问题

Oracle 连接失败

检查:
- Oracle.ManagedDataAccess.dll 是否存在
- 连接字符串是否正确
- 网络是否可达

SQL Server 连接失败

检查:
- SQL Server 是否启用 TCP/IP
- 端口是否开放 (默认 1433)
- 防火墙规则

12.6 自动更新问题

更新检查失败

排查:

  1. 检查 AutoUpdaterXml URL 是否可访问
  2. 检查 XML 格式是否正确
  3. 检查网络连接
  4. 查看日志文件

更新下载失败

排查:

  1. 检查更新包 URL 是否有效
  2. 检查磁盘空间
  3. 检查写权限

附录 A: 后端 API 端点

认证与用户

端点 说明
User/UserLogin 用户登录
User/GetUserLoginInfo 获取用户信息和菜单
User/SetUserOrg 切换组织

组织与菜单

端点 说明
Organization/GetListPage 获取组织列表
MenuAction/GetModelByNameSpace 根据命名空间获取窗体信息

通用列表查询

模式: {Module}/{Entity}/GetListPage

示例:
- BasicData/Customer/GetListPage - 客户列表
- BasicData/Items/GetListPage - 物料列表
- Warehouse/Inventory/GetListPage - 库存列表


附录 B: 快速参考

常用命令

# 还原 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);

附录 C: 相关文档

  • CLAUDE.md - Claude Code AI 辅助开发指南
  • DEVFRM_GUIDE.md - DevFrm 模块详细指南
  • ANALYSIS_REPORT.md - 架构分析报告
  • DevFrm详细分析.md - 模块分析 (中文)

联系与支持

如需技术支持或报告问题,请联系开发团队。

最后更新: 2025-10-16


本文档随项目持续更新,建议定期查看最新版本。