{*******************************************************************************
  单元名称：  OrderCheckerFme.pas

  单元说明：  动态添加审核人。

  作者时间：  Chenshilong, 2014-07-11
*******************************************************************************}

unit OrderCheckerFme;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, pngimage, CslButton, cxHint;

type
  TCheckerFrameType = (cftChecker, cftOwner, cftAdd);
  TCheckStatus = (csNotBegin, csChecking, csFinished, csNotPass);  // 末审核，审核中，审核完成，审核不通过

const
  CheckStatusNames: array[TCheckStatus] of string = ('未审批', '审批中', '审批通过', '审批不通过');
  CheckStatusColors: array[TCheckStatus] of TColor = ($00B7B7B7, $000099FF, $000E9D00, clRed);

type
  TOrderCheckerFrame = class(TFrame)
    pnlChecker: TPanel;
    shpImage: TShape;
    imgOrderCheckerPic: TImage;
    lblOrderCheckerName: TLabel;
    lblOrderCheckerRole: TLabel;
    lblOrderCheckerCompany: TLabel;
    shpBotom: TShape;
    lblOrderCheckerNum: TLabel;
    lblOrderStatus: TLabel;
    lblLast: TLabel;
    lblAdd: TLabel;
    lblAddHint: TLabel;
    shpAdd: TShape;
    imgChecking: TImage;
    imgNotBegin: TImage;
    imgFinish: TImage;
    imgNotPass: TImage;
    btnDelete: TCslButton;
    lblOrderCheckerMemo: TLabel;
    lblOrderCheckerTime: TLabel;
    procedure shpAddMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure btnDeleteClick(Sender: TObject);
  private
    FUserID: Integer;
    FOrder: Integer;
    FUserName: string;
    FOwner: TObject;
    FCheckerFrameType: TCheckerFrameType;
    FCheckStatus: TCheckStatus;
    FUserRole: string;
    FCheckerMemo: string;
    FCheckedTime: string;
    FCheckedOnline: Integer;
    procedure SetOrder(const Value: Integer);
    procedure SetCheckStatus(const Value: TCheckStatus);
    procedure SetCheckerMemo(const Value: string);
    procedure SetCheckedTime(const Value: string);
    procedure RightAlign(ALabel: TLabel);
    { Private declarations }
  public
    { Public declarations }
    procedure Init(AType: TCheckerFrameType; AID: Integer; AName, ARole,
    ACompany, AImagePath, ACheckerMemo: string; ACheckStatus: TCheckStatus;
    ACheckedTime: string; ACheckedOnLine: Integer);
    function IsMe(AID: Integer; AName: string): string;
    function IsChecking: Boolean;
    function IsFinished: Boolean;


    property Owner: TObject read FOwner write FOwner;
    property UserID: Integer read FUserID write FUserID;
    property UserName: string read FUserName write FUserName;
    property UserRole: string read FUserRole write FUserRole;
    property Order: Integer read FOrder write SetOrder;
    property CheckerFrameType: TCheckerFrameType read FCheckerFrameType write FCheckerFrameType;   // 审核人类型
    property CheckStatus: TCheckStatus read FCheckStatus write SetCheckStatus;     // 审核状态
    property CheckerMemo: string read FCheckerMemo write SetCheckerMemo;           // 审核意见
    property CheckedTime: string read FCheckedTime write SetCheckedTime;
    property CheckedOnLine: Integer read FCheckedOnLine write FCheckedOnLine;  // 0 线下审批(默认)；1 线上审批。
  end;

implementation

uses FindUserFrm, CheckerFme, PHPWebDm, ProjectData, ProjectFme,
  UtilMethods;

{$R *.dfm}

{ TOrderCheckerFrame }

procedure TOrderCheckerFrame.Init(AType: TCheckerFrameType; AID: Integer;
  AName, ARole, ACompany, AImagePath, ACheckerMemo: string;
  ACheckStatus: TCheckStatus; ACheckedTime: string; ACheckedOnLine: Integer);
var bAdd, bOwner: Boolean;
  sOnLine: string;
begin
  bAdd := AType = cftAdd;
  shpAdd.Visible := bAdd;
  lblAdd.Visible := bAdd;
  lblAddHint.Visible := bAdd;
  lblOrderCheckerName.Visible := not bAdd;
  lblOrderCheckerRole.Visible := not bAdd;
  lblOrderCheckerCompany.Visible := not bAdd;
  lblOrderStatus.Visible := not bAdd;

  shpImage.Visible := not bAdd;
  lblOrderCheckerMemo.Visible := not bAdd;
  bOwner := AType = cftOwner;
  lblLast.Visible := bOwner;
  lblOrderCheckerNum.Visible := not bOwner;

  CheckerFrameType := AType;
  CheckStatus := ACheckStatus;

  lblOrderStatus.Visible := not bAdd;
  if lblOrderStatus.Visible then
    RightAlign(lblOrderStatus);

  lblOrderCheckerTime.Visible := (not bAdd) and (CheckStatus in [csFinished, csNotPass]);
  if lblOrderCheckerTime.Visible then
    RightAlign(lblOrderCheckerTime);

  case AType of
    cftChecker, cftOwner:
    begin
      UserID := AID;
      UserName := IsMe(AID, AName);
      UserRole := ARole;

      lblOrderCheckerName.Caption := UserName;
      lblOrderCheckerRole.Caption := ARole;
      lblOrderCheckerCompany.Caption := ACompany;

      if CheckStatus in [csFinished, csNotPass] then
      begin
        CheckedOnLine := ACheckedOnLine;
        if ACheckedOnLine = 0 then
          sOnLine := '线下审批'
        else if ACheckedOnLine = 1 then
          sOnLine := '线上审批';

        CheckedTime := Format('[%s][%s]', [ACheckedTime, sOnLine]);
      end;

      CheckerMemo := RecoverCharsFromJson(ACheckerMemo);
      if FileExists(AImagePath) then
        imgOrderCheckerPic.Picture.LoadFromFile(AImagePath)
      else
        imgOrderCheckerPic.Picture.LoadFromFile(ExtractFilePath(Application.ExeName) + 'DefaultImage.jpg');
    end;
    cftAdd:
    begin
      UserID := -1;
      UserName := '';
      UserRole := '';
    end;
  end;
end;

function TOrderCheckerFrame.IsChecking: Boolean;
begin
  Result := CheckStatus = csChecking;
end;

function TOrderCheckerFrame.IsFinished: Boolean;
begin
  Result := CheckStatus = csFinished;
end;

function TOrderCheckerFrame.IsMe(AID: Integer; AName: string): string;
begin
  if AID = PHPWeb.UserID then
    Result := AName + '（我）'
  else
    Result := AName;
end;

// 审核状态：状态名称、颜色（状态名称、终审、编号）、图像边框
procedure TOrderCheckerFrame.SetCheckStatus(const Value: TCheckStatus);
var vColor: TColor;
begin
  FCheckStatus := Value;
  lblOrderStatus.Caption := CheckStatusNames[Value];
  RightAlign(lblOrderStatus);
  vColor := CheckStatusColors[Value];
  lblOrderCheckerNum.Font.Color := vColor;
  lblOrderStatus.Font.Color := vColor;
  lblLast.Font.Color := vColor;
  lblOrderCheckerMemo.Font.Color := vColor;
  lblOrderCheckerTime.Font.Color := vColor;
//  cxHintStyleController1.HintStyle.Color := clWindow;        气泡Hint，很帅，但是有Bug，频繁操作时会出错，废弃不用，可惜！
//  cxHintStyleController1.HintStyle.Font.Color := vColor;

  imgNotBegin.Visible := False;
  imgChecking.Visible := False;
  imgFinish.Visible := False;
  imgNotPass.Visible := False;

  if FCheckerFrameType <> cftAdd then
  begin
    case Value of
      csNotBegin:
        imgNotBegin.Visible := True;
      csChecking:
        imgChecking.Visible := True;
      csFinished:
        imgFinish.Visible := True;
      csNotPass:
        imgNotPass.Visible := True;
    end;
  end;
end;

procedure TOrderCheckerFrame.SetOrder(const Value: Integer);
begin
  FOrder := Value;
  lblOrderCheckerNum.Caption := IntToStr(FOrder);
  lblOrderCheckerNum.Update;
end;

procedure TOrderCheckerFrame.shpAddMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  FindUserForm: TFindUserForm;
  vPD: TProjectData;
begin
  if Button = mbLeft then
  begin
    vPD := TProjectData(TCheckerFrame(Owner).ProjectData);
    FindUserForm := TFindUserForm.Create(Self, 0, [vPD.WebID, vPD.PhaseIndex]);
    try
      FindUserForm.ShowModal;
    finally
      FindUserForm.Free;
    end;
  end;
end;

procedure TOrderCheckerFrame.btnDeleteClick(Sender: TObject);
var sURL: string;
  vProj: TProjectData;
  vArr: array of string;
begin
  if Application.MessageBox('确定要删除该审批人吗？', '询问', MB_YESNO + MB_ICONQUESTION) = ID_No then
    Exit;

  vProj := TProjectData(TCheckerFrame(Owner).ProjectData);
  sURL := Format('%suser/del/%d/%d/%d/audit', [PHPWeb.MeasureURL, Self.UserID,
    vProj.WebID, vProj.PhaseIndex]);

  vArr := VarArrayOf(['msg']);
  case PHPWeb.Search(sURL, [], [], vArr) of
    1:
    begin
      // 这里直接调用Init方法会出问题，因为事件还没影响完就被释放了，运行出错。
      // 问题的根源在于触发事件的位置来自控件的内部（即使这里调用外部的方法来
      // 搞定它也不行），CS常规的设计方法是外部来控制它，而不是由自身来控制。
      // 这算是BS设计跟CS设计差异的一个体现吧。
      TCheckerFrame(Owner).tRefreshCheckers.Enabled := True;
    end;
    0:
    begin
      Application.MessageBox(PChar(PHPWeb.PageError('无法删除审批人' + '[' + vArr[0] + ']')),
        '警告', MB_OK + MB_ICONWARNING);
      Exit;
    end;
    -1:
    begin
      Application.MessageBox(PChar(PHPWeb.NetError('无法删除审批人')),
        '警告', MB_OK + MB_ICONWARNING);
    end;
  end;
end;

procedure TOrderCheckerFrame.SetCheckerMemo(const Value: string);
begin
  FCheckerMemo := Value;

  lblOrderCheckerMemo.Caption := ShortText(FCheckerMemo, 250);
  lblOrderCheckerMemo.Hint := CustomWidthText(FCheckerMemo, 300);
  lblOrderCheckerMemo.Update;
end;


procedure TOrderCheckerFrame.SetCheckedTime(const Value: string);
begin
  FCheckedTime := Value;

  lblOrderCheckerTime.Caption := Value;
  lblOrderCheckerTime.Visible := (CheckStatus in [csFinished, csNotPass]);
  RightAlign(lblOrderCheckerTime);
end;

procedure TOrderCheckerFrame.RightAlign(ALabel: TLabel);
begin
  ALabel.Left := btnDelete.Left + btnDelete.Width - ALabel.Width;
end;

end.
