ProjectManagerFme.pas 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800
  1. unit ProjectManagerFme;
  2. interface
  3. uses
  4. ProjectManagerDm, ZhAPI,
  5. NewProjectFrm,
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, ZjGridDBA, ZJGrid, ComCtrls, ToolWin, ActnList,
  8. dxBar, sdGridDBA, sdGridTreeDBA, sdIDTree, CslJson, ExtCtrls,
  9. StdCtrls, sdDB, CslButton, OrderCheckerFme, Contnrs;
  10. type
  11. TStrArr = array of string;
  12. TProjectManagerFrame = class(TFrame)
  13. ToolBar: TToolBar;
  14. tobtnOpen: TToolButton;
  15. zgProjects: TZJGrid;
  16. tobtnDelete: TToolButton;
  17. ActionList1: TActionList;
  18. actnOpen: TAction;
  19. actnDelete: TAction;
  20. dxpmProjectManager: TdxBarPopupMenu;
  21. actnReceiveProject: TAction;
  22. stdProjects: TsdGridTreeDBA;
  23. actnNewProject: TAction;
  24. actnNewSubProject: TAction;
  25. actnNewTender: TAction;
  26. pnlTenderProperty: TPanel;
  27. sdTenderProperty: TsdGridDBA;
  28. sprProperty: TSplitter;
  29. tobtnRenane: TToolButton;
  30. actnRename: TAction;
  31. tobtnImport: TToolButton;
  32. tobtnExport: TToolButton;
  33. actnImport: TAction;
  34. actnExport: TAction;
  35. tobtn1: TToolButton;
  36. pnlWeb: TPanel;
  37. pnlProject: TPanel;
  38. shp2: TShape;
  39. shp1: TShape;
  40. shp3: TShape;
  41. shp4: TShape;
  42. pnlTenderTitle: TPanel;
  43. lblBidName: TLabel;
  44. pnlShadow: TPanel;
  45. pnlProgress: TPanel;
  46. lblPeriodTotal: TLabel;
  47. lblPeriodState: TLabel;
  48. lblProgress: TLabel;
  49. lblPeriod: TLabel;
  50. pnlBelongProject: TPanel;
  51. lblBelongProject: TLabel;
  52. lblProjName: TLabel;
  53. lblLeftHalfBracket: TLabel;
  54. lblOnwerCompany: TLabel;
  55. lblOnwerName: TLabel;
  56. pnlProjectType: TPanel;
  57. lblProjectType: TLabel;
  58. lblWebProjCtgyName: TLabel;
  59. zgTenderProperty: TZJGrid;
  60. actnOpenBackupFolder: TAction;
  61. sbChecker: TScrollBox;
  62. procedure actnOpenExecute(Sender: TObject);
  63. procedure actnDeleteExecute(Sender: TObject);
  64. procedure zgProjectsMouseDown(Sender: TObject; Button: TMouseButton;
  65. Shift: TShiftState; X, Y: Integer);
  66. procedure actnReceiveProjectExecute(Sender: TObject);
  67. procedure actnNewProjectExecute(Sender: TObject);
  68. procedure actnNewSubProjectExecute(Sender: TObject);
  69. procedure actnNewTenderExecute(Sender: TObject);
  70. procedure zgProjectsDrawCellText(ACanvas: TCanvas; const ARect: TRect;
  71. const ACoord: TPoint; AGrid: TZJGrid; const Text: String;
  72. var ADefaultDraw: Boolean);
  73. procedure actnNewSubProjectUpdate(Sender: TObject);
  74. procedure actnNewTenderUpdate(Sender: TObject);
  75. procedure zgProjectsCurrentChanged(Sender: TObject; Col, Row: Integer);
  76. procedure actnSubmitProjectUpdate(Sender: TObject);
  77. procedure actnReplyProjectUpdate(Sender: TObject);
  78. procedure actnRenameExecute(Sender: TObject);
  79. procedure actnOpenUpdate(Sender: TObject);
  80. procedure actnImportExecute(Sender: TObject);
  81. procedure actnExportExecute(Sender: TObject);
  82. procedure actnDeleteUpdate(Sender: TObject);
  83. procedure actnOpenBackupFolderExecute(Sender: TObject);
  84. procedure actnRenameUpdate(Sender: TObject);
  85. procedure zgProjectsShowHint(var HintStr: String; var CanShow: Boolean;
  86. var HintInfo: THintInfo; const ACoord: TPoint);
  87. private
  88. FProjectManagerData: TProjectManagerData;
  89. // Chenshilong,2016.03.24
  90. // 这部分线上和本地一致,无需区分
  91. FID: Integer; // 本地标段文件ID
  92. FWebID: Integer; // 关联服务器用的ID(服务器有自己的ID体系)
  93. FWebAuthorID: Integer; // 编制人
  94. FWebOwnerID: Integer; // 业主
  95. // 本地存储值、线上存储值。线上修改后,需要同步到本地
  96. FWebMD5_Local: string; // 本地存储的MD5
  97. FWebMD5_OnLine: string; // 线上存储的最新的MD5(下同)
  98. FWebBidName_Local: string; // 标段名 (当无法同线上取得联系时,本地需要用到该名称来提示)
  99. FWebBidName_OnLine: string;
  100. FWebFolder_OnLine: string; // 这个命名不妥,但很直观。线上的项目名称、项目类型概念跟本地颠倒,很混乱。
  101. FWebSubFolder_OnLine: string;
  102. FWebOwnerCompany: string;
  103. FWebOwnerRole: string;
  104. FWebOwnerName: string;
  105. FWebCheckStatusMy: TCheckStatus; // 登陆用户在当前项目中的工作状态。
  106. FWebCheckStatusProject: TCheckStatus; // 项目的审核状态。
  107. FOnLineCheckerBegin: Integer; // 线上审批的起始人。 010110111 起7止9。 0101101110 起0止0。
  108. FOnLineCheckerEnd: Integer; // 线上审批的截止人。
  109. FPhaseTotal: Integer;
  110. FPhaseNo: Integer;
  111. FCurPos: Integer; // 用来控制审核人的添加位置
  112. FCheckerList: TObjectList;
  113. function ReceiveFile(const AFileName: string; AIsReback: Boolean = False): Boolean;
  114. function ImportFile(const AFileName: string; AFileMD5: string = ''): Boolean;
  115. procedure ConnectButtonWithAction;
  116. function GetImportProjectName(const AFileName: string; AParent: TsdIDTreeNode): string;
  117. function IsProject(ANode: TsdIDTreeNode): Boolean;
  118. function IsLeafProject(ANode: TsdIDTreeNode): Boolean;
  119. function IsUnEmptyLeafProject(ANode: TsdIDTreeNode): Boolean;
  120. function CheckOpened(ANode: TsdIDTreeNode): Boolean;
  121. procedure SetPropertyVisible(AVisible: Boolean);
  122. procedure ShowProjectInfoTopAndCheckers;
  123. // 网络上的目录结构,本地有则定位,没有则创建。
  124. procedure CheckWebFolders(AFolderID, ASubFolderID: Integer;
  125. AFolderName, ASubFolderName: string);
  126. // ANewBidName: 项目的最新标段名(取自服务器,有人改名了,本地的就变成旧的)
  127. procedure CheckBidName(AID: Integer; ANewBidName: string); overload;
  128. procedure CheckBidName(AUserID, AWebID: Integer; ANewBidName: string); overload;
  129. procedure ClearLocalValues;
  130. procedure GetLocalValues(ARec: TsdDataRecord); overload;
  131. // 用户ID、网络标段ID、Type=1可以定位一个标段。
  132. procedure GetLocalValues(AUserID, AWebID: Integer); overload;
  133. // 1 等待我审核的标段文件; 2 我参与的全部标段文件
  134. procedure DoBatchReceiveOnline(ARequestType: Integer);
  135. function LocalMD5(AUserID, AWebID: Integer): string;
  136. procedure BubbleSortProjects;
  137. // AReceiveKind: 1 接收; 2 导入
  138. function FileDownAndReceive(ADownURL: string; AReceiveKind: Integer): Boolean;
  139. // 线上审批的起止人
  140. procedure OnLineChecker(AAr: TOVArr; var ABegin, AEnd: Integer);
  141. public
  142. constructor Create(AOwner: TComponent); override;
  143. destructor Destroy; override;
  144. procedure DoBatchReceiveAllOnline;
  145. // AType: -2 繁忙; -1 正常读取; 0 第0期; 1 第1期。
  146. procedure ShowProjectInfoTop(AType: Integer = -1);
  147. function Rec(AProjectID: Integer): TsdDataRecord;
  148. function CurRec: TsdDataRecord;
  149. function CurRecAttachmentPath: string;
  150. function AttachmentFileCountsWithoutManageFile(ANode: TsdIDTreeNode): Integer;
  151. property ProjectCheckStatus: TCheckStatus read FWebCheckStatusProject;
  152. end;
  153. implementation
  154. uses
  155. MainFrm, UtilMethods, ProjectCommands, Globals, ConfigDoc, ConstUnit,
  156. WebNewTenderFrm, PHPWebDm, Math, mProgressFrm, ProgressHintFrm,
  157. ShellAPI;
  158. {$R *.dfm}
  159. procedure TProjectManagerFrame.ConnectButtonWithAction;
  160. begin
  161. SetDxBtnAction(actnNewProject, MainForm.dxbtnNewProject);
  162. SetDxBtnAction(actnNewSubProject, MainForm.dxbtnNewSubProject);
  163. SetDxBtnAction(actnNewTender, MainForm.dxbtnNewTender);
  164. SetDxBtnAction(actnOpen, MainForm.dxbtnOpenProject);
  165. SetDxBtnAction(actnDelete, MainForm.dxbtnDeleteProject);
  166. SetDxBtnAction(actnReceiveProject, MainForm.dxbtnReceiveProject);
  167. SetDxBtnAction(actnOpenBackupFolder, MainForm.dxbtnOpenBackupFolder);
  168. SetDxBtnAction(actnRename, MainForm.dxbtnRename);
  169. end;
  170. constructor TProjectManagerFrame.Create(AOwner: TComponent);
  171. begin
  172. inherited;
  173. FCheckerList := TObjectList.Create;
  174. FProjectManagerData := ProjectManager;
  175. FProjectManagerData.Open;
  176. stdProjects.IDTree := FProjectManagerData.ProjectsTree;
  177. sdTenderProperty.DataView := FProjectManagerData.sdvTenderProperty;
  178. ConnectButtonWithAction;
  179. SetPropertyVisible(False);
  180. sbChecker.Height := 0;
  181. if G_IsCloud then
  182. begin
  183. Application.HintPause := 200;
  184. Application.HintHidePause := 60000;
  185. tobtnImport.Visible := False;
  186. stdProjects.TreeOptions := stdProjects.TreeOptions - [aoAllowUpLevel, aoAllowDownLevel];
  187. stdProjects.Options := stdProjects.Options - [aoAllowUpMove, aoAllowDownMove];
  188. CreateProgress('正在从云端下载新项目');
  189. try
  190. actnReceiveProject.Execute;
  191. finally
  192. CloseProgress;
  193. end;
  194. end;
  195. end;
  196. function SearchFileOnline(AURL: string; var ADownURL, AFolder, ASubFolder, ABidName, AMD5Web, AError: string;
  197. var AFolderID, ASubFolderID: Integer): Integer;
  198. var vArr: TOVArr;
  199. begin
  200. Result := PHPWeb.Search(AURL, [''], [''], vArr);
  201. AError := '';
  202. if Result = 1 then
  203. begin
  204. if High(vArr) >= 0 then
  205. begin
  206. ADownURL := vArr[0, 0];
  207. AFolder := vArr[0, 2];
  208. ASubFolder := vArr[0, 3];
  209. AMD5Web := vArr[0, 1];
  210. AFolderID := StrToInt(vArr[0, 4]);
  211. ASubFolderID := StrToInt(vArr[0, 5]);
  212. ABidName := vArr[0, 6];
  213. end
  214. else
  215. Result := 10; // 返回10,表示无记录。用这个数字代表是否觉得怪异?没办法,0被占用了。
  216. end
  217. else if Result = 0 then
  218. AError := PHPWeb.PageError('标段更新数据失败')
  219. else if Result = -1 then
  220. AError := PHPWeb.NetError('标段更新数据失败');
  221. end;
  222. // 双击打开项目 TagB
  223. procedure TProjectManagerFrame.actnOpenExecute(Sender: TObject);
  224. var
  225. vSel: TsdIDTreeNode;
  226. vRec: TsdDataRecord;
  227. sHint: string;
  228. function CanOpen: Boolean;
  229. var
  230. sSearchURL, sDownURL,
  231. sMD5_UnLock, sError, sLocalFile: string;
  232. iSearch, iFolderID, iSubFolderID: Integer;
  233. function HasWebBidInfo(AWebID: Integer): Boolean;
  234. var vArr: array of string;
  235. iResult: Integer;
  236. begin
  237. sSearchURL := Format('%stender/get/%d/exist', [PHPWeb.MeasureURL, AWebID]);
  238. vArr := VarArrayOf(['id', 'name']);
  239. iResult := PHPWeb.Search(sSearchURL, [''], [''], vArr);
  240. if (iResult = 1) and (High(vArr) >= 0) then
  241. Result := True
  242. else
  243. Result := False;
  244. end;
  245. begin
  246. Result := False;
  247. // 先按正常接口找到最新的MD5码看是否需要更新
  248. sSearchURL := Format('%stender/get/%d/update', [PHPWeb.MeasureURL, FWebID]);
  249. iSearch := SearchFileOnline(sSearchURL, sDownURL, FWebFolder_OnLine, FWebSubFolder_OnLine, FWebBidName_OnLine, FWebMD5_OnLine, sError, iFolderID, iSubFolderID);
  250. if iSearch = 1 then
  251. begin
  252. try
  253. CheckWebFolders(iFolderID, iSubFolderID, FWebFolder_OnLine, FWebSubFolder_OnLine);
  254. CheckBidName(FID, FWebBidName_OnLine);
  255. finally
  256. if vSel <> nil then
  257. vSel.LocateInControl;
  258. end;
  259. // 打开前一定要先下载最新的标段文件(无论审核有没有通过)
  260. if FWebMD5_OnLine <> FWebMD5_Local then
  261. if not FileDownAndReceive(sDownURL, 1) then Exit;
  262. // 编制人且项目末通过
  263. if (FWebAuthorID = PHPWeb.UserID) and (FWebCheckStatusProject = csNotPass) then
  264. begin
  265. sHint := '本期计量审批不通过,你现在可以:' + #10#13 + '点击【是(Y)】重新开始本期计量,软件将打开本期上报时的数据,开始重新计量;' +
  266. #10#13 +'点击【否(N)】查看不通过计量,软件将打开本期最后审批的数据,重新打开标段' + '可再次打开本确认窗口。';
  267. if Application.MessageBox(PChar(sHint), '询问', MB_YESNO + MB_ICONQUESTION) = ID_Yes then
  268. begin
  269. sSearchURL := Format('%suser/create/%d/%d/new/audit', [PHPWeb.MeasureURL, FWebID, FPhaseNo]);
  270. case SearchFileOnline(sSearchURL, sDownURL, FWebFolder_OnLine, FWebSubFolder_OnLine, FWebBidName_OnLine, sMD5_UnLock, sError, iFolderID, iSubFolderID) of
  271. 1:
  272. begin
  273. if not FileDownAndReceive(sDownURL, 2) then Exit;
  274. end;
  275. 0, -1:
  276. begin
  277. sHint := sError + '(因网络出错,无法连接到云端以获取本期原报上传的无锁文件,无法重新开始本期,本次操作已取消。请重试。';
  278. Application.MessageBox(PChar(sHint), '警告', MB_OK + MB_ICONWARNING);
  279. Exit;
  280. end;
  281. end;
  282. end;
  283. end;
  284. end
  285. else if (iSearch = 10) then
  286. begin
  287. if not HasWebBidInfo(FWebID) then
  288. begin
  289. sHint :='该项目[' + FWebBidName_Local + ']在云端已被删除,点击"确定"后,可手动删除该项目。';
  290. Application.MessageBox(PChar(sHint), '提示', MB_OK + MB_ICONINFORMATION);
  291. Exit;
  292. end;
  293. end
  294. else if (iSearch = 0) or (iSearch = -1) then
  295. begin
  296. sHint := sError + '(因网络出错,无法检测[' + FWebBidName_Local + ']在云端是否有更新,本次操作已取消,请重试)。';
  297. Application.MessageBox(PChar(sHint), '警告', MB_OK + MB_ICONWARNING);
  298. Exit;
  299. end;
  300. Result := True;
  301. end;
  302. begin
  303. // 打开前先下载更新
  304. Screen.Cursor := crHourGlass;
  305. try
  306. vSel := stdProjects.IDTree.Selected;
  307. vRec := vSel.Rec;
  308. if G_IsCloud then
  309. begin
  310. GetLocalValues(CurRec);
  311. // 以下这段已经包含在MainForm.OpenProject(vRec)中了,但在调用这句之前,网络版要提前用一下。
  312. if MainForm.HasOpened(FID) then
  313. begin
  314. MainForm.LocateProject(FID);
  315. Exit;
  316. end;
  317. if not CanOpen then
  318. Exit;
  319. end;
  320. MainForm.OpenProject(vRec);
  321. if G_IsCloud then
  322. begin
  323. if not MainForm.CurProjectFrame.CheckFileAndCloudChekerList then
  324. begin
  325. sHint := '项目校验:“' + FWebBidName_OnLine + '”文件中的审核人和云端的审核人不一致,' +
  326. '禁止继续操作,项目即将关闭!请删除本地项目重新从云端获取,' +
  327. '重新获取后如果仍然存在同样的问题,请联系纵横服务人员以寻求帮助。';
  328. Application.MessageBox(PChar(sHint), '文件错误', MB_OK +MB_ICONWARNING);
  329. MainForm.actnCloseProject.Execute;
  330. Exit;
  331. end;
  332. end;
  333. finally
  334. Screen.Cursor := crDefault;
  335. end;
  336. end;
  337. procedure TProjectManagerFrame.actnDeleteExecute(Sender: TObject);
  338. begin
  339. if stdProjects.IDTree.Count = 0 then Exit;
  340. with stdProjects.IDTree.Selected.Rec do
  341. if QuestMessage(Format('确定要删除[%s]吗?', [ValueByName('Name').AsString])) then
  342. begin
  343. Screen.Cursor := crHourGlass;
  344. try
  345. FProjectManagerData.Delete;
  346. finally
  347. Screen.Cursor := crDefault;
  348. end;
  349. end;
  350. end;
  351. procedure TProjectManagerFrame.zgProjectsMouseDown(Sender: TObject;
  352. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  353. begin
  354. if Button = mbRight then
  355. dxpmProjectManager.PopupFromCursorPos
  356. else if (zgProjects.CurCol = 1) and (Button = mbLeft) and (ssDouble in Shift)
  357. and Assigned(stdProjects.IDTree.Selected) then
  358. begin
  359. if IsProject(stdProjects.IDTree.Selected) then
  360. stdProjects.IDTree.Selected.Expand
  361. else
  362. actnOpen.Execute;
  363. end;
  364. end;
  365. function TProjectManagerFrame.ReceiveFile(const AFileName: string; AIsReback: Boolean): Boolean;
  366. var
  367. vRP: TReceiveProject;
  368. vNode: TsdIDTreeNode;
  369. bLock, bIsOwner: Boolean;
  370. begin
  371. Result := False;
  372. vRP := TReceiveProject.Create(stdProjects.IDTree.Selected);
  373. try
  374. ProjectManager.RefreshSeedID;
  375. if G_IsCloud then
  376. begin
  377. vRP.IsReback := AIsReback;
  378. bLock := (FWebAuthorID = PHPWeb.UserID) or
  379. ((FWebAuthorID <> PHPWeb.UserID) and (FWebCheckStatusMy <> csChecking));
  380. vRP.Lock := bLock;
  381. bIsOwner := FWebOwnerID = PHPWeb.UserID;
  382. vNode := vRP.ReceiveForLost(AFileName, FOnLineCheckerBegin, FOnLineCheckerEnd, bIsOwner);
  383. if vNode <> nil then
  384. begin
  385. vNode.Rec.BeginUpdate;
  386. vNode.Rec.ValueByName('WebMD5').AsString := FWebMD5_OnLine;
  387. vNode.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
  388. vNode.Rec.EndUpdate;
  389. end;
  390. end
  391. else
  392. vNode := vRP.Receive(AFileName);
  393. finally
  394. case vRP.MessageID of
  395. 0: begin
  396. Result := True;
  397. vNode.LocateInControl;
  398. end;
  399. 1: ErrorMessage('当前标段处于打开状态,未能成功接收,请先关闭标段再次接收。');
  400. 2: ErrorMessage('下载数据与审核状态不一致,未能成功接收,请再次接收。');
  401. 3: ErrorMessage('升级数据失败,未能成功接收,请再次接收。');
  402. end;
  403. vRP.Free;
  404. FProjectManagerData.Save;
  405. end;
  406. end;
  407. // 登录后自动扫描等待我审核的项目 TagC
  408. procedure TProjectManagerFrame.actnReceiveProjectExecute(Sender: TObject);
  409. procedure DoReceiveLocal;
  410. var
  411. sFileName: string;
  412. begin
  413. if SelectFile(sFileName, '.rmf;*.arf') then
  414. begin
  415. ShowProgressHint('正在接收项目并升级数据');
  416. try
  417. ReceiveFile(sFileName);
  418. finally
  419. CloseProgressHint;
  420. end;
  421. end;
  422. end;
  423. var OnCC: TZjCellNotifyEvent;
  424. begin
  425. Screen.Cursor := crHourGlass;
  426. try
  427. if G_IsCloud then
  428. begin
  429. OnCC := zgProjects.OnCurrentChanged;
  430. try
  431. zgProjects.OnCurrentChanged := nil;
  432. DoBatchReceiveOnline(1);
  433. if stdProjects.IDTree.FirstNode <> nil then
  434. stdProjects.IDTree.FirstNode.LocateInControl;
  435. finally
  436. zgProjects.OnCurrentChanged := OnCC;
  437. end;
  438. end
  439. else
  440. DoReceiveLocal;
  441. finally
  442. Screen.Cursor := crDefault;
  443. end;
  444. end;
  445. function TProjectManagerFrame.GetImportProjectName(
  446. const AFileName: string; AParent: TsdIDTreeNode): string;
  447. begin
  448. Result := ExtractSimpleFileName(AFileName);
  449. while FProjectManagerData.ExistProject(Result, AParent) do
  450. if not InputNewProjectName(Result, '导入', AParent) then Abort;
  451. end;
  452. procedure TProjectManagerFrame.actnNewProjectExecute(Sender: TObject);
  453. var
  454. sName: string;
  455. begin
  456. if G_IsCloud then Exit; // 云版线上与本地要保持同步,不允许本地新建
  457. if InputNewProjectName(sName, '新建', stdProjects.IDTree.Selected) then
  458. FProjectManagerData.InsertProject(sName, stdProjects.IDTree.Selected);
  459. end;
  460. procedure TProjectManagerFrame.actnNewSubProjectExecute(Sender: TObject);
  461. var
  462. sName: string;
  463. begin
  464. if G_IsCloud then Exit;
  465. if InputNewProjectName(sName, '新建', stdProjects.IDTree.Selected) then
  466. FProjectManagerData.InsertSubProject(sName, stdProjects.IDTree.Selected);
  467. end;
  468. procedure TProjectManagerFrame.actnNewTenderExecute(Sender: TObject);
  469. function AddAndOpenTender(const ATenderName: string): TsdIDTreeNode;
  470. begin
  471. Result := FProjectManagerData.InsertTender(ATenderName, stdProjects.IDTree.Selected);
  472. MainForm.OpenProject(Result.Rec);
  473. end;
  474. // 网络版新建标段 TagD
  475. procedure NewProjectWithOnline;
  476. var
  477. WebNewTenderForm: TWebNewTenderForm;
  478. sName, sKey, sURL: string;
  479. stnNew: TsdIDTreeNode;
  480. iID, iFolderID, iSubFolderID: Integer;
  481. vRec: TsdDataRecord;
  482. vArr: array of string;
  483. begin
  484. WebNewTenderForm := TWebNewTenderForm.Create(nil);
  485. try
  486. WebNewTenderForm.ShowModal;
  487. if WebNewTenderForm.ModalResult = mrOK then
  488. begin
  489. sKey := WebNewTenderForm.edtKey.Text;
  490. sName := WebNewTenderForm.edtTenderName.Text;
  491. // 同服务器取得联系
  492. iID := -1;
  493. vArr := VarArrayOf(['catid', 'name', 'company', 'phone', 'mobile', 'qq',
  494. 'pname', 'ptype', 'jobs', 'avatar', 'ownuid', 'pnameid', 'ptypeid']);
  495. sURL := Format('%s%d/%s/%s/creatmeasure', [PHPWeb.MeasureURL, PHPWeb.UserID, sName, sKey]); // AnsiToUtf8(sName)
  496. case PHPWeb.Search(sURL, [], [], vArr) of
  497. 1:
  498. begin
  499. iID := StrToInt(vArr[0]);
  500. iFolderID := StrToInt(vArr[11]);
  501. iSubFolderID := StrToInt(vArr[12]);
  502. CheckWebFolders(iFolderID, iSubFolderID, vArr[6], vArr[7]);
  503. end;
  504. 0:
  505. begin
  506. Application.MessageBox(PChar(PHPWeb.PageError('创建标段失败' + '[' + vArr[0] + ']')),
  507. '警告', MB_OK + MB_ICONWARNING);
  508. Exit;
  509. end;
  510. -1:
  511. begin
  512. Application.MessageBox(PChar(PHPWeb.NetError('创建标段失败')),
  513. '警告', MB_OK + MB_ICONWARNING);
  514. Exit;
  515. end;
  516. end;
  517. // 本地创建
  518. stnNew := FProjectManagerData.InsertTender(sName, stdProjects.IDTree.Selected);
  519. // 这里把Web获取的信息存储到项目管理里面。
  520. vRec := stnNew.Rec;
  521. vRec.BeginUpdate;
  522. vRec.ValueByName('WebID').AsInteger := iID;
  523. vRec.ValueByName('WebOwnerID').AsInteger := StrToInt(vArr[10]); // 业主
  524. vRec.ValueByName('WebAuthorID').AsInteger := PHPWeb.UserID; // 编制人
  525. vRec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID; // 当前用户,用于只显示自己的项目
  526. vRec.ValueByName('WebKey').AsString := sKey;
  527. vRec.EndUpdate;
  528. GetLocalValues(vRec);
  529. FWebOwnerName := vArr[1];
  530. FWebOwnerCompany := vArr[2];
  531. FWebOwnerRole := vArr[8];
  532. FWebFolder_OnLine := vArr[6];
  533. FWebSubFolder_OnLine := vArr[7];
  534. // WebOwnerImage := vArr[9];
  535. // WebOwnerPhone := vArr[3];
  536. // WebOwnerMobile := vArr[4];
  537. // WebOwnerQQ := vArr[5];
  538. ShowProjectInfoTop(0);
  539. FProjectManagerData.Save;
  540. MainForm.OpenProject(vRec);
  541. end;
  542. finally
  543. WebNewTenderForm.Free;
  544. end;
  545. end;
  546. procedure NewProject;
  547. var
  548. sName: string;
  549. begin
  550. if InputNewProjectName(sName, '新建', stdProjects.IDTree.Selected) then
  551. AddAndOpenTender(sName);
  552. end;
  553. begin
  554. if G_IsCloud then
  555. NewProjectWithOnline
  556. else
  557. NewProject;
  558. end;
  559. procedure TProjectManagerFrame.zgProjectsDrawCellText(ACanvas: TCanvas;
  560. const ARect: TRect; const ACoord: TPoint; AGrid: TZJGrid;
  561. const Text: String; var ADefaultDraw: Boolean);
  562. procedure GetBitmap(AImage: TBitmap; ANode: TsdIDTreeNode);
  563. begin
  564. if Assigned(ANode) and Assigned(ANode.Rec) then
  565. begin
  566. if ANode.Rec.ValueByName('Type').AsInteger = 0 then
  567. if ANode.Expanded and ANode.HasChildren then
  568. MainForm.Images.GetBitmap(34, AImage)
  569. else
  570. MainForm.Images.GetBitmap(34, AImage)
  571. else
  572. MainForm.Images.GetBitmap(11, AImage);
  573. end
  574. else
  575. AImage := nil;
  576. end;
  577. const
  578. rIconWidth = 16;
  579. rIconHeight = 16;
  580. var
  581. Img: TBitmap;
  582. Cell: TZjCell;
  583. rImg: TRect;
  584. vNode: TsdIDTreeNode;
  585. begin
  586. if (ACoord.X = 1) and (ACoord.Y > zgProjects.FixedRowCount - 1) then
  587. begin
  588. Cell := zgProjects.Cells[ACoord.X, ACoord.Y];
  589. Img := TBitmap.Create;
  590. try
  591. vNode := stdProjects.IDTree.Items[ACoord.Y-zgProjects.FixedRowCount];
  592. GetBitmap(Img, vNode);
  593. case Cell.Align of
  594. gaTopLeft, gaTopCenter, gaTopRight:
  595. rImg := Rect(ARect.Left + 2, ARect.Top, ARect.Left + rIconWidth, ARect.Top + rIconHeight);
  596. gaCenterLeft, gaCenterCenter, gaCenterRight:
  597. rImg := Rect(ARect.Left + 2, ARect.Top + (ARect.Bottom - ARect.Top - rIconHeight) div 2, ARect.Left + rIconWidth, ARect.Bottom - (ARect.Bottom - ARect.Top - rIconHeight) div 2);
  598. gaBottomLeft, gaBottomCenter, gaBottomRight:
  599. rImg := Rect(ARect.Left + 2, ARect.Bottom - rIconHeight, ARect.Left + rIconWidth, ARect.Bottom);
  600. end;
  601. ACanvas.StretchDraw(rImg, Img);
  602. WriteText(ACanvas, Rect(ARect.Left + rIconWidth, ARect.Top, ARect.Right, ARect.Bottom)
  603. , 2, 2, Text, Cell.Align, False);
  604. ADefaultDraw := False;
  605. finally
  606. Img.Free;
  607. end;
  608. end;
  609. end;
  610. procedure TProjectManagerFrame.actnNewSubProjectUpdate(Sender: TObject);
  611. begin
  612. TAction(Sender).Enabled := Assigned(stdProjects.IDTree.Selected)
  613. and IsProject(stdProjects.IDTree.Selected)
  614. and (not IsUnEmptyLeafProject(stdProjects.IDTree.Selected));
  615. end;
  616. procedure TProjectManagerFrame.actnNewTenderUpdate(Sender: TObject);
  617. var bCloud: Boolean;
  618. vNode: TsdIDTreeNode;
  619. begin
  620. bCloud := G_IsCloud;
  621. // 只有编制人才能创建新标段?逻辑先后有问题:编制人是在创建标段之后产生的。
  622. // 创建前,当前用户只是一个帐户,它是不是编制人末知,因为它还可以是其它角色。
  623. // 同一帐户在不同的标段可以作为不同的角色。
  624. if bCloud then
  625. begin
  626. TAction(Sender).Enabled := True;
  627. end
  628. else
  629. begin
  630. vNode := stdProjects.IDTree.Selected;
  631. TAction(Sender).Enabled := Assigned(vNode) and IsProject(vNode) and IsLeafProject(vNode);
  632. end;
  633. end;
  634. function TProjectManagerFrame.IsLeafProject(ANode: TsdIDTreeNode): Boolean;
  635. begin
  636. if ANode.HasChildren then
  637. Result := ANode.FirstChild.Rec.ValueByName('Type').AsInteger = 1
  638. else
  639. Result := ANode.Rec.ValueByName('Type').AsInteger = 0;
  640. end;
  641. function TProjectManagerFrame.IsProject(ANode: TsdIDTreeNode): Boolean;
  642. begin
  643. Result := ANode.Rec.ValueByName('Type').AsInteger = 0;
  644. end;
  645. function TProjectManagerFrame.IsUnEmptyLeafProject(
  646. ANode: TsdIDTreeNode): Boolean;
  647. begin
  648. Result := ANode.HasChildren and (ANode.Rec.ValueByName('Type').AsInteger = 1);
  649. end;
  650. procedure TProjectManagerFrame.SetPropertyVisible(AVisible: Boolean);
  651. begin
  652. // 单击刷新项目信息 TagA
  653. if G_IsCloud then
  654. begin
  655. if CurRec = nil then Exit;
  656. pnlTenderProperty.Visible := False;
  657. pnlWeb.Visible := AVisible;
  658. if AVisible then
  659. begin
  660. CreateProgress('云端读取项目信息');
  661. try
  662. ShowProjectInfoTopAndCheckers;
  663. finally
  664. CloseProgress;
  665. end;
  666. end;
  667. end
  668. else
  669. begin
  670. pnlWeb.Visible := False;
  671. pnlTenderProperty.Visible := AVisible;
  672. sprProperty.Visible := AVisible;
  673. end;
  674. end;
  675. procedure TProjectManagerFrame.zgProjectsCurrentChanged(Sender: TObject;
  676. Col, Row: Integer);
  677. begin
  678. if G_IsCloud then
  679. begin
  680. if CurRec <> nil then
  681. begin
  682. // 加这句后产生Bug:上报项目后,记录不曾移动,FID不变,不会刷新
  683. // if FID <> CurRec.ValueByName('ID').AsInteger then
  684. SetPropertyVisible(CurRec.ValueByName('Type').AsInteger = 1);
  685. // OnCurrentChanged取得的 CurRec.ValueByName() 值并不总是可靠,这里加保险。
  686. // 如调用locateInControl后,执行到这里取得的CurRec.ValueByName('ID')值还是上一条的。
  687. if (CurRec.ValueByName('Type').AsInteger = 1) and (not pnlWeb.Visible) then
  688. pnlWeb.Visible := True;
  689. end;
  690. end;
  691. end;
  692. procedure TProjectManagerFrame.actnSubmitProjectUpdate(Sender: TObject);
  693. begin
  694. TAction(Sender).Enabled := Assigned(stdProjects.IDTree.Selected)
  695. and (stdProjects.IDTree.Selected.Rec.ValueByName('Type').AsInteger = 1)
  696. and (stdProjects.IDTree.Selected.Rec.ValueByName('AuditStatus').AsInteger < iMaxStageCount-1);
  697. end;
  698. procedure TProjectManagerFrame.actnReplyProjectUpdate(Sender: TObject);
  699. begin
  700. TAction(Sender).Enabled := Assigned(stdProjects.IDTree.Selected)
  701. and (stdProjects.IDTree.Selected.Rec.ValueByName('Type').AsInteger = 1);
  702. end;
  703. procedure TProjectManagerFrame.actnRenameExecute(Sender: TObject);
  704. function CanRename(ARec: TsdDataRecord; const ANewName: string): Boolean;
  705. var
  706. sURL: string;
  707. iRename: Integer;
  708. vArr: array of string;
  709. begin
  710. Result := True;
  711. if not G_IsCloud then Exit;
  712. // 云版 重命名须确保同步服务器
  713. sURL := Format('%stender/%d/%s/update', [PHPWeb.MeasureURL, ARec.ValueByName('WebID').AsInteger, ANewName]);
  714. iRename := PHPWeb.Search(sURL, [], [], vArr);
  715. Result := iRename = 1;
  716. case iRename of
  717. 1: ShowMessage('新的标段名称已同步到服务器!');
  718. 0: Application.MessageBox(PChar(PHPWeb.PageError('重命名同步到云端失败' + '[' + vArr[0] + ']')),
  719. '警告', MB_OK + MB_ICONWARNING);
  720. -1: Application.MessageBox(PChar(PHPWeb.NetError('重命名同步到云端失败')),
  721. '警告', MB_OK + MB_ICONWARNING);
  722. end;
  723. end;
  724. var
  725. stnNode: TsdIDTreeNode;
  726. sName: string;
  727. begin
  728. stnNode := stdProjects.IDTree.Selected;
  729. sName := stnNode.Rec.ValueByName('Name').AsString;
  730. if not Assigned(OpenProjectManager.FindProjectData(stnNode.ID)) then
  731. begin
  732. if InputNewProjectName(sName, '重命名', stnNode.Parent, stnNode.ID) then
  733. begin
  734. if CanRename(stnNode.Rec, sName) then
  735. begin
  736. stnNode.Rec.ValueByName('Name').AsString := sName;
  737. ProjectManager.Save;
  738. end;
  739. end;
  740. end
  741. else
  742. ErrorMessage(Format('项目[%s]已经打开,无法重命名!', [sName]));
  743. end;
  744. procedure TProjectManagerFrame.actnOpenUpdate(Sender: TObject);
  745. begin
  746. TAction(Sender).Enabled := Assigned(stdProjects.IDTree.Selected)
  747. and (stdProjects.IDTree.Selected.Rec.ValueByName('Type').AsInteger = 1);
  748. end;
  749. procedure TProjectManagerFrame.actnImportExecute(Sender: TObject);
  750. procedure ImportTender(const AFileName, AProjectName: string);
  751. var
  752. Importor: TTenderImport;
  753. begin
  754. Importor := TTenderImport.Create(stdProjects.IDTree.Selected,
  755. AProjectName, AFileName);
  756. try
  757. Importor.Execute;
  758. finally
  759. Importor.Free;
  760. end;
  761. end;
  762. procedure ImportProject(const AFileName, AProjectName: string);
  763. var
  764. Importor: TProjectImport;
  765. begin
  766. Importor := TProjectImport.Create(stdProjects.IDTree.Selected,
  767. AProjectName, AFileName);
  768. try
  769. Importor.Execute;
  770. finally
  771. Importor.Free;
  772. end;
  773. end;
  774. var
  775. sFileName, sProjectName: string;
  776. vCur: TsdIDTreeNode;
  777. begin
  778. if SelectFile(sFileName, '.mtf;*.mpf') then
  779. begin
  780. vCur := stdProjects.IDTree.Selected;
  781. if Assigned(vCur) then
  782. begin
  783. if SameText(ExtractFileExt(sFileName), '.mtf')
  784. and (vCur.Rec.ValueByName('Type').AsInteger = 0) then
  785. sProjectName := GetImportProjectName(sFileName, stdProjects.IDTree.Selected)
  786. else
  787. sProjectName := GetImportProjectName(sFileName, stdProjects.IDTree.Selected.Parent);
  788. end
  789. else
  790. sProjectName := GetImportProjectName(sFileName, vCur);
  791. Screen.Cursor := crHourGlass;
  792. try
  793. if SameText(ExtractFileExt(sFileName), '.mtf') then
  794. ImportTender(sFileName, sProjectName)
  795. else
  796. ImportProject(sFileName, sProjectName);
  797. finally
  798. Screen.Cursor := crDefault;
  799. end;
  800. end;
  801. FProjectManagerData.Save;
  802. end;
  803. procedure TProjectManagerFrame.actnExportExecute(Sender: TObject);
  804. procedure ExportTender(ANode: TsdIDTreeNode);
  805. var
  806. Exportor: TTenderExport;
  807. sFileName, sHint: string;
  808. bExpAtch: Boolean;
  809. iCount: Integer;
  810. begin
  811. bExpAtch := False;
  812. sFileName := SupportManager.ConfigInfo.OutputPath + ANode.Rec.ValueByName('Name').AsString + '.mtf';
  813. if SaveFile(sFileName, '.mtf') then
  814. begin
  815. if FileExists(sFileName) and not QuestMessage(Format('存在同名文件“%s”,是否替换?', [ExtractFileName(sFileName)])) then
  816. Exit;
  817. Screen.Cursor := crHourGlass;
  818. try
  819. Exportor := TTenderExport.Create(ANode.Rec, sFileName);
  820. try
  821. { if not G_IsCloud then
  822. begin
  823. iCount := FileCount(CurRecAttachmentPath);
  824. if iCount > 1 then // 排除管理文件库
  825. begin
  826. sHint := Format('本标段包含 %d 个附件,是否将附件一起导出?', [iCount - 1]);
  827. bExpAtch := Application.MessageBox(PChar(sHint), '询问', MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2) = ID_Yes;
  828. end;
  829. end; } // FFFFF
  830. Exportor.Execute(bExpAtch);
  831. finally
  832. Exportor.Free;
  833. end;
  834. finally
  835. Screen.Cursor := crDefault;
  836. end;
  837. end;
  838. end;
  839. procedure ExportProject(ANode: TsdIDTreeNode);
  840. var
  841. Exportor: TProjectExport;
  842. sFileName, sHint: string;
  843. bExpAtch: Boolean;
  844. iCount: Integer;
  845. begin
  846. sFileName := SupportManager.ConfigInfo.OutputPath + ANode.Rec.ValueByName('Name').AsString + '.mpf';
  847. if SaveFile(sFileName, '.mpf') then
  848. begin
  849. if FileExists(sFileName) and not QuestMessage(Format('存在同名文件“%s”,是否替换?', [ExtractFileName(sFileName)])) then
  850. Exit;
  851. Screen.Cursor := crHourGlass;
  852. try
  853. bExpAtch := False;
  854. { if not G_IsCloud then
  855. begin
  856. iCount := AttachmentFileCountsWithoutManageFile(ANode);
  857. if iCount > 0 then
  858. begin
  859. sHint := Format('本建设项目共包含 %d 个附件,是否将附件一起导出?', [iCount]);
  860. bExpAtch := Application.MessageBox(PChar(sHint), '询问', MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2) = ID_Yes;
  861. end;
  862. end; } // FFFFF
  863. Exportor := TProjectExport.Create(ANode, sFileName, bExpAtch);
  864. try
  865. Exportor.Execute;
  866. finally
  867. Exportor.Free;
  868. end;
  869. finally
  870. Screen.Cursor := crDefault;
  871. end;
  872. end;
  873. end;
  874. var
  875. stnNode: TsdIDTreeNode;
  876. begin
  877. stnNode := stdProjects.IDTree.Selected;
  878. if stnNode.Rec.ValueByName('Type').AsInteger = 1 then
  879. begin
  880. ExportTender(stnNode);
  881. end
  882. else
  883. ExportProject(stnNode);
  884. end;
  885. procedure TProjectManagerFrame.actnDeleteUpdate(Sender: TObject);
  886. begin
  887. if Assigned(stdProjects.IDTree.Selected) then
  888. TAction(Sender).Enabled := not CheckOpened(stdProjects.IDTree.Selected);
  889. end;
  890. function TProjectManagerFrame.CheckOpened(ANode: TsdIDTreeNode): Boolean;
  891. var
  892. iChild: Integer;
  893. begin
  894. Result := False;
  895. if ANode.Rec.ValueByName('Type').AsInteger = 1 then
  896. Result := OpenProjectManager.ProjectIndex(ANode.ID) > -1
  897. else
  898. begin
  899. if not ANode.HasChildren then
  900. Result := False
  901. else
  902. begin
  903. for iChild := 0 to ANode.ChildCount - 1 do
  904. Result := Result or CheckOpened(ANode.ChildNodes[iChild]);
  905. end
  906. end;
  907. end;
  908. procedure TProjectManagerFrame.ShowProjectInfoTopAndCheckers;
  909. var
  910. vPSArr: TStrArr;
  911. vCArr: TOVArr; // Checkers
  912. vChecker: TOrderCheckerFrame;
  913. sPicPath, sURL: string;
  914. procedure AddChecker(AType: TCheckerFrameType; AArr: array of string);
  915. begin
  916. vChecker := TOrderCheckerFrame.Create(self);
  917. FCheckerList.Add(vChecker);
  918. vChecker.Owner := Self;
  919. sbChecker.VertScrollBar.Range := sbChecker.VertScrollBar.Range + vChecker.Height;
  920. sbChecker.Height := Min(sbChecker.Height + vChecker.Height, pnlWeb.Height - pnlProject.Height);
  921. vChecker.Parent := sbChecker;
  922. vChecker.Top := FCurPos;
  923. FCurPos := FCurPos + vChecker.Height;
  924. vChecker.Align := alTop;
  925. sPicPath := PHPWeb.UserPath + '1_' + AArr[0] + '.jpg';
  926. PHPWeb.DownFile(AArr[4], sPicPath);
  927. vChecker.Init(AType, StrToInt(AArr[0]), AArr[1], AArr[3],
  928. AArr[2], sPicPath, AArr[6], TCheckStatus(StrToInt(AArr[5])-1), AArr[8], StrToInt(AArr[7]));
  929. vChecker.Name := 'ProjectOrderFrame' + AArr[0];
  930. end;
  931. procedure RepairOrder;
  932. var k: Integer;
  933. begin
  934. for k := 0 to sbChecker.ControlCount - 1 do
  935. TOrderCheckerFrame(sbChecker.Controls[k]).Order := k + 1;
  936. end;
  937. procedure ShowProjectCheckers;
  938. var i, j, n: Integer;
  939. vOwner: array of string; // 业主信息
  940. begin
  941. FCheckerList.Clear;
  942. sbChecker.Height := 0;
  943. FCurPos := 0;
  944. n := Length(vCArr[Low(vCArr)]);
  945. SetLength(vOwner, n);
  946. sbChecker.VertScrollBar.Range := 0;
  947. for i := Low(vCArr) to High(vCArr) do
  948. begin
  949. if StrToInt(vCArr[i, 0]) = PHPWeb.UserID then
  950. FWebCheckStatusMy := TCheckStatus(StrToInt(vCArr[i, 5])-1);
  951. if StrToInt(vCArr[i, 0]) = FWebOwnerID then
  952. begin
  953. for j := 0 to n - 1 do
  954. vOwner[j] := vCArr[i, j];
  955. Continue;
  956. end;
  957. AddChecker(cftChecker, vCArr[i]);
  958. end;
  959. if vOwner[0] <> '' then
  960. AddChecker(cftOwner, vOwner);
  961. RepairOrder;
  962. OnLineChecker(vCArr, FOnLineCheckerBegin, FOnLineCheckerEnd);
  963. end;
  964. begin
  965. GetLocalValues(CurRec);
  966. if FWebID = 0 then Exit;
  967. SetLength(vPSArr, 8);
  968. sURL := Format('%smeasure/status/%d/get', [PHPWeb.MeasureURL, FWebID]);
  969. if PHPWeb.Search(sURL, [''], [''], 3, vPSArr, vCArr) = 1 then
  970. begin
  971. LockWindowUpdate(pnlWeb.Handle);
  972. try
  973. FPhaseNo := StrToInt(vPSArr[0]);
  974. FWebCheckStatusProject := TCheckStatus(StrToInt(vPSArr[1])-1);
  975. FPhaseTotal := StrToInt(vPSArr[2]);
  976. FWebFolder_OnLine := vPSArr[3];
  977. FWebSubFolder_OnLine := vPSArr[4];
  978. FWebOwnerName := vPSArr[5];
  979. FWebOwnerCompany := vPSArr[6];
  980. FWebOwnerRole := vPSArr[7];
  981. ShowProjectInfoTop;
  982. ShowProjectCheckers;
  983. finally
  984. LockWindowUpdate(0);
  985. end;
  986. end
  987. else
  988. begin
  989. FPhaseNo := 0;
  990. FWebCheckStatusProject := csNotBegin;
  991. FPhaseTotal := 0;
  992. FWebFolder_OnLine := '';
  993. FWebSubFolder_OnLine := '';
  994. FWebOwnerName := '';
  995. FWebOwnerCompany := '';
  996. FWebOwnerRole := '';
  997. ShowProjectInfoTop;
  998. sbChecker.Height := 0;
  999. end;
  1000. end;
  1001. procedure TProjectManagerFrame.ShowProjectInfoTop(AType: Integer);
  1002. procedure ShowOwner;
  1003. begin
  1004. lblBidName.Caption := FWebBidName_Local;
  1005. lblBidName.Update;
  1006. lblProjName.Caption := FWebFolder_OnLine;
  1007. lblProjName.Update;
  1008. lblWebProjCtgyName.Caption := FWebSubFolder_OnLine;
  1009. lblWebProjCtgyName.Update;
  1010. lblOnwerName.Caption := FWebOwnerName;
  1011. lblOnwerName.Update;
  1012. lblOnwerCompany.Caption := Format('-%s)', [FWebOwnerCompany]);
  1013. lblOnwerCompany.Update;
  1014. lblOnwerCompany.Left := lblOnwerName.Left + lblOnwerName.Width;
  1015. end;
  1016. procedure ShowStatus(ANo: Integer; AState: TCheckStatus);
  1017. begin
  1018. lblPeriod.Caption := Format('第%d期', [ANo]);
  1019. lblPeriod.Update;
  1020. lblPeriodState.Caption := CheckStatusNames[AState];
  1021. lblPeriodState.Font.Color := CheckStatusColors[AState];
  1022. lblPeriodState.Update;
  1023. lblPeriodState.Left := lblPeriod.Left + lblPeriod.Width + 5;
  1024. lblPeriodTotal.Caption := Format('(共%d期)', [ANo]);
  1025. lblPeriodTotal.Update;
  1026. lblPeriodTotal.Left := lblPeriodState.Left + lblPeriodState.Width + 3;
  1027. end;
  1028. begin
  1029. GetLocalValues(CurRec);
  1030. case AType of
  1031. -2:
  1032. begin
  1033. lblPeriod.Caption := '正在从云端读取状态信息...';
  1034. lblPeriod.Update;
  1035. end;
  1036. -1:
  1037. begin
  1038. ShowOwner;
  1039. ShowStatus(FPhaseNo, FWebCheckStatusProject);
  1040. end;
  1041. 0:
  1042. begin
  1043. ShowOwner;
  1044. ShowStatus(0, csNotBegin);
  1045. end;
  1046. end;
  1047. end;
  1048. // 检查后,应该定位到最后一层目录,不应该回到原先的选择节点。否则从网络拉下来的项目无法组织正确的树结构。
  1049. procedure TProjectManagerFrame.CheckWebFolders(AFolderID, ASubFolderID: Integer;
  1050. AFolderName, ASubFolderName: string);
  1051. var
  1052. vTree: TsdIDTree;
  1053. vNode, vSubNode: TsdIDTreeNode;
  1054. i: Integer;
  1055. sName: string;
  1056. iUserID, iWebID, iWebFolderLevel: Integer;
  1057. bExist, bSubExist, bModified: Boolean;
  1058. begin
  1059. bExist := False;
  1060. bSubExist := False;
  1061. bModified := False;
  1062. vTree := stdProjects.IDTree;
  1063. for i := 0 to vTree.Count - 1 do
  1064. begin
  1065. vNode := vTree.Items[i];
  1066. sName := vNode.Rec.ValueByName('Name').AsString;
  1067. iUserID := vNode.Rec.ValueByName('WebUserID').AsInteger;
  1068. iWebID := vNode.Rec.ValueByName('WebID').AsInteger;
  1069. iWebFolderLevel := vNode.Rec.ValueByName('WebFolderLevel').AsInteger;
  1070. if (iWebID = AFolderID) and (iWebFolderLevel = G_WFL_ProjName) and (iUserID = PHPWeb.UserID) then
  1071. begin
  1072. bExist := True;
  1073. vNode.LocateInControl;
  1074. if not SameText(sName, AFolderName) then
  1075. begin
  1076. vNode.Rec.ValueByName('Name').AsString := AFolderName;
  1077. bModified := True;
  1078. end;
  1079. Break;
  1080. end;
  1081. end;
  1082. if not bExist then
  1083. begin
  1084. vNode := vTree.Items[0];
  1085. if Assigned(vNode) then
  1086. vNode.LocateInControl;
  1087. vNode := FProjectManagerData.InsertProject(AFolderName, stdProjects.IDTree.Selected, AFolderID, G_WFL_ProjName);
  1088. vNode.LocateInControl;
  1089. end;
  1090. for i := 0 to vNode.ChildCount - 1 do
  1091. begin
  1092. vSubNode := vNode.ChildNodes[i];
  1093. sName := vSubNode.Rec.ValueByName('Name').AsString;
  1094. iUserID := vSubNode.Rec.ValueByName('WebUserID').AsInteger;
  1095. iWebID := vSubNode.Rec.ValueByName('WebID').AsInteger;
  1096. iWebFolderLevel := vSubNode.Rec.ValueByName('WebFolderLevel').AsInteger;
  1097. if (iWebID = ASubFolderID) and (iWebFolderLevel = G_WFL_BidType) and (iUserID = PHPWeb.UserID) then
  1098. begin
  1099. bSubExist := True;
  1100. vSubNode.LocateInControl;
  1101. if not SameText(sName, ASubFolderName) then
  1102. begin
  1103. vSubNode.Rec.ValueByName('Name').AsString := ASubFolderName;
  1104. bModified := True;
  1105. end;
  1106. Break;
  1107. end;
  1108. end;
  1109. if not bSubExist then
  1110. begin
  1111. vNode.LocateInControl;
  1112. vNode := FProjectManagerData.InsertSubProject(ASubFolderName, stdProjects.IDTree.Selected, ASubFolderID, G_WFL_BidType);
  1113. vNode.LocateInControl;
  1114. end;
  1115. if bModified then
  1116. ProjectManager.Save;
  1117. end;
  1118. function TProjectManagerFrame.Rec(AProjectID: Integer): TsdDataRecord;
  1119. var i: Integer;
  1120. vTree: TsdIDTree;
  1121. begin
  1122. vTree := stdProjects.IDTree;
  1123. if vTree.Selected.Rec.ValueByName('ID').AsInteger = AProjectID then
  1124. begin
  1125. Result := stdProjects.IDTree.Selected.Rec;
  1126. Exit;
  1127. end;
  1128. for i := 0 to vTree.Count - 1 do
  1129. begin
  1130. if vTree.Items[i].Rec.ValueByName('ID').AsInteger = AProjectID then
  1131. begin
  1132. Result := vTree.Items[i].Rec;
  1133. vTree.Items[i].LocateInControl;
  1134. Break;
  1135. end;
  1136. end;
  1137. end;
  1138. destructor TProjectManagerFrame.Destroy;
  1139. begin
  1140. FCheckerList.Free;
  1141. inherited;
  1142. end;
  1143. procedure TProjectManagerFrame.DoBatchReceiveOnline(ARequestType: Integer);
  1144. var
  1145. sURL, sCheckersURL, sHint: string;
  1146. vArr: TOVArr;
  1147. i, iFolderID, iSubFolderID: Integer;
  1148. vPSArr: TStrArr;
  1149. vCArr: TOVArr; // Checkers
  1150. begin
  1151. // 查询等待我审核的标段文件,杰哥说分三种:①业主未审核 ②业主审核中 ③审核人审核中 (为什么加①?问杰哥)
  1152. case PHPWeb.Search(PHPWeb.MeasureURL + 'user/get/audit/project', ['audituid', 'RequestType'],
  1153. [IntToStr(PHPWeb.UserID), IntToStr(ARequestType)], vArr) of
  1154. 1:
  1155. begin
  1156. CreateProgress('正在从云端下载新项目');
  1157. try
  1158. for i := Low(vArr) to High(vArr) do
  1159. begin
  1160. sURL := vArr[i, 0];
  1161. FWebFolder_OnLine := vArr[i, 1];
  1162. FWebSubFolder_OnLine := vArr[i, 2];
  1163. FWebMD5_OnLine := vArr[i, 3];
  1164. FWebID := StrToInt(vArr[i, 5]);
  1165. iFolderID := StrToInt(vArr[i, 6]);
  1166. iSubFolderID := StrToInt(vArr[i, 7]);
  1167. FWebCheckStatusMy := TCheckStatus(StrToInt(vArr[i, 8])-1); // vArr[i, 4]项目审核状态;vArr[i, 8]当前登陆用户的审核状态
  1168. FWebAuthorID := StrToInt(vArr[i, 9]);
  1169. FWebBidName_OnLine := vArr[i, 10];
  1170. FWebMD5_Local := LocalMD5(PHPWeb.UserID, FWebID);
  1171. CheckWebFolders(iFolderID, iSubFolderID, FWebFolder_OnLine, FWebSubFolder_OnLine);
  1172. CheckBidName(PHPWeb.UserID, FWebID, FWebBidName_OnLine);
  1173. if FWebMD5_OnLine <> FWebMD5_Local then
  1174. begin
  1175. sCheckersURL := Format('%smeasure/status/%d/get', [PHPWeb.MeasureURL, FWebID]);
  1176. if PHPWeb.Search(sCheckersURL, [''], [''], 3, vPSArr, vCArr) = 1 then
  1177. OnLineChecker(vCArr, FOnLineCheckerBegin, FOnLineCheckerEnd)
  1178. else
  1179. begin
  1180. FOnLineCheckerBegin := 0;
  1181. FOnLineCheckerEnd := 0;
  1182. end;
  1183. if not FileDownAndReceive(sURL, 1) then Exit;
  1184. end;
  1185. end;
  1186. BubbleSortProjects;
  1187. finally
  1188. CloseProgress;
  1189. end;
  1190. end;
  1191. 0, -1:
  1192. begin
  1193. sHint := '网络出错,无法查询云端项目的更新情况,请重试!';
  1194. Application.MessageBox(PChar(sHint), '警告', MB_OK + MB_ICONWARNING);
  1195. Exit;
  1196. end;
  1197. end;
  1198. end;
  1199. function TProjectManagerFrame.ImportFile(const AFileName: string; AFileMD5: string): Boolean;
  1200. var
  1201. vImport: TTenderImport;
  1202. vNode: TsdIDTreeNode;
  1203. begin
  1204. Result := False;
  1205. vNode := stdProjects.IDTree.Selected;
  1206. vImport := TTenderImport.Create(vNode, '', AFileName);
  1207. try
  1208. try
  1209. vImport.ImportToSelect;
  1210. vNode.LocateInControl;
  1211. Result := True;
  1212. except
  1213. Result := False;
  1214. end;
  1215. finally
  1216. vImport.Free;
  1217. vNode.Rec.BeginUpdate;
  1218. vNode.Rec.ValueByName('WebMD5').AsString := AFileMD5;
  1219. vNode.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
  1220. vNode.Rec.EndUpdate;
  1221. FProjectManagerData.Save;
  1222. end;
  1223. end;
  1224. procedure TProjectManagerFrame.actnOpenBackupFolderExecute(
  1225. Sender: TObject);
  1226. var
  1227. stnNode: TsdIDTreeNode;
  1228. begin
  1229. stnNode := stdProjects.IDTree.Selected;
  1230. if stnNode.Rec.ValueByName('BackupFolder').AsString = '' then
  1231. TipMessage('该项目暂无备份数据!')
  1232. else
  1233. ShellExecute(Handle, 'open', 'Explorer.exe',
  1234. PChar(FProjectManagerData.BackupPath(stnNode.ID)), nil, 1);
  1235. end;
  1236. procedure TProjectManagerFrame.actnRenameUpdate(Sender: TObject);
  1237. var
  1238. Rec: TsdDataRecord;
  1239. bNet: Boolean;
  1240. begin
  1241. if stdProjects.IDTree.Selected = nil then Exit;
  1242. Rec := stdProjects.IDTree.Selected.Rec;
  1243. if Rec = nil then Exit;
  1244. bNet := G_IsCloud;
  1245. if bNet then
  1246. begin
  1247. tobtnRenane.Enabled := (Rec.ValueByName('Type').AsInteger = 1) and
  1248. (Rec.ValueByName('WebAuthorID').AsInteger = PHPWeb.UserID);
  1249. end;
  1250. end;
  1251. procedure TProjectManagerFrame.CheckBidName(AID: Integer; ANewBidName: string);
  1252. var vNode: TsdIDTreeNode;
  1253. begin
  1254. vNode := stdProjects.IDTree.FindNode(AID);
  1255. if vNode = nil then Exit;
  1256. if vNode.Rec.ValueByName('Name').AsString <> ANewBidName then
  1257. begin
  1258. vNode.Rec.ValueByName('Name').AsString := ANewBidName;
  1259. ProjectManager.Save;
  1260. end;
  1261. end;
  1262. procedure TProjectManagerFrame.DoBatchReceiveAllOnline;
  1263. var
  1264. OnCC: TZjCellNotifyEvent;
  1265. begin
  1266. OnCC := zgProjects.OnCurrentChanged;
  1267. try
  1268. zgProjects.OnCurrentChanged := nil;
  1269. DoBatchReceiveOnline(2);
  1270. if stdProjects.IDTree.FirstNode <> nil then
  1271. stdProjects.IDTree.FirstNode.LocateInControl;
  1272. finally
  1273. zgProjects.OnCurrentChanged := OnCC;
  1274. end;
  1275. end;
  1276. procedure TProjectManagerFrame.GetLocalValues(ARec: TsdDataRecord);
  1277. begin
  1278. if not Assigned(ARec) then
  1279. begin
  1280. ClearLocalValues;
  1281. Exit;
  1282. end;
  1283. // 加这句后产生Bug:上报项目后,记录不曾移动,FID不变,不会刷新
  1284. // if ARec.ValueByName('ID').AsInteger <> FID then
  1285. begin
  1286. FID := ARec.ValueByName('ID').AsInteger;
  1287. FWebID := ARec.ValueByName('WebID').AsInteger;
  1288. FWebAuthorID := ARec.ValueByName('WebAuthorID').AsInteger;
  1289. FWebOwnerID := ARec.ValueByName('WebOwnerID').AsInteger;
  1290. FWebMD5_Local := ARec.ValueByName('WebMD5').AsString;
  1291. FWebBidName_Local := ARec.ValueByName('Name').AsString;
  1292. end;
  1293. end;
  1294. procedure TProjectManagerFrame.GetLocalValues(AUserID, AWebID: Integer);
  1295. var i: Integer;
  1296. vTree: TsdIDTree;
  1297. vRec: TsdDataRecord;
  1298. begin
  1299. ClearLocalValues; // 先清空,以防没找到。
  1300. if (CurRec <> nil) and
  1301. (CurRec.ValueByName('WebUserID').AsInteger = AUserID) and
  1302. (CurRec.ValueByName('WebID').AsInteger = AWebID) and
  1303. (CurRec.ValueByName('Type').AsInteger = 1) then
  1304. begin
  1305. GetLocalValues(vRec);
  1306. Exit;
  1307. end;
  1308. vTree := stdProjects.IDTree;
  1309. for i := 0 to vTree.Count - 1 do
  1310. begin
  1311. vRec := vTree.Items[i].Rec;
  1312. if (vRec.ValueByName('WebUserID').AsInteger = AUserID) and
  1313. (vRec.ValueByName('WebID').AsInteger = AWebID) and
  1314. (vRec.ValueByName('Type').AsInteger = 1) then
  1315. begin
  1316. GetLocalValues(vRec);
  1317. Break;
  1318. end;
  1319. end;
  1320. end;
  1321. procedure TProjectManagerFrame.ClearLocalValues;
  1322. begin
  1323. FID := -1;
  1324. FWebID := -1;
  1325. FWebAuthorID := -1;
  1326. FWebOwnerID := -1;
  1327. FWebMD5_Local := '';
  1328. FWebBidName_Local := '';
  1329. end;
  1330. function TProjectManagerFrame.LocalMD5(AUserID, AWebID: Integer): string;
  1331. var i: Integer;
  1332. vTree: TsdIDTree;
  1333. vRec: TsdDataRecord;
  1334. begin
  1335. Result := '本地无MD5码';
  1336. if (CurRec <> nil) and
  1337. (CurRec.ValueByName('WebUserID').AsInteger = AUserID) and
  1338. (CurRec.ValueByName('WebID').AsInteger = AWebID) and
  1339. (CurRec.ValueByName('Type').AsInteger = 1) then
  1340. begin
  1341. Result := vRec.ValueByName('WebMD5').AsString;
  1342. Exit;
  1343. end;
  1344. vTree := stdProjects.IDTree;
  1345. for i := 0 to vTree.Count - 1 do
  1346. begin
  1347. vRec := vTree.Items[i].Rec;
  1348. if (vRec.ValueByName('WebUserID').AsInteger = AUserID) and
  1349. (vRec.ValueByName('WebID').AsInteger = AWebID) and
  1350. (vRec.ValueByName('Type').AsInteger = 1) then
  1351. begin
  1352. Result := vRec.ValueByName('WebMD5').AsString;
  1353. Break;
  1354. end;
  1355. end;
  1356. end;
  1357. function TProjectManagerFrame.CurRec: TsdDataRecord;
  1358. begin
  1359. if stdProjects.IDTree.Selected = nil then
  1360. Result := nil
  1361. else
  1362. Result := stdProjects.IDTree.Selected.Rec;
  1363. end;
  1364. procedure TProjectManagerFrame.CheckBidName(AUserID, AWebID: Integer;
  1365. ANewBidName: string);
  1366. var i: Integer;
  1367. vTree: TsdIDTree;
  1368. vRec: TsdDataRecord;
  1369. begin
  1370. if (CurRec <> nil) and
  1371. (CurRec.ValueByName('WebUserID').AsInteger = AUserID) and
  1372. (CurRec.ValueByName('WebID').AsInteger = AWebID) and
  1373. (CurRec.ValueByName('Type').AsInteger = 1) then
  1374. begin
  1375. if (CurRec.ValueByName('Name').AsString <> ANewBidName) then
  1376. begin
  1377. CurRec.ValueByName('Name').AsString := ANewBidName;
  1378. ProjectManager.Save;
  1379. end;
  1380. Exit;
  1381. end;
  1382. vTree := stdProjects.IDTree;
  1383. for i := 0 to vTree.Count - 1 do
  1384. begin
  1385. vRec := vTree.Items[i].Rec;
  1386. if (vRec.ValueByName('WebUserID').AsInteger = AUserID) and
  1387. (vRec.ValueByName('WebID').AsInteger = AWebID) and
  1388. (vRec.ValueByName('Type').AsInteger = 1) then
  1389. begin
  1390. if vRec.ValueByName('Name').AsString <> ANewBidName then
  1391. begin
  1392. vRec.ValueByName('Name').AsString := ANewBidName;
  1393. ProjectManager.Save;
  1394. end;
  1395. Break;
  1396. end;
  1397. end;
  1398. end;
  1399. function TProjectManagerFrame.CurRecAttachmentPath: string;
  1400. begin
  1401. if G_IsCloud then
  1402. Result := PHPWeb.WebPath + 'Projects\' + CurRec.ValueByName('WebID').AsString + '\Attachment\'
  1403. else
  1404. Result := GetMyProjectsFilePath + 'Attachment\' + CurRec.ValueByName('FileName').AsString + '\';
  1405. end;
  1406. function TProjectManagerFrame.AttachmentFileCountsWithoutManageFile(ANode: TsdIDTreeNode): Integer;
  1407. function GetCount(ANode: TsdIDTreeNode): Integer;
  1408. var sPath: string;
  1409. begin
  1410. if not Assigned(ANode) then Exit;
  1411. Result := 0;
  1412. if ANode.Rec.ValueByName('Type').AsInteger = 0 then
  1413. Result := Result + 0
  1414. else
  1415. begin
  1416. sPath := GetMyProjectsFilePath + 'Attachment\' + ANode.Rec.ValueByName('FileName').AsString + '\';
  1417. Result := Result + FileCount(sPath) - 1;
  1418. end;
  1419. if Assigned(ANode.FirstChild) then
  1420. Result := Result + GetCount(ANode.FirstChild);
  1421. if Assigned(ANode.NextSibling) then
  1422. Result := Result + GetCount(ANode.NextSibling);
  1423. end;
  1424. begin
  1425. if not Assigned(ANode) then Exit;
  1426. if Assigned(ANode.FirstChild) then
  1427. Result := GetCount(ANode.FirstChild)
  1428. else
  1429. Result := 0;
  1430. end;
  1431. procedure TProjectManagerFrame.BubbleSortProjects;
  1432. // 不能排最顶层
  1433. procedure BubbleSort(ANode: TsdIDTreeNode);
  1434. var n, t, c, temp: Integer;
  1435. bSwap: Boolean;
  1436. vNode1, vNode2, vTempNode: TsdIDTreeNode;
  1437. begin
  1438. if ANode = nil then Exit;
  1439. // if ANode.Rec.ValueByName('WebFolderLevel').AsInteger = G_WFL_ProjName then Exit;
  1440. n := ANode.ChildCount;
  1441. for t := 1 to n - 1 do
  1442. begin
  1443. bSwap := False;
  1444. for c := 1 to (n - t) do
  1445. begin
  1446. vNode1 := ANode.ChildNodes[c - 1];
  1447. vNode2 := ANode.ChildNodes[c];
  1448. if AnsiCompareStr(vNode1.Rec.ValueByName('Name').AsString,
  1449. vNode2.Rec.ValueByName('Name').AsString) = 1 then
  1450. begin
  1451. vNode1.DownMove;
  1452. bSwap := True;
  1453. end;
  1454. end;
  1455. if bSwap = False then Break;
  1456. end;
  1457. if Assigned(ANode.FirstChild) then
  1458. BubbleSort(ANode.FirstChild);
  1459. if Assigned(ANode.NextSibling) then
  1460. BubbleSort(ANode.NextSibling);
  1461. end;
  1462. begin
  1463. BubbleSort(stdProjects.IDTree.FirstNode);
  1464. end;
  1465. procedure TProjectManagerFrame.zgProjectsShowHint(var HintStr: String;
  1466. var CanShow: Boolean; var HintInfo: THintInfo; const ACoord: TPoint);
  1467. var
  1468. vCell: TZjCell;
  1469. vNode: TsdIDTreeNode;
  1470. iLevelWidth: Integer;
  1471. rText: TRect;
  1472. procedure CalcTextRect(var R: TRect);
  1473. var
  1474. DC: HDC;
  1475. iTextHeight: Integer;
  1476. begin
  1477. DC := CreateCompatibleDC(0);
  1478. try
  1479. SelectObject(DC, vCell.Font.Handle);
  1480. iTextHeight := DrawText(DC, PChar(vCell.Text), Length(vCell.Text), R, DT_SINGLELINE or DT_VCenter
  1481. or DT_NOCLIP or DT_CALCRECT);
  1482. finally
  1483. DeleteDC(DC);
  1484. end;
  1485. end;
  1486. begin
  1487. if (ACoord.Y < 1) and (ACoord.X <> 1) then Exit;
  1488. vCell := zgProjects.Cells[ACoord.X, ACoord.Y];
  1489. with HintInfo do
  1490. begin
  1491. vNode := stdProjects.IDTree.Items[ACoord.Y - 1];
  1492. if not Assigned(vNode) then Exit;
  1493. iLevelWidth := (vNode.Level + 1) * 20 + 16;
  1494. rText := CursorRect;
  1495. CalcTextRect(rText);
  1496. if (rText.Right - rText.Left + iLevelWidth > CursorRect.Right - CursorRect.Left) or
  1497. (rText.Right > ClientWidth) then
  1498. begin
  1499. CanShow := True;
  1500. HintStr := vCell.Text;
  1501. GetCursorPos(HintPos);
  1502. end;
  1503. end;
  1504. end;
  1505. function TProjectManagerFrame.FileDownAndReceive(ADownURL: string; AReceiveKind: Integer): Boolean;
  1506. var sLocalFile, sHint: string;
  1507. bCanImp: Boolean;
  1508. vFileCheck: TTenderFileChecker;
  1509. begin
  1510. Result := False;
  1511. // 下载
  1512. sLocalFile := PHPWeb.UserPath + ExtractFileName(ADownURL);
  1513. if not PHPWeb.DownFile(ADownURL, sLocalFile) then
  1514. begin
  1515. sHint := Format('云端已找到[%s]的新文件,但由于网络原因下载失败!请重试!', [FWebBidName_Local]);
  1516. Application.MessageBox(PChar(sHint), '系统提醒', MB_OK + MB_ICONWARNING);
  1517. Exit;
  1518. end;
  1519. // 接收前先检验原报文件是否正确(审核不通过打回)
  1520. if AReceiveKind = 2 then
  1521. begin
  1522. // 有时原报文件出错:包含了1审2审的数据。
  1523. vFileCheck := TTenderFileChecker.Create;
  1524. try
  1525. // 有一期以上数据,且最新期数据审核状态为原报
  1526. bCanImp := vFileCheck.CheckFileValid(sLocalFile) and (vFileCheck.PhaseCount > 0) and (vFileCheck.AuditStatus = 0);
  1527. if not bCanImp then
  1528. begin
  1529. Application.MessageBox(PChar('已从云端下载原报文件到本地,但文件有错误(包含1审数据)禁止接收!请致电纵横服务人员以获取帮助。'),
  1530. '警告', MB_OK + MB_ICONWARNING);
  1531. Exit;
  1532. end;
  1533. finally
  1534. vFileCheck.Free;
  1535. end;
  1536. {注意: 审核末通过的导入更新,这里的MD5码应取最终审核不通过项目的,否则会带来下载循环问题。
  1537. 问题描述:
  1538. ①编制人运行软件,双击项目,发现审核不通过,自动下载无锁文件,开始新一期,保存关闭。
  1539. ②编制人再次运行软件,双击项目,MD5码不同,自动下载旧的审核不通过文件,覆盖本地。
  1540. ③编制人再次运行软件,双击项目,发现审核不通过,重复①,循环....
  1541. 问:①那里下载无锁文件后不能改成新的MD5码吗?
  1542. 答:不能,因为审核人的项目会变成无锁文件,看不到不通过项目。MD5码只能在上传后更新。
  1543. 且编制人有个交互界面2种选择:a.下载更新不通过项目查看;b.下载更新无锁文件开始新一期。}
  1544. end;
  1545. // 接收更新
  1546. if not ReceiveFile(sLocalFile, (AReceiveKind = 2)) then
  1547. begin
  1548. sHint := Format('已从云端下载新的[%s]到本地[%s],但接收失败,请删除该项目然后重新从云端获取!', [FWebBidName_Local, sLocalFile]);
  1549. Application.MessageBox(PChar(sHint), '系统提醒', MB_OK + MB_ICONWARNING);
  1550. Exit;
  1551. end;
  1552. if FileExists(sLocalFile) then
  1553. DeleteFile(sLocalFile);
  1554. Result := True;
  1555. end;
  1556. // 为了跟PHP的数组兼容,这里限制数组的第一个元素是A[0](不能是A[1])
  1557. procedure TProjectManagerFrame.OnLineChecker(AAr: TOVArr; var ABegin,
  1558. AEnd: Integer);
  1559. var i, j, n: Integer;
  1560. vCS: TCheckStatus;
  1561. begin
  1562. ABegin := 0;
  1563. AEnd := 0;
  1564. n := -1;
  1565. for i := 0 to High(AAr) do
  1566. begin
  1567. vCS := TCheckStatus(StrToInt(AAr[i, 5])-1);
  1568. if vCS = csChecking then
  1569. begin
  1570. n := i - 1; // 非常重要:传入的数组必须从第一个审核人到轮到工作中的那个人的前一个人
  1571. Break;
  1572. end;
  1573. end;
  1574. for i := n downto 0 do
  1575. begin
  1576. if AAr[i, 7] = '1' then // 接口返回的第7列是线上审批标记
  1577. begin
  1578. AEnd := i + 1;
  1579. Break;
  1580. end
  1581. else
  1582. Break;
  1583. end;
  1584. if AEnd = 0 then Exit;
  1585. i := i - 1;
  1586. if i < 0 then
  1587. begin
  1588. ABegin := 1;
  1589. Exit;
  1590. end;
  1591. for j := i downto 0 do
  1592. begin
  1593. if AAr[j, 7] = '0' then
  1594. begin
  1595. ABegin := j + 2;
  1596. Break;
  1597. end
  1598. else
  1599. begin
  1600. if j = 0 then
  1601. ABegin := 1;
  1602. end;
  1603. end;
  1604. end;
  1605. end.