ProjectManagerFme.pas 58 KB

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