NC65 查询单据所处的流程状态以及流程平台客户端工具类

发布时间:2023年12月21日

1、查询单据所处的流程状态

nc.bs.wfengine.engine.EngineService的queryFlowStatus()方法

/**
	 * 查询单据所处的流程状态
	 * 
	 * @param billId
	 * @param billType
	 * @param result
	 * @return
	 * @throws DbException
	 */
	public int queryFlowStatus(String billId, String billType, int flowType, String taskResult) throws DbException {
		IFlowStatusService flowStatusService = AbstractFlowStatusService.getFlowStatusService(flowType);
		return flowStatusService.queryFlowStatus(billId, billType, taskResult);
	}

在这里插入图片描述

nc.bs.pub.wfengine.status.AbstractFlowStatusService

package nc.bs.pub.wfengine.status;

import java.util.ArrayList;
import java.util.Iterator;

import nc.jdbc.framework.JdbcSession;
import nc.jdbc.framework.PersistenceManager;
import nc.jdbc.framework.SQLParameter;
import nc.jdbc.framework.exception.DbException;
import nc.jdbc.framework.processor.ArrayListProcessor;
import nc.jdbc.framework.processor.ArrayProcessor;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.vo.pub.pf.IPfRetCheckInfo;
import nc.vo.wfengine.definition.WorkflowTypeEnum;
import nc.vo.wfengine.pub.WfTaskOrInstanceStatus;
import nc.vo.wfengine.pub.WfTaskType;

public abstract class AbstractFlowStatusService implements IFlowStatusService {

	public static IFlowStatusService getFlowStatusService(int type) {
		WorkflowTypeEnum flowtype = WorkflowTypeEnum.fromIntValue(type);
		switch (flowtype) {
		case Approveflow:
		case SubApproveflow:
			return new ApproveflowStatusService();
		case Workflow:
		case SubWorkflow:
			return new WorkflowStatusService();
		case SubWorkApproveflow:
			return new SubWorkApproveflowStatusService();

		}
		return null;
	}

	public int queryFlowStatus(String billId, String billType, String taskResult)throws DbException{
		return 0;
	}

	protected int queryCurrentFlowStatus(String billId, String billType,
			int flowType) throws DbException {
		// 1.查询主流程实例的状态
		String sql = "select procstatus,procresult from pub_wf_instance"
				+ " where billversionpk=? and billtype=? and procstatus!="
				+ WfTaskOrInstanceStatus.Inefficient.getIntValue()
				+ " and ( isnull(cast(workflow_type as char),'~')='~' or workflow_type=?)";

		// 2.查询有无处于启动状态的修单任务
		String sql1 = "select b.pk_wf_task from pub_wf_task b,pub_wf_instance a"
				+ " where a.billversionpk=? and a.billtype=? and a.procstatus!="
				+ WfTaskOrInstanceStatus.Inefficient.getIntValue()
				+ " and (isnull(cast(a.workflow_type as char),'~')='~' or a.workflow_type=?)"
				+ " and b.pk_wf_instance=a.pk_wf_instance and b.tasktype="
				+ WfTaskType.Makebill.getIntValue() + " and b.taskstatus="
				+ WfTaskOrInstanceStatus.Started.getIntValue();

		// 3.查询有无已处于启动/完成状态的审批工作项
		String sql2 = "select a.approvestatus,b.pk_wf_task from pub_workflownote a,pub_wf_task b"
				+ " where a.pk_wf_task=b.pk_wf_task and b.tasktype=" + WfTaskType.Forward.getIntValue()
				+ " and a.approvestatus in(" + WfTaskOrInstanceStatus.Started.getIntValue() + ","
				+ WfTaskOrInstanceStatus.Finished.getIntValue() + ") and a.billversionpk=? and a.pk_billtype=?"
				+ " and (isnull(cast(a.workflow_type as char),'~')='~' or a.workflow_type=? or a.workflow_type = 3 or a.workflow_type = 5 or a.workflow_type = 6)"; 

		PersistenceManager persist = null;
		try {
			persist = PersistenceManager.getInstance();
			JdbcSession jdbc = persist.getJdbcSession();
			SQLParameter para = new SQLParameter();
			para.addParam(billId);
			para.addParam(billType);
			para.addParam(flowType);
			Object[] objs = (Object[]) jdbc.executeQuery(sql, para, new ArrayProcessor());
			if (objs != null) {
				// 单据已经拥有流程实例
				int status = ((Integer) objs[0]).intValue();
				String result = String.valueOf(objs[1]);

				if (status != WfTaskOrInstanceStatus.Finished.getIntValue()) {
					// 流程未结束
					Object objTaskPK = jdbc.executeQuery(sql1, para, new ColumnProcessor(1));
					if (objTaskPK != null) {
						String pk_wf_task = String.valueOf(objTaskPK);
						if (pk_wf_task != null && pk_wf_task.trim().length() > 0) {
							// 如果有修改单据的任务,为自由态
							return IPfRetCheckInfo.NOSTATE;
						}
					}

					ArrayList alResult = (ArrayList) jdbc.executeQuery(sql2, para, new ArrayListProcessor());
					boolean hasFinishedItem = false;
					boolean hasStartedItem = false;
					for (Iterator iterator = alResult.iterator(); iterator.hasNext();) {
						Object[] results = (Object[]) iterator.next();
						String taskPK2 = (String) results[1];
						int approveStatus = (Integer) results[0];
						if (taskPK2 != null) {
							if (approveStatus == WfTaskOrInstanceStatus.Finished.getIntValue())
								hasFinishedItem = true;
							if (approveStatus == WfTaskOrInstanceStatus.Started.getIntValue())
								hasStartedItem = true;
						}
					}
					if (hasFinishedItem) {
						// 如果存在已完成的审批任务,则进行中
						return IPfRetCheckInfo.GOINGON;
					} else if (hasStartedItem) {
						// 如果存在启动的审批任务,则提交态
						return IPfRetCheckInfo.COMMIT;
					} else
						// 如果无启动/完成的审批任务,则自由态
						return IPfRetCheckInfo.NOSTATE;
				}
				// 流程已经结束
				if (result != null && result.equalsIgnoreCase("Y"))
					return IPfRetCheckInfo.PASSING;
				if (result != null && result.equalsIgnoreCase("N"))
					return IPfRetCheckInfo.NOPASS;
			}

			// 尚无流程实例,则为自由态
			return IPfRetCheckInfo.NOSTATE;
		} finally {
			if (persist != null)
				persist.release();
		}

	}
}

2、流程平台客户端工具类

package nc.ui.pub.pf;

import java.awt.Container;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.Vector;

import javax.swing.JDialog;
import javax.swing.SwingUtilities;

import nc.bs.dao.DAOException;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.bs.pf.pub.BillTypeCacheKey;
import nc.bs.pf.pub.PfDataCache;
import nc.bs.pub.pf.PfUtilTools;
import nc.desktop.ui.WorkbenchEnvironment;
import nc.funcnode.ui.AbstractFunclet;
import nc.funcnode.ui.IFuncletWindow;
import nc.itf.uap.IUAPQueryBS;
import nc.itf.uap.pf.IPFConfig;
import nc.itf.uap.pf.IPFWorkflowQry;
import nc.itf.uap.pf.IPfExchangeService;
import nc.itf.uap.pf.IWorkflowDefine;
import nc.itf.uap.pf.IWorkflowMachine;
import nc.itf.uap.pf.IplatFormEntry;
import nc.itf.uap.pf.busiflow.PfButtonClickContext;
import nc.itf.uap.pf.metadata.IFlowBizItf;
import nc.message.Attachment;
import nc.message.vo.AttachmentVO;
import nc.uap.pf.metadata.PfMetadataTools;
import nc.ui.ml.NCLangRes;
import nc.ui.pf.change.PfUtilUITools;
import nc.ui.pf.clientutils.PfUtilClientAssistor;
import nc.ui.pf.pub.PFClientBizRetObj;
import nc.ui.pf.pub.PfUIDataCache;
import nc.ui.pf.workitem.ApproveFlowDispatchDialog;
import nc.ui.pf.workitem.ApproveWorkitemAcceptDlg;
import nc.ui.pf.workitem.BatchApproveModel;
import nc.ui.pf.workitem.BatchApproveWorkitemAcceptDlg;
import nc.ui.pf.workitem.WFStartDispatchDialog;
import nc.ui.pf.workitem.WorkflowWorkitemAcceptDlg;
import nc.ui.pf.workitem.beside.BesideApproveContext;
import nc.ui.pub.beans.MessageDialog;
import nc.ui.pub.beans.UIDialog;
import nc.ui.pub.bizflow.IBillReferQueryWithBusitype;
import nc.ui.pub.bizflow.IBillReferQueryWithScheme;
import nc.ui.pub.bizflow.IBillReferQueryWithTranstype;
import nc.ui.pub.workflowqry.WorkflowManageUtil;
import nc.ui.querytemplate.IBillReferQuery;
import nc.ui.querytemplate.QueryConditionDLG;
import nc.ui.querytemplate.querytree.IQueryScheme;
import nc.ui.wfengine.ext.ApplicationRuntimeAdjustContext;
import nc.ui.wfengine.ext.ApplicationRuntimeAdjustFactory;
import nc.ui.wfengine.ext.IApplicationRuntimeAdjust;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.pf.change.ExchangeVO;
import nc.vo.pf.change.PfUtilBaseTools;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.billtype2.Billtype2VO;
import nc.vo.pub.billtype2.ExtendedClassEnum;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.pf.AssignableInfo;
import nc.vo.pub.pf.PfAddInfo;
import nc.vo.pub.pf.PfClientBizProcessContext;
import nc.vo.pub.pf.workflow.IPFActionName;
import nc.vo.pub.pfflow.BillactionVO;
import nc.vo.pub.pfflow01.BillbusinessVO;
import nc.vo.pub.template.ITemplateStyle;
import nc.vo.pub.workflownote.WorkflownoteVO;
import nc.vo.querytemplate.TemplateInfo;
import nc.vo.sm.UserVO;
import nc.vo.uap.pf.FlowDefNotFoundException;
import nc.vo.uap.pf.PFBusinessException;
import nc.vo.uap.pf.PFRuntimeException;
import nc.vo.uap.pf.PfProcessBatchRetObject;
import nc.vo.wfengine.core.parser.XPDLNames;
import nc.vo.wfengine.definition.IApproveflowConst;
import nc.vo.wfengine.definition.WorkflowDefinitionVO;
import nc.vo.wfengine.definition.WorkflowTypeEnum;
import nc.vo.wfengine.pub.WFTask;
import nc.vo.wfengine.pub.WfTaskType;

/**
 * 流程平台客户端工具类
 * 
 * @author fangj 2001-10
 * @modifier leijun 2005-5 取消单据类型UI类名必须以<Y>开头才可指派的限制
 * @modifier leijun 2006-7 送审时的指派对话框,如果用户点击取消,则不送审
 * @modifier leijun 2007-5 使用新的查询模板
 * @modifier leijun 2008-3 重构动作处理的API,进一步精简
 * @modifier dingxm 2009-7 参照制单对于按钮逻辑的处理挪到BusinessDelegator,参照制单中本类只提供信息,不处理按钮
 * @modifier zhouzhenga 20120107 部分逻辑挪到PfUtilClientAssistor
 */
public class PfUtilClient {

	/**
	 * 审批变量如果审批则true反之false;
	 */
	private static boolean m_checkFlag = true;

	// 当前单据类型
	private static String m_currentBillType = null;

	/** 当前审批节点的审批结果 */
	private static int m_iCheckResult = IApproveflowConst.CHECK_RESULT_PASS;

	private static boolean m_isOk = false;

	/** fgj2001-11-27 判断当前动作是否执行成功 */
	private static boolean m_isSuccess = true;

	/** 源单据类型 */
	private static String m_sourceBillType = null;

	private static AggregatedValueObject m_tmpRetVo = null;

	private static AggregatedValueObject[] m_tmpRetVos = null;

	// 单据自制标志
	public static boolean makeFlag = false;

	private static IPfExchangeService exchangeService;

	private static int m_classifyMode = PfButtonClickContext.NoClassify;

	private static boolean isOpenedInDialog = false;
	private static boolean isAutoCloseParentDialog = false;

	/**
	 * 审批流定义查询服务
	 */
	private static IWorkflowDefine workflowDefService;

	private PfUtilClient() {
		// Noop!
	}

	/**
	 * 提交单据时,需要的指派信息
	 * <li>只有"SAVE","EDIT"动作才调用
	 */
	private static WorkflownoteVO checkOnSave(Container parent, String actionName, String billType, AggregatedValueObject billVo, Stack dlgResult, HashMap hmPfExParams) throws BusinessException {
		WorkflownoteVO worknoteVO = new WorkflownoteVO();

		// guowl+ 2010-5,如果是批处理,不用取指派信息,直接返回
		if (hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_BATCH) != null)
			return worknoteVO;

		try {
			worknoteVO = NCLocator.getInstance().lookup(IWorkflowMachine.class).checkWorkFlow(actionName, billType, billVo, hmPfExParams);
		} catch (FlowDefNotFoundException e) {
			return worknoteVO;
		}

		// 在审批处理框显示之前,调用业务处理
		PFClientBizRetObj retObj = executeBusinessPlugin(parent, billVo, worknoteVO, true);
		if (retObj != null && retObj.isStopFlow()) {
			m_isSuccess = false;
			return null;
		}

		if (worknoteVO != null) {
			// 得到可指派的输入数据
			Vector assignInfos = worknoteVO.getTaskInfo().getAssignableInfos();
			if (assignInfos != null && assignInfos.size() > 0) {
				// 显示指派对话框并收集实际指派信息
				ApproveFlowDispatchDialog dlg = new ApproveFlowDispatchDialog(parent);
				dlg.getDisPatchPanel().initByWorknoteVO(worknoteVO);
				int iClose = dlg.showModal();
				if (iClose == UIDialog.ID_CANCEL)
					dlgResult.push(Integer.valueOf(iClose));
			}
		}
		return worknoteVO;
	}

	/**
	 * 单据启动工作流时,需要的指派信息
	 * <li>包括选择后继活动参与者、选择后继分支转移
	 */
	private static WorkflownoteVO checkOnStart(Container parent, String actionName, String billType, AggregatedValueObject billVo, Stack dlgResult, HashMap hmPfExParams) throws BusinessException {
		WorkflownoteVO wfVo = NCLocator.getInstance().lookup(IWorkflowMachine.class).checkWorkFlow(actionName, billType, billVo, hmPfExParams);

		// guowl+ 2010-5,如果是批处理,不用取指派信息,直接返回
		if (hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_BATCH) != null)
			return wfVo;

		if (wfVo != null) {
			// 得到可指派的信息
			Vector assignInfos = wfVo.getTaskInfo().getAssignableInfos();
			Vector tSelectInfos = wfVo.getTaskInfo().getTransitionSelectableInfos();
			if (assignInfos.size() > 0 || tSelectInfos.size() > 0) {
				// 显示指派对话框并收集实际指派信息
				WFStartDispatchDialog wfdd = new WFStartDispatchDialog(parent, wfVo);
				int iClose = wfdd.showModal();
				if (iClose == UIDialog.ID_CANCEL)
					dlgResult.push(Integer.valueOf(iClose));
			}
		}
		return wfVo;
	}

	/**
	 * 检查当前单据是否处于工作流程中或工作流的审批子流程中,并进行交互
	 */
	private static WorkflownoteVO checkWorkitemWhenSignal(Container parent, String actionCode, String billType, AggregatedValueObject billVo, HashMap hmPfExParams, int voAryLen) throws BusinessException {
		WorkflownoteVO noteVO = null;
		UIDialog dlg = null;
		if (voAryLen != 0) {
			if (hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_WORKNOTE) != null) {
				noteVO = (WorkflownoteVO) hmPfExParams.get(PfUtilBaseTools.PARAM_WORKNOTE);
				m_checkFlag = true;
				return noteVO;
			}
		}
		try {
			// 检查当前用户的工作流工作项+审批子流程工作项
			noteVO = NCLocator.getInstance().lookup(IWorkflowMachine.class).checkWorkFlow(actionCode, billType, billVo, hmPfExParams);
			if (noteVO == null) {
				m_checkFlag = true;
				return noteVO;
			} else {
				// XXX:guowl+,检查是否弹出交互界面
				// 批量执行是按照每十条执行一次,当执行之后还剩下一条时,走单个执行方法,所以对工作项单独处理
				if (voAryLen == 0 && (hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_WORKNOTE) != null)) {
					WorkflownoteVO oldNoteVO = (WorkflownoteVO) hmPfExParams.get(PfUtilBaseTools.PARAM_WORKNOTE);
					noteVO.getTaskInfo().setTransitionSelectableInfos(oldNoteVO.getTaskInfo().getTransitionSelectableInfos());
					if (oldNoteVO.getTaskInfo().getTransitionSelectableInfos() != null && oldNoteVO.getTaskInfo().getTransitionSelectableInfos().size() > 0) {
						noteVO.getTaskInfo().setTransitionSelectableInfos(oldNoteVO.getTaskInfo().getTransitionSelectableInfos());
					}
					noteVO.setIscheck(oldNoteVO.getIscheck());
					noteVO.setApproveresult(oldNoteVO.getApproveresult());
					noteVO.setChecknote(oldNoteVO.getChecknote());
					if ("R".equals(oldNoteVO.getApproveresult()) && !noteVO.isAnyoneCanApprove()) {
						noteVO.getTaskInfo().getTask().setBackToFirstActivity(true);
						noteVO.getTaskInfo().getTask().setTaskType(WfTaskType.Backward.getIntValue());
					}
					Object value = noteVO.getRelaProperties().get(XPDLNames.ELECSIGNATURE);
					if (value != null && "true".equalsIgnoreCase(value.toString())) {
						noteVO.setCiphertext(oldNoteVO.getCiphertext());
					}
					return noteVO;
				}

				if (!PfUtilClientAssistor.isExchange(noteVO.getTaskInfo().getTask())) {
					m_checkFlag = true;
					noteVO.setApproveresult("Y");
					return noteVO;
				}

				if (noteVO.getWorkflow_type() == WorkflowTypeEnum.SubWorkApproveflow.getIntValue()) {
					// 工作流的审批子流程
					if (hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_BATCH) != null) {
						dlg = new BatchApproveWorkitemAcceptDlg(parent, noteVO);

						BatchApproveModel batchApproveMode = new BatchApproveModel();
						batchApproveMode.setBillUI(true);
						batchApproveMode.setSingleBillSelected(true);
						batchApproveMode.setContainUnApproveBill(false);
						batchApproveMode.setBillItem(voAryLen);

						((BatchApproveWorkitemAcceptDlg) dlg).setBachApproveMode(batchApproveMode);
					} else {
						dlg = new ApproveWorkitemAcceptDlg(parent, noteVO, true);
					}
				} else
					// 工作流或工作子流程
					dlg = new WorkflowWorkitemAcceptDlg(parent, noteVO, PfUtilClientAssistor.isCanTransfer(noteVO.getTaskInfo().getTask()));

				if (dlg.showModal() == UIDialog.ID_OK) {
					// 返回处理后的工作项
					m_checkFlag = true;
				} else {
					// 用户取消
					m_checkFlag = false;
					noteVO = null;
				}
				if ((hmPfExParams != null && (!hmPfExParams.containsKey(PfUtilBaseTools.PARAM_WORKNOTE) || hmPfExParams.get(PfUtilBaseTools.PARAM_WORKNOTE) == null)) && hmPfExParams.get(PfUtilBaseTools.PARAM_BATCH) != null) {
					hmPfExParams.put(PfUtilBaseTools.PARAM_WORKNOTE, noteVO);
				}
			}
		} finally {
			if (dlg != null) {
				nc.ui.pub.beans.UIComponentUtil.removeAllComponentRefrence(dlg);
			}
		}
		return noteVO;
	}

	/**
	 * 检查当前单据是否处于审批流程中,并进行交互
	 */
	private static WorkflownoteVO checkWorkitemWhenApprove(Container parent, String actionName, String billType, Object billvos, HashMap hmPfExParams, int voAryLen) throws BusinessException {
		WorkflownoteVO noteVO = null;
		UIDialog dlg = null;

		if (voAryLen != 0) {
			if (hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_WORKNOTE) != null) {
				noteVO = (WorkflownoteVO) hmPfExParams.get(PfUtilBaseTools.PARAM_WORKNOTE);
				m_checkFlag = true;
				return noteVO;
			}
		}

		// billvos传值为单值或者数组 qf@2015-1-22
		AggregatedValueObject billvo = null;
		AggregatedValueObject[] vos = null;
		if (billvos instanceof AggregatedValueObject) {
			billvo = (AggregatedValueObject) billvos;
		} else if (billvos instanceof AggregatedValueObject[]) {
			vos = (AggregatedValueObject[]) billvos;
			billvo = vos[0];
		}
		if (hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_BATCH) != null) {

			Object notSilent = hmPfExParams.get(PfUtilBaseTools.PARAM_NOTSILENT);
			// 检查单据是否定义了审批流,如果没有定义,则不弹出,此处只简单检查第一张单据的单据类型上是否有流程定义
			if (notSilent == null && !hasApproveflowDef(billType, billvo)) {
				m_checkFlag = true;
				noteVO = new WorkflownoteVO();
				noteVO.setApproveresult("Y");
				Logger.debug("*checkWorkitemWhenApprove 1 billType.");
				return noteVO;
			} else {
				// 预算开发部要求批审时不管有没有流程定义,都弹出审批意见框
				noteVO = new WorkflownoteVO();
				// 判断是否需要CA
				List<String> billIdList = new ArrayList<String>();
				if (vos != null && vos.length != 0) {
					for (AggregatedValueObject vo : vos) {
						billIdList.add(vo.getParentVO().getPrimaryKey());
					}
					noteVO.getRelaProperties().put(XPDLNames.ELECSIGNATURE, NCLocator.getInstance().lookup(IPFWorkflowQry.class).isNeedCASign4Batch(PfUtilUITools.getLoginUser(), new String[] { billType }, billIdList.toArray(new String[0])));
				}
				BatchApproveModel batchApproveMode = new BatchApproveModel();
				batchApproveMode.setBillUI(true);
				batchApproveMode.setSingleBillSelected(true);
				batchApproveMode.setContainUnApproveBill(false);
				batchApproveMode.setBillItem(voAryLen);
				dlg = new BatchApproveWorkitemAcceptDlg(parent, noteVO);
				((BatchApproveWorkitemAcceptDlg) dlg).setBachApproveMode(batchApproveMode);
				Logger.debug("*checkWorkitemWhenApprove 2.");
			}
		} else {
			noteVO = NCLocator.getInstance().lookup(IWorkflowMachine.class).checkWorkFlow(actionName, billType, billvo, hmPfExParams);
			Logger.debug("*checkWorkitemWhenApprove 3.");

			if (noteVO != null && isBesideApprove(hmPfExParams)) {
				noteVO = BesideApprove(hmPfExParams, noteVO);
			} else {
				Object notSilent = null;
				if (hmPfExParams != null) {
					notSilent = hmPfExParams.get(PfUtilBaseTools.PARAM_NOTSILENT);
				}

				if (noteVO == null) {
					if (notSilent == null) {
						m_checkFlag = true;
						Logger.debug("*checkWorkitemWhenApprove 1 billType.");
						return noteVO;
					} else {
						noteVO = new WorkflownoteVO();
					}
				}

				PFClientBizRetObj retObj = executeBusinessPlugin(parent, billvo, noteVO, false);
				int workflowtype = noteVO.getWorkflow_type();
				boolean isInWorkflow = false;
				if (workflowtype == WorkflowTypeEnum.SubWorkApproveflow.getIntValue())
					isInWorkflow = true;
				dlg = new ApproveWorkitemAcceptDlg(parent, noteVO, billvo, isInWorkflow, isOpenedInDialog, retObj == null ? null : retObj.getHintMessage());
				ApproveWorkitemAcceptDlg acceptDlg = ((ApproveWorkitemAcceptDlg) dlg);

				if (retObj != null) {
					// yanke1 2012-02-22 根据前台业务处理的返回值来控制审批界面
					acceptDlg.setShowPass(retObj.isShowPass());
//					acceptDlg.setShowNoPass(retObj.isShowNoPass());
					acceptDlg.setShowReject(retObj.isShowReject());
				}
				acceptDlg.setShowNoPass(!PfUtilClientAssistor.isHideNoPassing(noteVO.getTaskInfo().getTask()));
				Logger.debug("*checkWorkitemWhenApprove 4.");
			}

		}

		Logger.debug("*checkWorkitemWhenApprove 5.");

		if (!isBesideApprove(hmPfExParams)) {
			if (hmPfExParams == null) {
				hmPfExParams = new HashMap<String, Object>();
			}
			if (dlg.showModal() == UIDialog.ID_OK) { // 如果用户审批

				if (dlg instanceof ApproveWorkitemAcceptDlg) {
					isAutoCloseParentDialog = ((ApproveWorkitemAcceptDlg) dlg).isAutoCloseParentDialog();
				}
				m_checkFlag = true;
			} else { // 用户不审批
				m_checkFlag = false;
				noteVO = null;
			}
			if ((!hmPfExParams.containsKey(PfUtilBaseTools.PARAM_WORKNOTE) || hmPfExParams.get(PfUtilBaseTools.PARAM_WORKNOTE) == null) && hmPfExParams.get(PfUtilBaseTools.PARAM_BATCH) != null) {
				hmPfExParams.put(PfUtilBaseTools.PARAM_WORKNOTE, noteVO);
			}
		}

		return noteVO;
	}

	/**
	 * 侧边栏审批
	 * 
	 * @throws BusinessException
	 */
	private static WorkflownoteVO BesideApprove(HashMap hmPfExParams, WorkflownoteVO noteVO) throws BusinessException {
		BesideApproveContext besideContext = (BesideApproveContext) hmPfExParams.get(PfUtilBaseTools.PARAM_BESIDEAPPROVE);
		m_checkFlag = true;
		if (besideContext.isNeedDispatch()) {
			// 填充指派信息
			ApproveFlowDispatchDialog disPatchDlg = new ApproveFlowDispatchDialog(null);
			disPatchDlg.getDisPatchPanel().initByWorknoteVO(noteVO, besideContext.getApproveResult().equalsIgnoreCase("Y") ? AssignableInfo.CRITERION_PASS : AssignableInfo.CRITERION_NOPASS);
			int result = disPatchDlg.showModal();
			if (result == UIDialog.ID_CANCEL) {
				// 如果指派对话框点击了取消,那么取消这次审批操作,重新回到审批面板 (changlx需求定义)modified by
				// zhangrui 2012-04-17
				noteVO = null;
				m_checkFlag = false;
				return noteVO;
			}
		}

		// 改派
		if (besideContext.getManagerContext() != null) {

			WorkflowManageUtil wfUtil = new WorkflowManageUtil();

			if (wfUtil.doAlterSend(null, besideContext.getManagerContext(), besideContext.getTransferList(), besideContext.getCheckNote())) {
				noteVO.getTaskInfo().getTask().setAppoint(true);

			} else {
				noteVO = null;
				m_isSuccess = false;
				return noteVO;
			}
			noteVO.setChecknote(besideContext.getCheckNote());
		}

		// 加签
		if (besideContext.isAddAssign()) {
			ApplicationRuntimeAdjustContext context = new ApplicationRuntimeAdjustContext();
			context.setStyle(besideContext.getAddAssignStyle());// style被去掉了
			context.setUserObject(besideContext.getAddAssignUserObj());
			// 记录加签发起人
			UserVO operator = WorkbenchEnvironment.getInstance().getLoginUser();
			noteVO.setSenderman(operator.getCuserid());
			noteVO.setChecknote(besideContext.getCheckNote());
			context.setWorkFlow(noteVO);
			IApplicationRuntimeAdjust runtimeObj = ApplicationRuntimeAdjustFactory.createAdjust(IApplicationRuntimeAdjust.ADJUST_TYPE_ADDASSIGN);
			try {
				runtimeObj.adjust(context);
				m_checkFlag = true;
			} catch (BusinessException e) {
				Logger.error(e.getMessage(), e);

				String message = e.getMessage();
				if (e.getCause() != null) {
					message = e.getCause().getMessage();
				}
				MessageDialog.showErrorDlg(null, null, message);
				m_isSuccess = false;
				noteVO = null;
				return noteVO;
			}
		}

		noteVO.setMailExtCpySenders(besideContext.getMailExtCpySenders());
		noteVO.setMsgExtCpySenders(besideContext.getMsgExtCpySenders());
		List<AttachmentVO> attchVOS = updateAttachment2DocServer(besideContext.getAttchlist());
		noteVO.setAttachmentSetting(attchVOS);
		noteVO.setApproveresult(besideContext.getApproveResult());
		noteVO.setChecknote(besideContext.getCheckNote());
		noteVO.setTrack(besideContext.isTracked());
		if (besideContext.getTaskType() != 0) {
			noteVO.getTaskInfo().getTask().setTaskType(besideContext.getTaskType());
		}
		noteVO.getTaskInfo().getTask().setBackToFirstActivity(besideContext.isBackToFirstActivity());
		noteVO.getTaskInfo().getTask().setJumpToActivity(besideContext.getJumpToActivity());
		m_checkFlag = true;
		m_isSuccess = true;
		return noteVO;
	}

	// 上传服务器,不影响流程
	private static List<AttachmentVO> updateAttachment2DocServer(List<Attachment> attchlist) throws BusinessException {
		List<AttachmentVO> vos = new ArrayList<AttachmentVO>();
		try {
			for (Attachment attachment : attchlist) {
				AttachmentVO vo = attachment.uploadToFileServer();
				vo.setFilesize(attachment.getSize());
				vo.setFilename(attachment.getName());
				vos.add(vo);
			}
		} catch (Exception e) {
			Logger.error(e.getMessage() + "上传附件失败!");
			throw new BusinessException(e.getMessage() + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("pfworkflow63", "Attachmentfile-0000")/** @res"上传附件失败!" */
			);
		}
		return vos;
	}

	private static boolean hasApproveflowDef(String billType, AggregatedValueObject billVo) throws BusinessException {
		IFlowBizItf fbi = PfMetadataTools.getBizItfImpl(billVo, IFlowBizItf.class);
		if (fbi == null)
			throw new PFRuntimeException(NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000000")/* 元数据实体没有提供业务接口IFlowBizItf的实现类 */);

		IWorkflowDefine wfDefine = NCLocator.getInstance().lookup(IWorkflowDefine.class);
		Logger.debug("查询流程定义: billType=" + billType + ";pkOrg=" + fbi.getPkorg() + ";userId=" + fbi.getBillMaker() + ";开始");
		return wfDefine.hasValidProcessDef(WorkbenchEnvironment.getInstance().getGroupVO().getPk_group(), billType, fbi.getPkorg(), fbi.getBillMaker(), fbi.getEmendEnum(), WorkflowTypeEnum.Approveflow.getIntValue());
	}

	/**
	 * 参照来源单据,用于
	 * <li>1.获取来源单据的查询对话框,并查询出来源单据
	 * <li>2.显示来源单据,并进行选择
	 * <li>3.获取选择的来源单据
	 * 
	 * @param srcBillType         参照制单 选择的来源单据类型
	 * @param pk_group
	 * @param userId
	 * @param currBillOrTranstype 当前单据或交易类型
	 * @param parent
	 * @param userObj
	 * @param srcBillId           如果为空,则直接进入参照上游单据界面
	 */
	public static void childButtonClicked(String srcBillType, String pk_group, String userId, String currBillOrTranstype, Container parent, Object userObj, String srcBillId) {

		childButtonClickedWithBusi(srcBillType, pk_group, userId, currBillOrTranstype, parent, userObj, srcBillId, null);
	}

	public static void childButtonClickedNew(final PfButtonClickContext context) {
		makeFlag = false;
		if (context.getSrcBillType().toUpperCase().equals("MAKEFLAG")) {
			Logger.debug("******自制单据******");
			makeFlag = true;
			return;
		}

		Logger.debug("******参照来源单据******");
		m_classifyMode = context.getClassifyMode();
		try {
			final String funNode = PfUIDataCache.getBillType(new BillTypeCacheKey().buildBilltype(context.getSrcBillType()).buildPkGroup(context.getPk_group())).getNodecode();
			if (funNode == null || funNode.equals(""))
				throw new PFBusinessException(NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000001", null, new String[] { context.getSrcBillType() })/* 请注册单据{0}的功能节点号 */);

			// 查询交换信息,以便得到一些参照制单的定制信息
			String src_qrytemplate = null;
			String src_billui = null; // 来源单据的显示UI类
			String src_nodekey = null; // 用于查询来源单据的查询模板的节点标识
			ExchangeVO changeVO = getExchangeService().queryMostSuitableExchangeVO(context.getSrcBillType(), context.getCurrBilltype(), null, PfUtilUITools.getLoginGroup(), null);
			if (changeVO != null) {
				src_qrytemplate = changeVO.getSrc_qrytemplate();
				src_qrytemplate = src_qrytemplate == null ? null : src_qrytemplate.trim();
				src_billui = changeVO.getSrc_billui();
				src_nodekey = changeVO.getSrc_nodekey();
			}
			// a.获取来源单据的查询对话框,即为m_condition赋值
			IBillReferQuery qcDLG = null;
			if (StringUtil.isEmptyWithTrim(src_qrytemplate)) {
				Logger.debug("使用来源单据类型对应节点使用的查询模板对话框");
				src_qrytemplate = PfUtilUITools.getTemplateId(ITemplateStyle.queryTemplate, context.getPk_group(), funNode, context.getUserId(), src_nodekey);
				qcDLG = setConditionClient(src_qrytemplate, context.getParent(), context.getUserId(), funNode, context.getPk_group());
			} else if (src_qrytemplate.startsWith("<")) {
				Logger.debug("使用产品组定制的来源单据查询对话框");
				src_qrytemplate = src_qrytemplate.substring(1, src_qrytemplate.length() - 1);
				qcDLG = loadUserQuery(context.getParent(), src_qrytemplate, context.getPk_group(), context.getUserId(), funNode, context.getCurrBilltype(), context.getSrcBillType(), src_nodekey, context.getUserObj());
			} else {
				Logger.debug("使用注册的查询模板的查询对话框");
				qcDLG = setConditionClient(src_qrytemplate, context.getParent(), context.getUserId(), funNode, context.getPk_group());
			}
			// 给查询对话框设置业务类型,asked by scm-puqh
			if (context.getBusiTypes() != null && qcDLG instanceof IBillReferQueryWithBusitype)
				((IBillReferQueryWithBusitype) qcDLG).setBusitypes(context.getBusiTypes());
			// 给查询对话框设置交易类型,用于过滤上游单据,asked by scm-puqh
			if (context.getTransTypes() != null && qcDLG instanceof IBillReferQueryWithTranstype)
				((IBillReferQueryWithTranstype) qcDLG).setTranstypes(context.getTransTypes());

			if (context.getSrcBillId() == null) {
				// b.显示来源单据的查询对话框
				if (qcDLG.showModal() == UIDialog.ID_OK) {
					// c.显示来源单据,并进行选择
					refBillSource(context.getPk_group(), funNode, context.getUserId(), context.getCurrBilltype(), context.getParent(), context.getUserObj(), context.getSrcBillType(), src_qrytemplate, src_billui, src_nodekey, null, qcDLG);
				} else {
					m_isOk = false;
					return;
				}
			} else {
				// b'.直接显示来源单据
				refBillSource(context.getPk_group(), funNode, context.getUserId(), context.getCurrBilltype(), context.getParent(), context.getUserObj(), context.getSrcBillType(), src_qrytemplate, src_billui, src_nodekey, context.getSrcBillId(), qcDLG);
				return;
			}
		} catch (Exception ex) {
			Logger.error(ex.getMessage(), ex);
			MessageDialog.showErrorDlg(context.getParent(), "null", NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000002", null, new String[] { ex.getMessage() })/* 参照上游单据出现异常={0} */);
		}
	}

	/**
	 * 参照来源单据,用于
	 * <li>1.获取来源单据的查询对话框,并查询出来源单据
	 * <li>2.显示来源单据,并进行选择
	 * <li>3.获取选择的来源单据
	 * 
	 * @param srcBillType         参照制单 选择的来源单据类型
	 * @param pk_group
	 * @param userId
	 * @param currBillOrTranstype 当前单据或交易类型
	 * @param parent
	 * @param userObj
	 * @param srcBillId           如果为空,则直接进入参照上游单据界面
	 * @param busiTypes           如果不为空,表示查找指定业务流程中的单据
	 */
	public static void childButtonClickedWithBusi(String srcBillType, String pk_group, String userId, String currBillOrTranstype, Container parent, Object userObj, String srcBillId, List<String> busiTypes) {

		m_classifyMode = PfButtonClickContext.NoClassify;
		makeFlag = false;
		if (srcBillType.toUpperCase().equals("MAKEFLAG")) {
			Logger.debug("******自制单据******");
			makeFlag = true;
			return;
		}

		Logger.debug("******参照来源单据******");
		try {
			String funNode = PfUIDataCache.getBillType(new BillTypeCacheKey().buildBilltype(srcBillType).buildPkGroup(pk_group)).getNodecode();
			if (funNode == null || funNode.equals(""))
				throw new PFBusinessException(NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000001", null, new String[] { srcBillType })/* 请注册单据{0}的功能节点号 */);

			// 查询交换信息,以便得到一些参照制单的定制信息
			String src_qrytemplate = null;
			String src_billui = null; // 来源单据的显示UI类
			String src_nodekey = null; // 用于查询来源单据的查询模板的节点标识
			ExchangeVO changeVO = getExchangeService().queryMostSuitableExchangeVO(srcBillType, currBillOrTranstype, null, PfUtilUITools.getLoginGroup(), null);
			if (changeVO != null) {
				src_qrytemplate = changeVO.getSrc_qrytemplate();
				src_qrytemplate = src_qrytemplate == null ? null : src_qrytemplate.trim();
				src_billui = changeVO.getSrc_billui();
				src_nodekey = changeVO.getSrc_nodekey();
			}
			// a.获取来源单据的查询对话框,即为m_condition赋值
			IBillReferQuery qcDLG = null;
			if (StringUtil.isEmptyWithTrim(src_qrytemplate)) {
				Logger.debug("使用来源单据类型对应节点使用的查询模板对话框");
				src_qrytemplate = PfUtilUITools.getTemplateId(ITemplateStyle.queryTemplate, pk_group, funNode, userId, src_nodekey);
				qcDLG = setConditionClient(src_qrytemplate, parent, userId, funNode, pk_group);
			} else if (src_qrytemplate.startsWith("<")) {
				Logger.debug("使用产品组定制的来源单据查询对话框");
				src_qrytemplate = src_qrytemplate.substring(1, src_qrytemplate.length() - 1);
				qcDLG = loadUserQuery(parent, src_qrytemplate, pk_group, userId, funNode, currBillOrTranstype, srcBillType, src_nodekey, userObj);
			} else {
				Logger.debug("使用注册的查询模板的查询对话框");
				qcDLG = setConditionClient(src_qrytemplate, parent, userId, funNode, pk_group);
			}
			if (busiTypes != null && qcDLG instanceof IBillReferQueryWithBusitype)
				((IBillReferQueryWithBusitype) qcDLG).setBusitypes(busiTypes);

			if (srcBillId == null) {
				// b.显示来源单据的查询对话框
				if (qcDLG.showModal() == UIDialog.ID_OK) {
					// c.显示来源单据,并进行选择
					refBillSource(pk_group, funNode, userId, currBillOrTranstype, parent, userObj, srcBillType, src_qrytemplate, src_billui, src_nodekey, null, qcDLG);

				} else {
					m_isOk = false;
					return;
				}
			} else {
				// b'.直接显示来源单据
				refBillSource(pk_group, funNode, userId, currBillOrTranstype, parent, userObj, srcBillType, src_qrytemplate, src_billui, src_nodekey, srcBillId, qcDLG);
				return;
			}
		} catch (Exception ex) {
			Logger.error(ex.getMessage(), ex);
			MessageDialog.showErrorDlg(parent, NCLangRes.getInstance().getStrByID("pfworkflow1", "SplitRuleRegisterUI-000005")/* 错误 */, NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000002", null, new String[] { ex.getMessage() })/* 参照上游单据出现异常={0} */);
		}
	}

	/**
	 * 参照制单时,显示来源单据;并进行VO交换
	 */
	private static void refBillSource(String pk_group, String funNode, String pkOperator, String currBillOrTranstype, Container parent, Object userObj, String billType, String strQueryTemplateId, String src_billui, String srcNodekey, String sourceBillId, IBillReferQuery qcDLG) throws Exception {
		// 获取主表的关键字段
		String pkField = PfUtilBaseTools.findPkField(billType);
		if (pkField == null || pkField.trim().length() == 0)
			throw new PFBusinessException(NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000003")/* 无法通过单据类型获取单据实体的主表PK字段 */);
		String whereString = null;
		IQueryScheme qryScheme = null;
		if (sourceBillId == null) {
			if (qcDLG instanceof IBillReferQueryWithScheme) {
				qryScheme = ((IBillReferQueryWithScheme) qcDLG).getQueryScheme();
			} else
				whereString = qcDLG.getWhereSQL();
		} else
			whereString = pkField + "='" + sourceBillId + "'";

		// 载入来源单据展现对话框,并显示
		BillSourceVar bsVar = new BillSourceVar();
		bsVar.setBillType(billType);
		bsVar.setCurrBillOrTranstype(currBillOrTranstype);
		bsVar.setFunNode(funNode);
		bsVar.setNodeKey(srcNodekey);
		bsVar.setPk_group(pk_group);
		bsVar.setPkField(pkField);
		bsVar.setQryTemplateId(strQueryTemplateId);
		bsVar.setUserId(pkOperator);
		bsVar.setUserObj(userObj);
		bsVar.setWhereStr(whereString);
		if (qryScheme != null)
			bsVar.setQueryScheme(qryScheme);

		AbstractBillSourceDLG bsDlg = null;
		if (!StringUtil.isEmptyWithTrim(src_billui)) {
			Logger.debug("产品组定制的来源单据展现对话框,必须继承自" + AbstractBillSourceDLG.class.getName());
			bsDlg = loadCustomBillSourceDLG(src_billui, bsVar, parent);
		} else {
			Logger.debug("使用通用的来源单据展现对话框");
			bsDlg = new BillSourceDLG(parent, bsVar);
		}

		bsDlg.setQueyDlg(qcDLG); // 放入查询模板对话框
		// 加载模版
		bsDlg.addBillUI();
		// 加载数据
		bsDlg.loadHeadData();

		if (bsDlg.showModal() == UIDialog.ID_OK) {
			m_sourceBillType = billType;
			m_currentBillType = currBillOrTranstype;
			m_tmpRetVo = bsDlg.getRetVo();
			m_tmpRetVos = bsDlg.getRetVos();
			m_isOk = true;
		} else {
			m_isOk = false;
		}
	}

	/**
	 * 返回 当前审批节点的处理结果 lj+ 2005-1-20
	 */
	public static int getCurrentCheckResult() {
		return m_iCheckResult;
	}

	/**
	 * 返回 用户选择的VO
	 */
	public static AggregatedValueObject getRetOldVo() {
		return m_tmpRetVo;
	}

	/**
	 * 返回 用户选择VO数组.
	 */
	public static AggregatedValueObject[] getRetOldVos() {
		return m_tmpRetVos;
	}

	/**
	 * 返回 用户选择的VO或交换过的VO
	 * 
	 * @return
	 */
	public static AggregatedValueObject getRetVo() {
		try {
			// 需要进行VO交换
			m_tmpRetVo = getExchangeService().runChangeData(m_sourceBillType, m_currentBillType, m_tmpRetVo, null);
			jumpBusitype(m_tmpRetVo == null ? null : new AggregatedValueObject[] { m_tmpRetVo });
		} catch (Exception ex) {
			Logger.error(ex.getMessage(), ex);
			throw new PFRuntimeException(NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000004", null, new String[] { ex.getMessage() })/* VO交换错误:{0} */, ex);
		}
		return m_tmpRetVo;
	}

	/**
	 * 返回 用户选择VO数组或交换过的VO数组
	 * 
	 * @return
	 * @throws BusinessException
	 */
	public static AggregatedValueObject[] getRetVos() throws BusinessException {
		// 默认根据业务流程进行VO交换
		return getRetVos(true);
	}

	/**
	 * 返回 用户选择VO数组或交换过的VO数组
	 * 
	 * @param exchangeByBusiType 是否根据业务流程进行交换,如果否,则在交换前将来源业务流程PK清除
	 * @return
	 * @throws BusinessException
	 */
	public static AggregatedValueObject[] getRetVos(boolean exchangeByBusiType) throws BusinessException {
		// 如果不根据业务流程进行交换,则将单据中的业务流程PK去掉(供应链的需求,来源单据有业务流程pK,但是想走的是另外的流程)
		if (!exchangeByBusiType && m_tmpRetVos != null) {
			for (int i = 0; i < m_tmpRetVos.length; i++) {
				AggregatedValueObject aggVO = m_tmpRetVos[i];
				IFlowBizItf fbi = PfMetadataTools.getBizItfImpl(aggVO, IFlowBizItf.class);
				if (fbi != null) {
					fbi.setBusitype(null);
				}
			}
		}
		// 需要进行VO交换
		m_tmpRetVos = changeVos(m_tmpRetVos, m_classifyMode);
		jumpBusitype(m_tmpRetVos);
		return m_tmpRetVos;
	}

	private static IPfExchangeService getExchangeService() {
		if (exchangeService == null)
			exchangeService = NCLocator.getInstance().lookup(IPfExchangeService.class);
		return exchangeService;
	}

	/**
	 * 返回 用户选择的VO或交换过的VO
	 * 
	 * @return
	 */
	private static AggregatedValueObject[] changeVos(AggregatedValueObject[] vos, int classifyMode) {
		AggregatedValueObject[] tmpRetVos = null;

		try {
			tmpRetVos = getExchangeService().runChangeDataAryNeedClassify(m_sourceBillType, m_currentBillType, vos, null, classifyMode);
		} catch (BusinessException ex) {
			Logger.error(ex.getMessage(), ex);
			throw new PFRuntimeException(NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000004", null, new String[] { ex.getMessage() })/* VO交换错误:{0} */, ex);
		}

		return tmpRetVos;
	}

	/**
	 * 业务流跳转
	 * 
	 * @throws BusinessException
	 */
	private static void jumpBusitype(AggregatedValueObject[] vos) throws BusinessException {
		if (vos == null || vos.length == 0)
			return;
		IFlowBizItf fbi = PfMetadataTools.getBizItfImpl(vos[0], IFlowBizItf.class);
		// 未实现业务流接口的单据或者未走流程直接return
		if (fbi == null || StringUtil.isEmptyWithTrim(fbi.getBusitype()))
			return;
		BillbusinessVO condVO = new BillbusinessVO();
		condVO.setPk_businesstype(fbi.getBusitype());
		condVO.setJumpflag(UFBoolean.TRUE);
		// 得到单据类型编码
		String billtype = PfUtilBaseTools.getRealBilltype(m_currentBillType);
		condVO.setPk_billtype(billtype);
		condVO.setTranstype(fbi.getTranstype());
		try {
			Collection co = NCLocator.getInstance().lookup(IUAPQueryBS.class).retrieve(condVO, true);
			if (co.size() > 0) {
				HashMap<String, String> busitypeMaps = new HashMap<String, String>();
				for (AggregatedValueObject vo : vos) {
					String destBusitypePk = null;
					fbi = PfMetadataTools.getBizItfImpl(vo, IFlowBizItf.class);
					String transtype = fbi.getTranstype();
					String pk_org = fbi.getPkorg();
					String operator = PfUtilUITools.getLoginUser();
					if (StringUtil.isEmptyWithTrim(billtype)) {
						// 单据类型不能为空
						continue;
					}
					String key = billtype + (StringUtil.isEmptyWithTrim(transtype) ? "" : transtype) + (StringUtil.isEmptyWithTrim(pk_org) ? "" : pk_org) + operator;
					if (busitypeMaps.containsKey(key)) {
						destBusitypePk = busitypeMaps.get(key);
					} else {
						destBusitypePk = NCLocator.getInstance().lookup(IPFConfig.class).retBusitypeCanStart(billtype, transtype, pk_org, operator);
					}
					// 如果没有找到要跳转的业务流
					if (StringUtil.isEmptyWithTrim(destBusitypePk)) {
						continue;
					}
					fbi.setBusitype(destBusitypePk);
				}
			}
		} catch (DAOException e) {
			Logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 判断用户是否点击了"取消"按钮
	 * 
	 * @return boolean leijun+
	 */
	public static boolean isCanceled() {
		return !m_checkFlag;
	}

	/**
	 * 返回 参照单据是否正常关闭
	 * 
	 * @return boolean
	 */
	public static boolean isCloseOK() {
		return m_isOk;
	}

	/**
	 * 返回 当前单据动作执行是否成功
	 * 
	 * @return boolean
	 */
	public static boolean isSuccess() {
		return m_isSuccess;
	}

	/**
	 * 载入产品组注册的来源单据显示对话框
	 */
	private static AbstractBillSourceDLG loadCustomBillSourceDLG(String src_billui, BillSourceVar bsVar, Container parent) {
		Class c = null;

		try {
			c = Class.forName(src_billui);
			Class[] argCls = new Class[] { Container.class, BillSourceVar.class };
			Object[] args = new Object[] { parent, bsVar };
			// 实例化带参构造方法
			Constructor cc = c.getConstructor(argCls);
			return (AbstractBillSourceDLG) cc.newInstance(args);
		} catch (Exception ex) {
			Logger.error(ex.getMessage(), ex);
			MessageDialog.showErrorDlg(parent, null, NCLangRes.getInstance().getStrByID("pfworkflow1", "PfUtilClient-000005", null, new String[] { ex.getMessage() })/* 载入产品组注册的来源单据显示对话框 发生异常:{0} */);
		}
		return null;
	}

	private static IBillReferQuery loadUserQuery(Container parent, String src_qrytemplate, String pk_group, String userId, String FunNode, String currBillOrTranstype, String sourceBillType, String nodeKey, Object userObj) {

		Class c = null;
		try {
			// 先判定是否为新查询模板UI的子类
			String qtId = PfUtilUITools.getTemplateId(ITemplateStyle.queryTemplate, pk_group, FunNode, userId, nodeKey);
			TemplateInfo ti = new TemplateInfo();
			ti.setTemplateId(qtId);
			ti.setPk_Org(pk_group);
			ti.setUserid(userId);
			ti.setCurrentCorpPk(pk_group);
			ti.setFunNode(FunNode);
			ti.setNodekey(nodeKey);

			c = Class.forName(src_qrytemplate);
			Object retObj = c.getConstructor(new Class[] { Container.class, TemplateInfo.class }).newInstance(new Object[] { parent, ti });
			// 对查询模版对话框的一些定制初始化
			if (retObj instanceof IinitQueryData) {
				((IinitQueryData) retObj).initData(pk_group, userId, FunNode, currBillOrTranstype, sourceBillType, nodeKey, userObj);
			}

			return (IBillReferQuery) retObj;
		} catch (NoSuchMethodException e) {
			Logger.warn("找不到新查询模板UI的构造方法,继续判定是否有老查询模板的构造方法", e);
			try {
				// 应该为老查询模板UI的子类
				Object retObj = c.getConstructor(new Class[] { Container.class }).newInstance(new Object[] { parent });
				// 对查询模版对话框的一些定制初始化
				if (retObj instanceof IinitQueryData) {
					((IinitQueryData) retObj).initData(pk_group, userId, FunNode, currBillOrTranstype, sourceBillType, nodeKey, userObj);
				}
				return (IBillReferQuery) retObj;
			} catch (Exception ex) {
				Logger.error(ex.getMessage(), ex);
			}
		} catch (Exception e) {
			Logger.error(e.getMessage(), e);
		}
		return null;
	}

	private static IFuncletWindow getParentFuncletWindow(Container parent, String actionCode, String billType) {
		if (PfUtilBaseTools.isApproveAction(actionCode, billType)) {
			// yanke1+ 2011-9-8
			// 找到单据节点的IFuncletWindow
			// 判断打开方式是否为对话框
			if (parent instanceof AbstractFunclet) {
				AbstractFunclet func = (AbstractFunclet) parent;

				String funcCode = func.getFuncCode();

				IFuncletWindow[] windows = WorkbenchEnvironment.getInstance().getAllOpenedFuncletWindow();

				for (IFuncletWindow window : windows) {
					String windowCode = window.getFuncRegisterVO().getFuncode();
					if (windowCode.equals(funcCode)) {
						isOpenedInDialog = (window instanceof JDialog);
						return window;
					}
				}
			}
		}

		return null;
	}

	/**
	 * 前台单据动作处理API,算法如下:
	 * <li>1.动作执行前提示以及事前处理,如果用户取消,则方法直接返回
	 * <li>2.查看扩展参数,判断是否需要审批流相关处理。如果为提交动作,则可能需要收集提交人的指派信息; 如果为审批动作,则可能需要收集审批人的审批信息
	 * <li>3.后台执行动作。并返回动作执行结果。
	 * 
	 * @param parent          父窗体 -- 需要LoginContext.EntranceUI
	 * @param actionCode      动作编码,比如"SAVE"
	 * @param billOrTranstype 单据(或交易)类型PK
	 * @param billvo          单据聚合VO
	 * @param userObj         用户自定义对象
	 * @param checkVo         校验单据聚合VO
	 * @param eParam          扩展参数
	 * @return 动作处理的返回结果
	 * @throws BusinessException
	 * @throws Exception
	 * @since 5.5
	 */
	public static Object runAction(Container parent, String actionCode, String billOrTranstype, AggregatedValueObject billvo, Object userObj, String strBeforeUIClass, AggregatedValueObject checkVo, HashMap eParam) throws BusinessException {
		eParam = initEParam(eParam);
		Logger.debug("*单据动作处理 开始");
		debugParams(actionCode, billOrTranstype, billvo, userObj);
		long start = System.currentTimeMillis();
		m_isSuccess = true;
		m_checkFlag = true;

		isOpenedInDialog = false;
		IFuncletWindow parentFuncletWindow = getParentFuncletWindow(parent, actionCode, billOrTranstype);

//TODO 先注释掉,目前的调用方式有问题,会增加远程调用次数,不应该在这个时机判断,后续如果有人提问题了再分析一下具体场景
//		if (PfUtilBaseTools.isStartAction(actionCode, billOrTranstype)) {
//			String actionSignlCode = actionCode.replace(IPFActionName.START,
//					IPFActionName.SIGNAL);
//			try {
//				WorkflownoteVO noteVO = NCLocator.getInstance().lookup(IWorkflowMachine.class).checkWorkFlow(actionSignlCode, billOrTranstype,billvo, eParam);
//				// 如果有代办任务
//				if (noteVO != null)
//					actionCode = actionSignlCode;
//			} catch (BusinessException be) {
//				Logger.error("工作流回退业务处理,找不到工作项即不用替换动作代码,继续执行即可");
//			}
//		}

		// 1.动作执行前提示
		boolean isContinue = hintBeforeAction(parent, actionCode, billOrTranstype);
		if (!isContinue) {
			Logger.debug("*动作执行前提示,返回");
			m_isSuccess = false;
			return null;
		}

		// 2.查看扩展参数,是否要流程交互处理
		WorkflownoteVO worknoteVO = null;/// 批量审批出错(WorkflownoteVO)getParamFromMap(eParam,
											/// PfUtilBaseTools.PARAM_WORKNOTE);
		Object paramSilent = getParamFromMap(eParam, PfUtilBaseTools.PARAM_SILENTLY);
		/// if(worknoteVO == null){//批量审批出错
		Object paramNoflow = getParamFromMap(eParam, PfUtilBaseTools.PARAM_NOFLOW);
		if (paramNoflow == null && paramSilent == null) {
			// 需要交互处理
			if (PfUtilBaseTools.isSaveAction(actionCode, billOrTranstype) || PfUtilBaseTools.isApproveAction(actionCode, billOrTranstype)) {
				// 审批流交互处理
				worknoteVO = actionAboutApproveflow(parent, actionCode, billOrTranstype, billvo, eParam, 0);
				if (!m_isSuccess)
					return null;
			} else if (PfUtilBaseTools.isStartAction(actionCode, billOrTranstype) || PfUtilBaseTools.isSignalAction(actionCode, billOrTranstype)) {
				// 工作流互处理
				worknoteVO = actionAboutWorkflow(parent, actionCode, billOrTranstype, billvo, eParam, 0);
				if (!m_isSuccess)
					return null;
			}
			// putParam(eParam, PfUtilBaseTools.PARAM_WORKNOTE, worknoteVO);
		}
		/// }//批量审批出错
		// 如果用户在交互处理时候选择加签或者改派,则无需驱动流程@2009-5
		if (worknoteVO != null && PfUtilClientAssistor.isAddApproverOrAppoint(worknoteVO)) {
			// zhouhenga 此时返回原始的单据vo,使得侧边栏刷新
			// liangyub 通过侧边栏加签操作,成功后加以提示
			if (eParam != null && eParam.get(PfUtilBaseTools.PARAM_BESIDEAPPROVE) != null) {
				if (eParam.get(PfUtilBaseTools.PARAM_BESIDEAPPROVE) instanceof BesideApproveContext) {
					BesideApproveContext besideContext = (BesideApproveContext) eParam.get(PfUtilBaseTools.PARAM_BESIDEAPPROVE);
					if (besideContext.isAddAssign()) {
						MessageDialog.showHintDlg(parent, NCLangRes.getInstance().getStrByID("pfworkflow63", "2PLATFORM-00082")/* 操作成功 */, NCLangRes.getInstance().getStrByID("pfworkflow63", "2PLATFORM-00083")/* 单据加签成功 */);
					}
				}
			}
			return billvo;
		}
		if (worknoteVO == null) {
			// 检查不到工作项,则后台无需再次检查
			if (eParam == null)
				eParam = new HashMap<String, String>();
			if (paramSilent == null)
				eParam.put(PfUtilBaseTools.PARAM_NOTE_CHECKED, PfUtilBaseTools.PARAM_NOTE_CHECKED);
		}

		// 4.后台执行动作
		Object retObj = null;

		Logger.debug("*后台动作处理 开始");
		long start2 = System.currentTimeMillis();
		IplatFormEntry iIplatFormEntry = (IplatFormEntry) NCLocator.getInstance().lookup(IplatFormEntry.class.getName());
		retObj = iIplatFormEntry.processAction(actionCode, billOrTranstype, worknoteVO, billvo, userObj, eParam);
		Logger.debug("*后台动作处理 结束=" + (System.currentTimeMillis() - start2) + "ms");

		m_isSuccess = true;

		// 5.返回对象执行
		// retObjRun(parent, retObj);
		Logger.debug("*单据动作处理 结束=" + (System.currentTimeMillis() - start) + "ms");

		if (m_isSuccess && worknoteVO != null) {
			// 更新消息的状态

			MessageProcessorContext.setHandledWithProcessor(worknoteVO);
		}

		if (m_isSuccess && isOpenedInDialog && isAutoCloseParentDialog && parentFuncletWindow != null && PfUtilBaseTools.isApproveAction(actionCode, billOrTranstype)) {

			// 审批成功、单据为对话框打开、且审批时选择了自动关闭单据界面
			// yanke1 2012-7-18 那么关闭单据界面
			final IFuncletWindow p = parentFuncletWindow;

			// 放到swing线程里,否则界面会卡死掉
			SwingUtilities.invokeLater(new Runnable() {

				@Override
				public void run() {
					p.forceCloseWindow();
				}
			});

		}

		return retObj;
	}

	private static Object getParamFromMap(HashMap eParam, String paramKey) {
		return eParam == null ? null : eParam.get(paramKey);
	}

	/**
	 * 工作流相关的交互处理
	 * 
	 * @throws BusinessException
	 */
	private static WorkflownoteVO actionAboutWorkflow(Container parent, String actionName, String billType, AggregatedValueObject billvo, HashMap eParam, int voAryLen) throws BusinessException {
		WorkflownoteVO worknoteVO = null;

		if (PfUtilBaseTools.isStartAction(actionName, billType)) {
			Logger.debug("*启动动作=" + actionName + ",检查工作流");
			Stack dlgResult = new Stack();
			worknoteVO = checkOnStart(parent, actionName, billType, billvo, dlgResult, eParam);
			if (dlgResult.size() > 0) {
				m_isSuccess = false;
				Logger.debug("*用户指派时点击了取消,则停止启动工作流");
			}
		} else if (PfUtilBaseTools.isSignalAction(actionName, billType)) {
			Logger.debug("*执行动作=" + actionName + ",检查工作流");
			// 检查该单据是否处于工作流中
			worknoteVO = checkWorkitemWhenSignal(parent, actionName, billType, billvo, eParam, voAryLen);
			if (worknoteVO != null) {
				if ("Y".equals(worknoteVO.getApproveresult())) {
					m_iCheckResult = IApproveflowConst.CHECK_RESULT_PASS;
				} else if ("R".equals(worknoteVO.getApproveresult())) {
					// XXX::驳回也作为审批通过的一种,需要继续判断 lj+
					WFTask currTask = worknoteVO.getTaskInfo().getTask();
					if (currTask != null && currTask.getTaskType() == WfTaskType.Backward.getIntValue()) {
						if (currTask.isBackToFirstActivity())
							m_iCheckResult = IApproveflowConst.CHECK_RESULT_REJECT_FIRST;
						else
							m_iCheckResult = IApproveflowConst.CHECK_RESULT_REJECT_LAST;
					}
				} else
					m_iCheckResult = IApproveflowConst.CHECK_RESULT_NOPASS;
			} else if (!m_checkFlag) {
				m_isSuccess = false;
				Logger.debug("*用户驱动工作流时点击了取消,则停止执行工作流");
			}
		}
		return worknoteVO;
	}

	/**
	 * 审批流相关的交互处理
	 * 
	 * @throws BusinessException
	 */
	private static WorkflownoteVO actionAboutApproveflow(Container parent, String actionName, String billType, Object billvos, HashMap eParam, int voAryLen) throws BusinessException {
		WorkflownoteVO worknoteVO = null;

		if (PfUtilBaseTools.isSaveAction(actionName, billType)) {
			Logger.debug("*提交动作=" + actionName + ",检查审批流");
			// 如果为提交动作,可能需要收集提交人的指派信息,这里统一动作名称 lj@2005-4-8
			Stack dlgResult = new Stack();
			// billvos传值为单值或者数组 qf@2015-1-22
			AggregatedValueObject billvo = null;
			if (billvos instanceof AggregatedValueObject) {
				billvo = (AggregatedValueObject) billvos;
			} else if (billvos instanceof AggregatedValueObject[]) {
				AggregatedValueObject[] vos = (AggregatedValueObject[]) billvos;
				billvo = vos[0];
			}
			worknoteVO = checkOnSave(parent, IPFActionName.SAVE, billType, billvo, dlgResult, eParam);
			if (dlgResult.size() > 0) {
				m_isSuccess = false;
				Logger.debug("*用户指派时点击了取消,则停止送审");
			}
		} else if (PfUtilBaseTools.isApproveAction(actionName, billType)) {
			Logger.debug("*审批动作=" + actionName + ",检查审批流");
			// 检查该单据是否处于审批流中,并收集审批人的审批信息
			worknoteVO = checkWorkitemWhenApprove(parent, actionName, billType, billvos, eParam, voAryLen);
			if (worknoteVO != null) {
				if ("Y".equals(worknoteVO.getApproveresult())) {
					m_iCheckResult = IApproveflowConst.CHECK_RESULT_PASS;
				} else if ("R".equals(worknoteVO.getApproveresult())) {
					// XXX::驳回也作为审批通过的一种,需要继续判断 lj+
					WFTask currTask = worknoteVO.getTaskInfo().getTask();
					if (currTask != null && currTask.getTaskType() == WfTaskType.Backward.getIntValue()) {
						if (currTask.isBackToFirstActivity())
							m_iCheckResult = IApproveflowConst.CHECK_RESULT_REJECT_FIRST;
						else
							m_iCheckResult = IApproveflowConst.CHECK_RESULT_REJECT_LAST;
					}
				} else
					m_iCheckResult = IApproveflowConst.CHECK_RESULT_NOPASS;
			} else if (!m_checkFlag) {
				m_isSuccess = false;
				Logger.debug("*用户审批时点击了取消,则停止审批");
			}
		}
		return worknoteVO;
	}

	private static PFClientBizRetObj executeBusinessPlugin(Container parent, AggregatedValueObject billVo, WorkflownoteVO wfVo, boolean isMakeBill) {
		if (wfVo != null && wfVo.getApplicationArgs() != null && wfVo.getApplicationArgs().size() > 0) {
			String billtype = wfVo.getTaskInfo().getTask().getBillType();
			ArrayList<Billtype2VO> bt2VOs = PfDataCache.getBillType2Info(billtype, ExtendedClassEnum.PROC_CLIENT.getIntValue());

			// 实例化
			for (Iterator iterator = bt2VOs.iterator(); iterator.hasNext();) {
				Billtype2VO bt2VO = (Billtype2VO) iterator.next();
				try {
					Object obj = PfUtilTools.findBizImplOfBilltype(billtype, bt2VO.getClassname());
					PfClientBizProcessContext context = new PfClientBizProcessContext();
					context.setBillvo(billVo);
					context.setArgsList(wfVo.getApplicationArgs());
					context.setMakeBill(isMakeBill);
					return ((IPFClientBizProcess) obj).execute(parent, context);
				} catch (Exception e) {
					Logger.error("无法实例化前台业务插件类billType=" + billtype + ",className=" + bt2VO.getClassname(), e);
				}
			}
		}
		return null;

	}

	/**
	 * @return 是否侧边栏审批
	 */
	private static boolean isBesideApprove(HashMap hmPfExParams) {
		return hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_BESIDEAPPROVE) != null;
	}

//	/**
//	 * 批审时的交互处理
//	 * @throws BusinessException 
//	 */
//	private static WorkflownoteVO batchActionAboutApproveflow(Container parent, String actionName,
//			String billType, AggregatedValueObject[] voAry, HashMap eParam) throws BusinessException {
//		WorkflownoteVO worknoteVO = null;
//
//		if (PfUtilBaseTools.isSaveAction(actionName)) {
//			Logger.debug("*提交动作=" + actionName + ",检查审批流");
//		} else if (PfUtilBaseTools.isApproveAction(actionName)) {
//			Logger.debug("*审批动作=" + actionName + ",检查审批流");
//			// 检查该单据是否处于审批流中,并收集审批人的审批信息
//			worknoteVO = checkWorkitemWhenApprove(parent, actionName, billType, null, eParam);
//			if (worknoteVO != null) {
//				if ("Y".equals(worknoteVO.getApproveresult())) {
//					// XXX::驳回也作为审批通过的一种,需要继续判断 lj+
//					WFTask currTask = worknoteVO.getTaskInfo().getTask();
//					if (currTask.getTaskType() == WfTaskType.Backward.getIntValue()) {
//						if (currTask.isBackToFirstActivity())
//							m_iCheckResult = IApproveflowConst.CHECK_RESULT_REJECT_FIRST;
//						else
//							m_iCheckResult = IApproveflowConst.CHECK_RESULT_REJECT_LAST;
//					} else
//						m_iCheckResult = IApproveflowConst.CHECK_RESULT_PASS;
//				} else
//					m_iCheckResult = IApproveflowConst.CHECK_RESULT_NOPASS;
//			} else if (!m_checkFlag) {
//				m_isSuccess = false;
//				Logger.debug("*用户审批时点击了取消,则停止审批");
//			}
//		}
//		return worknoteVO;
//	}

	/**
	 * 日志一下动作处理的上下文参数
	 */
	private static void debugParams(String actionCode, String billType, Object billEntity, Object userObj) {
		Logger.debug("*********************************************");
		Logger.debug("* actionCode=" + actionCode);
		Logger.debug("* billType=" + billType);
		Logger.debug("* billEntity=" + billEntity);
		Logger.debug("* userObj=" + userObj);
		Logger.debug("*********************************************");
	}

	/**
	 * 动作执行前提示
	 */
	private static boolean hintBeforeAction(Container parent, String actionName, String billType) {
		ActionClientParams acp = new ActionClientParams();
		acp.setUiContainer(parent);
		acp.setActionCode(actionName);
		acp.setBillType(billType);

		return PfUtilUITools.beforeAction(acp);
	}

	/**
	 * 前台单据动作批处理API,算法如下:
	 * <li>1.动作执行前提示以及事前处理,如果用户取消,则方法直接返回
	 * <li>2.查看扩展参数,判断是否需要审批流相关处理。如果为提交动作,且单据VO数组中只有一张单据时可能需要收集提交人的指派信息;
	 * 如果为审批动作,则针对第一张单据可能需要收集审批人的审批信息
	 * <li>3.后台执行批动作。并返回动作执行结果。
	 * 
	 * @param parent          父窗体
	 * @param actionCode      动作编码,比如"SAVE"
	 * @param billOrTranstype 单据类型(或交易类型)PK
	 * @param voAry           单据聚合VO数组
	 * @param userObjAry      用户自定义对象数组
	 * @param eParam          扩展参数
	 * @return 动作批处理的返回结果
	 * @throws Exception
	 * @since 5.5
	 */
	public static Object[] runBatch(Container parent, String actionCode, String billOrTranstype, AggregatedValueObject[] voAry, Object[] userObjAry, String strBeforeUIClass, HashMap eParam) throws Exception {
		eParam = initEParam(eParam);
		Logger.debug("*单据动作批处理 开始");
		debugParams(actionCode, billOrTranstype, voAry, userObjAry);
		long start = System.currentTimeMillis();
		if (isSingleDataRun(voAry, eParam)) {
			Object obj = runAction(parent, actionCode, billOrTranstype, voAry[0], userObjAry, strBeforeUIClass, null, eParam);
			Object[] ret = null;
			ret = PfUtilBaseTools.composeResultAry(obj, 1, 0, ret);
			return ret;
		}

		m_isSuccess = true;
		m_checkFlag = true;

		// 1.动作执行前提示以及事前处理
		boolean isContinue = beforeProcessBatchAction(parent, actionCode, billOrTranstype);
		if (!isContinue) {
			Logger.debug("*动作执行前提示以及事前处理,返回");
			m_isSuccess = false;
			return null;
		}

		WorkflownoteVO workflownote = null;

		// 2.查看扩展参数,是否要流程交互处理
		Object paramNoflow = getParamFromMap(eParam, PfUtilBaseTools.PARAM_NOFLOW);
		Object paramSilent = getParamFromMap(eParam, PfUtilBaseTools.PARAM_SILENTLY);
		if (paramNoflow == null && paramSilent == null) {
			// XXX:guowl,2010-5,批审时,审批处理对话框上只显示批准、不批准、驳回,故传入一个参数用于甄别
			// 如果传人的VO数组长度为1,同单个处理一样
			if (voAry != null && voAry.length > 1) {
				eParam = putParam(eParam, PfUtilBaseTools.PARAM_BATCH, PfUtilBaseTools.PARAM_BATCH);
			}
			if (PfUtilBaseTools.isSaveAction(actionCode, billOrTranstype) || PfUtilBaseTools.isApproveAction(actionCode, billOrTranstype)) {
				// 审批流交互处理
				workflownote = actionAboutApproveflow(parent, actionCode, billOrTranstype, voAry, eParam, voAry.length);
				if (!m_isSuccess)
					return null;
			} else if (PfUtilBaseTools.isStartAction(actionCode, billOrTranstype) || PfUtilBaseTools.isSignalAction(actionCode, billOrTranstype)) {
				// 工作流交互处理
				workflownote = actionAboutWorkflow(parent, actionCode, billOrTranstype, voAry[0], eParam, voAry.length);
				if (!m_isSuccess)
					return null;
			}
		}

		// 3.后台批处理动作
		Logger.debug("*后台动作批处理 开始");
		Object retObj = NCLocator.getInstance().lookup(IplatFormEntry.class).processBatch(actionCode, billOrTranstype, workflownote, voAry, userObjAry, eParam);
		if (retObj instanceof PfProcessBatchRetObject) {
			String errMsg = ((PfProcessBatchRetObject) retObj).getExceptionMsg();
			if (!StringUtil.isEmptyWithTrim(errMsg))
				MessageDialog.showErrorDlg(parent, null, errMsg);
			retObj = ((PfProcessBatchRetObject) retObj).getRetObj();
		}
		if (retObj != null && ((Object[]) retObj).length > 0) {
			// 批处理时,有一个成功的就认为成功
			m_isSuccess = true;
		}
		Logger.debug("*单据动作批处理 结束=" + (System.currentTimeMillis() - start) + "ms");

		return (Object[]) retObj;
	}

	private static HashMap initEParam(HashMap eParam) {
		eParam = eParam != null ? eParam : new HashMap();
		return eParam;
	}

	public static PfProcessBatchRetObject runBatchNew(Container parent, String actionCode, String billOrTranstype, AggregatedValueObject[] voAry, Object[] userObjAry, String strBeforeUIClass, HashMap eParam) throws Exception {
		eParam = initEParam(eParam);
		Logger.debug("*单据动作批处理 开始");
		debugParams(actionCode, billOrTranstype, voAry, userObjAry);
		long start = System.currentTimeMillis();
		if (isSingleDataRun(voAry, eParam)) {
			Object obj = runAction(parent, actionCode, billOrTranstype, voAry[0], userObjAry, strBeforeUIClass, null, eParam);
			Object[] retObj = null;
			retObj = PfUtilBaseTools.composeResultAry(obj, 1, 0, retObj);
			return new PfProcessBatchRetObject(retObj, null);
		}

		m_isSuccess = true;
		m_checkFlag = true;

		// 1.动作执行前提示以及事前处理
		boolean isContinue = beforeProcessBatchAction(parent, actionCode, billOrTranstype);
		if (!isContinue) {
			Logger.debug("*动作执行前提示以及事前处理,返回");
			m_isSuccess = false;
			return null;
		}

		// 2.查看扩展参数,是否要流程交互处理
		WorkflownoteVO workflownote = null;// (WorkflownoteVO)getParamFromMap(eParam, PfUtilBaseTools.PARAM_WORKNOTE);
//		if(workflownote == null){
		Object paramNoflow = getParamFromMap(eParam, PfUtilBaseTools.PARAM_NOFLOW);
		Object paramSilent = getParamFromMap(eParam, PfUtilBaseTools.PARAM_SILENTLY);
		if (paramNoflow == null && paramSilent == null) {
			// XXX:guowl,2010-5,批审时,审批处理对话框上只显示批准、不批准、驳回,故传入一个参数用于甄别
			// 如果传人的VO数组长度为1,同单个处理一样
			if (voAry != null && voAry.length > 1) {
				eParam = putParam(eParam, PfUtilBaseTools.PARAM_BATCH, PfUtilBaseTools.PARAM_BATCH);
			}
			if (PfUtilBaseTools.isSaveAction(actionCode, billOrTranstype) || PfUtilBaseTools.isApproveAction(actionCode, billOrTranstype)) {
				// 审批流交互处理
				workflownote = actionAboutApproveflow(parent, actionCode, billOrTranstype, voAry, eParam, voAry.length);
				if (!m_isSuccess)
					return null;
			} else if (PfUtilBaseTools.isStartAction(actionCode, billOrTranstype) || PfUtilBaseTools.isSignalAction(actionCode, billOrTranstype)) {
				// 工作流交互处理
				workflownote = actionAboutWorkflow(parent, actionCode, billOrTranstype, voAry[0], eParam, voAry.length);
				if (!m_isSuccess)
					return null;
			}
//				putParam(eParam, PfUtilBaseTools.PARAM_WORKNOTE, workflownote);
		}
		// }
		// 3.后台批处理动作
		Logger.debug("*后台动作批处理 开始");
		Object retObj = NCLocator.getInstance().lookup(IplatFormEntry.class).processBatch(actionCode, billOrTranstype, workflownote, voAry, userObjAry, eParam);
		Logger.debug("*单据动作批处理 结束=" + (System.currentTimeMillis() - start) + "ms");

		return (PfProcessBatchRetObject) retObj;
	}

	private static boolean isSingleDataRun(AggregatedValueObject[] voAry, HashMap eParam) {
		return voAry != null && voAry.length == 1 && eParam.get(PfUtilBaseTools.PARAM_WORKNOTE) == null;
	}

	private static HashMap putParam(HashMap eParam, String paramKey, Object value) {
		if (eParam == null) {
			eParam = new HashMap();
		}
		eParam.put(paramKey, value);
		return eParam;
	}

	/**
	 * 动作执行前提示以及事前处理
	 */
	private static boolean beforeProcessBatchAction(Container parent, String actionName, String billType) throws Exception {

		ActionClientParams acp = new ActionClientParams();
		acp.setUiContainer(parent);
		acp.setActionCode(actionName);
		acp.setBillType(billType);

		return PfUtilUITools.beforeAction(acp);
	}

	/**
	 * 返回某个单据或交易类型可使用的“新增”下拉菜单信息
	 * <li>包括自制、来源单据
	 * 
	 * @param billtype
	 * @param transtype       如果没有交易类型,可空
	 * @param pk_group        某集团PK
	 * @param userId          某用户PK
	 * @param includeBillType 是否包括单据类型的来源单据信息,只用于transtype非空的情况
	 * @return
	 * @throws BusinessException
	 */
	public static PfAddInfo[] retAddInfo(String billtype, String transtype, String pk_group, String userId, boolean includeBillType) throws BusinessException {

		return NCLocator.getInstance().lookup(IPFConfig.class).retAddInfo(billtype, transtype, pk_group, userId, includeBillType);
	}

	/**
	 * 返回某个用户对某个单据或交易类型,在某组织下 可启动的业务流程
	 * 
	 * @param billtype
	 * @param transtype 如果没有交易类型,可空
	 * @param pk_org    某组织PK
	 * @param userId    某用户PK
	 * @return
	 * @throws BusinessException
	 */
	public static String retBusitypeCanStart(String billtype, String transtype, String pk_org, String userId) throws BusinessException {

		return NCLocator.getInstance().lookup(IPFConfig.class).retBusitypeCanStart(billtype, transtype, pk_org, userId);
	}

	/**
	 * 返回某单据或交易类型配置的某动作组的所有单据动作
	 * 
	 * @param billOrTranstype 单据或交易类型
	 * @param actiongroupCode 动作组编码
	 * @return
	 */
	public static BillactionVO[] getActionsOfActiongroup(String billOrTranstype, String actiongroupCode) {
		// 获得单据类型(或交易类型)的单据类型PK
		billOrTranstype = PfUtilBaseTools.getRealBilltype(billOrTranstype);
		BillactionVO[] billActionVos = (BillactionVO[]) PfUIDataCache.getButtonByBillAndGrp(billOrTranstype, actiongroupCode);
		return billActionVos;
	}

	/**
	 * 构造一个查询对话框,并为其设置查询模板
	 * 
	 * @param templateId
	 * @param parent
	 * @param isRelationCorp
	 * @param pkOperator
	 * @param funNode
	 */
	private static IBillReferQuery setConditionClient(String templateId, Container parent, final String pkOperator, final String funNode, String pkCorp) {
		TemplateInfo ti = new TemplateInfo();
		ti.setTemplateId(templateId);
		ti.setPk_Org(pkCorp);
		ti.setUserid(pkOperator);
		ti.setCurrentCorpPk(pkCorp);
		ti.setFunNode(funNode);

		QueryConditionDLG qcDlg = new QueryConditionDLG(parent, ti);

		qcDlg.setVisibleNormalPanel(false);
		return qcDlg;
	}

	/**
	 * 为NC预算提供的支持不同审批流的工作项批量处理的接口(只用于NC预算批量处理) add by liangyub 2014-04-21
	 * 
	 * @param VOArrayMap map<审批流pk,审批的对象级(业务组聚合VO)>
	 */
	public static Map<String, PfProcessBatchRetObject> runBatchNewForNC(Container parent, String actionCode, Map<String, List<AggregatedValueObject>> VOArrayMap) throws Exception {
		Logger.debug("*单据动作批处理 runBatchNewForNC方法开始");

		// 批量处理逻辑
		m_isSuccess = true;
		m_checkFlag = true;

		Map<String, PfProcessBatchRetObject> result = new HashMap<String, PfProcessBatchRetObject>();
		// 查询所关联的流程定义
		String[] defPks = VOArrayMap.keySet().toArray(new String[0]);
		WorkflowDefinitionVO[] defVOs = getWorkflowDefService().findDefinitionsWithoutContentByPrimaryKeys(defPks);
		Map<String, String> billTypeMap = new HashMap<String, String>();
		for (WorkflowDefinitionVO def : defVOs) {
			billTypeMap.put(def.getPk_wf_def(), def.getBilltype());
		}

		// 处理单个逻辑
		if (VOArrayMap != null && VOArrayMap.size() == 1 && VOArrayMap.get(defPks[0]).size() == 1) {
			processForSingle(parent, actionCode, VOArrayMap, result, defPks, billTypeMap);
			return result;
		}

		long start = System.currentTimeMillis();
		Logger.debug("*后台动作批处理 开始");
		processForMultiple(parent, actionCode, VOArrayMap, result, defPks, billTypeMap);
		Logger.debug("*单据动作批处理 结束=" + (System.currentTimeMillis() - start) + "ms");
		return result;
	}

	private static IWorkflowDefine getWorkflowDefService() {
		if (workflowDefService == null) {
			workflowDefService = NCLocator.getInstance().lookup(IWorkflowDefine.class);
		}
		return workflowDefService;
	}

	/**
	 * 处理单个任务
	 */
	private static void processForSingle(Container parent, String actionCode, Map<String, List<AggregatedValueObject>> VOArrayMap, Map<String, PfProcessBatchRetObject> result, String[] defPks, Map<String, String> billTypeMap) throws BusinessException {
		// 补全调用参数
		String billType = billTypeMap.get(defPks[0]);
		HashMap<String, Object> eParam = new HashMap<String, Object>();
		eParam.put(PfUtilBaseTools.PARAM_FLOWPK, defPks[0]);
		Object obj = runAction(parent, actionCode, billType, VOArrayMap.get(defPks[0]).get(0), new Object[] { Integer.valueOf(0) }, null, null, eParam);
		Object[] retObj = null;
		retObj = PfUtilBaseTools.composeResultAry(obj, 1, 0, retObj);
		result.put(defPks[0], new PfProcessBatchRetObject(retObj, null));
	}

	/**
	 * 批量处理任务
	 */
	private static void processForMultiple(Container parent, String actionCode, Map<String, List<AggregatedValueObject>> VOArrayMap, Map<String, PfProcessBatchRetObject> result, String[] defPks, Map<String, String> billTypeMap) throws BusinessException, Exception {
		if (VOArrayMap.size() > 1) {
			processForSingleBillType(parent, actionCode, VOArrayMap, result, defPks, billTypeMap);
		} else {
			processForMultipleBillType(parent, actionCode, VOArrayMap, result, defPks, billTypeMap);
		}
	}

	/**
	 * 如果只有一个流程,是属于相同流程的工作项批量处理(有动作执行前提示)
	 */
	private static void processForSingleBillType(Container parent, String actionCode, Map<String, List<AggregatedValueObject>> VOArrayMap, Map<String, PfProcessBatchRetObject> result, String[] defPks, Map<String, String> billTypeMap) throws Exception, BusinessException {
		// 1.动作执行前提示以及事前处理
		String billType = billTypeMap.get(defPks[0]);
		AggregatedValueObject[] voAry = VOArrayMap.get(defPks[0]).toArray(new AggregatedValueObject[0]);
		boolean isContinue = beforeProcessBatchAction(parent, actionCode, billType);
		if (!isContinue) {
			Logger.debug("*动作执行前提示以及事前处理,返回");
			m_isSuccess = false;
		}

		// 2.流程交互处理
		HashMap<String, Object> eParam = new HashMap<String, Object>();
		eParam.put(PfUtilBaseTools.PARAM_FLOWPK, defPks[0]);
		eParam.put(PfUtilBaseTools.PARAM_NOTSILENT, new Boolean(true));
		WorkflownoteVO workflownote = processForBatch(parent, actionCode, billType, voAry, eParam);

		// 3.后台批处理动作
		Object retObj = NCLocator.getInstance().lookup(IplatFormEntry.class).processBatch(actionCode, billType, workflownote, voAry, new Object[] { Integer.valueOf(1) }, eParam);
		result.put(defPks[0], (PfProcessBatchRetObject) retObj);
	}

	/**
	 * 如果存在多个流程,是属于不同流程的工作项批量处理(有动作执行前提示)
	 */
	private static void processForMultipleBillType(Container parent, String actionCode, Map<String, List<AggregatedValueObject>> VOArrayMap, Map<String, PfProcessBatchRetObject> result, String[] defPks, Map<String, String> billTypeMap) throws BusinessException {
		// 取第一流程定义下的审批结果,用于补全剩余工作项
		String billType = billTypeMap.get(defPks[0]);
		AggregatedValueObject[] voAry = VOArrayMap.get(defPks[0]).toArray(new AggregatedValueObject[0]);
		HashMap<String, Object> eParam = new HashMap<String, Object>();
		eParam.put(PfUtilBaseTools.PARAM_FLOWPK, defPks[0]);
		eParam.put(PfUtilBaseTools.PARAM_NOTSILENT, new Boolean(true));
		WorkflownoteVO workflownote = processForBatch(parent, actionCode, billType, voAry, eParam);
		Object retObj = NCLocator.getInstance().lookup(IplatFormEntry.class).processBatch(actionCode, billType, workflownote, voAry, new Object[] { Integer.valueOf(1) }, eParam);
		result.put(defPks[0], (PfProcessBatchRetObject) retObj);
		for (int i = 1; i < defPks.length; i++) {
			String type = billTypeMap.get(defPks[i]);
			WorkflownoteVO noteVO = new WorkflownoteVO();
			completeWorkItemInfo(workflownote, noteVO);
			AggregatedValueObject[] ary = VOArrayMap.get(defPks[i]).toArray(new AggregatedValueObject[0]);
			HashMap<String, Object> param = new HashMap<String, Object>();
			eParam.put(PfUtilBaseTools.PARAM_FLOWPK, defPks[i]);
			Object ret = NCLocator.getInstance().lookup(IplatFormEntry.class).processBatch(actionCode, type, noteVO, ary, new Object[] { Integer.valueOf(1) }, param);
			result.put(defPks[i], (PfProcessBatchRetObject) ret);
		}
	}

	/**
	 * 用于处理批量审批同一流程的多个工作项,并返回处理过的WorkflownoteVO<br/>
	 */
	@SuppressWarnings("unchecked")
	private static WorkflownoteVO processForBatch(Container parent, String actionCode, String billOrTranstype, AggregatedValueObject[] voAry, HashMap<String, Object> eParam) throws BusinessException {
		// 1.加入扩展承参数
		putElecsignatureValue(billOrTranstype, voAry, eParam);
		// 2.查看扩展参数,是否要流程交互处理
		WorkflownoteVO workflownote = null;
		Object paramNoflow = getParamFromMap(eParam, PfUtilBaseTools.PARAM_NOFLOW);
		Object paramSilent = getParamFromMap(eParam, PfUtilBaseTools.PARAM_SILENTLY);
		if (paramNoflow == null && paramSilent == null) {
			// 批审时,审批处理对话框上只显示批准、不批准、驳回,故传入一个参数用于甄别
			// 如果传人的VO数组长度为1,同单个处理一样
			if (voAry != null && voAry.length > 1) {
				eParam = putParam(eParam, PfUtilBaseTools.PARAM_BATCH, PfUtilBaseTools.PARAM_BATCH);
			}
			if (PfUtilBaseTools.isSaveAction(actionCode, billOrTranstype) || PfUtilBaseTools.isApproveAction(actionCode, billOrTranstype)) {
				// 审批流交互处理
				workflownote = actionAboutApproveflow(parent, actionCode, billOrTranstype, voAry[0], eParam, voAry.length);
			} else if (PfUtilBaseTools.isStartAction(actionCode, billOrTranstype) || PfUtilBaseTools.isSignalAction(actionCode, billOrTranstype)) {
				// 工作流交互处理
				workflownote = actionAboutWorkflow(parent, actionCode, billOrTranstype, voAry[0], eParam, voAry.length);
			}
		}

		return workflownote;
	}

	/**
	 * 根据已有工作项,补全当前工作项信息 用于NC预算不同审批流的批量审批
	 */
	private static void completeWorkItemInfo(WorkflownoteVO baseVO, WorkflownoteVO toCompleteVO) {
		toCompleteVO.setChecknote(baseVO.getChecknote());
		if (baseVO.getApproveresult().equals("Y")) {
			// 批准
			toCompleteVO.setApproveresult("Y");
		} else if (baseVO.getApproveresult().equals("N")) {
			// 不批准
			toCompleteVO.setApproveresult("N");
		} else if (baseVO.getApproveresult().equals("R")) {
			// 驳回到制单人
			if (toCompleteVO.getTaskInfo().getTask() != null) {
				toCompleteVO.getTaskInfo().getTask().setTaskType(WfTaskType.Backward.getIntValue());
				toCompleteVO.getTaskInfo().getTask().setBackToFirstActivity(true);
			}
			toCompleteVO.setApproveresult("R");
		}
		toCompleteVO.setApproveresult(baseVO.getApproveresult());
	}

	/**
	 * 
	 * @since 6.3 批审时候预先判断是否需要CA
	 */
	private static void putElecsignatureValue(String billOrTranstype, AggregatedValueObject[] voAry, HashMap eParam) throws BusinessException {
		// 判断是否需要CA
		List<String> billIdList = new ArrayList<String>();
		for (AggregatedValueObject vo : voAry) {
			billIdList.add(vo.getParentVO().getPrimaryKey());
		}

		boolean isNeedCASign = NCLocator.getInstance().lookup(IPFWorkflowQry.class).isNeedCASign4Batch(PfUtilUITools.getLoginUser(), new String[] { billOrTranstype }, billIdList.toArray(new String[0]));

		if (isNeedCASign) {
			putParam(eParam, XPDLNames.ELECSIGNATURE, "Y");
		}
	}

}

流程平台客户端工具类中提交单据时,需要的指派信息方法:

/**
	 * 提交单据时,需要的指派信息
	 * <li>只有"SAVE","EDIT"动作才调用
	 */
	private static WorkflownoteVO checkOnSave(Container parent, String actionName, String billType, AggregatedValueObject billVo, Stack dlgResult, HashMap hmPfExParams) throws BusinessException {
		WorkflownoteVO worknoteVO = new WorkflownoteVO();

		// guowl+ 2010-5,如果是批处理,不用取指派信息,直接返回
		if (hmPfExParams != null && hmPfExParams.get(PfUtilBaseTools.PARAM_BATCH) != null)
			return worknoteVO;

		try {
			worknoteVO = NCLocator.getInstance().lookup(IWorkflowMachine.class).checkWorkFlow(actionName, billType, billVo, hmPfExParams);
		} catch (FlowDefNotFoundException e) {
			return worknoteVO;
		}

		// 在审批处理框显示之前,调用业务处理
		PFClientBizRetObj retObj = executeBusinessPlugin(parent, billVo, worknoteVO, true);
		if (retObj != null && retObj.isStopFlow()) {
			m_isSuccess = false;
			return null;
		}

		if (worknoteVO != null) {
			// 得到可指派的输入数据
			Vector assignInfos = worknoteVO.getTaskInfo().getAssignableInfos();
			if (assignInfos != null && assignInfos.size() > 0) {
				// 显示指派对话框并收集实际指派信息
				ApproveFlowDispatchDialog dlg = new ApproveFlowDispatchDialog(parent);
				dlg.getDisPatchPanel().initByWorknoteVO(worknoteVO);
				int iClose = dlg.showModal();
				if (iClose == UIDialog.ID_CANCEL)
					dlgResult.push(Integer.valueOf(iClose));
			}
		}
		return worknoteVO;
	}

如应收单保存时,弹出需要指派下个审批环节的参与者弹框就是调用该方法
在这里插入图片描述

文章来源:https://blog.csdn.net/u010741112/article/details/135133009
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。