起步软件技术论坛-X3

 找回密码
 立即注册
搜索
查看: 7086|回复: 68

[分享]根据需要做一个查询任务的功能,并且可以运行查询到的任务

[复制链接]
发表于 2007-10-29 09:55:28 | 显示全部楼层 |阅读模式
平台提供的流程监控功能是从流程、任务的角度出发来查询出任务,对任务做相应的控制的。很多时候,用户需要从业务数据的视角触发来查看并且运行控制任务。
这时候需要做以下几件事情:
1 在业务数据中记录状态,例如这条业务数据当前在处理的环节,处理的状态,可能还有更详细的状态显示。
2 在流程中,根据流程状态来设置这个状态字段。例如在AfterFlowOut事件中修改这个状态字段的值,或者在AfterFlowBack中修改状态字段的值等。(在流程中控制这些业务数据不需要主动的启动事务,流程中的这些事务控制都是由平台来做的),参考 http://wiki.justep.cn/%E4%BA%8B% ... 73a56db2280784acbff
3 做一个功能来根据状态字段或者业务数据的其他字段查询需要的业务数据,查询功能跟其他的功能没有任何区别。在查询到相应的业务数据以后,要根据这条业务数据,找到相应的流程任务,用流程控制代码控制任务的执行或者其他动作。
回复

使用道具 举报

 楼主| 发表于 2007-10-29 10:00:07 | 显示全部楼层
上面的第3步,根据业务数据定位需要的流程任务,要用到
Business.Model.Flow.Flow.FlowEngine.GetTasks 函数,根据流程条件或者任务条件定位需要的任务
procedure GetTasks(ATaskParam: TLoadTaskParam; ATasks: TTasks); overload;
procedure GetTasks(AFlowParam: TLoadFlowParam; ATaskParam: TLoadTaskParam; ATasks: TTasks); overload;

TLoadFlowParam = class(Business.System.TPersistent)
public
  constructor create;
  procedure Assign(Source: Business.System.TPersistent); override;
  procedure Destroy; override;
  //流程实例创建时间范围
  property CreateDateTimeRange: TDateTimeRange;
  //流程guid
  property GUIDs: Business.System.TStrings;
  //流程ID(流程字段的值),目前有缺陷,不能用这个条件,可以用GUIDs代替
  property IDs: Business.System.TStrings;
  //流程模型的BizURL
  property ProcURLs: Business.System.TStrings;
  //流程状态,TFlowState的集合
  property States: TFlowStates;
end;

TLoadTaskParam = class(Business.System.TPersistent)
protected
  property TaskMessageParam: TLoadTaskMessageParam;
public
  constructor create;
  procedure Assign(Source: Business.System.TPersistent); override;
  function DefinedFilter: Boolean;
  procedure Destroy; override;
  //流程环节上定义的任务类型
  property BizKinds: Business.System.TStringList;
  //任务结束时间的时间范围
  property FinishDateTimeRange: TDateTimeRange;
  //流程Guid,对应的流程表中的FGuid字段值
  property FlowGUIDs: Business.System.TStringList;
  //组任务Guid,在流程批处理的分组处理时候会出现组任务
  property GroupGUIDs: Business.System.TStringList;
  //任务Guid,任务表中的FGuid字段值
  property GUIDs: Business.System.TStringList;
  property IncludeReceiverChildren: Boolean;
  property IncludeReceiverDisplayName: Boolean;
  property IncludeReceiverParent: Boolean;
  property IncludeSenderChildren: Boolean;
  property IncludeSenderDisplayName: Boolean;
  property IncludeSenderParent: Boolean;
  property IncludeTaskMessage: Boolean;
  property Kinds: Business.System.TStringList;
  property LimiteDateTimeRange: TDateTimeRange;
  //父任务的Guid,任务合并处理会出现父任务
  property ParentGUIDs: Business.System.TStringList;
  //流程环节的ID
  property ProcUnitIDs: Business.System.TStringList;
  //流程模型的BizURL
  property ProcURLs: Business.System.TStringList;
  //任务的接收者列表
  property Receivers: Business.Model.Org.TOrgURLs;
  //任务的发送者列表
  property Senders: Business.Model.Org.TOrgURLs;
  //任务开始时间的时间范围
  property StartDateTimeRange: TDateTimeRange;
  //任务状态,TTaskState的集合
  property States: TTaskStates;
  //任务消息状态,TTaskMessageState的集合
  property TaskMessageStates: TTaskMessageStates;
end;
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-10-29 10:43:16 | 显示全部楼层
例如:根据当前业务数据,显示这条业务数据对应流程的流程轨迹
uses
  Business.Model.Flow;

//查询流程ID表,根据流程ID,查询出对应的FlowGuid值
procedure TMainForm.DoGetFlowGUIDs(const AFlowID: string; AFlowGUIDs: TStrings);
begin
  Query.CommandText := SysUtils.Format('SELECT FFLOWGUID FROM TFLOWID WHERE FID = ''%s''', [AFlowID]);
  Query.Open;
  while not Query.Eof do
  begin
    AFlowGUIDs.Add(Query.FieldByName('FFLOWGUID').AsString);
    Query.Next;
  end;
  Query.Close;
end;

procedure TMainForm.btnFlowViewClick(Sender: TObject);
var
  lTaskParam: TLoadTaskParam;
  lFlowParam: TLoadFlowParam;
  lTasks: TTasks;
  lFlows: TObjectList;
  i: Integer;
  lDataSet : TDataSet;
begin
  lDataSet := DataSetBroker1.DataSet;
  if not lDataSet.Active or lDataSet.Eof then
    Exit;

  lFlowParam := TLoadFlowParam.Create;
  lFlows := TObjectList.Create;
  try
    //根据ProductID,找到对应的流程Guid值
    DoGetFlowGUIDs(lDataSet.FieldByName('ProductID').AsString, lFlowParam.GUIDs);
    //以给定的条件查询流程实例(这里给定的条件由lFlowParam给出,根据流程Guid值查询)
    Flow.FlowEngine.GetFlows(lFlowParam, lFlows);
    Dialogs.Showmessage(SysUtils.IntToStr(lFlows.Count));
    for i:=0 to lFlows.Count-1 do
      SystemCore.TSystemCore.SystemInterface.ShowFlowView(lFlows as TFlow);
  finally
    lFlowParam.Free;
    lFlows.Free;
  end;
end;
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-10-29 11:55:46 | 显示全部楼层
例如:根据当前业务数据,查询出对应的任务,并且运行起这个任务,就像任务中心一样
procedure TMainForm.DoGetTaskReceivers(AOrgURLs: TOrgURLs);
var
  lOrgUnit: TOrgUnit;
  i: Integer;
begin
  for i:=0 to SystemCore.TSystemCore.Operator.PositionCount-1 do
  begin
    //每一个岗位环境下的人员成员
    lOrgUnit := SystemCore.TSystemCore.Operator.Positions.PersonMember;

    while lOrgUnit <> nil do
    begin
      case lOrgUnit.OrgKind of
        TOrgUnitKind.boOrgan, TOrgUnitKind.boDept:
          AOrgURLs.Add(lOrgUnit.ID, '', '');
        TOrgUnitKind.boPositionMember:
        begin
          AOrgURLs.Add(lOrgUnit.Parent.ID, lOrgUnit.ID, '');
          AOrgURLs.Add('', lOrgUnit.ID, '');
        end;
        TOrgUnitKind.boPersonMember:
          AOrgURLs.Add(lOrgUnit.Parent.Parent.ID, lOrgUnit.Parent.ID, lOrgUnit.ID);
      end;
      //找组织单元的父,因为分配到父单元上的任务,也是可以执行的
      //例如:直接分配在部门上的任务,部门内的每一个人员成员都可以执行
      lOrgUnit := lOrgUnit.Parent;
    end;
  end;
end;

function TMAINFORM.GetTaskContext(ATask: TTask): TContext;
var
  i: Integer;
  lTask: TaskLib.TTask;
begin
  //需要在项目管理中引入 协同系统\任务\任务库
  lTask := TaskLib.TTask.Create;
  try
    lTask.Assign(ATask);
    for i:=0 to ATask.TaskMessages.Count-1 do
    begin
      //调用任务库中的静态函数FindTaskRunContext,用每一个任务消息查找环境
      Result := TaskLib.TTaskServices.FindTaskRunContext(Context, lTask, lTask.TaskMessages);
      if Assigned(Result) then
        Break;
    end;
    if not Assigned(Result) then
      Result := SystemCore.TSystemCore.Operator.Positions[0].Context;
  finally
    lTask := nil;
  end;
end;

procedure TMainForm.btnRunTaskClick(Sender: TObject);
var
  lTaskParam: TLoadTaskParam;
  lFlowParam: TLoadFlowParam;
  lTasks: TTasks;
  lDataSet : TDataSet;
  lContext: TContext;
begin
  lDataSet := DataSetBroker1.DataSet;
  if not lDataSet.Active or lDataSet.Eof then
    Exit;

  lFlowParam := TLoadFlowParam.Create;
  lTaskParam := TLoadTaskParam.Create;
  lTasks := TTasks.Create;
  try
    //根据ProductID,找到对应的流程Guid值
    DoGetFlowGUIDs(lDataSet.FieldByName('ProductID').AsString, lFlowParam.GUIDs);
    if cbUnFinished.Checked then
      lTaskParam.States := Task.SUnFinishedTaskStates;
    if cbMyTask.Checked then
      DoGetTaskReceivers(lTaskParam.Receivers);
    //以给定的条件查询任务(这里给定的条件由lFlowParam给出,根据流程Guid值查询,lTaskParam条件是按照任务状态,只查询出需要处理的任务)
    Flow.FlowEngine.GetTasks(lFlowParam, lTaskParam, lTasks);
    if lTasks.Count=0 then
      raise Exception.Create('没有符合条件的任务!');
    lContext := GetTaskContext(lTasks[0]);
    lFunc := SystemCore.TSystemCore.FuncManager.RunTask(lContext, lTasks[0]);
  finally
    lFlowParam.Free;
    lTaskParam.Free;
    lTasks.Free;
  end;
end;

此贴修改历史:
2007-10-29 11:55  提供第一个版本,可以用第一个岗位运行查询出的任务
2007-12-03 15:01 更新了如下内容
    1  只检查自己的任务(当然,如果给管理员使用可以不是自己的任务)
    2  要检查得到的任务列表不为空
    3  如果人员有多个岗位,需要找到合适的岗位环境来运行任务
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-10-29 13:29:28 | 显示全部楼层
举例2:根据业务数据找到相应的任务,并运行起来
procedure TMainForm.btnRunTaskClick(Sender: TObject);
var
  lTaskParam: TLoadTaskParam;
  lFlowParam: TLoadFlowParam;
  lTasks: TTasks;
  lDataSet : TDataSet;
  lFunc: TFunc;
  lFlowControl: TFlowControl;
begin
  lDataSet := DataSetBroker1.DataSet;
  if not lDataSet.Active or lDataSet.Eof then
    Exit;

  lFlowParam := TLoadFlowParam.Create;
  lTaskParam := TLoadTaskParam.Create;
  lTasks := TTasks.Create;
  try

    //根据ProductID,找到对应的流程Guid值
    DoGetFlowGUIDs(lDataSet.FieldByName('ProductID').AsString, lFlowParam.GUIDs);
    lTaskParam.States := [TTaskState.tsStarted, TTaskState.tsProcessing, TTaskState.tsWaiting];
    //以给定的条件查询任务(这里给定的条件由lFlowParam给出,根据流程Guid值查询,lTaskParam条件是按照任务状态,只查询出需要处理的任务)
    Flow.FlowEngine.GetTasks(lFlowParam, lTaskParam, lTasks);
    lFunc := SystemCore.TSystemCore.FuncManager.RunTask(SystemCore.TSystemCore.Operator.Positions[0], lTasks[0]);
  //如果需要自动流转,则需要下面的代码vvvvvvvvvvvvvv
    lFlowControl := lFunc.Context.GetParentContext(BizSys.IL_FLOW).Owner as TFlowControl;
    lFlowControl.FlowOut(nil);
  //如果需要自动流转,则需要下面的代码^^^^^^^^^^^^^^
  finally
    lFlowParam.Free;
    lTaskParam.Free;
    lTasks.Free;
  end;
end;
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-10-29 13:55:27 | 显示全部楼层
举例3:在自定义的流程监控窗体上,通过截获流程事件作各种流程的控制
procedure TMainForm.btnRunTaskClick(Sender: TObject);
var
  lTaskParam: TLoadTaskParam;
  lFlowParam: TLoadFlowParam;
  lTasks: TTasks;
  lDataSet : TDataSet;
  lFunc: TFunc;
  lFlowControl: TFlowControl;
  FlowBroker: TFlowBroker;
begin
  lDataSet := DataSetBroker1.DataSet;
  if not lDataSet.Active or lDataSet.Eof then
    Exit;

  lFlowParam := TLoadFlowParam.Create;
  lTaskParam := TLoadTaskParam.Create;
  lTasks := TTasks.Create;
  try

    //根据ProductID,找到对应的流程Guid值
    DoGetFlowGUIDs(lDataSet.FieldByName('ProductID').AsString, lFlowParam.GUIDs);
    lTaskParam.States := [TTaskState.tsStarted, TTaskState.tsProcessing, TTaskState.tsWaiting];
    //以给定的条件查询任务(这里给定的条件由lFlowParam给出,根据流程Guid值查询,lTaskParam条件是按照任务状态,只查询出需要处理的任务)
    Flow.FlowEngine.GetTasks(lFlowParam, lTaskParam, lTasks);
    lFunc := SystemCore.TSystemCore.FuncManager.RunTask(SystemCore.TSystemCore.Operator.Positions[0], lTasks[0]);
    lFlowControl := lFunc.Context.GetParentContext(BizSys.IL_FLOW).Owner as TFlowControl;
    //创建一个流程代理,对流程代理的事件赋值,可以在流程监控中自己控制流程流转时是否显示流转对话框,根据业务数据确定下一个环节执行者等
    FlowBroker := TFlowBroker.Create(lFunc);
    FlowBroker.OnCreateFlowOutFlowTasks := FlowBrokerBeforeFlowOut;
    //在流程控制中,注册自己创建的流程代理
    lFlowControl.RegisterFlowBroker(FlowBroker);
    lFlowControl.FlowOut(nil);
    lFlowControl.UnRegisterFlowBroker(FlowBroker);
  finally
    lFlowParam.Free;
    lTaskParam.Free;
    lTasks.Free;
  end;
end;
回复 支持 反对

使用道具 举报

发表于 2007-10-29 15:25:09 | 显示全部楼层
因为流程种类多,我们开发了一个流程查询界面,把相同流程放一起,但是功能待完善,可方便查询本流程的轨迹及状态。流程监控需有三项内容:流程类型、流程列表、流程步骤。按流程类型过滤出流程列表,点击流程列表中其中一条流程,显示该流程的所有步骤。(也就是如何与流程的图等关联起来)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-10-29 15:41:55 | 显示全部楼层
请楼主用平台上的技术词汇解释一下:流程类型、流程列表、流程步骤 的含义
这三个分别代表了平台上的什么?
回复 支持 反对

使用道具 举报

发表于 2007-10-29 16:10:02 | 显示全部楼层
要不这样
根据当前业务数据,查询出对应的任务并能处理,可查看对应的流程图(流程轨迹)等

要如何做。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-10-29 16:17:50 | 显示全部楼层
天啊,上面我给的例子是干什么的?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Justep Inc.

GMT+8, 2024-12-22 18:56 , Processed in 0.039592 second(s), 16 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表