ProjectManagerFme.pas 71 KB

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