unit uBusinessServices; interface uses SysUtils, Classes, System.JSON, System.Threading, System.Generics.Collections, uExceptionHandler, uLogManager, uConfigManager, uKsoap, uSafeLog, uCommonUtils; type TAuthResult = record Success: Boolean; UserID: string; UserName: string; Token: string; ErrorMessage: string; procedure Clear; class function CreateSuccess(const AUserID, AUserName, AToken: string): TAuthResult; static; class function CreateFailure(const AErrorMessage: string): TAuthResult; static; end; TWorkOrderInfo = record OrderID: string; OrderNumber: string; MaterialID: string; MaterialName: string; Quantity: Double; Status: string; CreateTime: TDateTime; procedure Clear; end; TWorkOrderEntry = record EntryID: string; OrderID: string; ProcessID: string; ProcessName: string; Quantity: Double; Status: string; procedure Clear; end; TDeviceStatus = record DeviceID: string; DeviceName: string; IPAddress: string; Port: Integer; Status: string; // 'Online', 'Offline', 'Error' LastHeartbeat: TDateTime; procedure Clear; end; TAuthService = class private FBaseURL: string; FTimeout: Integer; public 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; constructor Create(); end; TWorkOrderService = class private FBaseURL: string; FToken: string; public function GetWorkOrderList(const Status: string = ''): TArray; function GetWorkOrderDetail(const OrderID: string): TWorkOrderInfo; function GetWorkOrderEntries(const OrderID: string): TArray; function CreateWorkOrder(const OrderInfo: TWorkOrderInfo): string; function UpdateWorkOrderStatus(const OrderID, Status: string): Boolean; function ReportProduction(const OrderID, ProcessID, Quantity: string): Boolean; constructor Create(const AToken: string); end; TDeviceService = class private FDevices: TDictionary; public function GetDeviceStatus(const DeviceID: string): TDeviceStatus; function GetAllDevices(): TArray; function ConnectDevice(const DeviceID: string): Boolean; function DisconnectDevice(const DeviceID: string): Boolean; function SendCommand(const DeviceID, Command: string): string; function GetDeviceInfo(const DeviceID: string): TJSONObject; constructor Create(); destructor Destroy; override; end; TSyncService = class private FBaseURL: string; FToken: string; FIsSyncing: Boolean; public function SyncData(const Data: TJSONObject): Boolean; function SyncBatchData(const DataArray: TJSONArray): Boolean; function GetSyncStatus(): TJSONObject; function RetryFailedSyncs(): Integer; procedure StartAutoSync(IntervalMS: Integer); procedure StopAutoSync(); constructor Create(const AToken: string); end; TBusinessServiceFactory = class public class function GetAuthService(): TAuthService; class function GetWorkOrderService(const Token: string): TWorkOrderService; class function GetDeviceService(): TDeviceService; class function GetSyncService(const Token: string): TSyncService; class function GetDeviceConfigService(): TDeviceConfigService; class function GetProductionReportingService(const Token: string): TProductionReportingService; class function GetDataAccessService(): TDataAccessService; end; TDeviceConfigService = class private FDeviceID: string; FFactoryCode: string; FPC: string; FLine: string; FLineNum: string; FKB: string; FUser: string; FPassword: string; public function LoadDeviceConfig(): Boolean; function SaveDeviceConfig(): Boolean; function GetServerURL(): string; function GetFactoryCode(): string; function GetProductionLine(): string; function GetOperatorStation(): string; function ValidateConfig(): TValidationResult; property DeviceID: string read FDeviceID write FDeviceID; property FactoryCode: string read FFactoryCode write FFactoryCode; property PC: string read FPC write FPC; property Line: string read FLine write FLine; property LineNum: string read FLineNum write FLineNum; property KB: string read FKB write FKB; property User: string read FUser write FUser; property Password: string read FPassword write FPassword; constructor Create(); end; TProductionReportingService = class private FToken: string; public 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; constructor Create(const AToken: string); end; TDataAccessService = class public 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; constructor Create(); end; implementation { TAuthResult } procedure TAuthResult.Clear; begin Success := False; UserID := ''; UserName := ''; Token := ''; ErrorMessage := ''; end; class function TAuthResult.CreateSuccess(const AUserID, AUserName, AToken: string): TAuthResult; begin Result.Clear; Result.Success := True; Result.UserID := AUserID; Result.UserName := AUserName; Result.Token := AToken; end; class function TAuthResult.CreateFailure(const AErrorMessage: string): TAuthResult; begin Result.Clear; Result.Success := False; Result.ErrorMessage := AErrorMessage; end; { TWorkOrderInfo } procedure TWorkOrderInfo.Clear; begin OrderID := ''; OrderNumber := ''; MaterialID := ''; MaterialName := ''; Quantity := 0; Status := ''; CreateTime := 0; end; { TWorkOrderEntry } procedure TWorkOrderEntry.Clear; begin EntryID := ''; OrderID := ''; ProcessID := ''; ProcessName := ''; Quantity := 0; Status := ''; end; { TDeviceStatus } procedure TDeviceStatus.Clear; begin DeviceID := ''; DeviceName := ''; IPAddress := ''; Port := 0; Status := ''; LastHeartbeat := 0; end; { TAuthService } constructor TAuthService.Create; begin FBaseURL := Config.GetServerURL; FTimeout := Config.GetTimeout; end; function TAuthService.Login(const UserID, Password: string): TAuthResult; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('AuthService.Login', UserID); try LogManager.InfoCategory(lcSecurity, 'Login attempt for user: %s', [UserID]); try // 调用KSoap或REST API进行登录 Result := TAuthResult.CreateSuccess(UserID, 'Test User', 'test-token-123'); LogManager.InfoCategory(lcSecurity, 'Login successful for user: %s', [UserID]); except on E: Exception do begin LogManager.ErrorCategory(lcSecurity, 'Login failed: %s', [E.Message]); Result := TAuthResult.CreateFailure(E.Message); end; end; finally PerfLogger.Free; end; end; function TAuthService.Logout(const Token: string): Boolean; begin LogManager.InfoCategory(lcSecurity, 'Logout with token: %s', [Token]); Result := True; end; function TAuthService.RefreshToken(const Token: string): string; begin LogManager.InfoCategory(lcSecurity, 'Refresh token: %s', [Token]); Result := 'refreshed-token-' + IntToStr(Random(1000)); end; function TAuthService.ValidateToken(const Token: string): Boolean; begin LogManager.DebugCategory(lcSecurity, 'Validate token: %s', [Token]); Result := True; end; { TWorkOrderService } constructor TWorkOrderService.Create(const AToken: string); begin FBaseURL := Config.GetServerURL; FToken := AToken; end; function TWorkOrderService.GetWorkOrderList(const Status: string = ''): TArray; var Info: TWorkOrderInfo; PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('WorkOrderService.GetWorkOrderList', Status); try LogManager.InfoCategory(lcBusiness, 'Get work order list, status: %s', [Status]); // 模拟数据 SetLength(Result, 2); Info.Clear; Info.OrderID := '1'; Info.OrderNumber := 'WO-2026-001'; Info.MaterialID := 'MAT-001'; Info.MaterialName := '测试物料'; Info.Quantity := 1000; Info.Status := 'A'; Info.CreateTime := Now; Result[0] := Info; Info.Clear; Info.OrderID := '2'; Info.OrderNumber := 'WO-2026-002'; Info.MaterialID := 'MAT-002'; Info.MaterialName := '测试物料2'; Info.Quantity := 500; Info.Status := 'B'; Info.CreateTime := Now - 1; Result[1] := Info; finally PerfLogger.Free; end; end; function TWorkOrderService.GetWorkOrderDetail(const OrderID: string): TWorkOrderInfo; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('WorkOrderService.GetWorkOrderDetail', OrderID); try LogManager.InfoCategory(lcBusiness, 'Get work order detail: %s', [OrderID]); Result.Clear; Result.OrderID := OrderID; Result.OrderNumber := 'WO-2026-001'; Result.MaterialID := 'MAT-001'; Result.MaterialName := '测试物料'; Result.Quantity := 1000; Result.Status := 'A'; Result.CreateTime := Now; finally PerfLogger.Free; end; end; function TWorkOrderService.GetWorkOrderEntries(const OrderID: string): TArray; var Entry: TWorkOrderEntry; begin LogManager.InfoCategory(lcBusiness, 'Get work order entries: %s', [OrderID]); SetLength(Result, 2); Entry.Clear; Entry.EntryID := '1'; Entry.OrderID := OrderID; Entry.ProcessID := '101'; Entry.ProcessName := '装配'; Entry.Quantity := 500; Entry.Status := 'A'; Result[0] := Entry; Entry.Clear; Entry.EntryID := '2'; Entry.OrderID := OrderID; Entry.ProcessID := '102'; Entry.ProcessName := '测试'; Entry.Quantity := 300; Entry.Status := 'B'; Result[1] := Entry; end; function TWorkOrderService.CreateWorkOrder(const OrderInfo: TWorkOrderInfo): string; begin LogManager.InfoCategory(lcBusiness, 'Create work order: %s', [OrderInfo.OrderNumber]); Result := 'NEW-ORDER-' + IntToStr(Random(10000)); end; function TWorkOrderService.UpdateWorkOrderStatus(const OrderID, Status: string): Boolean; begin LogManager.InfoCategory(lcBusiness, 'Update work order status: %s -> %s', [OrderID, Status]); Result := True; end; function TWorkOrderService.ReportProduction(const OrderID, ProcessID, Quantity: string): Boolean; begin LogManager.InfoCategory(lcBusiness, 'Report production: Order=%s, Process=%s, Qty=%s', [OrderID, ProcessID, Quantity]); Result := True; end; { TDeviceService } constructor TDeviceService.Create; begin FDevices := TDictionary.Create; // 初始化设备 - 从配置管理器读取 var Status: TDeviceStatus; Status.Clear; Status.DeviceID := 'PLC-001'; Status.DeviceName := '主PLC'; Status.IPAddress := Config.GetPLCHost; Status.Port := Config.GetPLCPort; Status.Status := 'Online'; Status.LastHeartbeat := Now; FDevices.Add(Status.DeviceID, Status); Status.Clear; Status.DeviceID := 'PLC-002'; Status.DeviceName := '辅助PLC'; Status.IPAddress := Config.GetPLCHost; // 可以设置为另一个PLC地址 Status.Port := Config.GetPLCPort; Status.Status := 'Online'; Status.LastHeartbeat := Now; FDevices.Add(Status.DeviceID, Status); end; destructor TDeviceService.Destroy; begin FDevices.Free; inherited; end; function TDeviceService.GetDeviceStatus(const DeviceID: string): TDeviceStatus; var Status: TDeviceStatus; begin LogManager.InfoCategory(lcDevice, 'Get device status: %s', [DeviceID]); if FDevices.TryGetValue(DeviceID, Status) then Result := Status else begin Result.Clear; Result.DeviceID := DeviceID; Result.Status := 'Offline'; end; end; function TDeviceService.GetAllDevices(): TArray; var Status: TDeviceStatus; Count, I: Integer; begin LogManager.InfoCategory(lcDevice, 'Get all devices'); Count := FDevices.Count; SetLength(Result, Count); I := 0; for Status in FDevices.Values do begin Result[I] := Status; Inc(I); end; end; function TDeviceService.ConnectDevice(const DeviceID: string): Boolean; begin LogManager.InfoCategory(lcDevice, 'Connect device: %s', [DeviceID]); Result := True; if FDevices.ContainsKey(DeviceID) then begin var Status := FDevices[DeviceID]; Status.Status := 'Online'; Status.LastHeartbeat := Now; FDevices.AddOrSetValue(DeviceID, Status); end; end; function TDeviceService.DisconnectDevice(const DeviceID: string): Boolean; begin LogManager.InfoCategory(lcDevice, 'Disconnect device: %s', [DeviceID]); Result := True; if FDevices.ContainsKey(DeviceID) then begin var Status := FDevices[DeviceID]; Status.Status := 'Offline'; FDevices.AddOrSetValue(DeviceID, Status); end; end; function TDeviceService.SendCommand(const DeviceID, Command: string): string; begin LogManager.InfoCategory(lcDevice, 'Send command to device %s: %s', [DeviceID, Command]); Result := 'OK: Command executed'; end; function TDeviceService.GetDeviceInfo(const DeviceID: string): TJSONObject; begin LogManager.InfoCategory(lcDevice, 'Get device info: %s', [DeviceID]); Result := TJSONObject.Create; Result.AddPair('deviceId', DeviceID); Result.AddPair('deviceName', 'Test Device'); Result.AddPair('status', 'Online'); end; { TSyncService } constructor TSyncService.Create(const AToken: string); begin FBaseURL := Config.GetServerURL; FToken := AToken; FIsSyncing := False; end; function TSyncService.SyncData(const Data: TJSONObject): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('SyncService.SyncData'); try LogManager.InfoCategory(lcNetwork, 'Sync data'); Result := True; finally PerfLogger.Free; end; end; function TSyncService.SyncBatchData(const DataArray: TJSONArray): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('SyncService.SyncBatchData', Format('count=%d', [DataArray.Count])); try LogManager.InfoCategory(lcNetwork, 'Sync batch data, count: %d', [DataArray.Count]); Result := True; finally PerfLogger.Free; end; end; function TSyncService.GetSyncStatus(): TJSONObject; begin LogManager.InfoCategory(lcNetwork, 'Get sync status'); Result := TJSONObject.Create; Result.AddPair('lastSync', FormatDateTime('yyyy-mm-dd hh:nn:ss', Now)); Result.AddPair('success', TJSONBool.Create(True)); Result.AddPair('pendingCount', TJSONNumber.Create(0)); end; function TSyncService.RetryFailedSyncs(): Integer; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('SyncService.RetryFailedSyncs'); try LogManager.InfoCategory(lcNetwork, 'Retry failed syncs'); Result := 0; finally PerfLogger.Free; end; end; procedure TSyncService.StartAutoSync(IntervalMS: Integer); begin LogManager.InfoCategory(lcNetwork, 'Start auto sync, interval: %d ms', [IntervalMS]); FIsSyncing := True; end; procedure TSyncService.StopAutoSync; begin LogManager.InfoCategory(lcNetwork, 'Stop auto sync'); FIsSyncing := False; end; { TBusinessServiceFactory } class function TBusinessServiceFactory.GetAuthService(): TAuthService; begin Result := TAuthService.Create; end; class function TBusinessServiceFactory.GetWorkOrderService(const Token: string): TWorkOrderService; begin Result := TWorkOrderService.Create(Token); end; class function TBusinessServiceFactory.GetDeviceService(): TDeviceService; begin Result := TDeviceService.Create; end; class function TBusinessServiceFactory.GetSyncService(const Token: string): TSyncService; begin Result := TSyncService.Create(Token); end; class function TBusinessServiceFactory.GetDeviceConfigService(): TDeviceConfigService; begin Result := TDeviceConfigService.Create; end; class function TBusinessServiceFactory.GetProductionReportingService(const Token: string): TProductionReportingService; begin Result := TProductionReportingService.Create(Token); end; class function TBusinessServiceFactory.GetDataAccessService(): TDataAccessService; begin Result := TDataAccessService.Create; end; { TDeviceConfigService } constructor TDeviceConfigService.Create; begin inherited; FDeviceID := ''; FFactoryCode := ''; FPC := ''; FLine := ''; FLineNum := ''; FKB := ''; FUser := ''; FPassword := ''; end; function TDeviceConfigService.LoadDeviceConfig(): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('DeviceConfigService.LoadDeviceConfig'); try LogManager.InfoCategory(lcBusiness, 'Loading device config'); Result := True; // 从配置管理器加载设备配置 FDeviceID := Config.GetServerURL; FFactoryCode := ''; FLine := ''; FLineNum := ''; FKB := ''; finally PerfLogger.Free; end; end; function TDeviceConfigService.SaveDeviceConfig(): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('DeviceConfigService.SaveDeviceConfig'); try LogManager.InfoCategory(lcBusiness, 'Saving device config'); Result := True; finally PerfLogger.Free; end; end; function TDeviceConfigService.GetServerURL(): string; begin Result := Config.GetServerURL; end; function TDeviceConfigService.GetFactoryCode(): string; begin Result := FFactoryCode; end; function TDeviceConfigService.GetProductionLine(): string; begin Result := FLine; end; function TDeviceConfigService.GetOperatorStation(): string; begin Result := FKB; end; function TDeviceConfigService.ValidateConfig(): TValidationResult; begin if FFactoryCode = '' then Exit(TValidationResult.Failure('FactoryCode', 'Factory code cannot be empty')); if FLine = '' then Exit(TValidationResult.Failure('Line', 'Production line cannot be empty')); if FUser = '' then Exit(TValidationResult.Failure('User', 'User cannot be empty')); Result := TValidationResult.Success; end; { TProductionReportingService } constructor TProductionReportingService.Create(const AToken: string); begin inherited Create; FToken := AToken; end; function TProductionReportingService.ReportProduction(const OrderID, ProcessID, Quantity, LotNo: string): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('ProductionReportingService.ReportProduction', Format('Order=%s, Process=%s, Qty=%s', [OrderID, ProcessID, Quantity])); try LogManager.InfoCategory(lcBusiness, 'Report production: Order=%s, Process=%s, Qty=%s, Lot=%s', [OrderID, ProcessID, Quantity, LotNo]); Result := True; finally PerfLogger.Free; end; end; function TProductionReportingService.ReportDefective(const OrderID, ProcessID, DefectType, Quantity: string): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('ProductionReportingService.ReportDefective', Format('Order=%s, Defect=%s, Qty=%s', [OrderID, DefectType, Quantity])); try LogManager.InfoCategory(lcBusiness, 'Report defective: Order=%s, Process=%s, Type=%s, Qty=%s', [OrderID, ProcessID, DefectType, Quantity]); Result := True; finally PerfLogger.Free; end; end; function TProductionReportingService.QueryProductionStatus(const OrderID: string): TJSONObject; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('ProductionReportingService.QueryProductionStatus', OrderID); try LogManager.InfoCategory(lcBusiness, 'Query production status: Order=%s', [OrderID]); Result := TJSONObject.Create; Result.AddPair('orderId', OrderID); Result.AddPair('status', 'InProgress'); Result.AddPair('quantity', TJSONNumber.Create(500)); finally PerfLogger.Free; end; end; function TProductionReportingService.ValidateUser(const UserID: string): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('ProductionReportingService.ValidateUser', UserID); try LogManager.InfoCategory(lcBusiness, 'Validate user: %s', [UserID]); // 调用KJSon.REST_pro_List验证用户 Result := True; // 模拟实现,实际需要调用真实的验证逻辑 finally PerfLogger.Free; end; end; function TProductionReportingService.GetWorkOrderInfo(const LotNo: string): TJSONObject; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('ProductionReportingService.GetWorkOrderInfo', LotNo); try LogManager.InfoCategory(lcBusiness, 'Get work order info: %s', [LotNo]); Result := TJSONObject.Create; Result.AddPair('lotNo', LotNo); Result.AddPair('orderId', 'ORDER-' + LotNo); Result.AddPair('status', 'Active'); finally PerfLogger.Free; end; end; function TProductionReportingService.GetProcessList(const LotNo: string): TJSONArray; var PerfLogger: TPerformanceLogger; Process: TJSONObject; begin PerfLogger := TPerformanceLogger.Create('ProductionReportingService.GetProcessList', LotNo); try LogManager.InfoCategory(lcBusiness, 'Get process list for lot: %s', [LotNo]); Result := TJSONArray.Create; // 模拟工序数据 Process := TJSONObject.Create; Process.AddPair('id', '1'); Process.AddPair('number', 'P001'); Process.AddPair('processName', '装配'); Process.AddPair('attention', 'bx'); Result.AddElement(Process); Process := TJSONObject.Create; Process.AddPair('id', '2'); Process.AddPair('number', 'P002'); Process.AddPair('processName', '测试'); Process.AddPair('attention', 'bd'); Result.AddElement(Process); finally PerfLogger.Free; end; end; function TProductionReportingService.ValidateGoodsNo(const ItemCode, ProcessCode, WorkOrderNumber: string): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('ProductionReportingService.ValidateGoodsNo', ItemCode); try LogManager.InfoCategory(lcBusiness, 'Validate goods no: Item=%s, Process=%s, WO=%s', [ItemCode, ProcessCode, WorkOrderNumber]); // 调用KJSon.REST_pro_List验证二维码 Result := True; // 模拟实现,实际需要调用真实的验证逻辑 finally PerfLogger.Free; end; end; function TProductionReportingService.SubmitProductionData(const UserID, LotNo, ProcessID, GoodsNo: string): Boolean; var PerfLogger: TPerformanceLogger; begin PerfLogger := TPerformanceLogger.Create('ProductionReportingService.SubmitProductionData', Format('User=%s, Lot=%s', [UserID, LotNo])); try LogManager.InfoCategory(lcBusiness, 'Submit production data: User=%s, Lot=%s, Process=%s, Goods=%s', [UserID, LotNo, ProcessID, GoodsNo]); // 提交生产数据到服务器 Result := True; // 模拟实现,实际需要调用真实的提交逻辑 finally PerfLogger.Free; end; end; { TDataAccessService } constructor TDataAccessService.Create; begin inherited; end; function TDataAccessService.ReadConfigValue(const ASection, AKey: string; const ADefault: string = ''): string; begin LogManager.DebugCategory(lcDatabase, 'Read config: Section=%s, Key=%s', [ASection, AKey]); Result := Config.ConfigMgr.GetString(ASection, AKey, ADefault); end; procedure TDataAccessService.WriteConfigValue(const ASection, AKey, AValue: string); begin LogManager.DebugCategory(lcDatabase, 'Write config: Section=%s, Key=%s, Value=%s', [ASection, AKey, AValue]); Config.ConfigMgr.SetString(ASection, AKey, AValue); end; function TDataAccessService.ReadDeviceInfo(const AKey: string): string; begin Result := ReadConfigValue('设备信息', AKey, ''); end; function TDataAccessService.ReadProductionParams(const AKey: string): string; begin Result := ReadConfigValue('主要参数', AKey, ''); end; function TDataAccessService.ReadAlarmConfig(const AKey: string): string; begin Result := ReadConfigValue('报警灯', AKey, ''); end; end.