570 lines
15 KiB
Markdown
570 lines
15 KiB
Markdown
# Delphi 代码框架文档
|
|
|
|
## 概述
|
|
|
|
本文档描述了为 MES 客户端应用创建的代码框架,包括配置管理、业务服务、异常处理、日志管理和单元测试等模块。
|
|
|
|
---
|
|
|
|
## 1. 配置管理框架 (uConfigManager.pas)
|
|
|
|
### 1.1 主要组件
|
|
|
|
| 组件 | 说明 |
|
|
|-----|------|
|
|
| `TConfigManager` | 通用配置管理器,支持INI和JSON格式 |
|
|
| `TAppConfig` | 应用配置单例,提供预定义的配置项 |
|
|
|
|
### 1.2 TConfigManager 核心方法
|
|
|
|
```pascal
|
|
// 读取配置
|
|
function GetString(const Section, Key, Default: string): string;
|
|
function GetInteger(const Section, Key: string; Default: Integer): Integer;
|
|
function GetBoolean(const Section, Key: string; Default: Boolean): Boolean;
|
|
function GetFloat(const Section, Key: string; Default: Double): Double;
|
|
|
|
// 写入配置
|
|
procedure SetString(const Section, Key, Value: string);
|
|
procedure SetInteger(const Section, Key: string; Value: Integer);
|
|
procedure SetBoolean(const Section, Key: string; Value: Boolean);
|
|
procedure SetFloat(const Section, Key: string; Value: Double);
|
|
```
|
|
|
|
### 1.3 TAppConfig 预定义配置
|
|
|
|
```pascal
|
|
// 网络配置
|
|
Config.GetServerURL: string; // 服务器地址
|
|
Config.GetServerPort: Integer; // 服务器端口
|
|
Config.GetTimeout: Integer; // 超时时间(ms)
|
|
Config.GetRetryCount: Integer; // 重试次数
|
|
Config.GetCORSOrigin: string; // CORS允许源
|
|
Config.GetAPIPath: string; // API路径
|
|
Config.GetAdminAPIPath: string; // 管理API路径
|
|
|
|
// 设备配置
|
|
Config.GetPLCHost: string; // PLC主机地址
|
|
Config.GetPLCPort: Integer; // PLC端口
|
|
Config.GetSerialPort: string; // 串口号
|
|
Config.GetBaudRate: Integer; // 波特率
|
|
|
|
// 文件服务器配置
|
|
Config.GetFileServerPath: string; // 文件服务器路径
|
|
Config.GetBackupServerPath: string; // 备份服务器路径
|
|
|
|
// 数据同步配置
|
|
Config.GetSyncInterval: Integer; // 同步间隔(ms)
|
|
Config.GetMaxRetryCount: Integer; // 最大重试次数
|
|
|
|
// 日志配置
|
|
Config.GetLogFileDir: string; // 日志文件目录
|
|
Config.GetLogFileMaxSize: Integer; // 日志文件最大大小(bytes)
|
|
Config.GetLogLevel: Integer; // 日志级别(0-5)
|
|
```
|
|
|
|
### 1.4 使用示例
|
|
|
|
```pascal
|
|
// 读取配置
|
|
ServerURL := Config.GetServerURL;
|
|
Timeout := Config.GetTimeout;
|
|
|
|
// 修改配置
|
|
Config.System.SetString('Network', 'ServerURL', 'http://new-server:8080');
|
|
Config.Save; // 保存配置
|
|
```
|
|
|
|
---
|
|
|
|
## 2. 业务服务框架 (uBusinessServices.pas)
|
|
|
|
### 2.1 服务工厂
|
|
|
|
```pascal
|
|
class function TBusinessServiceFactory.GetAuthService(): TAuthService;
|
|
class function TBusinessServiceFactory.GetWorkOrderService(const Token: string): TWorkOrderService;
|
|
class function TBusinessServiceFactory.GetDeviceService(): TDeviceService;
|
|
class function TBusinessServiceFactory.GetSyncService(const Token: string): TSyncService;
|
|
class function TBusinessServiceFactory.GetDeviceConfigService(): TDeviceConfigService;
|
|
class function TBusinessServiceFactory.GetProductionReportingService(const Token: string): TProductionReportingService;
|
|
class function TBusinessServiceFactory.GetDataAccessService(): TDataAccessService;
|
|
```
|
|
|
|
### 2.2 认证服务 (TAuthService)
|
|
|
|
```pascal
|
|
// 登录
|
|
function Login(const UserID, Password: string): TAuthResult;
|
|
|
|
// 注销
|
|
function Logout(const Token: string): Boolean;
|
|
|
|
// 刷新令牌
|
|
function RefreshToken(const Token: string): string;
|
|
|
|
// 验证令牌
|
|
function ValidateToken(const Token: string): Boolean;
|
|
```
|
|
|
|
### 2.3 工单服务 (TWorkOrderService)
|
|
|
|
```pascal
|
|
// 获取工单列表
|
|
function GetWorkOrderList(const Status: string = ''): TArray<TWorkOrderInfo>;
|
|
|
|
// 获取工单详情
|
|
function GetWorkOrderDetail(const OrderID: string): TWorkOrderInfo;
|
|
|
|
// 获取工单工序
|
|
function GetWorkOrderEntries(const OrderID: string): TArray<TWorkOrderEntry>;
|
|
|
|
// 创建工单
|
|
function CreateWorkOrder(const OrderInfo: TWorkOrderInfo): string;
|
|
|
|
// 更新工单状态
|
|
function UpdateWorkOrderStatus(const OrderID, Status: string): Boolean;
|
|
|
|
// 生产报工
|
|
function ReportProduction(const OrderID, ProcessID, Quantity: string): Boolean;
|
|
```
|
|
|
|
### 2.4 设备服务 (TDeviceService)
|
|
|
|
```pascal
|
|
// 获取设备状态
|
|
function GetDeviceStatus(const DeviceID: string): TDeviceStatus;
|
|
|
|
// 获取所有设备
|
|
function GetAllDevices(): TArray<TDeviceStatus>;
|
|
|
|
// 连接设备
|
|
function ConnectDevice(const DeviceID: string): Boolean;
|
|
|
|
// 断开设备
|
|
function DisconnectDevice(const DeviceID: string): Boolean;
|
|
|
|
// 发送命令
|
|
function SendCommand(const DeviceID, Command: string): string;
|
|
```
|
|
|
|
### 2.5 同步服务 (TSyncService)
|
|
|
|
```pascal
|
|
// 同步数据
|
|
function SyncData(const Data: TJSONObject): Boolean;
|
|
|
|
// 批量同步
|
|
function SyncBatchData(const DataArray: TJSONArray): Boolean;
|
|
|
|
// 获取同步状态
|
|
function GetSyncStatus(): TJSONObject;
|
|
|
|
// 重试失败同步
|
|
function RetryFailedSyncs(): Integer;
|
|
```
|
|
|
|
### 2.6 设备配置服务 (TDeviceConfigService)
|
|
|
|
```pascal
|
|
// 加载设备配置
|
|
function LoadDeviceConfig(): Boolean;
|
|
|
|
// 保存设备配置
|
|
function SaveDeviceConfig(): Boolean;
|
|
|
|
// 验证配置
|
|
function ValidateConfig(): TValidationResult;
|
|
|
|
// 获取服务器URL
|
|
function GetServerURL(): string;
|
|
|
|
// 获取工厂代码
|
|
function GetFactoryCode(): string;
|
|
|
|
// 获取生产线
|
|
function GetProductionLine(): string;
|
|
|
|
// 获取操作工位
|
|
function GetOperatorStation(): string;
|
|
```
|
|
|
|
### 2.7 生产报工服务 (TProductionReportingService)
|
|
|
|
```pascal
|
|
// 报工
|
|
function ReportProduction(const OrderID, ProcessID, Quantity, LotNo: string): Boolean;
|
|
|
|
// 报不良
|
|
function ReportDefective(const OrderID, ProcessID, DefectType, Quantity: string): Boolean;
|
|
|
|
// 查询生产状态
|
|
function QueryProductionStatus(const OrderID: string): TJSONObject;
|
|
|
|
// 验证用户
|
|
function ValidateUser(const UserID: string): Boolean;
|
|
|
|
// 获取工单信息
|
|
function GetWorkOrderInfo(const LotNo: string): TJSONObject;
|
|
|
|
// 获取工序列表
|
|
function GetProcessList(const LotNo: string): TJSONArray;
|
|
|
|
// 验证二维码
|
|
function ValidateGoodsNo(const ItemCode, ProcessCode, WorkOrderNumber: string): Boolean;
|
|
|
|
// 提交生产数据
|
|
function SubmitProductionData(const UserID, LotNo, ProcessID, GoodsNo: string): Boolean;
|
|
```
|
|
|
|
### 2.8 数据访问服务 (TDataAccessService)
|
|
|
|
```pascal
|
|
// 读取配置值
|
|
function ReadConfigValue(const ASection, AKey: string; const ADefault: string = ''): string;
|
|
|
|
// 写入配置值
|
|
procedure WriteConfigValue(const ASection, AKey, AValue: string);
|
|
|
|
// 读取设备信息
|
|
function ReadDeviceInfo(const AKey: string): string;
|
|
|
|
// 读取生产参数
|
|
function ReadProductionParams(const AKey: string): string;
|
|
|
|
// 读取报警配置
|
|
function ReadAlarmConfig(const AKey: string): string;
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 异常处理框架 (uExceptionHandler.pas)
|
|
|
|
### 3.1 异常类型层次
|
|
|
|
```
|
|
EBaseException
|
|
├── ENetworkException (网络错误)
|
|
├── EDataException (数据错误)
|
|
├── EBusinessException (业务错误)
|
|
├── EDeviceException (设备错误)
|
|
└── EValidationException (验证错误)
|
|
```
|
|
|
|
### 3.2 EBaseException 属性
|
|
|
|
```pascal
|
|
property ErrorCode: Integer; // 错误码
|
|
property ErrorType: string; // 错误类型
|
|
property Cause: string; // 错误原因
|
|
property Context: TStrings; // 错误上下文
|
|
property Timestamp: TDateTime; // 时间戳
|
|
```
|
|
|
|
### 3.3 快捷抛出函数
|
|
|
|
```pascal
|
|
procedure RaiseNetworkException(const AMsg: string; AErrorCode: Integer = 0);
|
|
procedure RaiseDataException(const AMsg: string; AErrorCode: Integer = 0);
|
|
procedure RaiseBusinessException(const AMsg: string; AErrorCode: Integer = 0);
|
|
procedure RaiseDeviceException(const AMsg: string; AErrorCode: Integer = 0);
|
|
procedure RaiseValidationException(const AFieldName, AFieldValue, AMsg: string);
|
|
```
|
|
|
|
### 3.4 使用示例
|
|
|
|
```pascal
|
|
// 抛出特定类型异常
|
|
RaiseNetworkException('连接失败: %s', [E.Message], 1001);
|
|
RaiseBusinessException('工单不存在', 2001);
|
|
|
|
// 全局异常处理
|
|
TExceptionHandler.Instance.HandleException(E);
|
|
```
|
|
|
|
---
|
|
|
|
## 4. 日志管理框架 (uLogManager.pas)
|
|
|
|
### 4.1 日志级别
|
|
|
|
| 级别 | 值 | 说明 |
|
|
|-----|---|------|
|
|
| `llTrace` | 0 | 跟踪信息 |
|
|
| `llDebug` | 1 | 调试信息 |
|
|
| `llInfo` | 2 | 一般信息 |
|
|
| `llWarn` | 3 | 警告信息 |
|
|
| `llError` | 4 | 错误信息 |
|
|
| `llFatal` | 5 | 致命错误 |
|
|
|
|
### 4.2 日志分类
|
|
|
|
| 分类 | 说明 |
|
|
|-----|------|
|
|
| `lcSystem` | 系统日志 |
|
|
| `lcNetwork` | 网络日志 |
|
|
| `lcDatabase` | 数据库日志 |
|
|
| `lcBusiness` | 业务日志 |
|
|
| `lcDevice` | 设备日志 |
|
|
| `lcUI` | 界面日志 |
|
|
| `lcSecurity` | 安全日志 |
|
|
| `lcPerformance` | 性能日志 |
|
|
|
|
### 4.3 日志方法
|
|
|
|
```pascal
|
|
// 基础日志
|
|
procedure Log(Level: TLogLevel; Category: TLogCategory; const Message: string; const Args: array of const);
|
|
|
|
// 分级日志
|
|
procedure Trace(const Message: string; const Args: array of const = []);
|
|
procedure Debug(const Message: string; const Args: array of const = []);
|
|
procedure Info(const Message: string; const Args: array of const = []);
|
|
procedure Warn(const Message: string; const Args: array of const = []);
|
|
procedure Error(const Message: string; const Args: array of const = []);
|
|
procedure Fatal(const Message: string; const Args: array of const = []);
|
|
|
|
// 分类日志
|
|
procedure InfoCategory(Category: TLogCategory; const Message: string; const Args: array of const = []);
|
|
procedure ErrorCategory(Category: TLogCategory; const Message: string; const Args: array of const = []);
|
|
```
|
|
|
|
### 4.4 性能日志
|
|
|
|
```pascal
|
|
// 方式1: 使用TPerformanceLogger
|
|
var Logger := TPerformanceLogger.Create('数据查询');
|
|
try
|
|
// 执行操作
|
|
finally
|
|
Logger.Free;
|
|
end;
|
|
|
|
// 方式2: 使用静态方法
|
|
TPerformanceLogger.Measure<T>(
|
|
'数据查询',
|
|
function: T begin
|
|
// 执行操作
|
|
Result := ...;
|
|
end,
|
|
'Tag信息'
|
|
);
|
|
```
|
|
|
|
### 4.5 使用示例
|
|
|
|
```pascal
|
|
// 记录日志
|
|
LogManager.InfoCategory(lcNetwork, '连接成功: %s', ['192.168.1.100']);
|
|
LogManager.ErrorCategory(lcDevice, 'PLC通信失败: %s', [E.Message]);
|
|
|
|
// 记录异常
|
|
LogManager.LogException(E, lcNetwork, '额外的上下文信息');
|
|
|
|
// 性能监控
|
|
var PerfLogger := TPerformanceLogger.Create('耗时操作');
|
|
// ... 执行代码 ...
|
|
PerfLogger.Finish;
|
|
```
|
|
|
|
### 4.6 UI操作和网络请求监控
|
|
|
|
```pascal
|
|
// UI操作监控
|
|
LogManager.LogUIOperation('Click', 'Button1', 50);
|
|
LogManager.LogUIOperation('Select', 'ComboBox1', -1);
|
|
|
|
// 网络请求监控
|
|
LogManager.LogNetworkRequest('http://example.com/api', 'GET', 200, 150);
|
|
LogManager.LogNetworkRequest('http://example.com/api', 'POST', 500, 300);
|
|
|
|
// 表单监控
|
|
LogManager.LogFormShow('MainForm', 100);
|
|
LogManager.LogFormClose('MainForm', 50);
|
|
|
|
// 数据操作监控
|
|
LogManager.LogDataOperation('INSERT', 10, 25);
|
|
LogManager.LogDataOperation('UPDATE', 5, -1);
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 通用工具 (uCommonUtils.pas)
|
|
|
|
### 5.1 数据验证 (TValidator)
|
|
|
|
```pascal
|
|
class function TValidator.IsEmpty(const AValue: string): Boolean;
|
|
class function TValidator.IsInteger(const AValue: string): Boolean;
|
|
class function TValidator.IsFloat(const AValue: string): Boolean;
|
|
class function TValidator.IsEmail(const AValue: string): Boolean;
|
|
class function TValidator.IsPhone(const AValue: string): Boolean;
|
|
class function TValidator.IsIPAddress(const AValue: string): Boolean;
|
|
class function TValidator.ValidateBarcode(const ABarcode: string): TValidationResult;
|
|
```
|
|
|
|
### 5.2 字符串扩展 (TStringHelperEx)
|
|
|
|
```pascal
|
|
function IsInteger: Boolean;
|
|
function IsFloat: Boolean;
|
|
function ToIntegerDef(ADefault: Integer): Integer;
|
|
function ToFloatDef(ADefault: Double): Double;
|
|
function Contains(const ASubStr: string): Boolean;
|
|
function StartsWith(const AStr: string): Boolean;
|
|
function EndsWith(const AStr: string): Boolean;
|
|
function ReplaceAll(const AFrom, ATo: string): string;
|
|
```
|
|
|
|
### 5.3 日期时间工具 (TDateTimeHelper)
|
|
|
|
```pascal
|
|
class function TDateTimeHelper.FormatDateTime(const AFormat: string; ADateTime: TDateTime): string;
|
|
class function TDateTimeHelper.ParseDateTime(const AValue: string): TDateTime;
|
|
class function TDateTimeHelper.IsToday(ADateTime: TDateTime): Boolean;
|
|
class function TDateTimeHelper.IsSameDay(ADate1, ADate2: TDateTime): Boolean;
|
|
```
|
|
|
|
### 5.4 JSON工具 (TJSONHelper)
|
|
|
|
```pascal
|
|
class function TJSONHelper.GetString(AJSON: TJSONObject; const AKey: string; const ADefault: string = ''): string;
|
|
class function TJSONHelper.GetInteger(AJSON: TJSONObject; const AKey: string; const ADefault: Integer = 0): Integer;
|
|
class function TJSONHelper.TryGetString(AJSON: TJSONObject; const AKey: string; out AValue: string): Boolean;
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 单元测试 (uUnitTests.pas)
|
|
|
|
### 6.1 测试套件
|
|
|
|
| 测试套件 | 测试内容 |
|
|
|---------|---------|
|
|
| `ExceptionHandler` | 异常处理框架测试 |
|
|
| `LogManager` | 日志管理框架测试 |
|
|
| `ConfigManager` | 配置管理框架测试 |
|
|
| `BusinessServices` | 业务服务框架测试 |
|
|
| `CommonUtils` | 通用工具测试 |
|
|
|
|
### 6.2 运行测试
|
|
|
|
```bash
|
|
# GUI模式
|
|
TestRunner.exe
|
|
|
|
# 控制台模式
|
|
TestRunner.exe -console
|
|
```
|
|
|
|
### 6.3 测试示例
|
|
|
|
```pascal
|
|
procedure TTestConfigManager.TestConfigTypes;
|
|
var
|
|
Config: TConfigManager;
|
|
begin
|
|
Config := TConfigManager.Create('test_config.ini');
|
|
try
|
|
Config.SetString('Test', 'String', 'Hello');
|
|
Config.SetInteger('Test', 'Integer', 123);
|
|
Config.SetBoolean('Test', 'Boolean', True);
|
|
Config.SetFloat('Test', 'Float', 123.45);
|
|
|
|
CheckEquals('Hello', Config.GetString('Test', 'String', ''));
|
|
CheckEquals(123, Config.GetInteger('Test', 'Integer', 0));
|
|
CheckEquals(True, Config.GetBoolean('Test', 'Boolean', False));
|
|
CheckEquals(123.45, Config.GetFloat('Test', 'Float', 0.0), 0.01);
|
|
finally
|
|
Config.Free;
|
|
end;
|
|
end;
|
|
```
|
|
|
|
---
|
|
|
|
## 7. 文件结构
|
|
|
|
```
|
|
pas\
|
|
├── uConfigManager.pas # 配置管理框架
|
|
├── uBusinessServices.pas # 业务服务框架
|
|
├── uExceptionHandler.pas # 异常处理框架
|
|
├── uLogManager.pas # 日志管理框架
|
|
├── uCommonUtils.pas # 通用工具
|
|
├── uUnitTests.pas # 单元测试
|
|
├── uSafeLog.pas # 安全日志(已集成新框架)
|
|
├── uDM.pas # 数据模块(已集成新框架)
|
|
├── uFrameBase.pas # 框架基类(已添加文档)
|
|
└── 其他业务框架文件...
|
|
```
|
|
|
|
---
|
|
|
|
## 8. 迁移指南
|
|
|
|
### 8.1 使用配置管理器替代硬编码
|
|
|
|
**Before:**
|
|
```pascal
|
|
PLCHost := '192.168.1.100';
|
|
PLCPort := 502;
|
|
```
|
|
|
|
**After:**
|
|
```pascal
|
|
PLCHost := Config.GetPLCHost;
|
|
PLCPort := Config.GetPLCPort;
|
|
```
|
|
|
|
### 8.2 使用新的异常处理
|
|
|
|
**Before:**
|
|
```pascal
|
|
raise Exception.Create('错误信息');
|
|
```
|
|
|
|
**After:**
|
|
```pascal
|
|
RaiseBusinessException('错误信息', 1001);
|
|
// 或
|
|
RaiseDeviceException('PLC连接失败: %s', [E.Message], 5001);
|
|
```
|
|
|
|
### 8.3 使用新的日志框架
|
|
|
|
**Before:**
|
|
```pascal
|
|
WorkLog.MessageInfo('操作成功');
|
|
WorkLog.Error('操作失败: %s', [E.Message]);
|
|
```
|
|
|
|
**After:**
|
|
```pascal
|
|
LogManager.InfoCategory(lcBusiness, '操作成功');
|
|
LogManager.ErrorCategory(lcBusiness, '操作失败: %s', [E.Message]);
|
|
```
|
|
|
|
---
|
|
|
|
## 9. 最佳实践
|
|
|
|
1. **配置管理**: 所有硬编码的配置值都应迁移到配置管理器
|
|
2. **异常处理**: 使用特定的异常类型,便于分类处理
|
|
3. **日志记录**: 在关键业务操作中添加日志和性能监控
|
|
4. **单元测试**: 新增功能应同步添加单元测试
|
|
5. **代码文档**: 复杂函数应添加文档注释
|
|
|
|
---
|
|
|
|
## 10. 版本信息
|
|
|
|
| 版本 | 日期 | 说明 |
|
|
|-----|------|-----
|
|
| 1.1 | 2026-04-26 | 扩展生产报工服务,添加用户验证、工单查询、二维码验证等功能 |
|
|
| 1.0 | 2026-04-26 | 初始版本,包含核心框架 |
|
|
|
|
---
|
|
|
|
*文档最后更新: 2026-04-26*
|