Files
2026-05-07 20:25:34 +08:00

986 lines
37 KiB
ObjectPascal
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
unit uDM;
{
================================================
数据模块单元 - uDM.pas
================================================
【模块说明】
本单元是应用程序的核心数据模块(TDataModule),负责:
- 管理主从表结构的数据操作
- 提供内存表(MemTable)的CRUD功能
- 处理业务数据的持久化和加载
- 管理工单和批次记录
【数据结构】
- FDMemMain: 主表,存储工单批次等核心业务数据
- FDMemDetail: 从表,存储详细生产记录
- FDMemTable1: 配置表,存储系统配置和键值对
【主要功能】
- 主从表数据插入、删除、更新操作
- 内存表数据加载和保存
- 配置信息的读写管理
- 后台数据同步线程
【使用注意】
- 使用FireDAC内存表支持离线操作
- 数据变更后需要调用SaveMain/SaveDetail保存
- 线程安全:TDbSoapThread用于后台数据同步
【版本信息】
- 创建时间: 2024年
- 最后修改: 2026年4月
- 版本: 1.0
================================================
}
interface
uses
System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,System.Variants,
FireDAC.DApt.Intf, FireDAC.Stan.StorageBin, FireDAC.Stan.StorageJSON, Data.DB,
FireDAC.Comp.DataSet, FireDAC.Comp.Client,FMX.TabControl,FMX.Grid,System.JSON,
System.ImageList, FMX.ImgList,uKsoap,Winapi.ActiveX,uSafelog,FMX.Dialogs,
Vcl.ImgList, Vcl.Controls, uExceptionHandler;
type
TDbSoapThread = class(TThread)
private
protected
procedure Execute; override;
public
constructor Create;
end;
TDM = class(TDataModule)
FDMemTable1: TFDMemTable;
FDMemTable1ID: TIntegerField;
FDMemTable1TabName: TStringField;
FDMemTable1KeyName: TStringField;
FDMemTable1KeyDesc: TStringField;
FDMemTable1KeyValue: TStringField;
FDStanStorageJSONLink1: TFDStanStorageJSONLink;
ImageList1: TImageList;
FDStanStorageBinLink1: TFDStanStorageBinLink;
FDMemMain: TFDMemTable;
FDMemDetail: TFDMemTable;
procedure DataModuleCreate(Sender: TObject);
private
function CreateMainTable():boolean;
function CreateDetailTable():boolean;
public
MainUI,DataOpline,Operate:Integer;
procedure MemTableLoadTab(TabName:string;GridFrame:TStringGrid);
procedure MemTableSaveTab(GridFrame:TStringGrid);
procedure MemTableReadTabList(var Strings: TStrings);
function MemTableReadKeyValue(TabName,KeyName:string):string;
procedure MemTableWriteKeyValue(TabName,KeyName,Value:string);
procedure MemTableWriteKey(TabName,KeyName:string);
procedure ClearBlankTab();
function TabNameExists(TabName:string):boolean;
//主从表
function InsertDetail(vId:Integer;DetailRecord:TDetailRecord):boolean;
function InsertMain(var vId:Integer;LotNoRecord:TLotNoRecord;IsOnlyMain:boolean=false):boolean;
function InsertQtyTime(vID,vP_ID,vP_ACT_QTY,vP_LINE_SPEED,vP_BK1,vP_BK2,vP_BK3:string):boolean;
function UpdateMainId(vID:Integer;vP_ID:string;Inserted:boolean):boolean;
function DeleteDetailById(vID:Integer):boolean;
function DeleteMainById(vID:Integer):boolean;
function SaveMain():boolean;
function SaveDetail():boolean;//从表
function LoadMain():boolean;
function LoadDetail():boolean; //从表
procedure Tim_Timer(sText: String);
// function SaveMainToRecord(var LotNoRecord:TLotNoRecord);
// function SaveDetailToRecord(var DetailRecord:TDetailRecord);
//InsertLotEntity(null, FACTORY_CODE, mWorkNum, mLotNum, PROCESS, PRODUCT_LINE, LINE_NUM, LOT_TYPE, "Y", ID, false);
end;
var
DM: TDM;
implementation
Uses System.StrUtils;
{%CLASSGROUP 'FMX.Controls.TControl'}
{$R *.dfm}
function TDM.CreateMainTable():boolean;
begin
FDMemMain.Close;
with FDMemMain.FieldDefs do
begin
Clear;
Add('ID', ftAutoInc);
Add('P_ORG_CODE',ftString,30,false);
Add('P_NUM',ftString,30,false);
Add('P_LOT',ftString,30,false);
Add('P_PC',ftString,30,false);
Add('P_LINE',ftString,30,false);
Add('P_LINE_NUM',ftString,30,false);
Add('P_LOT_TYPE',ftString,30,false);
Add('P_BKfile',ftString,30,false);
Add('P_Buffer',ftString,30,false);
Add('P_DIE_NAME',ftString,30,false);
Add('P_Enable',ftString,30,false);
Add('P_MESH',ftString,30,false);
Add('P_COUNTERPOINT_MODE',ftString,30,false);
Add('P_SHORT_CIRCUIT',ftString,30,false);
Add('P_CREATION_DATE',ftString,30,false);
Add('P_TROLLEY_NUM',ftString,30,false);
Add('P_TROLLEY_FLAG',ftString,30,false);
Add('P_COPPER_MODEL',ftString,30,false);
Add('P_COMP_PROGRAM',ftString,30,false);
Add('P_COMP_AREA',ftString,30,false);
Add('P_PLATE_WIDTH',ftString,30,false);
Add('P_PLATE_HEIGHT',ftString,30,false);
Add('P_JET_FLOW',ftString,30,false);
Add('P_SIDE',ftString,30,false);
Add('P_DRY_FILM_TYPE',ftString,30,false);
Add('P_NEGATIVE',ftString,30,false);
Add('P_ID',ftString,30,false);
Add('P_LINE_SPEED',ftSingle,0,false);
Add('P_ELE_CUR_DENSITY',ftSingle,0,false);
Add('P_ELE_AREA1',ftSingle,0,false);
Add('P_ELE_AREA2',ftSingle,0,false);
Add('P_COM_TEMPERATURE',ftSingle,0,false);
Add('P_PRODUCT_PRESSURE',ftSingle,0,false);
Add('P_PREHEATING_SEC',ftSingle,0,false);
Add('P_COMPRESS_SEC',ftSingle,0,false);
Add('P_STAMPING_DEPTH',ftSingle,0,false);
Add('P_DIE_USE_NUM',ftSingle,0,false);
Add('P_NUM_PER_ARR',ftSingle,0,false);
Add('P_UPPER_PRESSURE',ftSingle,0,false);
Add('P_DOWN_PRESSURE',ftSingle,0,false);
Add('P_SLICKER_ANGLE',ftSingle,0,false);
Add('P_INK_KNIFE_ANGLE',ftSingle,0,false);
Add('P_SLICKER_SPEED',ftSingle,0,false);
Add('P_INK_KNIFE_SPEED',ftSingle,0,false);
Add('P_NET_SPACING',ftSingle,0,false);
Add('P_EXPOSURE_TIME',ftSingle,0,false);
Add('P_SLAB_THICKNESS',ftSingle,0,false);
Add('P_JE_SETUP',ftSingle,0,false);
Add('P_EXPOSURE_ENERGY',ftSingle,0,false);
Add('P_DEVELOP_PRESSURE',ftSingle,0,false);
Add('P_ETCH_FACTOR',ftSingle,0,false);
Add('P_RESOLUTION',ftSingle,0,false);
Add('P_SLICKER_PRESSURE',ftSingle,0,false);
Add('P_INK_KNIFE_PRESSURE',ftSingle,0,false);
Add('P_OFF_NET',ftSingle,0,false);
Add('P_SLICKER_DEPTH',ftSingle,0,false);
Add('P_INK_RETURN_KNIFE_DEPTH',ftSingle,0,false);
Add('Inserted',ftBoolean,0,false);
Add('IsOnlyMain',ftBoolean,0,false);
end;
FDMemMain.CreateDataSet();
end;
function TDM.CreateDetailTable():boolean;
begin
FDMemDetail.Close;
with FDMemDetail.FieldDefs do
begin
Clear;
Add('ID', ftAutoInc);
Add('ParentID',ftInteger,0,false);
Add('P_ORG_CODE',ftString,30,false);
Add('P_BC',ftString,30,false);
Add('P_LOT',ftString,30,false);
Add('P_PC',ftString,30,false);
Add('P_LINE',ftString,30,false);
Add('P_LINE_NUM',ftString,30,false);
Add('P_LOT_TYPE',ftString,30,false);
Add('P_ID',ftString,30,false);
Add('P_TROLLEY_NUM',ftString,30,false);
Add('P_COPPER_MODEL',ftString,30,false);
Add('P_BUFFER_TYPE',ftString,30,false);
Add('P_CREATION_DATE',ftString,30,false);
Add('iNum',ftInteger,0,false); //当前记数
Add('Style',ftInteger,0,false); // 1=明细, 2=最后提交更新
Add('P_BK1',ftString,30,false);
Add('P_BK2',ftString,30,false);
Add('P_BK3',ftString,30,false);
Add('P_ACT_QTY',ftString,30,false);
Add('P_END_TIME',ftString,30,false);
Add('P_LINE_SPEED',ftString,30,false);
end;
FDMemDetail.CreateDataSet();
end;
function TDM.SaveMain():boolean;
begin
FDMemMain.CachedUpdates;
FDMemMain.CommitUpdates;
FDMemMain.SaveToFile(ExtractFilePath(Paramstr(0))+'tmpdb/main.dat',sfBinary);
end;
function TDM.SaveDetail():boolean;//从表
begin
FDMemDetail.CachedUpdates;
FDMemDetail.CommitUpdates;
FDMemDetail.SaveToFile(ExtractFilePath(Paramstr(0))+'tmpdb/Detail.dat',sfBinary);
end;
function TDM.LoadMain():boolean;
var
sFileName, FLogFileDir:string;
begin
FLogFileDir := ExtractFilePath(Paramstr(0))+'tmpdb';
if not DirectoryExists(FLogFileDir) then
if not ForceDirectories(FLogFileDir) then //创建目录
begin
RaiseDataException('tmpdb路径错误,数据类对象不能被创建', 1001);
end;
sFileName:=ExtractFilePath(Paramstr(0))+'tmpdb/main.dat';
if FileExists(sFileName) then
begin
FDMemMain.LoadFromFile(sFileName,sfBinary);
WorkLog.MessageInfo('主表记录数:%d',[FDMemMain.RecordCount]);
end;
end;
function TDM.LoadDetail():boolean; //从表
var
sFileName:string;
begin
sFileName:=ExtractFilePath(Paramstr(0))+'tmpdb/Detail.dat';
if FileExists(sFileName) then
begin
FDMemDetail.LoadFromFile(ExtractFilePath(Paramstr(0))+'tmpdb/Detail.dat',sfBinary);
WorkLog.MessageInfo('从表记录数:%d',[FDMemDetail.RecordCount]);
end;
end;
function TDM.TabNameExists(TabName:string):boolean;
begin
Result:=FDMemTable1.Locate('TabName',TabName);
end;
procedure TDM.DataModuleCreate(Sender: TObject);
begin
if FileExists(ExtractFilePath(Paramstr(0))+'system.json') then
FDMemTable1.LoadFromFile(ExtractFilePath(Paramstr(0))+'system.json');
FDMemTable1.LogChanges := False;
FDMemTable1.Active:=true;
FDMemTable1.DisableControls;
with FDMemMain do
begin
LogChanges := False;
CachedUpdates:=false;
fetchoptions.RecsMax:=300000;
resourceoptions.SilentMode:=true;
UpdateOptions.LockMode:=lmNone;
UpdateOptions.LockPoint:=lpDeferred;
UpdateOptions.FetchGeneratorsPoint:=gpImmediate;
DisableControls;
CreateMainTable();
Active:=true;
end;
with FDMemDetail do
begin
LogChanges := False;
CachedUpdates:=false;
fetchoptions.RecsMax:=300000;
resourceoptions.SilentMode:=true;
UpdateOptions.LockMode:=lmNone;
UpdateOptions.LockPoint:=lpDeferred;
UpdateOptions.FetchGeneratorsPoint:=gpImmediate;
DisableControls;
CreateDetailTable();
Active:=true;
end;
end;
function TDM.DeleteDetailById(vID:Integer):boolean;
begin
System.MonitorEnter(FDMemDetail);
try
with FDMemDetail do //标记已插入
begin
if Locate('ID',vID) then
begin
delete;
SaveDetail;
end;
end;
finally
System.MonitorExit(FDMemDetail);
end;
end;
function TDM.DeleteMainById(vID:Integer):boolean;
begin
System.MonitorEnter(FDMemMain);
try
with FDMemMain do //标记已插入
begin
if Locate('ID',vID) then
begin
delete;
SaveMain;
end;
end;
finally
System.MonitorExit(FDMemMain);
end;
end;
procedure TDM.MemTableLoadTab(TabName:string;GridFrame:TStringGrid);
var
i:integer;
begin
with FDMemTable1 do
begin
First;
GridFrame.BeginUpdate;
i:=0;
while not Eof do
begin
if FieldByName('TabName').AsString=TabName then
begin
GridFrame.Cells[0,i]:=FieldByName('Id').AsString;
GridFrame.Cells[1,i]:=FieldByName('KeyName').AsString;
GridFrame.Cells[2,i]:=FieldByName('KeyDesc').AsString;
GridFrame.Cells[3,i]:=FieldByName('KeyValue').AsString;
inc(i);
end;
Next;
end;
GridFrame.EndUpdate;
end;
end;
procedure TDM.ClearBlankTab(); //当9个键值都为空时,删除掉整个TAB面的数据
var
TmpTabName:TStrings;
i:integer;
begin
with FDMemTable1 do
begin
TmpTabName:=TStringlist.Create;
MemTableReadTabList(TmpTabName);
for i := TmpTabName.Count-1 downto 0 do //去掉有数据的Tab
begin
First;
while not Eof do
begin
if FieldByName('TabName').AsString=TmpTabName.Strings[i] then
begin
if (FieldByName('KeyName').AsString<>'') or (FieldByName('KeyDesc').AsString<>'')
or (FieldByName('KeyValue').AsString<>'') then //有数据
begin
TmpTabName.Delete(i);
break;
end;
end;
Next;
end;
end;
//删除无数据的Tab
for i := TmpTabName.Count-1 downto 0 do //去掉有数据的Tab
begin
First;
while not Eof do
begin
if FieldByName('TabName').AsString=TmpTabName.Strings[i] then
begin
delete;
end;
Next;
end;
end;
end;
end;
procedure TDM.MemTableSaveTab(GridFrame:TStringGrid);
var
i:integer;
begin
for i := 0 to GridFrame.RowCount-1 do
begin
with FDMemTable1 do
begin
if trim(GridFrame.Cells[0,i])<>'' then
if Locate('id',GridFrame.Cells[0,i]) then
begin
Edit;
FieldByName('KeyName').AsString:=Trim(GridFrame.Cells[1,i]);
FieldByName('KeyDesc').AsString:=Trim(GridFrame.Cells[2,i]);
FieldByName('KeyValue').AsString:=Trim(GridFrame.Cells[3,i]).Replace('',',');
Post;
//if (FieldByName('KeyName').AsString='') and (FieldByName('KeyDesc').AsString='')
//and (FieldByName('KeyValue').AsString='') then
//delete;
end;
end;
end;
ClearBlankTab;
FDMemTable1.MergeChangeLog;
FDMemTable1.ApplyUpdates(0);
end;
procedure TDM.MemTableWriteKey(TabName,KeyName:string);
begin
with FDMemTable1 do
begin
Append;
FieldByName('TabName').AsString:=TabName;
FieldByName('KeyName').AsString:=KeyName;
Post;
end;
end;
function TDM.MemTableReadKeyValue(TabName,KeyName:string):string;
begin
Result:='';
if (TabName<>'') and (KeyName<>'') then
begin
if FDMemTable1.Locate('TabName;KeyName',vararrayof([TabName,KeyName]),[]) then
Result:=FDMemTable1.FieldByName('KeyValue').AsString;
end;
end;
procedure TDM.MemTableWriteKeyValue(TabName,KeyName,Value:string);
begin
if (TabName<>'') and (KeyName<>'') and (Value<>'') then
begin
if FDMemTable1.Locate('TabName;KeyName',vararrayof([TabName,KeyName]),[]) then
begin
FDMemTable1.Edit;
FDMemTable1.FieldByName('KeyValue').AsString:= Value;
FDMemTable1.Post;
fdmemtable1.SaveToFile(ExtractFilePath(Paramstr(0))+'system.json');
WorkLog.MessageInfo(Value+',数据保存成功');
end;
end;
end;
procedure TDM.MemTableReadTabList(var Strings: TStrings);
begin
FDMemTable1.First;
Strings.Clear;
while not FDMemTable1.Eof do
begin
if Strings.IndexOf(FDMemTable1.FieldByName('TabName').AsString)<0 then
Strings.Add(FDMemTable1.FieldByName('TabName').AsString);
FDMemTable1.Next;
end;
end;
procedure JsonToDataSet(AJson: string; ADataset: TDataSet);
var
jDataSet: TJSONArray;
jRecord: TJSONObject;
i, j: Integer;
begin
if (AJson = '') or (ADataset = nil) or (not ADataset.Active) then Exit;
jDataSet := TJSONObject.Create.ParseJSONValue(AJson, True) as TJSONArray;
for i :=0 to jDataSet.Size -1 do
begin
ADataset.Append;
jRecord := jDataSet.Get(i) as TJSONObject;
for j :=0 to ADataset.FieldCount -1 do
ADataset.Fields[j].Text := jRecord.GetValue(ADataset.Fields[j].FieldName).ToString;
ADataset.Post;
end;
end;
function DataSetToJson(ADataset: TDataSet): string;
var
LRecord: string;
LField: TField;
i: integer;
begin
Result := '';
if (not ADataset.Active) or (ADataset.IsEmpty) then Exit;
Result := '[';
ADataset.First;
while not ADataset.Eof do
begin
for i :=0 to ADataset.FieldCount -1 do
begin
LField := ADataset.Fields[i];
if LRecord = '' then
LRecord := '{"' + LField.FieldName + '":"' + LField.Text + '"'
else
LRecord := LRecord + ',"' + LField.FieldName + '":"' + LField.Text + '"';
if i = ADataset.FieldCount -1 then
begin
LRecord := LRecord + '}';
if Result = '[' then
Result := Result + LRecord
else
Result := Result + ',' + LRecord;
LRecord := '';
end;
end;
ADataset.Next;
end;
Result := Result + ']';
end;
function TDM.InsertQtyTime(vID,vP_ID,vP_ACT_QTY,vP_LINE_SPEED,vP_BK1,vP_BK2,vP_BK3:string):boolean;
begin
System.MonitorEnter(FDMemDetail);
try
WITH FDMemDetail DO
BEGIN
Append;
FieldbyName('P_ID').AsString:=vP_ID;
FieldbyName('P_LINE_SPEED').AsString:=vP_LINE_SPEED;
FieldbyName('P_BK1').AsString:=vP_BK1;
FieldbyName('P_BK2').AsString:=vP_BK2;
FieldbyName('P_BK3').AsString:=vP_BK3;
FieldbyName('P_ACT_QTY').AsString:=vP_ACT_QTY;
FieldbyName('P_END_TIME').AsString:=FormatDateTime('yyyymmdd hh:mm:ss',Now);
FieldbyName('Style').AsInteger:=2;
FieldByName('ParentId').AsString:=vID;
Post;
END;
finally
SaveDetail();
System.MonitorExit(FDMemDetail);
end;
end;
function TDM.InsertDetail(vId:Integer;DetailRecord:TDetailRecord):boolean; //
begin
System.MonitorEnter(FDMemDetail);
try
WITH FDMemDetail DO
BEGIN
Append;
FieldbyName('ParentID').AsInteger:=vId;
FieldbyName('P_ORG_CODE').AsString:=DetailRecord.P_ORG_CODE;
FieldbyName('P_BC').AsString:=DetailRecord.P_BC;
FieldbyName('P_LOT').AsString:=DetailRecord.P_LOT;
FieldbyName('P_PC').AsString:=DetailRecord.P_PC;
FieldbyName('P_LINE').AsString:=DetailRecord.P_LINE;
FieldbyName('P_LINE_NUM').AsString:=DetailRecord.P_LINE_NUM;
FieldbyName('P_LOT_TYPE').AsString:=DetailRecord.P_LOT_TYPE;
FieldbyName('P_ID').AsString:=DetailRecord.P_ID;
FieldbyName('P_TROLLEY_NUM').AsString:=DetailRecord.P_TROLLEY_NUM;
FieldbyName('P_COPPER_MODEL').AsString:=DetailRecord.P_COPPER_MODEL;
FieldbyName('P_BUFFER_TYPE').AsString:=DetailRecord.P_BUFFER_TYPE;
FieldbyName('P_CREATION_DATE').AsString:=DetailRecord.P_CREATION_DATE;
FieldbyName('Style').Index:=1;
Post;
END;
finally
SaveDetail();
System.MonitorExit(FDMemDetail);
end;
END;
function TDM.InsertMain(var vId:Integer;LotNoRecord:TLotNoRecord;IsOnlyMain:boolean=false):boolean;
BEGIN
Result:=false;
System.MonitorEnter(FDMemMain);
try
WITH FDMemMain DO
BEGIN
Append;
FieldByName('P_ORG_CODE').AsString:=LotNoRecord.P_ORG_CODE;
FieldByName('P_NUM').AsString:=LotNoRecord.P_NUM;
FieldByName('P_LOT').AsString:=LotNoRecord.P_LOT;
FieldByName('P_PC').AsString:=LotNoRecord.P_PC;
FieldByName('P_LINE').AsString:=LotNoRecord.P_LINE;
FieldByName('P_LINE_NUM').AsString:=LotNoRecord.P_LINE_NUM;
FieldByName('P_LOT_TYPE').AsString:=LotNoRecord.P_LOT_TYPE;
FieldByName('P_BKfile').AsString:=LotNoRecord.P_BKfile;
FieldByName('P_Buffer').AsString:=LotNoRecord.P_Buffer;
FieldByName('P_DIE_NAME').AsString:=LotNoRecord.P_DIE_NAME;
FieldByName('P_Enable').AsString:=LotNoRecord.P_Enable;
FieldByName('P_MESH').AsString:=LotNoRecord.P_MESH;
FieldByName('P_COUNTERPOINT_MODE').AsString:=LotNoRecord.P_COUNTERPOINT_MODE;
FieldByName('P_SHORT_CIRCUIT').AsString:=LotNoRecord.P_SHORT_CIRCUIT;
FieldByName('P_CREATION_DATE').AsString:=LotNoRecord.P_CREATION_DATE;
FieldByName('P_TROLLEY_NUM').AsString:=LotNoRecord.P_TROLLEY_NUM;
FieldByName('P_TROLLEY_FLAG').AsString:=LotNoRecord.P_TROLLEY_FLAG;
FieldByName('P_COPPER_MODEL').AsString:=LotNoRecord.P_COPPER_MODEL;
FieldByName('P_COMP_PROGRAM').AsString:=LotNoRecord.P_COMP_PROGRAM;
FieldByName('P_COMP_AREA').AsString:=LotNoRecord.P_COMP_AREA;
FieldByName('P_PLATE_WIDTH').AsString:=LotNoRecord.P_PLATE_WIDTH;
FieldByName('P_PLATE_HEIGHT').AsString:=LotNoRecord.P_PLATE_HEIGHT;
FieldByName('P_JET_FLOW').AsString:=LotNoRecord.P_JET_FLOW;
FieldByName('P_SIDE').AsString:=LotNoRecord.P_SIDE;
FieldByName('P_DRY_FILM_TYPE').AsString:=LotNoRecord.P_DRY_FILM_TYPE;
FieldByName('P_NEGATIVE').AsString:=LotNoRecord.P_NEGATIVE;
FieldByName('P_ID').AsString:=LotNoRecord.P_ID.ToString;
FieldByName('P_LINE_SPEED').AsSingle:=LotNoRecord.P_LINE_SPEED;
FieldByName('P_ELE_CUR_DENSITY').AsSingle:=LotNoRecord.P_ELE_CUR_DENSITY;
FieldByName('P_ELE_AREA1').AsSingle:=LotNoRecord.P_ELE_AREA1;
FieldByName('P_ELE_AREA2').AsSingle:=LotNoRecord.P_ELE_AREA2;
FieldByName('P_COM_TEMPERATURE').AsSingle:=LotNoRecord.P_COM_TEMPERATURE;
FieldByName('P_PRODUCT_PRESSURE').AsSingle:=LotNoRecord.P_PRODUCT_PRESSURE;
FieldByName('P_PREHEATING_SEC').AsSingle:=LotNoRecord.P_PREHEATING_SEC;
FieldByName('P_COMPRESS_SEC').AsSingle:=LotNoRecord.P_COMPRESS_SEC;
FieldByName('P_STAMPING_DEPTH').AsSingle:=LotNoRecord.P_STAMPING_DEPTH;
FieldByName('P_DIE_USE_NUM').AsSingle:=LotNoRecord.P_DIE_USE_NUM;
FieldByName('P_NUM_PER_ARR').AsSingle:=LotNoRecord.P_NUM_PER_ARR;
FieldByName('P_UPPER_PRESSURE').AsSingle:=LotNoRecord.P_UPPER_PRESSURE;
FieldByName('P_DOWN_PRESSURE').AsSingle:=LotNoRecord.P_DOWN_PRESSURE;
FieldByName('P_SLICKER_ANGLE').AsSingle:=LotNoRecord.P_SLICKER_ANGLE;
FieldByName('P_INK_KNIFE_ANGLE').AsSingle:=LotNoRecord.P_INK_KNIFE_ANGLE;
FieldByName('P_SLICKER_SPEED').AsSingle:=LotNoRecord.P_SLICKER_SPEED;
FieldByName('P_INK_KNIFE_SPEED').AsSingle:=LotNoRecord.P_INK_KNIFE_SPEED;
FieldByName('P_NET_SPACING').AsSingle:=LotNoRecord.P_NET_SPACING;
FieldByName('P_EXPOSURE_TIME').AsSingle:=LotNoRecord.P_EXPOSURE_TIME;
FieldByName('P_SLAB_THICKNESS').AsSingle:=LotNoRecord.P_SLAB_THICKNESS;
FieldByName('P_JE_SETUP').AsSingle:=LotNoRecord.P_JE_SETUP;
FieldByName('P_EXPOSURE_ENERGY').AsSingle:=LotNoRecord.P_EXPOSURE_ENERGY;
FieldByName('P_DEVELOP_PRESSURE').AsSingle:=LotNoRecord.P_DEVELOP_PRESSURE;
FieldByName('P_ETCH_FACTOR').AsSingle:=LotNoRecord.P_ETCH_FACTOR;
FieldByName('P_RESOLUTION').AsSingle:=LotNoRecord.P_RESOLUTION;
FieldByName('P_SLICKER_PRESSURE').AsSingle:=LotNoRecord.P_SLICKER_PRESSURE;
FieldByName('P_INK_KNIFE_PRESSURE').AsSingle:=LotNoRecord.P_INK_KNIFE_PRESSURE;
FieldByName('P_OFF_NET').AsSingle:=LotNoRecord.P_OFF_NET;
FieldByName('P_SLICKER_DEPTH').AsSingle:=LotNoRecord.P_SLICKER_DEPTH;
FieldByName('P_INK_RETURN_KNIFE_DEPTH').AsSingle:=LotNoRecord.P_INK_RETURN_KNIFE_DEPTH;
FieldByName('Inserted').asboolean:=false;
FieldByName('IsOnlyMain').asboolean:=IsOnlyMain;
Post;
vId:=FieldByName('ID').AsInteger;
Result:=true;
END;
finally
SaveMain();
System.MonitorExit(FDMemMain);
end;
END;
function TDM.UpdateMainId(vID:Integer;vP_ID:string;Inserted:boolean):boolean;
BEGIN
System.MonitorEnter(FDMemMain);
try
with FDMemMain do //标记已插入
begin
if FDMemMain.Locate('ID',vID) then
begin
Edit;
FieldByName('Inserted').asboolean:=Inserted;
FieldByName('P_ID').AsString:=vP_ID;
Post;
SaveMain;
end;
end;
finally
System.MonitorExit(FDMemMain);
end;
END;
////////////////////////////////////////////////////////////////////////////////////
constructor TDbSoapThread.Create();
begin
inherited Create(True);
FreeOnTerminate := True;
end;
procedure TDbSoapThread.Execute; //提交数据
VAR
vP_ID:Double;
sError:string;
vId:Integer;
bHaveNoSucced:boolean;
LotNoRecord:TLotNoRecord;
DetailRecord:TDetailRecord;
LotNoBuf,DetailBuf:TFDMemTable;
procedure CopyDataSet(AOptions:TFDCopyDataSetOptions);
begin
System.MonitorEnter(dm.FDMemMain);
try
LotNoBuf.CopyDataSet(dm.FDMemMain,AOptions);
finally
System.MonitorExit(dm.FDMemMain);
end;
System.MonitorEnter(dm.FDMemDetail);
try
DetailBuf.CopyDataSet(dm.FDMemDetail,AOptions);
finally
System.MonitorExit(dm.FDMemDetail);
end;
end;
procedure SaveMainToRecord(var vLotNoRecord:TLotNoRecord);
begin
with LotNoBuf do
begin
LotNoRecord.P_ORG_CODE:=FieldByName('P_ORG_CODE').AsString;
LotNoRecord.P_NUM:=FieldByName('P_NUM').AsString;
LotNoRecord.P_LOT:=FieldByName('P_LOT').AsString;
LotNoRecord.P_PC:=FieldByName('P_PC').AsString;
LotNoRecord.P_LINE:=FieldByName('P_LINE').AsString;
LotNoRecord.P_LINE_NUM:=FieldByName('P_LINE_NUM').AsString;
LotNoRecord.P_LOT_TYPE:=FieldByName('P_LOT_TYPE').AsString;
LotNoRecord.P_BKfile:=FieldByName('P_BKfile').AsString;
LotNoRecord.P_Buffer:=FieldByName('P_Buffer').AsString;
LotNoRecord.P_DIE_NAME:=FieldByName('P_DIE_NAME').AsString;
LotNoRecord.P_Enable:=FieldByName('P_Enable').AsString;
LotNoRecord.P_MESH:=FieldByName('P_MESH').AsString;
LotNoRecord.P_COUNTERPOINT_MODE:=FieldByName('P_COUNTERPOINT_MODE').AsString;
LotNoRecord.P_SHORT_CIRCUIT:=FieldByName('P_SHORT_CIRCUIT').AsString;
LotNoRecord.P_CREATION_DATE:=FieldByName('P_CREATION_DATE').AsString;
LotNoRecord.P_TROLLEY_NUM:=FieldByName('P_TROLLEY_NUM').AsString;
LotNoRecord.P_TROLLEY_FLAG:=FieldByName('P_TROLLEY_FLAG').AsString;
LotNoRecord.P_COPPER_MODEL:=FieldByName('P_COPPER_MODEL').AsString;
LotNoRecord.P_COMP_PROGRAM:=FieldByName('P_COMP_PROGRAM').AsString;
LotNoRecord.P_COMP_AREA:=FieldByName('P_COMP_AREA').AsString;
LotNoRecord.P_PLATE_WIDTH:=FieldByName('P_PLATE_WIDTH').AsString;
LotNoRecord.P_PLATE_HEIGHT:=FieldByName('P_PLATE_HEIGHT').AsString;
LotNoRecord.P_JET_FLOW:=FieldByName('P_JET_FLOW').AsString;
LotNoRecord.P_SIDE:=FieldByName('P_SIDE').AsString;
LotNoRecord.P_DRY_FILM_TYPE:=FieldByName('P_DRY_FILM_TYPE').AsString;
LotNoRecord.P_NEGATIVE:=FieldByName('P_NEGATIVE').AsString;
LotNoRecord.P_ID:=FieldByName('P_ID').AsFloat;
LotNoRecord.P_LINE_SPEED:=FieldByName('P_LINE_SPEED').AsSingle;
LotNoRecord.P_ELE_CUR_DENSITY:=FieldByName('P_ELE_CUR_DENSITY').AsSingle;
LotNoRecord.P_ELE_AREA1:=FieldByName('P_ELE_AREA1').AsSingle;
LotNoRecord.P_ELE_AREA2:=FieldByName('P_ELE_AREA2').AsSingle;
LotNoRecord.P_COM_TEMPERATURE:=FieldByName('P_COM_TEMPERATURE').AsSingle;
LotNoRecord.P_PRODUCT_PRESSURE:=FieldByName('P_PRODUCT_PRESSURE').AsSingle;
LotNoRecord.P_PREHEATING_SEC:=FieldByName('P_PREHEATING_SEC').AsSingle;
LotNoRecord.P_COMPRESS_SEC:=FieldByName('P_COMPRESS_SEC').AsSingle;
LotNoRecord.P_STAMPING_DEPTH:=FieldByName('P_STAMPING_DEPTH').AsSingle;
LotNoRecord.P_DIE_USE_NUM:=FieldByName('P_DIE_USE_NUM').AsSingle;
LotNoRecord.P_NUM_PER_ARR:=FieldByName('P_NUM_PER_ARR').AsSingle;
LotNoRecord.P_UPPER_PRESSURE:=FieldByName('P_UPPER_PRESSURE').AsSingle;
LotNoRecord.P_DOWN_PRESSURE:=FieldByName('P_DOWN_PRESSURE').AsSingle;
LotNoRecord.P_SLICKER_ANGLE:=FieldByName('P_SLICKER_ANGLE').AsSingle;
LotNoRecord.P_INK_KNIFE_ANGLE:=FieldByName('P_INK_KNIFE_ANGLE').AsSingle;
LotNoRecord.P_SLICKER_SPEED:=FieldByName('P_SLICKER_SPEED').AsSingle;
LotNoRecord.P_INK_KNIFE_SPEED:=FieldByName('P_INK_KNIFE_SPEED').AsSingle;
LotNoRecord.P_NET_SPACING:=FieldByName('P_NET_SPACING').AsSingle;
LotNoRecord.P_EXPOSURE_TIME:=FieldByName('P_EXPOSURE_TIME').AsSingle;
LotNoRecord.P_SLAB_THICKNESS:=FieldByName('P_SLAB_THICKNESS').AsSingle;
LotNoRecord.P_JE_SETUP:=FieldByName('P_JE_SETUP').AsSingle;
LotNoRecord.P_EXPOSURE_ENERGY:=FieldByName('P_EXPOSURE_ENERGY').AsSingle;
LotNoRecord.P_DEVELOP_PRESSURE:=FieldByName('P_DEVELOP_PRESSURE').AsSingle;
LotNoRecord.P_ETCH_FACTOR:=FieldByName('P_ETCH_FACTOR').AsSingle;
LotNoRecord.P_RESOLUTION:=FieldByName('P_RESOLUTION').AsSingle;
LotNoRecord.P_SLICKER_PRESSURE:=FieldByName('P_SLICKER_PRESSURE').AsSingle;
LotNoRecord.P_INK_KNIFE_PRESSURE:=FieldByName('P_INK_KNIFE_PRESSURE').AsSingle;
LotNoRecord.P_OFF_NET:=FieldByName('P_OFF_NET').AsSingle;
LotNoRecord.P_SLICKER_DEPTH:=FieldByName('P_SLICKER_DEPTH').AsSingle;
LotNoRecord.P_INK_RETURN_KNIFE_DEPTH:=FieldByName('P_INK_RETURN_KNIFE_DEPTH').AsSingle;
end;
end;
procedure SaveDetailToRecord(var vDetailRecord:TDetailRecord);
begin
with DetailBuf do
begin
DetailRecord.P_ORG_CODE:=FieldbyName('P_ORG_CODE').AsString;
DetailRecord.P_BC:=FieldbyName('P_BC').AsString;
DetailRecord.P_LOT:=FieldbyName('P_LOT').AsString;
DetailRecord.P_PC:=FieldbyName('P_PC').AsString;
DetailRecord.P_LINE:=FieldbyName('P_LINE').AsString;
DetailRecord.P_LINE_NUM:=FieldbyName('P_LINE_NUM').AsString;
DetailRecord.P_LOT_TYPE:=FieldbyName('P_LOT_TYPE').AsString;
DetailRecord.P_ID:=FieldbyName('P_ID').AsString;
DetailRecord.P_TROLLEY_NUM:=FieldbyName('P_TROLLEY_NUM').AsString;
DetailRecord.P_COPPER_MODEL:=FieldbyName('P_COPPER_MODEL').AsString;
DetailRecord.P_BUFFER_TYPE:=FieldbyName('P_BUFFER_TYPE').AsString;
DetailRecord.P_CREATION_DATE:=FieldbyName('P_CREATION_DATE').AsString;
end;
end;
begin
CoInitialize(nil);
LotNoBuf:=TFDMemTable.Create(nil);
DetailBuf:=TFDMemTable.Create(nil);
try
//dm.LoadMain;
//dm.LoadDetail;
CopyDataSet([coStructure,coRestart, coAppend]);
while not self.Terminated do
begin
Sleep(200);
if (LotNoBuf.RecordCount=0) and (DetailBuf.RecordCount=0) then
begin
Sleep(1000);
CopyDataSet([coRestart, coAppend]);
continue;
end;
if ((LotNoBuf.RecordCount=0) and (DetailBuf.RecordCount>0)) then //处理只有从表数据
begin
DBApiLog.MessageInfo('存在明细表数据没有提交,请处理');
//找到明细数据,并提交
DetailBuf.First;
bHaveNoSucced:=false;
while not DetailBuf.Eof do
begin
SaveDetailToRecord(DetailRecord);
DetailRecord.P_ID:=DetailBuf.FieldByName('ParentID').AsInteger.ToString;
if Ksoap.Insert_cc_wip_lot_bc_history(DetailRecord,sError) then
begin
dm.DeleteDetailById(DetailBuf.FieldByName('ID').AsInteger);
end
else
begin //提交不成功
if sError='連接數據庫服務器失败' then
begin
bHaveNoSucced:=true;
DBApiLog.MessageInfo(sError);
end
else
dm.DeleteDetailById(DetailBuf.FieldByName('ID').AsInteger);
end;
SLEEP(200);
DetailBuf.Next;
end;
continue;
end;
try
LotNoBuf.First;
while not LotNoBuf.Eof do //提交主表
begin
if (LotNoBuf.FieldByName('P_ID').AsString='0') or (LotNoBuf.FieldByName('P_ID').AsString='') then //取ID
begin
vP_ID:=Ksoap.cf_traceability_seq_f(LotNoBuf.FieldByName('P_ORG_CODE').AsString,sError);
//inc(vP_ID);////////////////////////////////
if vP_ID=0 then //取不到ID
begin
Sleep(10000);
LotNoBuf.Next;
continue;
end;
LotNoBuf.Edit;
LotNoBuf.FieldByName('P_ID').AsString:=vP_ID.ToString;
vId:=LotNoBuf.FieldByName('ID').AsInteger;
LotNoBuf.Post;
SaveMainToRecord(LotNoRecord);
LotNoRecord.P_ID:=vP_ID;
dm.UpdateMainId(vId,vP_ID.ToString,false); //更新主表ID
end
else //已有ID的,并且未插入的
begin
vId:=LotNoBuf.FieldByName('ID').AsInteger;
vP_ID:=LotNoBuf.FieldByName('P_ID').AsFloat;
if not LotNoBuf.FieldByName('Inserted').asboolean then //未提交
begin
SaveMainToRecord(LotNoRecord);
LotNoRecord.P_ID:=vP_ID;
end
else
LotNoRecord.P_ORG_CODE:='-1';
end;
//提交主表
if LotNoRecord.P_ORG_CODE<>'-1' then //提交
if Ksoap.Insert_CM_WIP_PROCESS_LINE_HISTORY_NEW(LotNoRecord,sError) then //提交主表成功
begin
if LotNoBuf.FieldByName('IsOnlyMain').asboolean then //只有主表
dm.DeleteMainById(vId)
else
dm.UpdateMainId(vId,vP_ID.ToString,True); //更新主表ID
end
else //主表提交未成功
begin
Sleep(1000);
LotNoBuf.Next;
continue;
end;
//找到明细数据,并提交
DetailBuf.First;
bHaveNoSucced:=false;
while not DetailBuf.Eof do
begin
if DetailBuf.FieldByName('ParentID').AsInteger=vId then //提交从表数据
begin
if (DetailBuf.FieldByName('Style').AsInteger=2) and (not bHaveNoSucced) then //最终提交的数据
begin
with DetailBuf do
if Ksoap.Update_qty_time_p(vP_ID.ToString,FieldByName('P_ACT_QTY').AsString,
FieldByName('P_END_TIME').AsString,FieldByName('P_LINE_SPEED').AsString,FieldByName('P_BK1').AsString,
FieldByName('P_BK2').AsString,FieldByName('P_BK3').AsString,sError) then
begin
dm.DeleteDetailById(DetailBuf.FieldByName('ID').AsInteger); //提交成功,删除该记录
dm.DeleteMainById(vId);
end;
end
else
begin
SaveDetailToRecord(DetailRecord);
DetailRecord.P_ID:=vP_ID.ToString;
if Ksoap.Insert_cc_wip_lot_bc_history(DetailRecord,sError) then
begin
dm.DeleteDetailById(DetailBuf.FieldByName('ID').AsInteger);
end
else
begin //提交不成功
if sError='連接數據庫服務器失败' then
bHaveNoSucced:=true
else
dm.DeleteDetailById(DetailBuf.FieldByName('ID').AsInteger);
end;
end;
SLEEP(400);
end;
DetailBuf.Next;
end;
LotNoBuf.Next;
Sleep(200);
end;
LotNoBuf.EmptyDataSet;
DetailBuf.EmptyDataSet;
except
workLog.Error('后台线程提交主从数据出错');
Sleep(20000);
end;
end;
finally
CoUninitialize;
DetailBuf.Free;
LotNoBuf.Free;
end;
end;
procedure TDM.Tim_Timer(sText: String);
var
sPath:string;
begin
//判断整点,就上传日志
if RightStr(sText,5)=':00:00' then //整点
begin
sPath:=TRIM(dm.MemTableReadKeyValue('主要参数','LogBakDir'));
if sPath<>'' then
CopyLogFile(sPath);
end;
end;
end.