CheckerFme.pas 11 KB

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