ProjectManagerFme.pas 52 KB

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