UpFileManageFrame.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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. Menus, Buttons;
  12. type
  13. TUpFileManageView = class(TFrame)
  14. pnlHead: TPanel;
  15. lblBillName: TLabel;
  16. btnSelectUpFile: TPNGButton;
  17. Shape5: TShape;
  18. Label6: TLabel;
  19. Label7: TLabel;
  20. Shape6: TShape;
  21. pnlDetail: TPanel;
  22. btnEditNo: TPNGButton;
  23. btnEdit: TPNGButton;
  24. lblCaption: TLabel;
  25. Shape1: TShape;
  26. Shape2: TShape;
  27. Shape3: TShape;
  28. btnDown: TPNGButton;
  29. Shape4: TShape;
  30. Label1: TLabel;
  31. Label2: TLabel;
  32. lblUper: TLabel;
  33. lblUpTime: TLabel;
  34. Label3: TLabel;
  35. lblExt: TLabel;
  36. Label5: TLabel;
  37. lblCategory: TLabel;
  38. Label4: TLabel;
  39. btnEditYes: TPNGButton;
  40. mmMemo: TMemo;
  41. edtFileName: TEdit;
  42. sbFile: TScrollBox;
  43. tDelView: TTimer;
  44. pmUp: TPopupMenu;
  45. miLocalUp: TMenuItem;
  46. miServerUp: TMenuItem;
  47. procedure btnEditClick(Sender: TObject);
  48. procedure btnEditYesClick(Sender: TObject);
  49. procedure btnEditNoClick(Sender: TObject);
  50. procedure btnSelectUpFileClick(Sender: TObject);
  51. procedure tDelViewTimer(Sender: TObject);
  52. procedure btnDownClick(Sender: TObject);
  53. procedure miLocalUpClick(Sender: TObject);
  54. procedure miServerUpClick(Sender: TObject);
  55. procedure FrameMouseWheel(Sender: TObject; Shift: TShiftState;
  56. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  57. private
  58. FDetailIsEdit: Boolean;
  59. FSelected: TUpFileView;
  60. FDatas: TUpFiles;
  61. FWaitForDelete: TUpFileView;
  62. FDeleteAttachmentOnLine: Boolean;
  63. //FOwner: TObject;
  64. FProjectData: TObject;
  65. FRec: TsdDataRecord;
  66. procedure SetSelected(const Value: TUpFileView);
  67. procedure SetDetailIsEdit(const Value: Boolean);
  68. procedure SetDatas(const Value: TUpFiles);
  69. procedure RefreshOtherFileFrames;
  70. procedure RefreshDetail;
  71. procedure RefreshBill;
  72. procedure ClearViews;
  73. procedure ClearDetail;
  74. procedure DetailOutEditStatus;
  75. procedure DetailIntoEditStatus;
  76. procedure AddUpFileView(AUpFile: TUpFile);
  77. procedure SetWaitForDelete(const Value: TUpFileView);
  78. //procedure SetOwner(const Value: TObject);
  79. procedure SetProjectData(const Value: TObject);
  80. procedure SetRec(const Value: TsdDataRecord);
  81. procedure SelectUpFile;
  82. public
  83. constructor Create(AOwner: TComponent); override;
  84. procedure DeleteViewAndData(AView: TUpFileView; ANeedDeleteOnLine: Boolean);
  85. procedure DoOnBillChange(ARec: TsdDataRecord);
  86. procedure RefreshViews;
  87. property ProjectData: TObject read FProjectData write SetProjectData;
  88. //property Owner: TObject read FOwner write SetOwner;
  89. property Selected: TUpFileView read FSelected write SetSelected;
  90. property DetailIsEdit: Boolean read FDetailIsEdit write SetDetailIsEdit; // 明细部分处理编辑状态
  91. property Datas: TUpFiles read FDatas write SetDatas;
  92. property WaitForDelete: TUpFileView read FWaitForDelete write SetWaitForDelete;
  93. property Rec: TsdDataRecord read FRec write SetRec;
  94. end;
  95. implementation
  96. uses PHPWebDm, ProjectData, IdGlobal, ProjectFme, ConstUnit, MainFrm,
  97. BillsMeasureDm, UtilMethods, UpFileSelectOnLineFrm, ShellAPI;
  98. {$R *.dfm}
  99. { TUpFileManageView }
  100. procedure TUpFileManageView.ClearDetail;
  101. begin
  102. edtFileName.Text := '';
  103. lblExt.Caption := '';
  104. lblUper.Caption := '';
  105. lblUpTime.Caption := '';
  106. lblCategory.Caption := '';
  107. mmMemo.Clear;
  108. btnEdit.Enabled := False;
  109. btnDown.Enabled := False;
  110. end;
  111. procedure TUpFileManageView.DetailIntoEditStatus;
  112. begin
  113. edtFileName.BorderStyle := bsSingle;
  114. edtFileName.ReadOnly := False;
  115. mmMemo.BorderStyle := bsSingle;
  116. mmMemo.ReadOnly := False;
  117. btnEdit.Visible := False;
  118. btnEditYes.Visible := True;
  119. btnEditNo.Visible := True;
  120. end;
  121. procedure TUpFileManageView.DetailOutEditStatus;
  122. begin
  123. edtFileName.BorderStyle := bsNone;
  124. edtFileName.ReadOnly := True;
  125. mmMemo.BorderStyle := bsNone;
  126. mmMemo.ReadOnly := True;
  127. btnEdit.Visible := True;
  128. btnEditYes.Visible := False;
  129. btnEditNo.Visible := False;
  130. end;
  131. procedure TUpFileManageView.ClearViews;
  132. var
  133. i: Integer;
  134. obj: TControl;
  135. begin
  136. for i := sbFile.ControlCount - 1 downto 0 do
  137. begin
  138. //if Assigned(sbFile.Controls[i]) then
  139. obj := sbFile.Controls[i];
  140. if Assigned(obj) then
  141. begin
  142. sbFile.RemoveControl(obj);
  143. FreeAndNil(obj);
  144. end;
  145. //TUpFileView(sbFile.Controls[i]).Free;
  146. end;
  147. end;
  148. procedure TUpFileManageView.RefreshViews;
  149. var i: Integer;
  150. begin
  151. //LockWindowUpdate(Self.Handle);
  152. //BeginUpdateWindow(Handle);
  153. try
  154. btnSelectUpFile.Visible := (not TProjectData(FProjectData).IsHistoryPhase) and (not TProjectData(FProjectData).IsGuest);
  155. ClearViews;
  156. ClearDetail;
  157. {'HasAttachment'是不可靠的。一但它不可靠,会导致:有附件却不显示,用户会以为
  158. 附件丢失。不可靠表现为:
  159. ①用户上传成功,本地标记修改完成,之后却因死机或程序出错导致项目没有保存成功,
  160. 这样本地标记没有保存,线上线下不一致。
  161. ②当前用户非工作状态,上传了附件。却因下次从服务器更新覆盖了本地项目,标记丢失。}
  162. if (FRec <> nil) {and (FRec.ValueByName('HasAttachment').AsBoolean = True)} then
  163. for i := 0 to Datas.Count - 1 do
  164. begin
  165. if (Datas[i].BillID = FRec.ValueByName('ID').AsInteger) and (Datas[i].Phase = TProjectData(FProjectData).PhaseIndex) then
  166. AddUpFileView(Datas[i]);
  167. end;
  168. finally
  169. pnlHead.Repaint;
  170. //LockWindowUpdate(0);
  171. // EndUpdateWindow(Handle);
  172. end;
  173. end;
  174. procedure TUpFileManageView.RefreshDetail;
  175. var vFile: TUpFile;
  176. begin
  177. if DetailIsEdit then
  178. DetailOutEditStatus;
  179. vFile := Selected.Data;
  180. if vFile.Status <> ufsNormal then
  181. ClearDetail
  182. else
  183. begin
  184. edtFileName.Text := ExtractFileNameWithoutExt(vFile.DisplayName);
  185. lblExt.Caption := ExtractFileExt(vFile.LocalFile);
  186. lblUper.Caption := vFile.UperName;
  187. lblUpTime.Caption := vFile.UpTime;
  188. lblCategory.Caption := vFile.Category;
  189. mmMemo.Text := vFile.Memo;
  190. end;
  191. btnEdit.Enabled := (edtFileName.Text <> '') and (PHPWeb.UserID = vFile.UperID); // TProjectData(FProjectData).CurUserIsAuthor;
  192. btnDown.Enabled := (edtFileName.Text <> '');
  193. end;
  194. procedure TUpFileManageView.RefreshOtherFileFrames;
  195. var i: Integer;
  196. begin
  197. for i := 0 to sbFile.ControlCount - 1 do
  198. begin
  199. if TUpFileView(sbFile.Controls[i]) <> Selected then
  200. TUpFileView(sbFile.Controls[i]).ShowNormal;
  201. end;
  202. end;
  203. procedure TUpFileManageView.SetSelected(const Value: TUpFileView);
  204. begin
  205. FSelected := Value;
  206. RefreshOtherFileFrames;
  207. if G_IsCloud then
  208. RefreshDetail;
  209. end;
  210. procedure TUpFileManageView.SetDetailIsEdit(const Value: Boolean);
  211. begin
  212. FDetailIsEdit := Value;
  213. end;
  214. procedure TUpFileManageView.btnEditClick(Sender: TObject);
  215. begin
  216. DetailIntoEditStatus;
  217. DetailIsEdit := True;
  218. end;
  219. procedure TUpFileManageView.btnEditYesClick(Sender: TObject);
  220. var sURL, sExt, sNewName, sNewMemo, sNewFile: string;
  221. vArr: array of string;
  222. begin
  223. sExt := Selected.Data.Ext;
  224. sNewName := Trim(edtFileName.Text);
  225. if HasExt(sNewName) then
  226. sNewName := ExtractFileNameWithoutExt(sNewName);
  227. sNewFile := ExtractFilePath(Selected.Data.LocalFile) + sNewName + sExt;
  228. // 以下这个不能判断:如果我只改了备注,没有改文件名,会提交不上。
  229. // if FileExists(sNewFile) then
  230. // begin
  231. // Application.MessageBox('本地已存在同名文件,请更换其它名称!', '编辑失败', MB_OK + MB_ICONWARNING);
  232. // Exit;
  233. // end;
  234. sURL := Format('%stender/attachment/info/%d/update', [PHPWeb.MeasureURL, Selected.Data.ID]);
  235. sNewMemo := mmMemo.Text;
  236. vArr := VarArrayOf(['msg']);
  237. if PHPWeb.Search(sURL, ['FileName', 'Memo'], [sNewName, sNewMemo], vArr) = 1 then
  238. begin
  239. if FileExists(Selected.Data.LocalFile) then
  240. if not RenameFile(Selected.Data.LocalFile, sNewFile) then
  241. begin
  242. Application.MessageBox('本地文件被占用,更换文件名失败,请关闭占用文件后重试!', '编辑失败', MB_OK + MB_ICONWARNING);
  243. Exit;
  244. end;
  245. Selected.Data.LocalFile := sNewFile;
  246. Selected.Data.DisplayName := sNewName + sExt;
  247. Selected.Data.Memo := sNewMemo;
  248. Selected.Refresh;
  249. edtFileName.Text := sNewName;
  250. DetailOutEditStatus;
  251. DetailIsEdit := False;
  252. end
  253. else
  254. begin
  255. Application.MessageBox('因网络原因导致编辑失败,请重试!', '编辑失败', MB_OK + MB_ICONWARNING);
  256. Exit;
  257. end;
  258. end;
  259. procedure TUpFileManageView.btnEditNoClick(Sender: TObject);
  260. begin
  261. DetailOutEditStatus;
  262. DetailIsEdit := False;
  263. edtFileName.Text := Selected.Data.DisplayName;
  264. mmMemo.Text := Selected.Data.Memo;
  265. end;
  266. procedure TUpFileManageView.btnSelectUpFileClick(Sender: TObject);
  267. var
  268. P: TPoint;
  269. begin
  270. GetCursorPos(P);
  271. pmUp.Popup(P.X, P.Y);
  272. end;
  273. procedure TUpFileManageView.SetDatas(const Value: TUpFiles);
  274. begin
  275. FDatas := Value;
  276. end;
  277. procedure TUpFileManageView.AddUpFileView(AUpFile: TUpFile);
  278. var vVew: TUpFileView;
  279. begin
  280. vVew := TUpFileView.Create(Self);
  281. // 先删再增会重复。
  282. // vVew.Name := Format('UpFileView%d', [AUpFile.No]); // 此时ID尚末获取,不能用ID
  283. vVew.Name := Format('UpFileView_%s', [PHPWeb.TempName]);
  284. //vVew.Owner := Self;
  285. vVew.ProjectData := FProjectData;
  286. //vVew.parent := sbFile;
  287. sbFile.InsertControl(vVew);
  288. vVew.Align := alTop;
  289. vVew.Data := AUpFile;
  290. end;
  291. procedure TUpFileManageView.DeleteViewAndData(AView: TUpFileView; ANeedDeleteOnLine: Boolean);
  292. begin
  293. WaitForDelete := AView;
  294. FDeleteAttachmentOnLine := ANeedDeleteOnLine;
  295. tDelView.Enabled := True;
  296. end;
  297. procedure TUpFileManageView.tDelViewTimer(Sender: TObject);
  298. var vUpFile: TUpFile;
  299. begin
  300. tDelView.Enabled := False;
  301. vUpFile := WaitForDelete.Data;
  302. if FDeleteAttachmentOnLine then
  303. if PHPWeb.DeleteAttachment(vUpFile.ID) <> 1 then
  304. begin
  305. Application.MessageBox('线上附件移除失败,请重试!', '警告', MB_OK + MB_ICONWARNING);
  306. Exit;
  307. end;
  308. sbFile.RemoveControl(WaitForDelete);
  309. WaitForDelete.Free;
  310. Datas.Delete(vUpFile);
  311. end;
  312. procedure TUpFileManageView.SetWaitForDelete(const Value: TUpFileView);
  313. begin
  314. FWaitForDelete := Value;
  315. end;
  316. {procedure TUpFileManageView.SetOwner(const Value: TObject);
  317. begin
  318. FOwner := Value;
  319. TProjectFrame(FOwner).BillsMeasureFrame.BillsMeasureData.OnRecChange := DoOnBillChange;
  320. TProjectFrame(FOwner).BillsCompileFrame.BillsCompileData.OnRecChange := DoOnBillChange;
  321. end;}
  322. procedure TUpFileManageView.SetProjectData(const Value: TObject);
  323. begin
  324. FProjectData := Value;
  325. end;
  326. procedure TUpFileManageView.btnDownClick(Sender: TObject);
  327. var svDlg: TSaveDialog;
  328. sFile, sName, sPath: string;
  329. begin
  330. if not Assigned(Selected) then Exit;
  331. svDlg := TSaveDialog.Create(nil);
  332. svDlg.InitialDir := ExtractFilePath(Application.ExeName) + 'UserData\';
  333. svDlg.FileName := Selected.Data.DisplayName;
  334. try
  335. if svDlg.Execute then
  336. begin
  337. if FileExists(svDlg.FileName) then
  338. begin
  339. if Application.MessageBox('文件已存在,是否覆盖?', '询问', MB_YESNO) = ID_NO then
  340. Exit;
  341. end;
  342. Screen.Cursor := crHourGlass;
  343. Selected.Data.Status := ufsDowning;
  344. sFile := svDlg.FileName;
  345. if PHPWeb.DownFile(Selected.Data.DownURL, sFile) then
  346. begin
  347. Selected.Data.Status := ufsNormal;
  348. sName := ExtractFileName(sFile);
  349. sPath := ExtractFilePath(sFile);
  350. TProjectData(FProjectData).AttachmentInfoData.SaveAttachmentPath(Selected.Data.ID, sFile);
  351. ShellExecute(Handle, 'open', pchar(sName), nil, pchar(sPath), SW_SHOWNORMAL);
  352. end
  353. else
  354. begin
  355. Selected.Data.Status := ufsDownFail;
  356. end;
  357. end
  358. else
  359. Exit;
  360. finally
  361. svDlg.Free;
  362. Screen.Cursor := crDefault;
  363. end;
  364. end;
  365. constructor TUpFileManageView.Create(AOwner: TComponent);
  366. begin
  367. inherited;
  368. FRec := nil;
  369. lblBillName.Caption := '';
  370. lblBillName.Update;
  371. pnlDetail.Visible := G_IsCloud;
  372. TProjectFrame(AOwner).BillsMeasureFrame.BillsMeasureData.OnRecChange := DoOnBillChange;
  373. TProjectFrame(AOwner).BillsCompileFrame.BillsCompileData.OnRecChange := DoOnBillChange;
  374. end;
  375. procedure TUpFileManageView.DoOnBillChange(ARec: TsdDataRecord);
  376. begin
  377. FRec := ARec;
  378. with TProjectFrame(Owner) do
  379. begin
  380. if not (jpsAssistant.Visible and (jpsAssistant.ActivePage = jpsAssistantUpFile)) then
  381. Exit;
  382. end;
  383. RefreshBill;
  384. RefreshViews;
  385. end;
  386. procedure TUpFileManageView.SetRec(const Value: TsdDataRecord);
  387. begin
  388. FRec := Value;
  389. end;
  390. procedure TUpFileManageView.RefreshBill;
  391. var sCode: string;
  392. begin
  393. if FRec <> nil then
  394. begin
  395. if FRec.ValueByName('Code').AsString <> '' then
  396. sCode := FRec.ValueByName('Code').AsString
  397. else
  398. sCode := FRec.ValueByName('B_Code').AsString;
  399. if sCode <> '' then
  400. sCode := sCode + ' ';
  401. lblBillName.Caption := sCode + FRec.ValueByName('Name').AsString;
  402. end
  403. else
  404. lblBillName.Caption := '';
  405. lblBillName.Update;
  406. end;
  407. procedure TUpFileManageView.SelectUpFile;
  408. var vODlg: TOpenDialog;
  409. i, iBillID: Integer;
  410. vFile: TUpFile;
  411. sFile, sName: string;
  412. iV: Int64;
  413. begin
  414. vODlg := TOpenDialog.Create(nil);
  415. vODlg.Options := vODlg.Options + [ofAllowMultiSelect];
  416. if vODlg.Execute then
  417. begin
  418. for i := 0 to vODlg.Files.Count - 1 do
  419. begin
  420. sFile := vODlg.Files[i];
  421. iV := FileSizeByName(sFile);
  422. if iV >= 52428800 then
  423. begin
  424. Application.MessageBox(PChar('“' + sFile + '”过大,单个文件上传不能超过50M!'), '提示', MB_OK + MB_ICONINFORMATION);
  425. Continue;
  426. end;
  427. with MainForm.CurProjectFrame.dxsbViewControl do
  428. begin
  429. if SelectedItem = Groups[0].Items[0] then
  430. iBillID := TProjectData(FProjectData).BillsCompileData.BillsCompileTree.Selected.ID
  431. else if SelectedItem = Groups[0].Items[1] then
  432. iBillID := TProjectData(FProjectData).BillsMeasureData.BillsMeasureTree.Selected.ID;
  433. end;
  434. sName := ExtractFileName(sFile);
  435. vFile := Datas.Add(iBillID);
  436. vFile.Phase := TProjectData(FProjectData).PhaseIndex;
  437. vFile.OrgFile := sFile;
  438. vFile.Category := '台帐附件';
  439. vFile.Memo := '我的备注';
  440. vFile.LocalFile := Datas.Path + sName;
  441. vFile.DisplayName := sName;
  442. vFile.Status := ufsNeedUp;
  443. if G_IsCloud then
  444. begin
  445. // 添加到类→上传到服务器,生成ID→再到类中修改ID。为什么不先上传到服务器生成ID
  446. // 再添加到类并设置ID这样可以一气呵成呢?因为需要给用户一个交互界面让用户可以批量
  447. // 操作并决定取消某几个上传。这个交互界面的数据来自类。
  448. vFile.WebID := TProjectData(FProjectData).WebID;
  449. vFile.UperID := PHPWeb.UserID;
  450. vFile.UperName := PHPWeb.RealName;
  451. vFile.UpTime := FormatDateTime('yyyy-mm-dd hh:mm', Now);
  452. end
  453. else
  454. begin
  455. //
  456. end;
  457. AddUpFileView(vFile);
  458. end;
  459. end;
  460. Application.ProcessMessages;
  461. end;
  462. procedure TUpFileManageView.miLocalUpClick(Sender: TObject);
  463. begin
  464. SelectUpFile;
  465. end;
  466. procedure TUpFileManageView.miServerUpClick(Sender: TObject);
  467. var
  468. vForm: TUpFileSelectOnLineForm;
  469. begin
  470. vForm := TUpFileSelectOnLineForm.Create(nil);
  471. try
  472. vForm.InitData(FDatas.List);
  473. if vForm.ModalResult = mrOK then
  474. begin
  475. vForm.UpOnlineFiles;
  476. end;
  477. finally
  478. vForm.Free;
  479. end;
  480. end;
  481. procedure TUpFileManageView.FrameMouseWheel(Sender: TObject;
  482. Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
  483. var Handled: Boolean);
  484. begin
  485. if WheelDelta < 0 then
  486. sbFile.Perform(WM_VSCROLL, SB_LINEDOWN, 0)
  487. else
  488. sbFile.Perform(WM_VSCROLL, SB_LINEUP, 0);
  489. end;
  490. end.