UpFileManageFrame.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. {*******************************************************************************
  2. 单元名称: UpFileManageFrame.pas
  3. 单元说明: 计量支付附件,UI界面。
  4. 作者时间: Chenshilong, 2015-01-13
  5. *******************************************************************************}
  6. unit UpFileManageFrame;
  7. interface
  8. uses
  9. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  10. Dialogs, StdCtrls, ExtCtrls, PNGButton, UpFileFrame, UpFileManageUnit, sdDB;
  11. type
  12. TUpFileManageView = class(TFrame)
  13. pnlHead: TPanel;
  14. lblBillName: TLabel;
  15. btnSelectUpFile: TPNGButton;
  16. Shape5: TShape;
  17. Label6: TLabel;
  18. Label7: TLabel;
  19. Shape6: TShape;
  20. pnlDetail: TPanel;
  21. btnEditNo: TPNGButton;
  22. btnEdit: TPNGButton;
  23. lblCaption: TLabel;
  24. Shape1: TShape;
  25. Shape2: TShape;
  26. Shape3: TShape;
  27. btnDown: TPNGButton;
  28. Shape4: TShape;
  29. Label1: TLabel;
  30. Label2: TLabel;
  31. lblUper: TLabel;
  32. lblUpTime: TLabel;
  33. Label3: TLabel;
  34. lblExt: TLabel;
  35. Label5: TLabel;
  36. lblCategory: TLabel;
  37. Label4: TLabel;
  38. btnEditYes: TPNGButton;
  39. mmMemo: TMemo;
  40. edtFileName: TEdit;
  41. sbFile: TScrollBox;
  42. tDelView: TTimer;
  43. procedure btnEditClick(Sender: TObject);
  44. procedure btnEditYesClick(Sender: TObject);
  45. procedure btnEditNoClick(Sender: TObject);
  46. procedure btnSelectUpFileClick(Sender: TObject);
  47. procedure tDelViewTimer(Sender: TObject);
  48. procedure btnDownClick(Sender: TObject);
  49. private
  50. FDetailIsEdit: Boolean;
  51. FSelected: TUpFileView;
  52. FDatas: TUpFiles;
  53. FWaitForDelete: TUpFileView;
  54. FOwner: TObject;
  55. FProjectData: TObject;
  56. FRec: TsdDataRecord;
  57. procedure SetSelected(const Value: TUpFileView);
  58. procedure SetDetailIsEdit(const Value: Boolean);
  59. procedure SetDatas(const Value: TUpFiles);
  60. procedure RefreshOtherFileFrames;
  61. procedure RefreshDetail;
  62. procedure RefreshBill;
  63. procedure ClearViews;
  64. procedure ClearDetail;
  65. procedure RefreshViews;
  66. procedure DetailOutEditStatus;
  67. procedure DetailIntoEditStatus;
  68. procedure AddUpFileView(AUpFile: TUpFile);
  69. procedure SetWaitForDelete(const Value: TUpFileView);
  70. procedure SetOwner(const Value: TObject);
  71. procedure SetProjectData(const Value: TObject);
  72. procedure SetRec(const Value: TsdDataRecord);
  73. public
  74. constructor Create(AOwner: TComponent); override;
  75. procedure DeleteViewAndData(AView: TUpFileView);
  76. procedure DoOnBillChange(ARec: TsdDataRecord);
  77. property ProjectData: TObject read FProjectData write SetProjectData;
  78. property Owner: TObject read FOwner write SetOwner;
  79. property Selected: TUpFileView read FSelected write SetSelected;
  80. property DetailIsEdit: Boolean read FDetailIsEdit write SetDetailIsEdit; // 明细部分处理编辑状态
  81. property Datas: TUpFiles read FDatas write SetDatas;
  82. property WaitForDelete: TUpFileView read FWaitForDelete write SetWaitForDelete;
  83. property Rec: TsdDataRecord read FRec write SetRec;
  84. end;
  85. implementation
  86. uses PHPWebDm, ProjectData, IdGlobal, ProjectFme, ConstUnit, MainFrm,
  87. BillsMeasureDm, UtilMethods;
  88. {$R *.dfm}
  89. { TUpFileManageView }
  90. procedure TUpFileManageView.ClearDetail;
  91. begin
  92. edtFileName.Text := '';
  93. lblExt.Caption := '';
  94. lblUper.Caption := '';
  95. lblUpTime.Caption := '';
  96. lblCategory.Caption := '';
  97. mmMemo.Clear;
  98. end;
  99. procedure TUpFileManageView.DetailIntoEditStatus;
  100. begin
  101. edtFileName.BorderStyle := bsSingle;
  102. edtFileName.ReadOnly := False;
  103. mmMemo.BorderStyle := bsSingle;
  104. mmMemo.ReadOnly := False;
  105. btnEdit.Visible := False;
  106. btnEditYes.Visible := True;
  107. btnEditNo.Visible := True;
  108. end;
  109. procedure TUpFileManageView.DetailOutEditStatus;
  110. begin
  111. edtFileName.BorderStyle := bsNone;
  112. edtFileName.ReadOnly := True;
  113. mmMemo.BorderStyle := bsNone;
  114. mmMemo.ReadOnly := True;
  115. btnEdit.Visible := True;
  116. btnEditYes.Visible := False;
  117. btnEditNo.Visible := False;
  118. end;
  119. procedure TUpFileManageView.ClearViews;
  120. var i: Integer;
  121. begin
  122. for i := sbFile.ControlCount - 1 downto 0 do
  123. TUpFileView(sbFile.Controls[i]).Free;
  124. end;
  125. procedure TUpFileManageView.RefreshViews;
  126. var i: Integer;
  127. begin
  128. ClearViews;
  129. ClearDetail;
  130. {'HasAttachment'是不可靠的。一但它不可靠,会导致:有附件却不显示,用户会以为
  131. 附件丢失。不可靠表现为:
  132. ①用户上传成功,本地标记修改完成,之后却因死机或程序出错导致项目没有保存成功,
  133. 这样本地标记没有保存,线上线下不一致。
  134. ②当前用户非工作状态,上传了附件。却因下次从服务器更新覆盖了本地项目,标记丢失。}
  135. if (FRec <> nil) {and (FRec.ValueByName('HasAttachment').AsBoolean = True)} then
  136. for i := 0 to Datas.Count - 1 do
  137. begin
  138. if Datas[i].BillID = FRec.ValueByName('ID').AsInteger then
  139. AddUpFileView(Datas[i]);
  140. end;
  141. end;
  142. procedure TUpFileManageView.RefreshDetail;
  143. var vFile: TUpFile;
  144. begin
  145. if DetailIsEdit then
  146. DetailOutEditStatus;
  147. vFile := Selected.Data;
  148. if vFile.Status <> ufsNormal then
  149. ClearDetail
  150. else
  151. begin
  152. edtFileName.Text := ExtractFileNameWithoutExt(vFile.DisplayName);
  153. lblExt.Caption := ExtractFileExt(vFile.LocalFile);
  154. lblUper.Caption := vFile.UperName;
  155. lblUpTime.Caption := vFile.UpTime;
  156. lblCategory.Caption := vFile.Category;
  157. mmMemo.Text := vFile.Memo;
  158. end;
  159. btnEdit.Enabled := edtFileName.Text <> '';
  160. end;
  161. procedure TUpFileManageView.RefreshOtherFileFrames;
  162. var i: Integer;
  163. begin
  164. for i := 0 to sbFile.ControlCount - 1 do
  165. begin
  166. if TUpFileView(sbFile.Controls[i]) <> Selected then
  167. TUpFileView(sbFile.Controls[i]).ShowNormal;
  168. end;
  169. end;
  170. procedure TUpFileManageView.SetSelected(const Value: TUpFileView);
  171. begin
  172. FSelected := Value;
  173. RefreshOtherFileFrames;
  174. if G_IsCloud then
  175. RefreshDetail;
  176. end;
  177. procedure TUpFileManageView.SetDetailIsEdit(const Value: Boolean);
  178. begin
  179. FDetailIsEdit := Value;
  180. end;
  181. procedure TUpFileManageView.btnEditClick(Sender: TObject);
  182. begin
  183. DetailIntoEditStatus;
  184. DetailIsEdit := True;
  185. end;
  186. procedure TUpFileManageView.btnEditYesClick(Sender: TObject);
  187. var sURL, sExt, sNewName, sNewMemo, sNewFile: string;
  188. vArr: array of string;
  189. begin
  190. sExt := Selected.Data.Ext;
  191. sNewName := Trim(edtFileName.Text);
  192. if HasExt(sNewName) then
  193. sNewName := ExtractFileNameWithoutExt(sNewName);
  194. sNewFile := ExtractFilePath(Selected.Data.LocalFile) + sNewName + sExt;
  195. // 以下这个不能判断:如果我只改了备注,没有改文件名,会提交不上。
  196. // if FileExists(sNewFile) then
  197. // begin
  198. // Application.MessageBox('本地已存在同名文件,请更换其它名称!', '编辑失败', MB_OK + MB_ICONWARNING);
  199. // Exit;
  200. // end;
  201. sURL := Format('%stender/attachment/info/%d/update', [PHPWeb.MeasureURL, Selected.Data.ID]);
  202. sNewMemo := mmMemo.Text;
  203. vArr := VarArrayOf(['msg']);
  204. if PHPWeb.Search(sURL, ['FileName', 'Memo'], [sNewName, sNewMemo], vArr) = 1 then
  205. begin
  206. if FileExists(Selected.Data.LocalFile) then
  207. if not RenameFile(Selected.Data.LocalFile, sNewFile) then
  208. begin
  209. Application.MessageBox('本地文件被占用,更换文件名失败,请关闭占用文件后重试!', '编辑失败', MB_OK + MB_ICONWARNING);
  210. Exit;
  211. end;
  212. Selected.Data.LocalFile := sNewFile;
  213. Selected.Data.DisplayName := sNewName + sExt;
  214. Selected.Data.Memo := sNewMemo;
  215. Selected.Refresh;
  216. edtFileName.Text := sNewName;
  217. DetailOutEditStatus;
  218. DetailIsEdit := False;
  219. end
  220. else
  221. begin
  222. Application.MessageBox('因网络原因导致编辑失败,请重试!', '编辑失败', MB_OK + MB_ICONWARNING);
  223. Exit;
  224. end;
  225. end;
  226. procedure TUpFileManageView.btnEditNoClick(Sender: TObject);
  227. begin
  228. DetailOutEditStatus;
  229. DetailIsEdit := False;
  230. edtFileName.Text := Selected.Data.DisplayName;
  231. mmMemo.Text := Selected.Data.Memo;
  232. end;
  233. procedure TUpFileManageView.btnSelectUpFileClick(Sender: TObject);
  234. var vODlg: TOpenDialog;
  235. i, iBillID, iPhase: Integer;
  236. vFile: TUpFile;
  237. sFile, sName: string;
  238. iV: Int64;
  239. begin
  240. vODlg := TOpenDialog.Create(nil);
  241. vODlg.Options := vODlg.Options + [ofAllowMultiSelect];
  242. if vODlg.Execute then
  243. begin
  244. for i := 0 to vODlg.Files.Count - 1 do
  245. begin
  246. sFile := vODlg.Files[i];
  247. iV := FileSizeByName(sFile);
  248. if iV >= 10485760 then
  249. begin
  250. Application.MessageBox(PChar('“' + sFile + '”过大,单个文件上传不能超过10M!'), '提示', MB_OK + MB_ICONINFORMATION);
  251. Continue;
  252. end;
  253. with MainForm.CurProjectFrame.dxsbViewControl do
  254. begin
  255. if SelectedItem = Groups[0].Items[0] then
  256. iBillID := TProjectData(FProjectData).BillsCompileData.BillsCompileTree.Selected.ID
  257. else if SelectedItem = Groups[0].Items[1] then
  258. iBillID := TProjectData(FProjectData).BillsMeasureData.BillsMeasureTree.Selected.ID;
  259. end;
  260. iPhase := TProjectData(FProjectData).PhaseIndex;
  261. sName := ExtractFileName(sFile);
  262. vFile := Datas.Add(iBillID, iPhase);
  263. vFile.OrgFile := sFile;
  264. vFile.Category := '台帐附件';
  265. vFile.Memo := '我的备注';
  266. vFile.LocalFile := Datas.Path + sName;
  267. vFile.DisplayName := sName;
  268. vFile.Status := ufsNeedUp;
  269. if G_IsCloud then
  270. begin
  271. // 添加到类→上传到服务器,生成ID→再到类中修改ID。为什么不先上传到服务器生成ID
  272. // 再添加到类并设置ID这样可以一气呵成呢?因为需要给用户一个交互界面让用户可以批量
  273. // 操作并决定取消某几个上传。这个交互界面的数据来自类。
  274. vFile.WebID := TProjectData(FProjectData).WebID;
  275. vFile.UperID := PHPWeb.UserID;
  276. vFile.UperName := PHPWeb.RealName;
  277. vFile.UpTime := FormatDateTime('yyyy-mm-dd hh:mm', Now);
  278. end
  279. else
  280. begin
  281. //
  282. end;
  283. AddUpFileView(vFile);
  284. end;
  285. end;
  286. Application.ProcessMessages;
  287. end;
  288. procedure TUpFileManageView.SetDatas(const Value: TUpFiles);
  289. begin
  290. FDatas := Value;
  291. end;
  292. procedure TUpFileManageView.AddUpFileView(AUpFile: TUpFile);
  293. var vVew: TUpFileView;
  294. begin
  295. vVew := TUpFileView.Create(Self);
  296. vVew.Name := Format('UpFileView%d', [AUpFile.No]); // 此时ID尚末获取,不能用ID
  297. vVew.Owner := Self;
  298. vVew.ProjectData := FProjectData;
  299. vVew.parent := sbFile;
  300. vVew.Align := alTop;
  301. vVew.Data := AUpFile;
  302. end;
  303. procedure TUpFileManageView.DeleteViewAndData(AView: TUpFileView);
  304. begin
  305. WaitForDelete := AView;
  306. tDelView.Enabled := True;
  307. end;
  308. procedure TUpFileManageView.tDelViewTimer(Sender: TObject);
  309. var vUpFile: TUpFile;
  310. begin
  311. tDelView.Enabled := False;
  312. vUpFile := WaitForDelete.Data;
  313. WaitForDelete.Free;
  314. Datas.Delete(vUpFile);
  315. end;
  316. procedure TUpFileManageView.SetWaitForDelete(const Value: TUpFileView);
  317. begin
  318. FWaitForDelete := Value;
  319. end;
  320. procedure TUpFileManageView.SetOwner(const Value: TObject);
  321. begin
  322. FOwner := Value;
  323. TProjectFrame(FOwner).BillsMeasureFrame.BillsMeasureData.OnRecChange := DoOnBillChange;
  324. TProjectFrame(FOwner).BillsCompileFrame.BillsCompileData.OnRecChange := DoOnBillChange;
  325. end;
  326. procedure TUpFileManageView.SetProjectData(const Value: TObject);
  327. begin
  328. FProjectData := Value;
  329. end;
  330. procedure TUpFileManageView.btnDownClick(Sender: TObject);
  331. var sFile: string;
  332. begin
  333. if not Assigned(Selected) then Exit;
  334. Screen.Cursor := crHourGlass;
  335. try
  336. Selected.Data.Status := ufsDowning;
  337. sFile := Selected.Data.LocalFile;
  338. if PHPWeb.DownFile(Selected.Data.DownURL, sFile) then
  339. begin
  340. Selected.Data.Status := ufsNormal;
  341. end
  342. else
  343. begin
  344. Selected.Data.Status := ufsDownFail;
  345. end;
  346. finally
  347. Screen.Cursor := crDefault;
  348. end;
  349. end;
  350. constructor TUpFileManageView.Create(AOwner: TComponent);
  351. begin
  352. inherited;
  353. FRec := nil;
  354. lblBillName.Caption := '';
  355. lblBillName.Update;
  356. pnlDetail.Visible := G_IsCloud;
  357. end;
  358. procedure TUpFileManageView.DoOnBillChange(ARec: TsdDataRecord);
  359. begin
  360. FRec := ARec;
  361. with TProjectFrame(Owner) do
  362. begin
  363. if not (jpsAssistant.Visible and (jpsAssistant.ActivePage = jpsAssistantUpFile)) then
  364. Exit;
  365. end;
  366. RefreshBill;
  367. RefreshViews;
  368. end;
  369. procedure TUpFileManageView.SetRec(const Value: TsdDataRecord);
  370. begin
  371. FRec := Value;
  372. end;
  373. procedure TUpFileManageView.RefreshBill;
  374. var sCode: string;
  375. begin
  376. if FRec <> nil then
  377. begin
  378. if FRec.ValueByName('Code').AsString <> '' then
  379. sCode := FRec.ValueByName('Code').AsString
  380. else
  381. sCode := FRec.ValueByName('B_Code').AsString;
  382. if sCode <> '' then
  383. sCode := sCode + ' ';
  384. lblBillName.Caption := sCode + FRec.ValueByName('Name').AsString;
  385. end
  386. else
  387. lblBillName.Caption := '';
  388. lblBillName.Update;
  389. end;
  390. end.