ProjectManagerFme.pas 54 KB

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