{******************************************************************************* 单元名称: CheckerFme.pas 单元说明: 审核人窗口。 作者时间: Chenshilong, 2014-07-11 *******************************************************************************} unit CheckerFme; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, OrderCheckerFme, JimLabels, Contnrs, Checker; type TCheckerFrame = class(TFrame) pnlProject: TPanel; sbChecker: TScrollBox; pnlTitle: TPanel; labTitle: TJimGradLabel; tRefreshCheckers: TTimer; procedure tRefreshCheckersTimer(Sender: TObject); private FProjectData: TObject; FCount: Integer; FOwner: TObject; FOwnerFrame: TOrderCheckerFrame; FAddFrame: TOrderCheckerFrame; FList: TObjectList; // Add窗也进FList FCurPos: Integer; procedure SetProjectData(const Value: TObject); procedure SetOwner(const Value: TObject); { Private declarations } public { Public declarations } property ProjectData: TObject read FProjectData write SetProjectData; property Owner: TObject read FOwner write SetOwner; property OwnerFrame: TOrderCheckerFrame read FOwnerFrame write FOwnerFrame; // 这个特指终审人的Frame property AddFrame: TOrderCheckerFrame read FAddFrame write FAddFrame; // 这个特指新增人的Frame property List: TObjectList read FList; property CurPos: Integer read FCurPos write FCurPos; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Init; // 审核人的名字、职位、公司、图像 procedure AddNewChecker(AType: TCheckerFrameType; AID: Integer; AName, ARole, ACompany, AImagePath, ACheckerMemo: string; ACheckStatus: TCheckStatus); function InCheckerList(ACheckerID: Integer): Boolean; function HasNormalChecker: Boolean; // 有普通审核人就返回True(光有业主不算) function HasChecker: Boolean; // 列表不为空即返回True(光Add也算) procedure CheckerNameList(var ASL: TStringList); procedure RepairOrder; procedure RepairDelete(ACanDelete: Boolean); function FirstChecker: TOrderCheckerFrame; function NextChecker: TOrderCheckerFrame; function LastChecker: TOrderCheckerFrame; function Me: TOrderCheckerFrame; function CheckNo(ACheckStatus: TCheckStatus): Integer; // 返回指定的审核状态是列表中的第几个人 end; implementation uses FindUserFrm, PHPWebDm, ProjectData, CslJson, ConstUnit, ProjectFme; {$R *.dfm} procedure TCheckerFrame.AddNewChecker(AType: TCheckerFrameType; AID: Integer; AName, ARole, ACompany, AImagePath, ACheckerMemo: string; ACheckStatus: TCheckStatus); var vChecker: TOrderCheckerFrame; begin vChecker := TOrderCheckerFrame.Create(Self); vChecker.Owner := Self; vChecker.Init(AType, AID, AName, ARole, ACompany, AImagePath, ACheckerMemo, ACheckStatus); sbChecker.Height := sbChecker.Height + vChecker.Height; vChecker.Parent := sbChecker; vChecker.Top := FCurPos; FCurPos := FCurPos + vChecker.Height; vChecker.Align := alTop; // 调整位置 case AType of cftChecker: begin vChecker.Name := 'OrderFrame' + IntToStr(AID); if Assigned(AddFrame) then // 适用于查找审核人添加数据库后,插入Add窗之前 begin vChecker.Top := AddFrame.Top; AddFrame.Top := vChecker.Top + vChecker.Height; OwnerFrame.Top := AddFrame.Top + AddFrame.Height; FList.Insert(FList.Indexof(AddFrame), vChecker); end else FList.Add(vChecker); end; cftOwner: // 保险,保证终审窗一定在Add窗之后 begin OwnerFrame := vChecker; vChecker.Name := 'OwnerFrame'; if Assigned(AddFrame) then OwnerFrame.Top := AddFrame.Top + AddFrame.Height; FList.Add(vChecker); end; cftAdd: // Add窗插入到终审窗之前 begin AddFrame := vChecker; vChecker.Name := 'AddFrame'; if Assigned(OwnerFrame) then begin AddFrame.Top := OwnerFrame.Top; OwnerFrame.Top := AddFrame.Top + AddFrame.Height; FList.Insert(FList.Indexof(OwnerFrame), vChecker); end else FList.Add(vChecker); end; end; end; procedure TCheckerFrame.Init; var i: Integer; vA: TOVArr; sURL, sPicPath, sID, sErrors: string; vProj: TProjectData; bOwner, bOwnerFinish: Boolean; vStatus: TCheckStatus; vCM: TChecker; begin FList.Clear; OwnerFrame := nil; AddFrame := nil; sbChecker.Height := 0; FCurPos := 0; vProj := TProjectData(FProjectData); vProj.Checkers.Clear; // 这里,这里搞死爹...编制人第一期上报后,关掉项目,重新打开这个项目,第一次, // 我说的是第一次——一定读取不了审核人列表,但第二次、以后每次都正常。你知道 // 读取不了这个列表的后果有多严重吗?网络版的每个角落都依赖于审核人的角色,所 // 以后果就是直接崩溃,无法使用。查明原因:服务器那头的PHP第一次接收不了传上 // 去的数据,日志显示读取到的数组为空。 // 所以这里把参数移到URL中,通过URL的方式传递,避开用数组传递,问题解决。 // 很明显,这种方式的局限性很大,只适合参数较少的情况。该问题已被珠海纵横公司 // 计量支付网络版研发团队定性为PHP业界的灵异事件。如果哪天你用科学解释了它,请 // 一定要告诉我个中缘由。chenshilong, 2014-07-21 sURL := Format('%suser/get/all/%d/%d/measure', [PHPWeb.MeasureURL, vProj.WebID, vProj.PhaseIndex]); if PHPWeb.Search(sURL, [''], [''], vA) = 1 then begin for i := Low(vA) to High(vA) do begin sID := vA[i, 4]; sPicPath := PHPWeb.UserPath + '1_' + sID + '.jpg'; PHPWeb.DownFile(vA[i, 5], sPicPath); vStatus := TCheckStatus(StrToInt(vA[i, 3])-1); // Json返回1、2、3、4 bOwner := StrToInt(sID) = TProjectData(ProjectData).WebOwnerID; if bOwner then // 添加业主 begin if TProjectData(ProjectData).CurUserIsAuthor then begin {如果是编制人,添加业主前先添加Add框。 数据库中,编制人没有审核人这样的状态。只有跟随标段的两种状态: ①有标段(顺便记录了编制人,标段是编制人创建的) ②没有标段。 为什么不通过是否有标段来判断当前是否显示“添加新的审核人”呢? 因为无法得知当前项目是数据库中已存在的最新一期还是仅存于本地尚末入库 的最新一期。改由添加的位置给出提示} if (TProjectData(ProjectData).PhaseIndex > 0) and (not TProjectFrame(Owner).IsUped) then AddNewChecker(cftAdd, -1, '', '', '', '', '', csNotBegin); end; AddNewChecker(cftOwner, StrToInt(sID), vA[i, 0], vA[i, 2], vA[i, 1], sPicPath, vA[i, 6], vStatus); end else AddNewChecker(cftChecker, StrToInt(vA[i, 4]), vA[i, 0], vA[i, 2], vA[i, 1], sPicPath, vA[i, 6], vStatus); vCM := TChecker.Create; vProj.Checkers.Add(StrToInt(vA[i, 4]), vA[i, 0], vA[i, 2], vA[i, 6]); end; RepairOrder; end else begin sErrors := Format('无法读取审核人列表,这将会导致桌面程序崩溃!%s地址:%s%s标段ID:%s,期号:%s', [#13#10#13#10, sURL, #13#10#13#10, IntToStr(vProj.WebID), IntToStr(vProj.PhaseIndex)]); Application.MessageBox(PChar(sErrors), '错误', MB_OK + MB_ICONERROR); Application.Terminate; end; end; procedure TCheckerFrame.SetProjectData(const Value: TObject); begin FProjectData := Value; end; function TCheckerFrame.InCheckerList(ACheckerID: Integer): Boolean; var i: Integer; begin Result := False; for i := 0 to FList.Count - 1 do begin if TOrderCheckerFrame(FList[i]).UserID = ACheckerID then begin Result := True; Break; end; end; end; procedure TCheckerFrame.CheckerNameList(var ASL: TStringList); var i: Integer; vFrame: TOrderCheckerFrame; begin ASL.Clear; for i := 0 to FList.Count - 1 do begin vFrame := TOrderCheckerFrame(FList[i]); if vFrame.CheckerFrameType <> cftAdd then ASL.Add(Format('%s', [vFrame.UserName])); end; end; procedure TCheckerFrame.SetOwner(const Value: TObject); begin FOwner := Value; end; procedure TCheckerFrame.RepairOrder; var i: Integer; begin for i := 0 to FList.Count - 1 do TOrderCheckerFrame(FList[i]).Order := i + 1; end; function TCheckerFrame.HasNormalChecker: Boolean; var i: Integer; begin Result := False; for i := 0 to FList.Count - 1 do begin if TOrderCheckerFrame(FList[i]).CheckerFrameType = cftChecker then begin Result := True; Break; end; end; end; constructor TCheckerFrame.Create(AOwner: TComponent); begin inherited; FList := TObjectList.Create; end; destructor TCheckerFrame.Destroy; begin FList.Free; inherited; end; function TCheckerFrame.FirstChecker: TOrderCheckerFrame; begin Result := nil; if FList.Count > 0 then begin if TOrderCheckerFrame(FList[0]).CheckerFrameType <> cftAdd then Result := TOrderCheckerFrame(FList[0]) else Result := TOrderCheckerFrame(FList[1]); end; end; function TCheckerFrame.NextChecker: TOrderCheckerFrame; var i: Integer; vFrame: TOrderCheckerFrame; begin Result := nil; if FList.Count = 0 then Exit; for i := 0 to FList.Count - 1 do begin if (TOrderCheckerFrame(FList[i]).UserID = PHPWeb.UserID) then begin if i = (FList.Count - 1) then Exit; // 最后一个 Result := TOrderCheckerFrame(FList[i + 1]); if Result.CheckerFrameType = cftAdd then Result := TOrderCheckerFrame(FList[i + 2]); Break; end; end; end; function TCheckerFrame.Me: TOrderCheckerFrame; var i: Integer; begin Result := nil; for i := 0 to FList.Count - 1 do begin if TOrderCheckerFrame(FList[i]).UserID = PHPWeb.UserID then begin Result := TOrderCheckerFrame(FList[i]); Break; end; end; end; procedure TCheckerFrame.RepairDelete(ACanDelete: Boolean); var i: Integer; begin for i := 0 to FList.Count - 1 do begin if (TOrderCheckerFrame(FList[i]) <> OwnerFrame) and (TOrderCheckerFrame(FList[i]) <> AddFrame) then TOrderCheckerFrame(FList[i]).btnDelete.Visible := ACanDelete; end; end; procedure TCheckerFrame.tRefreshCheckersTimer(Sender: TObject); begin tRefreshCheckers.Enabled := False; try init; RepairDelete(True); except ShowMessage('删除成功,这里做了异常保护'); end; end; function TCheckerFrame.HasChecker: Boolean; begin Result := (FList.Count > 0); end; function TCheckerFrame.CheckNo(ACheckStatus: TCheckStatus): Integer; var i, iCount: Integer; begin Result := -1; for i := 0 to FList.Count - 1 do begin if TOrderCheckerFrame(FList[i]).CheckStatus = ACheckStatus then begin Result := i + 1; Break; end; end; end; function TCheckerFrame.LastChecker: TOrderCheckerFrame; var i: Integer; begin Result := FOwnerFrame; end; end.