ProjectManagerFme.pas 57 KB

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