ProjectManagerFme.pas 53 KB

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