瀏覽代碼

在线审批。

CSL 9 年之前
父節點
當前提交
4f93e54f1a
共有 5 個文件被更改,包括 255 次插入172 次删除
  1. 2 2
      Dprs/CSL/Measure_Cloud.dof
  2. 24 1
      Dprs/CSL/Measure_Cloud.dpr
  3. 二進制
      Dprs/CSL/Measure_Cloud.res
  4. 2 2
      Frames/ProjectFme.pas
  5. 227 167
      Frames/ProjectManagerFme.pas

+ 2 - 2
Dprs/CSL/Measure_Cloud.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=3
 MajorVer=3
 MinorVer=1
 MinorVer=1
 Release=3
 Release=3
-Build=1060
+Build=1063
 Debug=0
 Debug=0
 PreRelease=0
 PreRelease=0
 Special=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横结算决算计量一体化云版
 FileDescription=纵横结算决算计量一体化云版
-FileVersion=3.1.3.1060
+FileVersion=3.1.3.1063
 InternalName=Measure
 InternalName=Measure
 LegalCopyright=版权所有(C) 珠海纵横创新软件有限公司 2003-2014。保留所有权利。
 LegalCopyright=版权所有(C) 珠海纵横创新软件有限公司 2003-2014。保留所有权利。
 LegalTrademarks=Measure
 LegalTrademarks=Measure

+ 24 - 1
Dprs/CSL/Measure_Cloud.dpr

@@ -153,7 +153,30 @@ uses
   BaseClipboard in '..\..\Units\BaseClipboard.pas',
   BaseClipboard in '..\..\Units\BaseClipboard.pas',
   SelectDetailGLsFrm in '..\..\Forms\SelectDetailGLsFrm.pas' {SelectDetailGLsForm},
   SelectDetailGLsFrm in '..\..\Forms\SelectDetailGLsFrm.pas' {SelectDetailGLsForm},
   DealPayPlanFrm in '..\..\Forms\DealPayPlanFrm.pas' {DealPayPlanForm},
   DealPayPlanFrm in '..\..\Forms\DealPayPlanFrm.pas' {DealPayPlanForm},
-  mProgressProFrm in '..\..\Forms\mProgressProFrm.pas' {ProgressProForm};
+  mProgressProFrm in '..\..\Forms\mProgressProFrm.pas' {ProgressProForm},
+  tpBaseGatherData in '..\..\TenderPartition\tpBaseGatherData.pas',
+  tpGatherGcl in '..\..\TenderPartition\tpGatherGcl.pas',
+  tpGatherTree in '..\..\TenderPartition\tpGatherTree.pas',
+  tpMainData in '..\..\TenderPartition\tpMainData.pas',
+  tpMainFrm in '..\..\TenderPartition\tpMainFrm.pas' {tpMainForm},
+  tpNoPegDm in '..\..\TenderPartition\tpNoPegDm.pas' {tpNoPegData: TDataModule},
+  tpPartTender in '..\..\TenderPartition\tpPartTender.pas',
+  tpPartTenderFme in '..\..\TenderPartition\tpPartTenderFme.pas' {tpPartTenderFrame: TFrame},
+  tpPartTenderSet in '..\..\TenderPartition\tpPartTenderSet.pas',
+  tpPartTenderSetFme in '..\..\TenderPartition\tpPartTenderSetFme.pas' {tpPartTenderSetFrame: TFrame},
+  tpPeg in '..\..\TenderPartition\tpPeg.pas',
+  tpPeg_GclDm in '..\..\TenderPartition\tpPeg_GclDm.pas' {tpPeg_GclData: TDataModule},
+  tpPeg_GclFme in '..\..\TenderPartition\tpPeg_GclFme.pas' {tpPeg_GclFrame: TFrame},
+  tpPegBlock in '..\..\TenderPartition\tpPegBlock.pas',
+  tpPegGclGatherDm in '..\..\TenderPartition\tpPegGclGatherDm.pas' {tpPegGclGatherData: TDataModule},
+  tpPegGclGatherFme in '..\..\TenderPartition\tpPegGclGatherFme.pas' {tpPegGclGatherFrame: TFrame},
+  tpPegPartSettingFrm in '..\..\TenderPartition\tpPegPartSettingFrm.pas' {tpPegPartSettingForm},
+  tpPricePartSettingFrm in '..\..\TenderPartition\tpPricePartSettingFrm.pas' {tpPricePartSettingForm},
+  tpSelectTenderDm in '..\..\TenderPartition\tpSelectTenderDm.pas' {tpSelectTenderData: TDataModule},
+  tpSelectTenderNode in '..\..\TenderPartition\tpSelectTenderNode.pas',
+  tpSelectTendersFrm in '..\..\TenderPartition\tpSelectTendersFrm.pas' {SelectTendersForm},
+  tpTrialPegInputFrm in '..\..\TenderPartition\tpTrialPegInputFrm.pas' {TrialPegInputForm},
+  mPegFilter in '..\..\Units\mPegFilter.pas';
 
 
 {$R *.res}
 {$R *.res}
 
 

二進制
Dprs/CSL/Measure_Cloud.res


+ 2 - 2
Frames/ProjectFme.pas

@@ -983,7 +983,7 @@ begin
 
 
         if ProjectData.PhaseIndex = 0 then   // 0ºĄ̊ÕË£¬ÏÖÒÑ·ÏÆú
         if ProjectData.PhaseIndex = 0 then   // 0ºĄ̊ÕË£¬ÏÖÒÑ·ÏÆú
         begin
         begin
-          MainForm.ProjectManagerFrame.ShowProjWebInfoTop(0);
+          MainForm.ProjectManagerFrame.ShowProjectInfoTop(0);
         end
         end
         else
         else
         Begin
         Begin
@@ -991,7 +991,7 @@ begin
           vRec.BeginUpdate;
           vRec.BeginUpdate;
           vRec.ValueByName('WebMD5').AsString := sMD5_JL;
           vRec.ValueByName('WebMD5').AsString := sMD5_JL;
           vRec.EndUpdate;
           vRec.EndUpdate;
-          MainForm.ProjectManagerFrame.ShowProjWebInfoTop;
+          MainForm.ProjectManagerFrame.ShowProjectInfoTop;
 
 
           if ProjectData.CurUserIsAuthor then
           if ProjectData.CurUserIsAuthor then
           begin
           begin

+ 227 - 167
Frames/ProjectManagerFme.pas

@@ -7,10 +7,12 @@ uses
   NewProjectFrm,
   NewProjectFrm,
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, ZjGridDBA, ZJGrid, ComCtrls, ToolWin, ActnList,
   Dialogs, ZjGridDBA, ZJGrid, ComCtrls, ToolWin, ActnList,
-  dxBar, sdGridDBA, sdGridTreeDBA, sdIDTree, ExtCtrls,
+  dxBar, sdGridDBA, sdGridTreeDBA, sdIDTree, CslJson, ExtCtrls,
   StdCtrls, sdDB, CslButton, OrderCheckerFme, Contnrs;
   StdCtrls, sdDB, CslButton, OrderCheckerFme, Contnrs;
 
 
 type
 type
+  TStrArr = array of string;
+
   TProjectManagerFrame = class(TFrame)
   TProjectManagerFrame = class(TFrame)
     ToolBar: TToolBar;
     ToolBar: TToolBar;
     tobtnOpen: TToolButton;
     tobtnOpen: TToolButton;
@@ -89,28 +91,38 @@ type
   private
   private
     FProjectManagerData: TProjectManagerData;
     FProjectManagerData: TProjectManagerData;
 
 
-    FID: Integer;
-    FWebID: Integer;
-    FWebAuthorID: Integer;
-    FWebOwnerID: Integer;
-    FWebMD5: string;
-    FBidName: string;
+                                             // Chenshilong,2016.03.24
+                                             // 这部分线上和本地一致,无需区分
+    FID: Integer;                            // 本地标段文件ID
+    FWebID: Integer;                         // 关联服务器用的ID(服务器有自己的ID体系)
+    FWebAuthorID: Integer;                   // 编制人
+    FWebOwnerID: Integer;                    // 业主
+
+                                             // 本地存储值、线上存储值。线上修改后,需要同步到本地
+    FWebMD5_Local: string;                   // 本地存储的MD5
+    FWebMD5_OnLine: string;                  // 线上存储的最新的MD5(下同)
+    FWebBidName_Local: string;               // 标段名 (当无法同线上取得联系时,本地需要用到该名称来提示)
+    FWebBidName_OnLine: string;
+
+    FWebFolder_OnLine: string;               // 这个命名不妥,但很直观。线上的项目名称、项目类型概念跟本地颠倒,很混乱。
+    FWebSubFolder_OnLine: string;
 
 
-    FWebProjCtgyName: string;
     FWebOwnerCompany: string;
     FWebOwnerCompany: string;
-    FWebProjectName: string;
     FWebOwnerRole: string;
     FWebOwnerRole: string;
     FWebOwnerName: string;
     FWebOwnerName: string;
+
+    FWebCheckStatusMy: TCheckStatus;          // 登陆用户在当前项目中的工作状态。
+    FWebCheckStatusProject: TCheckStatus;     // 项目的审核状态。
+
+    FOnLineCheckerBegin: Integer;               // 线上审批的起始人。 010110111 起7止9。 0101101110 起0止0。
+    FOnLineCheckerEnd: Integer;                 // 线上审批的截止人。
+
     FPhaseTotal: Integer;
     FPhaseTotal: Integer;
     FPhaseNo: Integer;
     FPhaseNo: Integer;
-    FMyCheckStatus: TCheckStatus;            // 登陆用户在当前项目中的工作状态。
-    FProjectCheckStatus: TCheckStatus;       // 项目的审核状态。
 
 
-    FCurPos: Integer;                        // 用来控制审核人的添加位置
+    FCurPos: Integer;                         // 用来控制审核人的添加位置
     FCheckerList: TObjectList;
     FCheckerList: TObjectList;
 
 
-
-
     function ReceiveFile(const AFileName: string; AFileMD5: string = ''; ANeedLock: Boolean = False): Boolean;
     function ReceiveFile(const AFileName: string; AFileMD5: string = ''; ANeedLock: Boolean = False): Boolean;
     function ImportFile(const AFileName: string; AFileMD5: string = ''): Boolean;
     function ImportFile(const AFileName: string; AFileMD5: string = ''): Boolean;
     procedure ConnectButtonWithAction;
     procedure ConnectButtonWithAction;
@@ -120,7 +132,7 @@ type
     function IsUnEmptyLeafProject(ANode: TsdIDTreeNode): Boolean;
     function IsUnEmptyLeafProject(ANode: TsdIDTreeNode): Boolean;
     function CheckOpened(ANode: TsdIDTreeNode): Boolean;
     function CheckOpened(ANode: TsdIDTreeNode): Boolean;
     procedure SetPropertyVisible(AVisible: Boolean);
     procedure SetPropertyVisible(AVisible: Boolean);
-    procedure SearchAndShowProjAllWebInfo(ARec: TsdDataRecord);
+    procedure ShowProjectInfoTopAndCheckers;
     // 网络上的目录结构,本地有则定位,没有则创建。
     // 网络上的目录结构,本地有则定位,没有则创建。
     procedure CheckWebFolders(AFolderID, ASubFolderID: Integer;
     procedure CheckWebFolders(AFolderID, ASubFolderID: Integer;
       AFolderName, ASubFolderName: string);
       AFolderName, ASubFolderName: string);
@@ -128,7 +140,6 @@ type
     procedure CheckBidName(AID: Integer; ANewBidName: string); overload;
     procedure CheckBidName(AID: Integer; ANewBidName: string); overload;
     procedure CheckBidName(AUserID, AWebID: Integer; ANewBidName: string); overload;
     procedure CheckBidName(AUserID, AWebID: Integer; ANewBidName: string); overload;
     procedure ClearLocalValues;
     procedure ClearLocalValues;
-    procedure GetLocalValues; overload;
     procedure GetLocalValues(ARec: TsdDataRecord); overload;
     procedure GetLocalValues(ARec: TsdDataRecord); overload;
     // 用户ID、网络标段ID、Type=1可以定位一个标段。
     // 用户ID、网络标段ID、Type=1可以定位一个标段。
     procedure GetLocalValues(AUserID, AWebID: Integer); overload;
     procedure GetLocalValues(AUserID, AWebID: Integer); overload;
@@ -136,24 +147,28 @@ type
     procedure DoBatchReceiveOnline(ARequestType: Integer);
     procedure DoBatchReceiveOnline(ARequestType: Integer);
     function LocalMD5(AUserID, AWebID: Integer): string;
     function LocalMD5(AUserID, AWebID: Integer): string;
     procedure BubbleSortProjects;
     procedure BubbleSortProjects;
+    // AReceiveKind: 1 接收; 2 导入
+    function FileDownAndReceive(ADownURL: string; AReceiveKind: Integer): Boolean;
+    // 线上审批的起止人
+    procedure OnLineChecker(AAr: TOVArr; var ABegin, AEnd: Integer);
   public
   public
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
     destructor Destroy; override;
     procedure DoBatchReceiveAllOnline;
     procedure DoBatchReceiveAllOnline;
     // AType: -2 繁忙; -1 正常读取; 0 第0期; 1 第1期。
     // AType: -2 繁忙; -1 正常读取; 0 第0期; 1 第1期。
-    procedure ShowProjWebInfoTop(AType: Integer = -1);
+    procedure ShowProjectInfoTop(AType: Integer = -1);
     function Rec(AProjectID: Integer): TsdDataRecord;
     function Rec(AProjectID: Integer): TsdDataRecord;
     function CurRec: TsdDataRecord;
     function CurRec: TsdDataRecord;
     function CurRecAttachmentPath: string;
     function CurRecAttachmentPath: string;
     function AttachmentFileCountsWithoutManageFile(ANode: TsdIDTreeNode): Integer;
     function AttachmentFileCountsWithoutManageFile(ANode: TsdIDTreeNode): Integer;
-    property ProjectCheckStatus: TCheckStatus read FProjectCheckStatus;
+    property ProjectCheckStatus: TCheckStatus read FWebCheckStatusProject;
   end;
   end;
 
 
 implementation
 implementation
 
 
 uses
 uses
   MainFrm, UtilMethods, ProjectCommands, Globals, ConfigDoc, ConstUnit,
   MainFrm, UtilMethods, ProjectCommands, Globals, ConfigDoc, ConstUnit,
-  WebNewTenderFrm, PHPWebDm, Math, CslJson, mProgressFrm, ProgressHintFrm,
+  WebNewTenderFrm, PHPWebDm, Math, mProgressFrm, ProgressHintFrm,
   ShellAPI;
   ShellAPI;
 
 
 {$R *.dfm}
 {$R *.dfm}
@@ -237,13 +252,10 @@ var
 
 
   function CanOpen: Boolean;
   function CanOpen: Boolean;
   var
   var
-    sSearchURL, sDownURL, sFolder, sSubFolder, sNewName, sMD5,
+    sSearchURL, sDownURL,
     sMD5_UnLock, sError, sLocalFile: string;
     sMD5_UnLock, sError, sLocalFile: string;
     iSearch, iFolderID, iSubFolderID: Integer;
     iSearch, iFolderID, iSubFolderID: Integer;
 
 
-    bLock, bCanImp: Boolean;
-    vFileCheck: TTenderFileChecker;
-
     function HasWebBidInfo(AWebID: Integer): Boolean;
     function HasWebBidInfo(AWebID: Integer): Boolean;
     var vArr: array of string;
     var vArr: array of string;
       iResult: Integer;
       iResult: Integer;
@@ -262,96 +274,34 @@ var
 
 
     // 先按正常接口找到最新的MD5码看是否需要更新
     // 先按正常接口找到最新的MD5码看是否需要更新
     sSearchURL := Format('%stender/get/%d/update', [PHPWeb.MeasureURL, FWebID]);
     sSearchURL := Format('%stender/get/%d/update', [PHPWeb.MeasureURL, FWebID]);
-    iSearch := SearchFileOnline(sSearchURL, sDownURL, sFolder, sSubFolder, sNewName, sMD5, sError, iFolderID, iSubFolderID);
+    iSearch := SearchFileOnline(sSearchURL, sDownURL, FWebFolder_OnLine, FWebSubFolder_OnLine, FWebBidName_OnLine, FWebMD5_OnLine, sError, iFolderID, iSubFolderID);
 
 
     if iSearch = 1 then
     if iSearch = 1 then
     begin
     begin
       try
       try
-        CheckWebFolders(iFolderID, iSubFolderID, sFolder, sSubFolder);
-        CheckBidName(FID, sNewName);
+        CheckWebFolders(iFolderID, iSubFolderID, FWebFolder_OnLine, FWebSubFolder_OnLine);
+        CheckBidName(FID, FWebBidName_OnLine);
       finally
       finally
         if vSel <> nil then
         if vSel <> nil then
           vSel.LocateInControl;
           vSel.LocateInControl;
       end;
       end;
 
 
       // 打开前一定要先下载最新的标段文件(无论审核有没有通过)
       // 打开前一定要先下载最新的标段文件(无论审核有没有通过)
-      if sMD5 <> FWebMD5 then
-      begin
-        // 下载
-        sLocalFile := PHPWeb.UserPath + ExtractFileName(sDownURL);
-        if not PHPWeb.DownFile(sDownURL, sLocalFile) then
-        begin
-          sHint := Format('云端已找到"%s"的新文件,但由于网络原因下载失败,请重试!', [FBidName]);
-          Application.MessageBox(PChar(sHint), '警告', MB_OK + MB_ICONWARNING);
-          Exit;
-        end;
-
-        // 接收更新
-        bLock := (FWebAuthorID = PHPWeb.UserID) or ((FWebAuthorID <> PHPWeb.UserID) and (FMyCheckStatus <> csChecking));
-        if not ReceiveFile(sLocalFile, sMD5, bLock) then
-        begin
-          sHint := Format('已从云端下载新的"%s"到本地[%s],但接收失败,请删除该项目然后重新从云端获取!', [FBidName, sLocalFile]);
-          Application.MessageBox(PChar(sHint), '警告', MB_OK + MB_ICONWARNING);
-          Exit;
-        end;
-      end;
-      DeleteFile(sLocalFile);
+      if FWebMD5_OnLine <> FWebMD5_Local then
+        if not FileDownAndReceive(sDownURL, 1) then Exit;
 
 
       // 编制人且项目末通过
       // 编制人且项目末通过
-      if (FWebAuthorID = PHPWeb.UserID) and (FProjectCheckStatus = csNotPass) then
+      if (FWebAuthorID = PHPWeb.UserID) and (FWebCheckStatusProject = csNotPass) then
       begin
       begin
-        sHint := '本期计量审批不通过,你现在可以:' + #10#13 +
-        '点击【是(Y)】重新开始本期计量,软件将打开本期上报时的数据,开始重新计量;' + #10#13 +
-        '点击【否(N)】查看不通过计量,软件将打开本期最后审批的数据,重新打开标段' + 
-        '可再次打开本确认窗口。';
+        sHint := '本期计量审批不通过,你现在可以:' + #10#13 + '点击【是(Y)】重新开始本期计量,软件将打开本期上报时的数据,开始重新计量;' +
+          #10#13 +'点击【否(N)】查看不通过计量,软件将打开本期最后审批的数据,重新打开标段' + '可再次打开本确认窗口。';
         if Application.MessageBox(PChar(sHint), '询问', MB_YESNO + MB_ICONQUESTION) = ID_Yes then
         if Application.MessageBox(PChar(sHint), '询问', MB_YESNO + MB_ICONQUESTION) = ID_Yes then
         begin
         begin
           sSearchURL := Format('%suser/create/%d/%d/new/audit', [PHPWeb.MeasureURL, FWebID, FPhaseNo]);
           sSearchURL := Format('%suser/create/%d/%d/new/audit', [PHPWeb.MeasureURL, FWebID, FPhaseNo]);
-          case SearchFileOnline(sSearchURL, sDownURL, sFolder, sSubFolder, sNewName, sMD5_UnLock, sError, iFolderID, iSubFolderID) of
-            1: {注意这里的MD5码应取最终审核不通过项目的,否则会带来下载循环问题。
-                问题描述:
-                ①编制人运行软件,双击项目,发现审核不通过,自动下载无锁文件,开始新一期,保存关闭。
-                ②编制人再次运行软件,双击项目,MD5码不同,自动下载旧的审核不通过文件,覆盖本地。
-                ③编制人再次运行软件,双击项目,发现审核不通过,重复①,循环....
-                问:①那里下载无锁文件后不能改成新的MD5码吗?
-                答:不能,因为审核人的项目会变成无锁文件,看不到不通过项目。MD5码只能在上传后更新。
-                且编制人有个交互界面2种选择:a.下载更新不通过项目查看;b.下载更新无锁文件开始新一期。
-                }
+          case SearchFileOnline(sSearchURL, sDownURL, FWebFolder_OnLine, FWebSubFolder_OnLine, FWebBidName_OnLine, sMD5_UnLock, sError, iFolderID, iSubFolderID) of
+            1:
             begin
             begin
-              // 下载
-              sLocalFile := PHPWeb.UserPath + ExtractFileName(sDownURL);
-              if not PHPWeb.DownFile(sDownURL, sLocalFile) then
-              begin
-                sHint := '云端已找到原报上传的无锁文件,但因网络出错无法下载,本次操作已取消。请重试!';
-                Application.MessageBox(PChar(sHint), '警告', MB_OK + MB_ICONWARNING);
-                Exit;
-              end;
-
-
-              // 导入更新-------------------------------------------------------
-
-              // 导入前须检测无锁文件中仅含有原报数据
-              vFileCheck := TTenderFileChecker.Create;
-              try
-                // 有一期以上数据,且最新期数据审核状态为原报
-                bCanImp := vFileCheck.CheckFileValid(sLocalFile)
-                    and (vFileCheck.PhaseCount > 0) and (vFileCheck.AuditStatus = 0);
-                if not bCanImp then
-                begin
-                  Application.MessageBox(PChar('已从云端下载原报上传的无锁文件到本地,但文件有错误,禁止导入!请致电纵横服务人员以获取帮助。'), '警告', MB_OK + MB_ICONWARNING);
-                  Exit;
-                end;
-              finally
-                vFileCheck.Free;
-              end;
-
-              if not ImportFile(sLocalFile, sMD5) then
-              begin
-                Application.MessageBox(PChar('已从云端下载原报上传的无锁文件到本地,但导入失败!请重试。'), '警告', MB_OK + MB_ICONWARNING);
-                Exit;
-              end;
-              
-              // 导入更新---------------------------------↑↑↑↑↑↑↑↑↑↑↑
+              if not FileDownAndReceive(sDownURL, 2) then Exit;
             end;
             end;
 
 
             0, -1:
             0, -1:
@@ -368,14 +318,14 @@ var
     begin
     begin
       if not HasWebBidInfo(FWebID) then
       if not HasWebBidInfo(FWebID) then
       begin
       begin
-        sHint :='该项目[' + FBidName + ']在云端已被删除,点击"确定"后,可手动删除该项目。';
+        sHint :='该项目[' + FWebBidName_Local + ']在云端已被删除,点击"确定"后,可手动删除该项目。';
         Application.MessageBox(PChar(sHint), '提示', MB_OK + MB_ICONINFORMATION);
         Application.MessageBox(PChar(sHint), '提示', MB_OK + MB_ICONINFORMATION);
         Exit;
         Exit;
       end;
       end;
     end
     end
     else if (iSearch = 0) or (iSearch = -1) then
     else if (iSearch = 0) or (iSearch = -1) then
     begin
     begin
-      sHint := sError + '(因网络出错,无法检测[' + FBidName + ']在云端是否有更新,本次操作已取消,请重试)。';
+      sHint := sError + '(因网络出错,无法检测[' + FWebBidName_Local + ']在云端是否有更新,本次操作已取消,请重试)。';
       Application.MessageBox(PChar(sHint), '警告', MB_OK + MB_ICONWARNING);
       Application.MessageBox(PChar(sHint), '警告', MB_OK + MB_ICONWARNING);
       Exit;
       Exit;
     end;
     end;
@@ -392,7 +342,7 @@ begin
 
 
     if G_IsCloud then
     if G_IsCloud then
     begin
     begin
-      GetLocalValues;
+      GetLocalValues(CurRec);
       // 以下这段已经包含在MainForm.OpenProject(vRec)中了,但在调用这句之前,网络版要提前用一下。
       // 以下这段已经包含在MainForm.OpenProject(vRec)中了,但在调用这句之前,网络版要提前用一下。
       if MainForm.HasOpened(FID) then
       if MainForm.HasOpened(FID) then
       begin
       begin
@@ -410,7 +360,7 @@ begin
     begin
     begin
       if not MainForm.CurProjectFrame.CheckFileAndCloudChekerList then
       if not MainForm.CurProjectFrame.CheckFileAndCloudChekerList then
       begin
       begin
-        sHint := '项目校验:“' + FBidName + '”文件中的审核人和云端的审核人不一致,' +
+        sHint := '项目校验:“' + FWebBidName_OnLine + '”文件中的审核人和云端的审核人不一致,' +
           '禁止继续操作,项目即将关闭!请删除本地项目重新从云端获取,' +
           '禁止继续操作,项目即将关闭!请删除本地项目重新从云端获取,' +
           '重新获取后如果仍然存在同样的问题,请联系纵横服务人员以寻求帮助。';
           '重新获取后如果仍然存在同样的问题,请联系纵横服务人员以寻求帮助。';
         Application.MessageBox(PChar(sHint), '文件错误', MB_OK +MB_ICONWARNING);
         Application.MessageBox(PChar(sHint), '文件错误', MB_OK +MB_ICONWARNING);
@@ -630,13 +580,13 @@ procedure TProjectManagerFrame.actnNewTenderExecute(Sender: TObject);
         FWebOwnerName := vArr[1];
         FWebOwnerName := vArr[1];
         FWebOwnerCompany := vArr[2];
         FWebOwnerCompany := vArr[2];
         FWebOwnerRole := vArr[8];
         FWebOwnerRole := vArr[8];
-        FWebProjectName := vArr[6];
-        FWebProjCtgyName := vArr[7];
+        FWebFolder_OnLine := vArr[6];
+        FWebSubFolder_OnLine := vArr[7];
 //          WebOwnerImage := vArr[9];
 //          WebOwnerImage := vArr[9];
 //          WebOwnerPhone := vArr[3];
 //          WebOwnerPhone := vArr[3];
 //          WebOwnerMobile := vArr[4];
 //          WebOwnerMobile := vArr[4];
 //          WebOwnerQQ := vArr[5];
 //          WebOwnerQQ := vArr[5];
-        ShowProjWebInfoTop(0);
+        ShowProjectInfoTop(0);
         FProjectManagerData.Save;
         FProjectManagerData.Save;
         MainForm.OpenProject(vRec);
         MainForm.OpenProject(vRec);
       end;
       end;
@@ -765,7 +715,7 @@ begin
     begin
     begin
       CreateProgress('云端读取项目信息');
       CreateProgress('云端读取项目信息');
       try
       try
-        SearchAndShowProjAllWebInfo(CurRec);
+        ShowProjectInfoTopAndCheckers;
       finally
       finally
         CloseProgress;
         CloseProgress;
       end;
       end;
@@ -1027,9 +977,9 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TProjectManagerFrame.SearchAndShowProjAllWebInfo(ARec: TsdDataRecord);
+procedure TProjectManagerFrame.ShowProjectInfoTopAndCheckers;
 var
 var
-  vPSArr: array[0..7] of string;
+  vPSArr: TStrArr;
   vCArr: TOVArr;    // Checkers
   vCArr: TOVArr;    // Checkers
   vChecker: TOrderCheckerFrame;
   vChecker: TOrderCheckerFrame;
   sPicPath, sURL: string;
   sPicPath, sURL: string;
@@ -1060,7 +1010,7 @@ var
       TOrderCheckerFrame(sbChecker.Controls[k]).Order := k + 1;
       TOrderCheckerFrame(sbChecker.Controls[k]).Order := k + 1;
   end;
   end;
 
 
-  procedure RefreshProjectCheckers;
+  procedure ShowProjectCheckers;
   var i, j, n: Integer;
   var i, j, n: Integer;
     vOwner: array of string;  // 业主信息
     vOwner: array of string;  // 业主信息
   begin
   begin
@@ -1074,7 +1024,7 @@ var
     for i := Low(vCArr) to High(vCArr) do
     for i := Low(vCArr) to High(vCArr) do
     begin
     begin
       if StrToInt(vCArr[i, 0]) = PHPWeb.UserID then
       if StrToInt(vCArr[i, 0]) = PHPWeb.UserID then
-        FMyCheckStatus := TCheckStatus(StrToInt(vCArr[i, 5])-1);
+        FWebCheckStatusMy := TCheckStatus(StrToInt(vCArr[i, 5])-1);
 
 
       if StrToInt(vCArr[i, 0]) = FWebOwnerID then
       if StrToInt(vCArr[i, 0]) = FWebOwnerID then
       begin
       begin
@@ -1083,32 +1033,36 @@ var
 
 
         Continue;
         Continue;
       end;
       end;
+      
       AddChecker(cftChecker, vCArr[i]);
       AddChecker(cftChecker, vCArr[i]);
     end;
     end;
     if vOwner[0] <> '' then
     if vOwner[0] <> '' then
       AddChecker(cftOwner, vOwner);
       AddChecker(cftOwner, vOwner);
     RepairOrder;
     RepairOrder;
+
+    OnLineChecker(vCArr, FOnLineCheckerBegin, FOnLineCheckerEnd);
   end;
   end;
 
 
 begin
 begin
-  GetLocalValues(ARec);
+  GetLocalValues(CurRec);
   if FWebID = 0 then Exit;
   if FWebID = 0 then Exit;
+  SetLength(vPSArr, 8);
   sURL := Format('%smeasure/status/%d/get', [PHPWeb.MeasureURL, FWebID]);
   sURL := Format('%smeasure/status/%d/get', [PHPWeb.MeasureURL, FWebID]);
   if PHPWeb.Search(sURL, [''], [''], 3, vPSArr, vCArr) = 1 then
   if PHPWeb.Search(sURL, [''], [''], 3, vPSArr, vCArr) = 1 then
   begin
   begin
     LockWindowUpdate(pnlWeb.Handle);
     LockWindowUpdate(pnlWeb.Handle);
     try
     try
       FPhaseNo := StrToInt(vPSArr[0]);
       FPhaseNo := StrToInt(vPSArr[0]);
-      FProjectCheckStatus := TCheckStatus(StrToInt(vPSArr[1])-1);
+      FWebCheckStatusProject := TCheckStatus(StrToInt(vPSArr[1])-1);
       FPhaseTotal := StrToInt(vPSArr[2]);
       FPhaseTotal := StrToInt(vPSArr[2]);
-      FWebProjectName := vPSArr[3];
-      FWebProjCtgyName := vPSArr[4];
+      FWebFolder_OnLine := vPSArr[3];
+      FWebSubFolder_OnLine := vPSArr[4];
       FWebOwnerName := vPSArr[5];
       FWebOwnerName := vPSArr[5];
       FWebOwnerCompany := vPSArr[6];
       FWebOwnerCompany := vPSArr[6];
       FWebOwnerRole := vPSArr[7];
       FWebOwnerRole := vPSArr[7];
 
 
-      ShowProjWebInfoTop;
-      RefreshProjectCheckers;
+      ShowProjectInfoTop;
+      ShowProjectCheckers;
     finally
     finally
       LockWindowUpdate(0);
       LockWindowUpdate(0);
     end;
     end;
@@ -1116,29 +1070,29 @@ begin
   else
   else
   begin
   begin
     FPhaseNo := 0;
     FPhaseNo := 0;
-    FProjectCheckStatus := csNotBegin;
+    FWebCheckStatusProject := csNotBegin;
     FPhaseTotal := 0;
     FPhaseTotal := 0;
-    FWebProjectName := '';
-    FWebProjCtgyName := '';
+    FWebFolder_OnLine := '';
+    FWebSubFolder_OnLine := '';
     FWebOwnerName := '';
     FWebOwnerName := '';
     FWebOwnerCompany := '';
     FWebOwnerCompany := '';
     FWebOwnerRole := '';
     FWebOwnerRole := '';
 
 
-    ShowProjWebInfoTop;
+    ShowProjectInfoTop;
 
 
     sbChecker.Height := 0;
     sbChecker.Height := 0;
   end;
   end;
 end;
 end;
 
 
-procedure TProjectManagerFrame.ShowProjWebInfoTop(AType: Integer);
+procedure TProjectManagerFrame.ShowProjectInfoTop(AType: Integer);
 
 
   procedure ShowOwner;
   procedure ShowOwner;
   begin
   begin
-    lblBidName.Caption := FBidName;
+    lblBidName.Caption := FWebBidName_Local;
     lblBidName.Update;
     lblBidName.Update;
-    lblProjName.Caption := FWebProjectName;
+    lblProjName.Caption := FWebFolder_OnLine;
     lblProjName.Update;
     lblProjName.Update;
-    lblWebProjCtgyName.Caption := FWebProjCtgyName;
+    lblWebProjCtgyName.Caption := FWebSubFolder_OnLine;
     lblWebProjCtgyName.Update;
     lblWebProjCtgyName.Update;
     lblOnwerName.Caption := FWebOwnerName;
     lblOnwerName.Caption := FWebOwnerName;
     lblOnwerName.Update;
     lblOnwerName.Update;
@@ -1160,7 +1114,7 @@ procedure TProjectManagerFrame.ShowProjWebInfoTop(AType: Integer);
     lblPeriodTotal.Left := lblPeriodState.Left + lblPeriodState.Width + 3;
     lblPeriodTotal.Left := lblPeriodState.Left + lblPeriodState.Width + 3;
   end;
   end;
 begin
 begin
-  GetLocalValues;
+  GetLocalValues(CurRec);
   case AType of
   case AType of
     -2:
     -2:
     begin
     begin
@@ -1170,7 +1124,7 @@ begin
     -1:
     -1:
     begin
     begin
       ShowOwner;
       ShowOwner;
-      ShowStatus(FPhaseNo, FProjectCheckStatus);
+      ShowStatus(FPhaseNo, FWebCheckStatusProject);
     end;
     end;
     0:
     0:
     begin
     begin
@@ -1293,11 +1247,9 @@ end;
 
 
 procedure TProjectManagerFrame.DoBatchReceiveOnline(ARequestType: Integer);
 procedure TProjectManagerFrame.DoBatchReceiveOnline(ARequestType: Integer);
 var
 var
-  sURL, sFolder, sSubFolder, sMD5, sName, sHint, sLocalFile: string;
-  vMyCheckStatus: TCheckStatus;
+  sURL, sHint: string;
   vArr: TOVArr;
   vArr: TOVArr;
-  bLock: Boolean;
-  i, iWebID, iFolderID, iSubFolderID, iAuthorID: Integer;
+  i, iFolderID, iSubFolderID: Integer;
 begin
 begin
   // 查询等待我审核的标段文件,杰哥说分三种:①业主未审核 ②业主审核中 ③审核人审核中 (为什么加①?问杰哥)
   // 查询等待我审核的标段文件,杰哥说分三种:①业主未审核 ②业主审核中 ③审核人审核中 (为什么加①?问杰哥)
   case PHPWeb.Search(PHPWeb.MeasureURL + 'user/get/audit/project', ['audituid', 'RequestType'],
   case PHPWeb.Search(PHPWeb.MeasureURL + 'user/get/audit/project', ['audituid', 'RequestType'],
@@ -1309,39 +1261,22 @@ begin
         for i := Low(vArr) to High(vArr) do
         for i := Low(vArr) to High(vArr) do
         begin
         begin
           sURL := vArr[i, 0];
           sURL := vArr[i, 0];
-          sFolder := vArr[i, 1];
-          sSubFolder := vArr[i, 2];
-          sMD5 := vArr[i, 3];
-          iWebID := StrToInt(vArr[i, 5]);
+          FWebFolder_OnLine := vArr[i, 1];
+          FWebSubFolder_OnLine := vArr[i, 2];
+          FWebMD5_OnLine := vArr[i, 3];
+          FWebID := StrToInt(vArr[i, 5]);
           iFolderID := StrToInt(vArr[i, 6]);
           iFolderID := StrToInt(vArr[i, 6]);
           iSubFolderID := StrToInt(vArr[i, 7]);
           iSubFolderID := StrToInt(vArr[i, 7]);
-          vMyCheckStatus := TCheckStatus(StrToInt(vArr[i, 8])-1);               // vArr[i, 4]项目审核状态;vArr[i, 8]当前登陆用户的审核状态
-          iAuthorID := StrToInt(vArr[i, 9]);                                    // 编制人ID
-          sName := vArr[i, 10];                                                 // 标段名称
-          
-          CheckWebFolders(iFolderID, iSubFolderID, sFolder, sSubFolder);
-          CheckBidName(PHPWeb.UserID, iWebID, sName);
-
-          if sMD5 <> LocalMD5(PHPWeb.UserID, iWebID) then
-          begin
-            // 下载
-            sLocalFile := PHPWeb.UserPath + ExtractFileName(sURL);
-            if not PHPWeb.DownFile(sURL, sLocalFile) then
-            begin
-              sHint := Format('云端已找到"%s"的新文件,但由于网络原因下载失败!请点击菜单“同步更新我参与的全部项目”重新下载!', [sName]);
-              Application.MessageBox(PChar(sHint), '系统提醒', MB_OK + MB_ICONWARNING);
-            end;
+          FWebCheckStatusMy := TCheckStatus(StrToInt(vArr[i, 8])-1);      // vArr[i, 4]项目审核状态;vArr[i, 8]当前登陆用户的审核状态
+          FWebAuthorID := StrToInt(vArr[i, 9]);
+          FWebBidName_OnLine := vArr[i, 10];
+          FWebMD5_Local := LocalMD5(PHPWeb.UserID, FWebID);
 
 
-            // 接收更新
-            bLock := (iAuthorID = PHPWeb.UserID) or ((iAuthorID <> PHPWeb.UserID) and (vMyCheckStatus <> csChecking));
-            if not ReceiveFile(sLocalFile, sMD5, bLock) then
-            begin
-              sHint := Format('已从云端下载新的"%s"到本地,但接收失败,请删除该项目然后重新从云端获取!', [sName]);
-              Application.MessageBox(PChar(sHint), '系统提醒', MB_OK + MB_ICONWARNING);
-              Exit;
-            end;
-            DeleteFile(sLocalFile);
-          end;
+          CheckWebFolders(iFolderID, iSubFolderID, FWebFolder_OnLine, FWebSubFolder_OnLine);
+          CheckBidName(PHPWeb.UserID, FWebID, FWebBidName_OnLine);
+
+          if FWebMD5_OnLine <> FWebMD5_Local then
+            if not FileDownAndReceive(sURL, 1) then Exit;
         end;
         end;
 
 
         BubbleSortProjects;
         BubbleSortProjects;
@@ -1447,11 +1382,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TProjectManagerFrame.GetLocalValues;
-begin
-  GetLocalValues(CurRec);
-end;
-
 
 
 procedure TProjectManagerFrame.GetLocalValues(ARec: TsdDataRecord);
 procedure TProjectManagerFrame.GetLocalValues(ARec: TsdDataRecord);
 begin
 begin
@@ -1468,8 +1398,8 @@ begin
     FWebID := ARec.ValueByName('WebID').AsInteger;
     FWebID := ARec.ValueByName('WebID').AsInteger;
     FWebAuthorID := ARec.ValueByName('WebAuthorID').AsInteger;
     FWebAuthorID := ARec.ValueByName('WebAuthorID').AsInteger;
     FWebOwnerID := ARec.ValueByName('WebOwnerID').AsInteger;
     FWebOwnerID := ARec.ValueByName('WebOwnerID').AsInteger;
-    FWebMD5 := ARec.ValueByName('WebMD5').AsString;
-    FBidName := ARec.ValueByName('Name').AsString;
+    FWebMD5_Local := ARec.ValueByName('WebMD5').AsString;
+    FWebBidName_Local := ARec.ValueByName('Name').AsString;
   end;
   end;
 end;
 end;
 
 
@@ -1509,8 +1439,8 @@ begin
   FWebID := -1;
   FWebID := -1;
   FWebAuthorID := -1;
   FWebAuthorID := -1;
   FWebOwnerID := -1;
   FWebOwnerID := -1;
-  FWebMD5 := '';
-  FBidName := '';
+  FWebMD5_Local := '';
+  FWebBidName_Local := '';
 end;
 end;
 
 
 
 
@@ -1718,4 +1648,134 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TProjectManagerFrame.FileDownAndReceive(ADownURL: string; AReceiveKind: Integer): Boolean;
+var sLocalFile, sHint: string;
+  bLock, bCanImp, bIsOwner: Boolean;
+  vFileCheck: TTenderFileChecker;
+begin
+  Result := False;
+
+  // 下载
+  sLocalFile := PHPWeb.UserPath + ExtractFileName(ADownURL);
+  if not PHPWeb.DownFile(ADownURL, sLocalFile) then
+  begin
+    if AReceiveKind = 1 then
+      sHint := Format('云端已找到[%s]的新文件,但由于网络原因下载失败!请重试!', [FWebBidName_Local])
+    else if AReceiveKind = 2 then
+      sHint := '云端已找到原报上传的无锁文件,但因网络出错无法下载,本次操作已取消。请重试!';
+
+    Application.MessageBox(PChar(sHint), '系统提醒', MB_OK + MB_ICONWARNING);
+    Exit;
+  end;
+
+  // 接收更新
+  if AReceiveKind = 1 then
+  begin
+    bLock := (FWebAuthorID = PHPWeb.UserID) or
+             ((FWebAuthorID <> PHPWeb.UserID) and (FWebCheckStatusMy <> csChecking));
+    bIsOwner := FWebOwnerID = PHPWeb.UserID;
+    if not ReceiveFile(sLocalFile, FWebMD5_OnLine, bLock) then
+//    if not ReceiveForLost(sLocalFile, FWebMD5_OnLine, bLock, FOnLineCheckerBegin, FOnLineCheckerEnd, bIsOwner) then
+    begin
+      sHint := Format('已从云端下载新的[%s]到本地[%s],但接收失败,请删除该项目然后重新从云端获取!', [FWebBidName_Local, sLocalFile]);
+      Application.MessageBox(PChar(sHint), '系统提醒', MB_OK + MB_ICONWARNING);
+      Exit;
+    end;
+  end
+
+  // 导入更新
+  else if AReceiveKind = 2 then
+  begin
+    // 有时无锁文件出错:包含了1审2审的数据。所以导入前须检测。
+    vFileCheck := TTenderFileChecker.Create;
+    try
+      // 有一期以上数据,且最新期数据审核状态为原报
+      bCanImp := vFileCheck.CheckFileValid(sLocalFile) and (vFileCheck.PhaseCount > 0) and (vFileCheck.AuditStatus = 0);
+      if not bCanImp then
+      begin
+        Application.MessageBox(PChar('已从云端下载原报上传的无锁文件到本地,但文件有错误,禁止导入!请致电纵横服务人员以获取帮助。'),
+          '警告', MB_OK + MB_ICONWARNING);
+        Exit;
+      end;
+    finally
+      vFileCheck.Free;
+    end;
+
+    {注意: 审核末通过的导入更新,这里的MD5码应取最终审核不通过项目的,否则会带来下载循环问题。
+    问题描述:
+    ①编制人运行软件,双击项目,发现审核不通过,自动下载无锁文件,开始新一期,保存关闭。
+    ②编制人再次运行软件,双击项目,MD5码不同,自动下载旧的审核不通过文件,覆盖本地。
+    ③编制人再次运行软件,双击项目,发现审核不通过,重复①,循环....
+    问:①那里下载无锁文件后不能改成新的MD5码吗?
+    答:不能,因为审核人的项目会变成无锁文件,看不到不通过项目。MD5码只能在上传后更新。
+    且编制人有个交互界面2种选择:a.下载更新不通过项目查看;b.下载更新无锁文件开始新一期。}
+    if not ImportFile(sLocalFile, FWebMD5_OnLine) then
+    begin
+      Application.MessageBox(PChar('已从云端下载原报上传的无锁文件到本地,但导入失败!请重试。'), '警告', MB_OK + MB_ICONWARNING);
+      Exit;
+    end;
+  end;
+
+  if FileExists(sLocalFile) then
+    DeleteFile(sLocalFile);
+
+  Result := True;
+end;
+
+// 为了跟PHP的数组兼容,这里限制数组的第一个元素是A[0](不能是A[1])
+procedure TProjectManagerFrame.OnLineChecker(AAr: TOVArr; var ABegin,
+  AEnd: Integer);
+var i, j, n: Integer;
+  vCS: TCheckStatus;
+begin
+  ABegin := 0;
+  AEnd := 0;
+  n := -1;
+
+  for i := 0 to High(AAr) do
+  begin
+    vCS := TCheckStatus(StrToInt(AAr[i, 5])-1);
+    if vCS = csChecking then
+    begin
+      n := i;  // 非常重要:传入的数组必须从第一个审核人到轮到工作中的那个人的前一个人
+      Break;
+    end;
+  end;
+
+  for i := n downto 0 do
+  begin
+    if AAr[i, 7] = '1' then             // 接口返回的第7列是线上审批标记
+    begin
+      AEnd := i + 1;
+      Break;
+    end
+    else
+      Break;
+  end;
+
+  if AEnd = 0 then Exit;
+
+  i := i - 1;
+  if i < 0 then
+  begin
+    ABegin := 1;
+    Exit;
+  end;
+
+
+  for j := i downto 0 do
+  begin
+    if AAr[j, 7] = '0' then
+    begin
+      ABegin := j + 2;
+      Break;
+    end
+    else
+    begin
+      if j = 0 then
+        ABegin := 1;
+    end;
+  end;
+end;
+
 end.
 end.