瀏覽代碼

优化大项目删除清单速度

JimiZhang 3 周之前
父節點
當前提交
8baebc6111
共有 6 個文件被更改,包括 104 次插入11 次删除
  1. 9 6
      Components/SmartDataSet/Source/sdDB.pas
  2. 2 2
      DPRs/ZY/SmartCost.dof
  3. 二進制
      DPRs/ZY/SmartCost.res
  4. 6 2
      MainModule/Model/ScRations.pas
  5. 87 1
      MainUI/Forms/ScMainFrm.pas
  6. 二進制
      MainUI/Forms/ScProjFrm.dfm

+ 9 - 6
Components/SmartDataSet/Source/sdDB.pas

@@ -5744,7 +5744,8 @@ begin
   Result := FDataList.Remove(ARec) >= 0;
   // 删除记录相关的索引信息
   DeleteRecordIndex(ARec);
-  RenumberIndex(iIndex);
+  if not IsUpdating then
+    RenumberIndex(iIndex);
   Changed(ARec, sroDelete);
   DoAfterDeleteRecord(ARec);
   // 是新记录,直接删除
@@ -5855,9 +5856,9 @@ begin
   end
   else
   begin
-    ClearRecords(True);
     FActive := Value;
     FHistory.Clear;
+    ClearRecords(True);
     if Assigned(FAfterClose) then
       FAfterClose(Self);
   end;
@@ -6408,6 +6409,7 @@ begin
     Dec(FUpdateLock);
   if not IsUpdating then
   begin
+    RenumberIndex;
     FIndexList.Sort;
     try
       FKeepPosition := True;
@@ -10210,7 +10212,8 @@ begin
   if IsUpdatingRecord then
     raise EsdHistory.Create('删除操作不支持批量处理');
   // 若OperationManager.SavePiont不是最新则Reset
-  FDataSet.OperationManager.ResetWhenNecessary;
+  if FDataSet.OperationManager <> nil then
+    FDataSet.OperationManager.ResetWhenNecessary;
   HistoryRec := TsdHistoryRecord.Create(Self);
   HistoryRec.FID := LastID + 1;
   FRecList.Add(HistoryRec);
@@ -10454,8 +10457,8 @@ begin
     begin
       // 释放条件:1.如果不是关闭DataSet的过程中,则所有删除操作的记录都释放;
       //           2.如果是关闭DataSet的过程中,且是新增记录,FRec才释放
-      // 因为关闭DataSet时会释放除新增记录外所有删除的记录,而正常保存不会先释放任何记录
-      if (Rec.Operation = sroDelete) and (FDataSet.Active or Rec.FRec.New) then
+      // 因为关闭DataSet时会释放除新增记录外所有删除的记录,而正常保存不会先释放任何记录
+      if (Rec.Operation = sroDelete) and (FDataSet.Active or (FDataSet.FDeletedList.IndexOf(Rec.FRec) < 0) or Rec.FRec.New) then
         Rec.FRec.Free;
     end;
   end;
@@ -10583,7 +10586,7 @@ end;
 
 function TsdHistoryList.GetStopping: Boolean;
 begin
-  Result := FDataSet.OperationManager.Active and (FStopping > 0);
+  Result := ((FDataSet.OperationManager = nil) or FDataSet.OperationManager.Active) and (FStopping > 0);
 end;
 
 procedure TsdHistoryList.Resume;

+ 2 - 2
DPRs/ZY/SmartCost.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=10
 MinorVer=3
 Release=0
-Build=1341
+Build=1342
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=SmartCost 2025专业版
-FileVersion=10.3.0.1343
+FileVersion=10.3.0.1342
 InternalName=SmartCost
 LegalCopyright=版权所有(C) 珠海纵横创新软件有限公司 2003-2024。保留所有权利。
 LegalTrademarks=SmartCost

二進制
DPRs/ZY/SmartCost.res


+ 6 - 2
MainModule/Model/ScRations.pas

@@ -2085,7 +2085,9 @@ var
   Rec: TScRationRecord;
   lstDel: TList;
 begin
-//  GLJ.DeleteByBillsItemID(ABillsItemID);
+  // 该预算没有分摊,直接按清单查找更快
+  if not (TScProject(FProject).IsBills or TScProject(FProject).IsGD3J) then
+    GLJ.DeleteByBillsItemID(ABillsItemID);
 
   lstDel := TList.Create;
   try
@@ -2103,7 +2105,9 @@ begin
         0: iType := ExprsID_Rations;
         1: iType := ExprsID_CountPrice;
       end;
-      GLJ.DeleteByRationID(Rec.ID.AsInteger, True);
+      // 清单、三级清单有分摊,要按定额查找
+      if TScProject(FProject).IsBills or TScProject(FProject).IsGD3J then
+        GLJ.DeleteByRationID(Rec.ID.AsInteger, True);
       TScProject(FProject).Exprs.Delete(iType, Rec.ID.AsInteger);
       RAdjusts.Delete(Rec.ID.AsInteger, True);
       sdsRations.Remove(Rec);

+ 87 - 1
MainUI/Forms/ScMainFrm.pas

@@ -1147,6 +1147,7 @@ type
     procedure DoOnAfterGridRemapedPaste(Sender: TObject);
     function ExpXMLEnabled: Boolean;
     procedure CheckBackUpFileSize(Action: TAction);
+    function SelectedGLJCount: Integer;
   protected
     procedure CreateWnd; override;
     procedure AddMenuItem(const APath: string; AHandle: TNotifyEvent);
@@ -1231,7 +1232,7 @@ uses
   {$IFDEF _ScOnline}
   , ScMicroWebFrm
   {$ENDIF}
-  , ScCheckNullRationFrm;
+  , ScCheckNullRationFrm, sdDB;
 
 {$R *.dfm}
 {$R ScIcons.res}
@@ -7445,6 +7446,51 @@ begin
     and (ActiveChild.Project.Properties.StaticBills <>1);
 end;
 
+var
+  iGLJCount, iSelectedGLJCount: Integer;
+  iTime: Cardinal;
+const
+  // 1900条工料机以下,使用直接删除更快(38万条工料机中删除1900条,14秒左右)),1900以上使用批量处理更快
+  SelectedGLJLimit = 1900;
+
+// 选中清单下工料机数量
+function TScMainForm.SelectedGLJCount: Integer;
+var
+  I, J, iFrom, iTo: Integer;
+  zgGrid: TZJGrid;
+  lstBills, lstGLJ: TList;
+  Node: TsdIDTreeNode;
+  Rec: TsdDataRecord;
+  idxGLJ: TsdIndex;
+begin
+  Result := 0;
+  lstBills := TList.Create;
+  lstGLJ := TList.Create;
+  try
+    zgGrid := ActiveChild.BillsView.zgBills;
+    iFrom := zgGrid.Selection.Top - zgGrid.FixedRowCount;
+    iTo := zgGrid.Selection.Bottom - 1 - zgGrid.FixedRowCount;
+    Node := ActiveChild.Project.Bills.BillsTree.Items[iTo];
+    if Node.LastPosterity <> nil then
+      iTo := Node.LastPosterity.MajorIndex;
+    for I := iFrom to iTo do
+    begin
+      Node := ActiveChild.Project.Bills.BillsTree.Items[I];
+      lstBills.Add(Node);
+    end;
+    idxGLJ := ActiveChild.Project.GLJ.sdsGLJ.FindIndex('idxBillsID');
+    for I := 0 to lstBills.Count - 1 do
+    begin
+      Node := TsdIDTreeNode(lstBills[I]);
+      idxGLJ.RecordsByKey(Node.ID, lstGLJ);
+      Inc(Result, lstGLJ.Count);
+    end;
+  finally
+    lstBills.Free;
+    lstGLJ.Free;
+  end;
+end;
+
 procedure TScMainForm.DoOnBeforeGridDelete(Sender: TObject;
   var CanExecute: Boolean);
 begin
@@ -7456,6 +7502,24 @@ begin
       ActiveChild.BillsView.zgBills.Selection.Bottom - 1 - ActiveChild.BillsView.zgBills.FixedRowCount);
     if CanExecute then
       ActiveChild.BillsView.SnapShootCurrent;
+    // 优化大数据量删除,删除清单时生效
+//    iTime := GetTickCount;
+//    iGLJCount := ActiveChild.Project.GLJ.sdsGLJ.RecordCount;
+    iSelectedGLJCount := SelectedGLJCount;
+//    ShowMessage(Format('Count %d selected GLJ  in %f s', [iSelectedGLJCount, (GetTickCount - iTime) / 1000]));
+//    iTime := GetTickCount;
+    // 1900条工料机以下,使用直接删除更快(38万条工料机中删除1900条,14秒左右)),1900以上使用批量处理更快
+    if iSelectedGLJCount > SelectedGLJLimit then
+    begin
+      ActiveChild.BillsSubItemView.RAdjustView.sgdGLJAdjust.DisableControl;
+      ActiveChild.Project.GLJ.sdsGLJ.BeginUpdate;
+      ActiveChild.Project.GLJ.sdsGLJ.DisableControls;
+      ActiveChild.BillsSubItemView.sgdRations.DisableControl;
+      ActiveChild.BillsSubItemView.sgdCountPrice.DisableControl;
+      ActiveChild.BillsSubItemView.sgdMachineElectron.DisableControl;
+      ActiveChild.Project.Rations.sdsRations.BeginUpdate;
+      ActiveChild.Project.Rations.sdsRations.DisableControls;
+    end;
   end
   else if CanExecute then
   begin
@@ -7475,6 +7539,28 @@ end;
 procedure TScMainForm.DoOnAfterGridDelete(Sender: TObject);
 begin
   if IsManageView then Exit;
+  if (Sender = ActiveChild.BillsView.zgBills) then
+  begin
+//    ShowMessage(Format('Delete %d GLJ in %f s', [iGLJCount - ActiveChild.Project.GLJ.sdsGLJ.RecordCount, (GetTickCount - iTime) / 1000]));
+//    iTime := GetTickCount;
+    if iSelectedGLJCount > SelectedGLJLimit then
+    begin
+      Screen.Cursor := crHourGlass;
+      try
+        ActiveChild.Project.GLJ.sdsGLJ.EndUpdate;
+        ActiveChild.Project.GLJ.sdsGLJ.EnableControls;
+        ActiveChild.BillsSubItemView.RAdjustView.sgdGLJAdjust.EnableControl;
+        ActiveChild.Project.Rations.sdsRations.EndUpdate;
+        ActiveChild.Project.Rations.sdsRations.EnableControls;
+        ActiveChild.BillsSubItemView.sgdRations.EnableControl;
+        ActiveChild.BillsSubItemView.sgdCountPrice.EnableControl;
+        ActiveChild.BillsSubItemView.sgdMachineElectron.EnableControl;
+      finally
+        Screen.Cursor := crDefault;
+      end;
+    end;
+//    ShowMessage(Format('Enable GLJ DataSet in %f s', [(GetTickCount - iTime) / 1000]));
+  end;
   if (Sender = ActiveChild.BillsView.zgBills)
       or (Sender = ActiveChild.BillsSubItemView.zgRations)
       or (Sender = ActiveChild.BillsSubItemView.zgMachineElectron)

二進制
MainUI/Forms/ScProjFrm.dfm