CheckerFme.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. {*******************************************************************************
  2. 单元名称: CheckerFme.pas
  3. 单元说明: 审核人窗口。
  4. 作者时间: Chenshilong, 2014-07-11
  5. *******************************************************************************}
  6. unit CheckerFme;
  7. interface
  8. uses
  9. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  10. Dialogs, ExtCtrls, StdCtrls, OrderCheckerFme, JimLabels, Contnrs, Checker;
  11. type
  12. TCheckerFrame = class(TFrame)
  13. pnlProject: TPanel;
  14. sbChecker: TScrollBox;
  15. pnlTitle: TPanel;
  16. labTitle: TJimGradLabel;
  17. tRefreshCheckers: TTimer;
  18. procedure tRefreshCheckersTimer(Sender: TObject);
  19. private
  20. FProjectData: TObject;
  21. FCount: Integer;
  22. FOwnerFrame: TOrderCheckerFrame;
  23. FAddFrame: TOrderCheckerFrame;
  24. FList: TList; // Add窗也进FList
  25. FCurPos: Integer;
  26. public
  27. constructor Create(AParent: TComponent; AProject: TObject);
  28. destructor Destroy; override;
  29. procedure Init;
  30. // 审核人的名字、职位、公司、图像
  31. procedure AddNewChecker(AType: TCheckerFrameType; AID: Integer; AName,
  32. ARole, ACompany, AImagePath, ACheckerMemo: string; ACheckStatus: TCheckStatus;
  33. ACheckeTime: string; ACheckeOnLine: Integer);
  34. function InCheckerList(ACheckerID: Integer): Boolean;
  35. function HasNormalChecker: Boolean; // 有普通审核人就返回True(光有业主不算)
  36. function HasChecker: Boolean; // 列表不为空即返回True(光Add也算)
  37. procedure CheckerNameList(var ASL: TStringList);
  38. procedure RepairOrder;
  39. procedure RepairDelete(ACanDelete: Boolean);
  40. function FirstChecker: TOrderCheckerFrame;
  41. function NextChecker: TOrderCheckerFrame;
  42. function LastChecker: TOrderCheckerFrame;
  43. function Me: TOrderCheckerFrame;
  44. function CheckNo(ACheckStatus: TCheckStatus): Integer; // 返回指定的审核状态是列表中的第几个人
  45. property ProjectData: TObject read FProjectData;
  46. property OwnerFrame: TOrderCheckerFrame read FOwnerFrame write FOwnerFrame; // 这个特指终审人的Frame
  47. property AddFrame: TOrderCheckerFrame read FAddFrame write FAddFrame; // 这个特指新增人的Frame
  48. property List: TList read FList;
  49. property CurPos: Integer read FCurPos write FCurPos;
  50. end;
  51. implementation
  52. uses FindUserFrm, PHPWebDm, ProjectData, CslJson, ConstUnit, ProjectFme, superobject, ZhAPI;
  53. {$R *.dfm}
  54. procedure TCheckerFrame.AddNewChecker(AType: TCheckerFrameType; AID: Integer;
  55. AName, ARole, ACompany, AImagePath, ACheckerMemo: string; ACheckStatus: TCheckStatus;
  56. ACheckeTime: string; ACheckeOnLine: Integer);
  57. var vChecker: TOrderCheckerFrame;
  58. begin
  59. vChecker := TOrderCheckerFrame.Create(Self);
  60. vChecker.Init(AType, AID, AName, ARole, ACompany, AImagePath, ACheckerMemo, ACheckStatus, ACheckeTime, ACheckeOnLine);
  61. sbChecker.Height := sbChecker.Height + vChecker.Height;
  62. vChecker.Parent := sbChecker;
  63. vChecker.Top := FCurPos;
  64. FCurPos := FCurPos + vChecker.Height;
  65. vChecker.Align := alTop;
  66. // 调整位置
  67. case AType of
  68. cftChecker:
  69. begin
  70. vChecker.Name := 'OrderFrame' + IntToStr(AID);
  71. if Assigned(AddFrame) then // 适用于查找审核人添加数据库后,插入Add窗之前
  72. begin
  73. vChecker.Top := AddFrame.Top;
  74. AddFrame.Top := vChecker.Top + vChecker.Height;
  75. OwnerFrame.Top := AddFrame.Top + AddFrame.Height;
  76. FList.Insert(FList.Indexof(AddFrame), vChecker);
  77. end
  78. else
  79. FList.Add(vChecker);
  80. end;
  81. cftOwner: // 保险,保证终审窗一定在Add窗之后
  82. begin
  83. OwnerFrame := vChecker;
  84. vChecker.Name := 'OwnerFrame';
  85. if Assigned(AddFrame) then
  86. OwnerFrame.Top := AddFrame.Top + AddFrame.Height;
  87. FList.Add(vChecker);
  88. end;
  89. cftAdd: // Add窗插入到终审窗之前
  90. begin
  91. AddFrame := vChecker;
  92. vChecker.Name := 'AddFrame';
  93. if Assigned(OwnerFrame) then
  94. begin
  95. AddFrame.Top := OwnerFrame.Top;
  96. OwnerFrame.Top := AddFrame.Top + AddFrame.Height;
  97. FList.Insert(FList.Indexof(OwnerFrame), vChecker);
  98. end
  99. else
  100. FList.Add(vChecker);
  101. end;
  102. end;
  103. end;
  104. procedure TCheckerFrame.Init;
  105. procedure AddChecker(AChecker: ISuperObject; AProj: TProjectData);
  106. var
  107. sID, sPicPath: String;
  108. vStatus: TCheckStatus;
  109. bOwner, bOwnerFinish: Boolean;
  110. iIndex: Integer;
  111. begin
  112. sID := AChecker.S['uid'];
  113. sPicPath := PHPWeb.UserPath + '1_' + sID + '.jpg';
  114. PHPWeb.DownFile(AChecker.S['avatar'], sPicPath);
  115. vStatus := TCheckStatus(AChecker.I['mastatus'] - 1); // Json返回1、2、3、4
  116. bOwner := StrToInt(sID) = TProjectData(ProjectData).WebOwnerID;
  117. if bOwner then // 添加业主
  118. begin
  119. if TProjectData(ProjectData).CurUserIsAuthor then
  120. begin
  121. {如果是编制人,添加业主前先添加Add框。
  122. 数据库中,编制人没有审核人这样的状态。只有跟随标段的两种状态:
  123. ①有标段(顺便记录了编制人,标段是编制人创建的) ②没有标段。
  124. 为什么不通过是否有标段来判断当前是否显示“添加新的审核人”呢?
  125. 因为无法得知当前项目是数据库中已存在的最新一期还是仅存于本地尚末入库
  126. 的最新一期。改由添加的位置给出提示}
  127. if (TProjectData(ProjectData).PhaseIndex > 0) and (not TProjectFrame(Owner).IsUped) then
  128. AddNewChecker(cftAdd, -1, '', '', '', '', '', csNotBegin, '', -1);
  129. end;
  130. AddNewChecker(cftOwner, StrToInt(sID),
  131. AChecker.S['name'], AChecker.S['jobs'], AChecker.S['company'], sPicPath,
  132. AChecker.S['CheckerMemo'], vStatus, AChecker.S['audittime'], AChecker.I['onlineaudit']);
  133. end
  134. else
  135. AddNewChecker(cftChecker, StrToInt(sID),
  136. AChecker.S['name'], AChecker.S['jobs'], AChecker.S['company'], sPicPath,
  137. AChecker.S['CheckerMemo'], vStatus, AChecker.S['audittime'], AChecker.I['onlineaudit']);
  138. iIndex := AProj.Checkers.Add(StrToInt(sID), AChecker.S['name'],
  139. AChecker.S['jobs'], AChecker.S['CheckerMemo'], AChecker.S['audittime']);
  140. if vStatus in [csFinished, csNotPass] then
  141. AProj.Checkers.LastChecker := AProj.Checkers.Item[iIndex]
  142. else
  143. AProj.Checkers.LastChecker := nil;
  144. end;
  145. var
  146. i, iCount: Integer;
  147. sURL, sPicPath, sID, sErrors, sResult: string;
  148. vProj: TProjectData;
  149. bOwner, bOwnerFinish: Boolean;
  150. vJ: ISuperObject;
  151. begin
  152. ClearObjects(FList);
  153. FList.Clear;
  154. OwnerFrame := nil;
  155. AddFrame := nil;
  156. sbChecker.Height := 0;
  157. FCurPos := 0;
  158. vProj := TProjectData(FProjectData);
  159. vProj.Checkers.Clear;
  160. // 这里,这里搞死爹...编制人第一期上报后,关掉项目,重新打开这个项目,第一次,
  161. // 我说的是第一次——一定读取不了审核人列表,但第二次、以后每次都正常。你知道
  162. // 读取不了这个列表的后果有多严重吗?网络版的每个角落都依赖于审核人的角色,所
  163. // 以后果就是直接崩溃,无法使用。查明原因:服务器那头的PHP第一次接收不了传上
  164. // 去的数据,日志显示读取到的数组为空。
  165. // 所以这里把参数移到URL中,通过URL的方式传递,避开用数组传递,问题解决。
  166. // 很明显,这种方式的局限性很大,只适合参数较少的情况。该问题已被珠海纵横公司
  167. // 计量支付网络版研发团队定性为PHP业界的灵异事件。如果哪天你用科学解释了它,请
  168. // 一定要告诉我个中缘由。chenshilong, 2014-07-21
  169. sURL := Format('%suser/get/all/%d/%d/measure', [PHPWeb.MeasureURL, vProj.WebID, vProj.PhaseIndex]);
  170. if PHPWeb.UrlGet(sURL, nil, sResult) = 1 then
  171. begin
  172. vJ := SO(sResult);
  173. try
  174. if not Assigned(vJ.AsArray) then Exit;
  175. iCount := vJ.AsArray.Length;
  176. for i := 0 to iCount - 1 do
  177. AddChecker(vJ.AsArray.O[i], vProj);
  178. RepairOrder;
  179. finally
  180. vJ := nil;
  181. end;
  182. end
  183. else
  184. begin
  185. sErrors := Format('无法读取审批人列表,这将会导致桌面程序崩溃!%s地址:%s%s标段ID:%s,期号:%s',
  186. [#13#10#13#10, sURL, #13#10#13#10, IntToStr(vProj.WebID), IntToStr(vProj.PhaseIndex)]);
  187. Application.MessageBox(PChar(sErrors), '错误', MB_OK + MB_ICONERROR);
  188. Application.Terminate;
  189. end;
  190. end;
  191. function TCheckerFrame.InCheckerList(ACheckerID: Integer): Boolean;
  192. var i: Integer;
  193. begin
  194. Result := False;
  195. for i := 0 to FList.Count - 1 do
  196. begin
  197. if TOrderCheckerFrame(FList[i]).UserID = ACheckerID then
  198. begin
  199. Result := True;
  200. Break;
  201. end;
  202. end;
  203. end;
  204. procedure TCheckerFrame.CheckerNameList(var ASL: TStringList);
  205. var i: Integer;
  206. vFrame: TOrderCheckerFrame;
  207. begin
  208. ASL.Clear;
  209. for i := 0 to FList.Count - 1 do
  210. begin
  211. vFrame := TOrderCheckerFrame(FList[i]);
  212. if vFrame.CheckerFrameType <> cftAdd then
  213. ASL.Add(Format('%s', [vFrame.UserName]));
  214. end;
  215. end;
  216. procedure TCheckerFrame.RepairOrder;
  217. var i: Integer;
  218. begin
  219. for i := 0 to FList.Count - 1 do
  220. TOrderCheckerFrame(FList[i]).Order := i + 1;
  221. end;
  222. function TCheckerFrame.HasNormalChecker: Boolean;
  223. var i: Integer;
  224. begin
  225. Result := False;
  226. for i := 0 to FList.Count - 1 do
  227. begin
  228. if TOrderCheckerFrame(FList[i]).CheckerFrameType = cftChecker then
  229. begin
  230. Result := True;
  231. Break;
  232. end;
  233. end;
  234. end;
  235. constructor TCheckerFrame.Create(AParent: TComponent; AProject: TObject);
  236. begin
  237. inherited Create(AParent);
  238. FProjectData := AProject;
  239. FList := TList.Create;
  240. end;
  241. destructor TCheckerFrame.Destroy;
  242. begin
  243. ClearObjects(FList);
  244. FList.Free;
  245. inherited;
  246. end;
  247. function TCheckerFrame.FirstChecker: TOrderCheckerFrame;
  248. begin
  249. Result := nil;
  250. if FList.Count > 0 then
  251. begin
  252. if TOrderCheckerFrame(FList[0]).CheckerFrameType <> cftAdd then
  253. Result := TOrderCheckerFrame(FList[0])
  254. else
  255. Result := TOrderCheckerFrame(FList[1]);
  256. end;
  257. end;
  258. function TCheckerFrame.NextChecker: TOrderCheckerFrame;
  259. var i: Integer;
  260. vFrame: TOrderCheckerFrame;
  261. begin
  262. Result := nil;
  263. if FList.Count = 0 then Exit;
  264. for i := 0 to FList.Count - 1 do
  265. begin
  266. if (TOrderCheckerFrame(FList[i]).UserID = PHPWeb.UserID) then
  267. begin
  268. if i = (FList.Count - 1) then Exit; // 最后一个
  269. Result := TOrderCheckerFrame(FList[i + 1]);
  270. if Result.CheckerFrameType = cftAdd then
  271. Result := TOrderCheckerFrame(FList[i + 2]);
  272. Break;
  273. end;
  274. end;
  275. end;
  276. function TCheckerFrame.Me: TOrderCheckerFrame;
  277. var i: Integer;
  278. begin
  279. Result := nil;
  280. for i := 0 to FList.Count - 1 do
  281. begin
  282. if TOrderCheckerFrame(FList[i]).UserID = PHPWeb.UserID then
  283. begin
  284. Result := TOrderCheckerFrame(FList[i]);
  285. Break;
  286. end;
  287. end;
  288. end;
  289. procedure TCheckerFrame.RepairDelete(ACanDelete: Boolean);
  290. var i: Integer;
  291. begin
  292. for i := 0 to FList.Count - 1 do
  293. begin
  294. if (TOrderCheckerFrame(FList[i]) <> OwnerFrame) and
  295. (TOrderCheckerFrame(FList[i]) <> AddFrame) then
  296. begin
  297. TOrderCheckerFrame(FList[i]).lblOrderStatus.Visible := (not ACanDelete);
  298. TOrderCheckerFrame(FList[i]).CanDelete := ACanDelete;
  299. end;
  300. end;
  301. end;
  302. procedure TCheckerFrame.tRefreshCheckersTimer(Sender: TObject);
  303. begin
  304. tRefreshCheckers.Enabled := False;
  305. try
  306. init;
  307. RepairDelete(True);
  308. except
  309. ShowMessage('删除成功,这里做了异常保护');
  310. end;
  311. end;
  312. function TCheckerFrame.HasChecker: Boolean;
  313. begin
  314. Result := (FList.Count > 0);
  315. end;
  316. function TCheckerFrame.CheckNo(ACheckStatus: TCheckStatus): Integer;
  317. var i, iCount: Integer;
  318. begin
  319. Result := -1;
  320. for i := 0 to FList.Count - 1 do
  321. begin
  322. if TOrderCheckerFrame(FList[i]).CheckStatus = ACheckStatus then
  323. begin
  324. Result := i + 1;
  325. Break;
  326. end;
  327. end;
  328. end;
  329. function TCheckerFrame.LastChecker: TOrderCheckerFrame;
  330. var i: Integer;
  331. begin
  332. Result := FOwnerFrame;
  333. end;
  334. end.