unit uFrameBase; { ================================================ 业务框架基类单元 - uFrameBase.pas ================================================ 【模块说明】 本单元定义了所有业务框架的基类(TFrameBase),采用工厂模式设计。 用于动态创建不同的业务框架,支持多种生产线和数据采集场景。 【设计模式】 - 工厂模式:通过TFrameClass类工厂动态创建业务框架实例 - 策略模式:各具体框架实现自己的业务逻辑 【主要功能】 - 提供业务框架的标准接口和虚方法 - 支持JSON数据解析和格式化 - 提供统一的错误处理机制 - 支持PLC设备通信集成 【使用方式】 1. 继承TFrameBase创建具体业务框架 2. 重写关键虚方法实现特定业务逻辑 3. 使用RegisterClass注册框架类 4. 通过TFrameClass(factory)动态创建实例 【版本信息】 - 创建时间: 2024年 - 最后修改: 2026年4月 - 版本: 1.0 ================================================ } interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.Layouts,FMX.Objects,FMX.Edit,FMX.ListBox, System.StrUtils, uSafeLog, System.JSON; type TFrameButtonClickEvent = procedure(Sender: TObject; ButtonID: Integer) of object; TFrameBase = class(TFrame) private FOnPanelButClick: TFrameButtonClickEvent; FTypePanelInt: Integer; procedure SetTypePanelInt(const Value: Integer); { Private declarations } public GridLayout: TGridLayout; sLotNum,sGoodsNo:string; //批号的数量 JSonProcessSensorData: string; function GetRightPart(const InputStr, Delimiter: string): string; virtual; function FormatDataToJSON(const AData: string): string; virtual; function GetJSONValue(const JSONString, Key: string): string; virtual; function DefaultXN: Boolean; virtual; procedure ClearAll(); function GetRadioTxt(var sTxt:string):boolean; function GetFixture_Code():string;virtual; //返回治具ID function GetFixture_work():string;virtual; //返回原物料編號 procedure Initialize();virtual; //初始化 //填写默认值 参数1 料号API返回数据,参数二是缺省值API返回数据 procedure FillDefaultValue(sPartnumValue,sDefaultTxt:string);virtual; function F2DCodeCreate(): boolean; virtual;//連接读头 function DoExec():boolean;virtual; //执行插入主表,或打开窗体 function DoPlc():boolean;virtual;//执行plc function CheckValid(var sTxt:string):boolean;virtual; //检测输入数据的有效性 procedure Error(Option:TStyledControl;TxtError:TText;sError:string); procedure ErrorLayout(Option:TGridLayout;TxtError:TText;sError:string); procedure NumbersOnly(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);virtual;//执行plc // 事件属性 property OnPanelButClick: TFrameButtonClickEvent read FOnPanelButClick write FOnPanelButClick; // 整数属性,可添加设置逻辑 property TypePanelInt: Integer read FTypePanelInt write SetTypePanelInt default 0; end; TFrameClass = class of TFrameBase; implementation {$R *.fmx} uses uListConent, uPucFun; //取最右边的值 function TFrameBase.GetRightPart(const InputStr, Delimiter: string): string; var PosIndex: Integer; begin // 查找分隔符位置 PosIndex := Pos(Delimiter, InputStr); if PosIndex > 0 then // 找到分隔符:截取分隔符右侧内容 Result := Copy(InputStr, PosIndex + Length(Delimiter), MaxInt) else // 未找到分隔符:返回整个字符串 Result := InputStr; // WorkLog.MessageInfo(IntToStr(PosIndex)+'Result:'+Result); end; function TFrameBase.FormatDataToJSON(const AData: string): string; var TempStr: string; StartPos, EndPos: Integer; Parts: TArray; I: Integer; KeyValue: TArray; JSONObj: TJSONObject; begin TempStr := AData; // 移除波形部分 StartPos := Pos('波形:[[', TempStr); if StartPos > 0 then begin EndPos := PosEx(']]', TempStr, StartPos); if EndPos > 0 then Delete(TempStr, StartPos, EndPos - StartPos + 2); end; // 移除所有单引号 TempStr := StringReplace(TempStr, '''', '', [rfReplaceAll]); // 移除所有空格 TempStr := StringReplace(TempStr, ' ', '', [rfReplaceAll]); //统一特:殊字符 TempStr := StringReplace(TempStr, ':', ':', [rfReplaceAll]); // 使用逗号分割字符串 Parts := TempStr.Split([',']); // 创建JSON对象 JSONObj := TJSONObject.Create; try for I := 0 to High(Parts) do begin // 跳过空部分 if Parts[I] = '' then Continue; // 分割键值对 KeyValue := Parts[I].Split([':']); // 确保有键和值 if Length(KeyValue) >= 2 then begin // 处理特殊情况:硬件版本和软件版本中的b字符 if (KeyValue[0] = '硬件版本') or (KeyValue[0] = '软件版本') then KeyValue[1] := StringReplace(KeyValue[1], 'b', '', [rfReplaceAll]); // 添加到JSON对象 JSONObj.AddPair(KeyValue[0], KeyValue[1]); end; end; // 返回格式化的JSON字符串 Result := JSONObj.Format(2); // WorkLog.MessageInfo('JSONObj: %s', [JSONObj.Format(2)]); finally JSONObj.Free; end; end; function TFrameBase.GetJSONValue(const JSONString, Key: string): string; var JSONValue: TJSONValue; JSONObj: TJSONObject; Pair: TJSONPair; begin Result := ''; try // WorkLog.MessageInfo('Result1: %s, %s', [JSONString,Key]); // 解析JSON字符串 JSONValue := TJSONObject.ParseJSONValue(JSONString); if Assigned(JSONValue) then begin // WorkLog.MessageInfo('Result2: %s', [JSONValue.ToString]); try // 检查是否为JSON对象 if JSONValue is TJSONObject then begin JSONObj := TJSONObject(JSONValue); // WorkLog.MessageInfo('Result3: %s', [JSONObj.ToString]); // 使用GetValue方法获取指定键的值 if JSONObj.GetValue(Key) <> nil then begin Result := JSONObj.GetValue(Key).Value; // WorkLog.MessageInfo('Result4: %s, %s', [Key, Result]); end; end; finally JSONValue.Free; end; end; except end; WorkLog.MessageInfo('GetJSONValue: %s, %s', [Key, Result]); end; procedure TFrameBase.NumbersOnly(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); var i: Boolean; begin i := (KeyChar <= #8) or (KeyChar <= #8) and (KeyChar < #48) or (KeyChar > #57); if i then KeyChar := #0; if not (KeyChar in ['0'..'9', '.', #13]) then KeyChar := #0; if (KeyChar = '.') and (Pos('.', TEdit(Sender).Text) > 0) then KeyChar := #0; end; function TFrameBase.GetFixture_Code():string; //返回治具ID begin Result:='-1'; end; function TFrameBase.GetFixture_work():string; //返回治具ID begin Result:='-1'; end; procedure TFrameBase.ClearAll(); var I:integer; begin for I := 0 to self.ComponentCount-1 do begin if TComponent(self.Components[i]) is TEdit then begin TEdit(self.Components[i]).Text:=''; Continue; end; if TComponent(self.Components[i]) is TComboBox then TComboBox(self.Components[i]).ItemIndex:=0; end; end; procedure TFrameBase.ErrorLayout(Option:TGridLayout;TxtError:TText;sError:string); var PointA,PointB: TPointF; begin PointA:=Option.LocalToAbsolute(PointF(Option.Width, 0)); PointB:=self.LocalToAbsolute(PointF(0,0)); TxtError.Position.X:=PointA.X-PointB.X-6; TxtError.Position.y:=PointA.Y-PointB.y+4; //PointA.Y-Self.ParentControl.Position.Y-30; TxtError.Text:=sError; end; procedure TFrameBase.Error(Option:TStyledControl;TxtError:TText;sError:string); var PointA,PointB: TPointF; begin PointA:=Option.LocalToAbsolute(PointF(Option.Width,0)); PointB:=self.LocalToAbsolute(PointF(0,0)); TxtError.Position.y:=PointA.Y-PointB.y+2; TxtError.Position.X:=PointA.X-PointB.X; TxtError.Text:=sError; if sError<>'' then Option.SetFocus; end; function TFrameBase.GetRadioTxt(var sTxt:string):boolean; var RadioButton:TRadioButton; i:integer; begin Result:=true; sTxt:=''; if GridLayout<>nil then //检测TOP面,BOT面 begin for i := 0 to GridLayout.ChildrenCount-1 do //有选项没显示,返回也为真 begin RadioButton:=TRadioButton(GridLayout.Children[i]); if RadioButton.Visible then begin Result:=false; end; end; if not Result then //有显示的 for i := 0 to GridLayout.ChildrenCount-1 do begin RadioButton:=TRadioButton(GridLayout.Children[i]); if RadioButton.IsChecked then begin sTxt:=RadioButton.Text; Result:=true; end; end; end; end; procedure TFrameBase.FillDefaultValue(sPartnumValue,sDefaultTxt:string); //填写默认值 begin with TStringList.Create do try // a:= TStringList.Create; Delimiter:= ','; DelimitedText:= sDefaultTxt; // if Count>=1 then Edit6.Text:=Strings[0]; // if Count>=2 then Edit5.Text:=Strings[1]; // if Count>=3 then Edit4.Text:=Strings[2]; // if Count>=4 then Edit2.Text:=Strings[3]; // if Count>=5 then Edit9.Text:=Strings[4]; // if Count>=6 then Edit1.Text:=Strings[5]; // if Count>=7 then Edit3.Text:=Strings[6]; // if Count>=8 then Edit_KuangJi.Text:=Strings[7]; // if Count>=9 then Edit_ChengShi.Text:=Strings[8]; // if Count>=10 then Edit7.Text:=Strings[9]; finally Free; end; end; function TFrameBase.DefaultXN: Boolean; begin Result:= True; end; function TFrameBase.DoExec():boolean; begin Result:=true; // //打开窗体 // if Result then // begin // frmListConent:=TfrmListConent.Create(nil); // try //// frmListConent.LotNoRecord:=LotNoRecord; //// frmListConent.vP_ID:=LotNoRecord.P_ID; //// frmListConent.vId:=vId; //// frmListConent.Text6.Text:='更改烤架編號'; // frmListConent.ShowModal; // finally // frmListConent.Free; // end; // end; end; function TFrameBase.CheckValid(var sTxt:string):boolean; begin Result:=false; end; function TFrameBase.F2DCodeCreate(): boolean; begin Result:=false; end; function TFrameBase.DoPlc(): boolean; begin Result:=true; end; procedure TFrameBase.Initialize(); //初始化 begin FTypePanelInt := 0; // 初始化默认值 end; procedure TFrameBase.SetTypePanelInt(const Value: Integer); begin if FTypePanelInt <> Value then begin FTypePanelInt := Value; // 这里可以添加值改变时的处理逻辑 end; end; end.