diff --git a/workflow/FlowContext.php b/workflow/FlowContext.php
new file mode 100644
index 00000000..473136f2
--- /dev/null
+++ b/workflow/FlowContext.php
@@ -0,0 +1,217 @@
+currentNode;
+ }
+
+ /**
+ * @param mixed|null $currentNode
+ * @return FlowContext
+ */
+ public function setCurrentNode($currentNode)
+ {
+ $this->currentNode = $currentNode;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSystemId()
+ {
+ return $this->systemId;
+ }
+
+ /**
+ * @param mixed $systemId
+ * @return FlowContext
+ */
+ public function setSystemId($systemId)
+ {
+ $this->systemId = $systemId;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlowId()
+ {
+ return $this->flowId;
+ }
+
+ /**
+ * @param mixed $flowId
+ * @return FlowContext
+ */
+ public function setFlowId($flowId)
+ {
+ $this->flowId = $flowId;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFormId()
+ {
+ return $this->formId;
+ }
+
+ /**
+ * @param mixed $formId
+ * @return FlowContext
+ */
+ public function setFormId($formId)
+ {
+ $this->formId = $formId;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCurrentUser()
+ {
+ return $this->currentAssigner;
+ }
+
+ /**
+ * @param mixed $currentAssigner
+ * @return FlowContext
+ */
+ public function setCurrentUser($currentAssigner)
+ {
+ $this->currentAssigner = $currentAssigner;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlowCode()
+ {
+ return $this->flowCode;
+ }
+
+ /**
+ * @param mixed $flowCode
+ * @return FlowContext
+ */
+ public function setFlowCode($flowCode)
+ {
+ $this->flowCode = $flowCode;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getNextAssigner()
+ {
+ return $this->nextAssigner;
+ }
+
+ /**
+ * @param mixed $nextAssigner
+ * @return FlowContext
+ */
+ public function setNextAssigner($nextAssigner)
+ {
+ $this->nextAssigner = $nextAssigner;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAssignStatus()
+ {
+ return $this->assignStatus;
+ }
+
+ /**
+ * @param mixed $assignStatus
+ * @return FlowContext
+ */
+ public function setAssignStatus($assignStatus)
+ {
+ $this->assignStatus = $assignStatus;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAssignOpinion()
+ {
+ return $this->assignOpinion;
+ }
+
+ /**
+ * @param mixed $assignOpinion
+ * @return FlowContext
+ */
+ public function setAssignOpinion($assignOpinion)
+ {
+ $this->assignOpinion = $assignOpinion;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFormKey()
+ {
+ return $this->formKey;
+ }
+
+ /**
+ * @param mixed $formKey
+ * @return FlowContext
+ */
+ public function setFormKey($formKey)
+ {
+ $this->formKey = $formKey;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWorkFLowParser()
+ {
+ return $this->workFlowParser;
+ }
+
+ /**
+ * @param mixed $workFlowParser
+ * @return FlowContext
+ */
+ public function setWorkFLowParser($workFlowParser)
+ {
+ $this->workFlowParser = $workFlowParser;
+ return $this;
+ }
+}
diff --git a/workflow/Handler/B4TaskHandler.php b/workflow/Handler/B4TaskHandler.php
new file mode 100644
index 00000000..99419ce6
--- /dev/null
+++ b/workflow/Handler/B4TaskHandler.php
@@ -0,0 +1,38 @@
+parseRole();
+ foreach ($nextAssigners as $row) {
+
+ foreach ($assigners as $key => $assigner) {
+
+ if ($assigners[$key][0] == $row['assign_status']) {
+ $assigners[$key][1] = $row['assigner_string'];
+ } else {
+ array_push($assigners, array(0 => $row['assign_status'], 1 => $row['assigner_string']));
+ }
+ }
+
+ }
+ return $assigners;
+ }
+
+}
\ No newline at end of file
diff --git a/workflow/Handler/B7TaskHandler.php b/workflow/Handler/B7TaskHandler.php
new file mode 100644
index 00000000..76b24fae
--- /dev/null
+++ b/workflow/Handler/B7TaskHandler.php
@@ -0,0 +1,38 @@
+parseRole();
+ foreach ($nextAssigners as $row) {
+
+ foreach ($assigners as $key => $assigner) {
+
+ if ($assigners[$key][0] == $row['assign_status']) {
+ $assigners[$key][1] = $row['assigner_string'];
+ } else {
+ array_push($assigners, array(0 => $row['assign_status'], 1 => $row['assigner_string']));
+ }
+ }
+
+ }
+ return $assigners;
+ }
+
+}
\ No newline at end of file
diff --git a/workflow/Handler/CounterSignSubtaskHandler.php b/workflow/Handler/CounterSignSubtaskHandler.php
new file mode 100644
index 00000000..c575dc38
--- /dev/null
+++ b/workflow/Handler/CounterSignSubtaskHandler.php
@@ -0,0 +1,141 @@
+formData = $formData;
+ $this->flowContext = $flowContext;
+ $parser = $flowContext->getWorkFLowParser();
+
+ $this->currentNode = $parser->getNodeByCode($flowContext->getFlowCode());
+
+ }
+
+ /**
+ * 1,根据签核状态变更workflow_sublow reply_flag Y:同意; N:不同意; NULL:未回复
+ */
+ public function doWork()
+ {
+ $flow = new Flow ($this->flowContext->getFormKey());
+ $sm = new SubflowManager(new Flow($flow->getParentKey()));
+ #是否同意标志
+ $flag = $this->flowContext->getAssignStatus() == AssignStatus::ACCEPT_STATUS ? 'Y' : 'N';
+ SubflowManager::updateReplyFlag($this->flowContext->getFormKey(), $flag);
+ SubflowManager::updateReplyComment($this->flowContext->getFormKey(), $this->flowContext->getAssignOpinion());
+
+ $unReplyCount = $sm->getUnReplyCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ if ($unReplyCount == 0) {
+ $mergeOption = $this->currentNode->getMergeOption();
+ $mergeOption = empty($mergeOption) ? self::DEFAULT_MERGE_OPTION : $mergeOption;
+ $function = "cond" . strtoupper($mergeOption);
+ $this->$function($sm);
+ }
+ #关闭任务
+ $task = new NodeTask();
+ $task->setFormKey($this->flowContext->getFormKey())
+ ->setFlowCode($this->flowContext->getCurrentNode()->getFlowCode())
+ ->setState("OPEN")
+ ->setTaskType("COUNTER_SIGN_SUBTASK")
+ ->setPhase("SUBMIT");
+
+ $tasks = TaskManager::getTasks($task);
+ foreach ($tasks as $task) {
+ $task->setState(NodeTask::TASK_FINISH_STATE)->update();
+
+ }
+
+
+ }
+
+ /**
+ * 同意一个即可
+ */
+ private function condOR($sm)
+ {
+ $cnt = $sm->getAcceptOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ if ($cnt >= 1) {
+ $this->nextAssign();
+ } else {
+ $this->backAssign();
+ }
+ }
+
+ /**
+ * 全部同意
+ */
+ private function condAND($sm)
+ {
+ $cnt = $sm->getRejectOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ if ($cnt == 0) {
+ $this->nextAssign();
+ } else {
+ $this->backAssign();
+ }
+ }
+
+ /**
+ *同意的占多数
+ */
+ private function condVOTE($sm)
+ {
+ $reject = $sm->getRejectOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ $accept = $sm->getAcceptOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ if ($accept >= $reject) {
+ $this->nextAssign();
+ } else {
+ $this->backAssign();
+ }
+ }
+
+ private function backAssign()
+ {
+
+ $currentFlow = new Flow($this->flowContext->getFormKey());
+ $parentKey = $currentFlow->getParentKey();
+ $prevNodes = $this->flowContext->getWorkFLowParser()->getPrevLevelNodes($this->flowContext->getCurrentNode()->getNodeId(),
+ Node::FLOW_NODE | Node::LOGIC_NODE);
+
+ foreach ($prevNodes as $key => $prevNode) {
+ $tmpNode = $prevNode[0];
+ $backFlowCode = $tmpNode->getFlowCode();
+ $backAssign = Assign::get_lastest_record($parentKey, $backFlowCode);
+ if (empty($backFlowCode)) continue;
+ Flow::updateFlowCode($parentKey, $backAssign['flow_code']);
+ Subflow::updateCurrentUser($parentKey, $backAssign['assigner']);
+ }
+
+
+ }
+
+ private function nextAssign()
+ {
+ $nextFlowNodes = $this->flowContext->getWorkFLowParser()->getNextLevelNodes($this->currentNode->getNodeId());
+ $nextFlowCode = "";
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nextFlowNodes)) continue;
+ foreach ($nextFlowNodes[$type] as $node) {
+ $nextFlowCode = $node->getFlowCode();
+ $nextAssigners = $node->getAssignerList($this->flowContext->getWorkFLowParser());
+ break 2;
+ }
+ }
+ //array(1) { [0]=> array(2) { [0]=> string(2) "F1" [1]=> string(29) "00017-贺正时 协理特助," } }
+ $nextAssigner = substr($nextAssigners[0][1], 0, 5);
+ $currentFlow = new Flow($this->flowContext->getFormKey());
+ Flow::updateFlowCode($currentFlow->getParentKey(), $nextFlowCode);
+ Subflow::updateCurrentUser($currentFlow->getParentKey(), $nextAssigner);
+
+ }
+}
\ No newline at end of file
diff --git a/workflow/Handler/CounterSignTaskHandler.php b/workflow/Handler/CounterSignTaskHandler.php
new file mode 100644
index 00000000..94ebcf7c
--- /dev/null
+++ b/workflow/Handler/CounterSignTaskHandler.php
@@ -0,0 +1,115 @@
+currentNode = $node;
+ $this->flowContext = $Context;
+ $this->formData = $formData;
+ }
+
+
+ /**
+ * 1.从流程图中解析出下个节点的Code 更新
+ */
+ function doWork()
+ {
+ //1.获取表单数据中的split_members 为字符串 成员1,成员2,
+ $currentNode = $this->flowContext->getCurrentNode();
+ $assignClass = $currentNode->getAssignClass();
+
+ $currentAssigner = $this->flowContext->getCurrentUser();
+ $currentFormKey = $this->flowContext->getFormKey();
+ $this->flowContext->getCurrentNode()
+ ->setFlow($this->flowContext);
+ $this->flowContext->getCurrentNode()
+ ->setformData($this->formData);
+
+ if (!$currentNode->checkTrust($assignClass, Employee::lead_code($currentAssigner))) {
+ $handler = new FlowNodeHandler($this->currentNode, $this->flowContext, $this->formData);
+ $handler->doWork();
+ /// Subflow::updateCurrentUser($currentFormKey, $this->flowContext->nextAssigner);
+
+ return;
+ }
+ $splitMembers = explode(',', $this->formData['split_members']);
+ //2.遍历$splitMembers数组 ,对其调用,AssignerStringParser::process(),获取具体的签核人员
+ $nextAssigners = array();
+ $sm = new SubflowManager(new Flow($currentFormKey));
+ var_dump($splitMembers);
+
+ foreach ($splitMembers as $member) {
+ var_dump($member);
+ $nextAssigners = explode(
+ ',',
+ AssignerStringParser::process($member, $format = "employee_no", ",")
+ );
+ #生成待签
+ $seq = 0;
+ foreach ($nextAssigners as $assigner) {
+ if (empty($assigner)) continue;
+ $flowCode = $this->currentNode->getFLowCode();
+ $childFlow = new Flow();
+ $childFlow->setSystemId($this->flowContext->getSystemId())
+ ->setFormId($this->flowContext->getFormId())
+ ->setFlowId($this->flowContext->getFlowId())
+ ->setFlowCode($flowCode)
+ ->insert();
+ $subflow = new Subflow($childFlow);
+ $subflow->setCurrentUser($assigner)->insert();
+ $sm->append($subflow, $currentAssigner);
+ #生成任务1
+ $task = new NodeTask();
+ $task->setFormKey($childFlow->getFormKey())
+ ->setFlowCode($flowCode)
+ ->setState("OPEN")
+ ->setTaskType("COUNTER_SIGN_SUBTASK")
+ ->setNecessary('Y')
+ ->setPhase("SUBMIT")
+ ->setCreator($currentAssigner);
+ TaskManager::insertTask($task);
+ #生成任务1结束
+
+ #生成任务2
+ $task = new NodeTask();
+ $task->setFormKey($childFlow->getFormKey())
+ ->setFlowCode($flowCode)
+ ->setState("OPEN")
+ ->setTaskType("NEXT_ASSIGNER_MODIFY_TASK")
+ ->setNecessary('Y')
+ ->setWfCondition("NEXT")
+ ->setJoinRole("select code_name assign_status,
+ case code_name when 'F1' then '00000-回传申请单位'
+ when 'Y1' then '00000-回传申请单位' end assigner_string from code
+ where code_name in('Y1','F1') and field_name='assign_status'")
+ ->setRoleType("SQL")
+ ->setPhase("LOAD")
+ ->setCreator($currentAssigner);
+ TaskManager::insertTask($task);
+ #生成任务2结束 $_SERVER['HTTP_HOST']
+
+
+ }
+ }
+
+ $nextAssigner = $this->flowContext->nextAssigner;
+ #变更流程下位签核者
+ Subflow::updateCurrentUser($currentFormKey, $nextAssigner);
+ #挂起该流程
+ Subflow::suspend($currentFormKey);
+ }
+
+ private function processAssignStatusFH()
+ {
+ }
+
+ private function processAssignStatusX3()
+ {
+ }
+}
diff --git a/workflow/Handler/EndNodeHandler.php b/workflow/Handler/EndNodeHandler.php
new file mode 100644
index 00000000..7d1d3943
--- /dev/null
+++ b/workflow/Handler/EndNodeHandler.php
@@ -0,0 +1,37 @@
+currentNode=$node;
+ $this->flowContext=$Context;
+ $this->formData=$formData;
+ }
+ /**
+ * 根据传入FlowNode节点的中的Code 更新Flow表
+ */
+ function doWork(){
+
+ //作为一般流程节点处理
+ $handler=new FlowNodeHandler( $this->currentNode,$this->flowContext,$this->formData);
+ $handler->doWork();
+
+ #删除流程上的所有任务
+ $task = new NodeTask();
+ $task->setFormKey($this->flowContext->getFormKey());
+ $tasks = TaskManager::getTasks($task);
+ foreach ($tasks as $task) {
+ $taskCreator = $task->getCreator();
+ if ($taskCreator == $this->flowContext->getNextAssigner()) {
+ $task->delete();
+ }
+ }
+ // Flow::updateFlowCode( $this->flowContext->formKey,$this->currentNode->getFlowCode());
+
+ // Subflow::updateCurrentUser($this->flowContext->formKey,$this->flowContext->nextAssigner);
+
+ }
+
+}
\ No newline at end of file
diff --git a/workflow/Handler/FhTaskHandler.php b/workflow/Handler/FhTaskHandler.php
new file mode 100644
index 00000000..bb82d8b1
--- /dev/null
+++ b/workflow/Handler/FhTaskHandler.php
@@ -0,0 +1,31 @@
+parseRole();
+ $newNextAssigners = array();
+ foreach ($nextAssigners as $row) {
+ array_push($newNextAssigners, array(0 => $row['assign_status'], 1 => $row['assigner_string']));
+ }
+
+ return $newNextAssigners;
+ }
+}
\ No newline at end of file
diff --git a/workflow/Handler/FlowNodeHandler.php b/workflow/Handler/FlowNodeHandler.php
new file mode 100644
index 00000000..f5ec3c91
--- /dev/null
+++ b/workflow/Handler/FlowNodeHandler.php
@@ -0,0 +1,227 @@
+currentNode = $node;
+ $this->flowContext = $flowContext;
+ $this->formData = $formData;
+ }
+
+ /**
+ * 根据传入FlowNode节点的中的Code 更新Flow表
+ */
+ function doWork()
+ {
+ $this->flowContext->getCurrentNode()->setFlow($this->flowContext);
+ $this->flowContext->getCurrentNode()->setformData($this->formData);
+ $function = "processAssignStatus" . $this->flowContext->getAssignStatus();
+ // echo $function ;
+ if (!method_exists('FlowNodeHandler', $function)) {
+ echo self::processUndefined($function);
+ exit();
+ }
+ #调用对应的处理函数
+ $this->$function();
+ }
+
+ /**
+ *
+ *处理AssignStatus=F1 同意 流程进入下个节点
+ *
+ */
+ private function processAssignStatusF1()
+ {
+ $assignClass = $this->flowContext->getCurrentNode()->getAssignClass();
+
+ $currentAssigner = Subflow::getCurrentUser($this->flowContext->getFormKey());
+ $nextFlowCode = $this->currentNode->getFlowCode();
+ $formKey = $this->flowContext->getFormKey();
+ $currentFlowCode = $this->flowContext->getFlowCode();
+
+ #符合条件,变更流程码,否则停在当前环节
+ if ($this->flowContext->getCurrentNode()->checkTrust($assignClass, Employee::lead_code($currentAssigner))) {
+ #节点附加的任务
+ $task = new NodeTask();
+ $task->setFormKey($this->flowContext->formKey)
+ ->setFlowCode($currentFlowCode)
+ ->setState("OPEN")
+ ->setPhase("SUBMIT");
+ $tasks = TaskManager::getTasks($task);
+
+ if (count($tasks) > 0) {
+ foreach ($tasks as $task) {
+ $handlerClass = NodeTask::$handlerClasses[constant("NodeTask::" . $task->getTaskType())];
+ $handler = new $handlerClass($this->flowContext, $this->formData);
+ $handler->doWork();
+ }
+ }
+ Flow::updateFlowCode($formKey, $nextFlowCode);
+ #关闭当前节点上的所有任务
+ $task = new NodeTask();
+ $task->setFormKey($this->flowContext->getFormKey())
+ ->setFlowCode($currentFlowCode)
+ ->setState("OPEN");
+ $closeTasks = TaskManager::getTasks($task);
+ foreach ($closeTasks as $task) {
+ $task->delete();
+ }
+ }
+ Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner());
+ }
+
+ /**
+ * 申请人申请S
+ */
+ private function processAssignStatusS()
+ {
+ $this->processAssignStatusF1();
+ }
+
+ /***
+ * 转工程科处理
+ */
+ private function processAssignStatusGC()
+ {
+ $this->processAssignStatusF1();
+ }
+
+ /***
+ * 会签不同意
+ */
+ private function processAssignStatusY1()
+ {
+ $this->processAssignStatusF1();
+ }
+
+ /**
+ *处理AssignStatus=FH 指派 流程还停留在当前节点
+ * 在LOAD阶段需要添加一个任务,使得被指派人选择下位签核者时,既能呈核,也能指派
+ *
+ */
+ private function processAssignStatusFH()
+ {
+ #生成任务
+ // echo "processAssignStatusFH";
+ $currentAssigner = new Employee(Subflow::getCurrentUser($this->flowContext->getFormKey()));
+ $nextUser = new Employee($this->flowContext->getNextAssigner());
+ // var_dump( $this->flowContext->getFormKey());
+ $task = new NodeTask();
+ $task->setFormKey($this->flowContext->getFormKey())
+ ->setFlowCode($this->flowContext->getFlowCode())
+ ->setState("OPEN")
+ ->setTaskType("FH_TASK")
+ ->setNecessary('Y')
+ ->setPhase("LOAD")
+ ->setWfCondition("SAME")
+ ->setJoinRole("select 'F6' assign_status, concat(
+ '" . $currentAssigner->employee_no . "' , '-','" . $currentAssigner->name . "' ) assigner_string from dual
+ union select 'FH' assign_status,concat(employee_no,'-',name) assigner_string from employee where
+ depart_no like '" . rtrim($nextUser->depart_no, 0) . "%'
+ and employee_no!='" . $nextUser->employee_no . "'
+ and lead_code >'" . $nextUser->lead_code . "'")
+ ->setRoleType('SQL')
+ ->setCreator($currentAssigner->employee_no)
+ ->setCreateCode($this->flowContext->getFlowCode());
+ TaskManager::insertTask($task);
+
+
+ Subflow::updateCurrentUser($this->flowContext->getFormKey(), $this->flowContext->getNextAssigner());
+ }
+
+ /**
+ * 处理AssignStatus=F6 呈核 流程还停留在当前节点,如果下位签核者,是
+ */
+ private function processAssignStatusF6()
+ {
+ #生成任务
+ $task = new NodeTask();
+ $task->setFormKey($this->flowContext->getFormKey())
+ ->setFlowCode($this->flowContext->getCurrentNode()->getFlowCode())
+ ->setState("OPEN")
+ ->setTaskType("FH_TASK")
+ ->setPhase("LOAD");
+ $tasks = TaskManager::getTasks($task);
+ // var_dump($task);
+ foreach ($tasks as $task) {
+ $taskCreator = $task->getCreator();
+ // var_dump($this->flowContext->getNextAssigner() );
+ // var_dump($taskCreator);
+ if ($taskCreator == $this->flowContext->getNextAssigner()) {
+ $task->setState(NodeTask::TASK_FINISH_STATE)->update();
+ }
+ }
+ Subflow::updateCurrentUser($this->flowContext->getFormKey(), $this->flowContext->getNextAssigner());
+ }
+
+ /**
+ * 处理AssignStatus=B4 退回上一个节点
+ */
+ private function processAssignStatusB4()
+ {
+
+ $formKey = $this->flowContext->getFormKey();
+ $prevNodes = $this->flowContext->workFlowParser->getPrevLevelNodes(
+ $this->flowContext->getCurrentNode()->getNodeId(),
+ [Node::FLOW_NODE, Node::LOGIC_NODE]
+ );
+
+ foreach ($prevNodes as $key => $prevNode) {
+ $tmpNode = $prevNode[0];
+ $backFlowCode = $tmpNode->getFlowCode();
+
+ $backAssign = Assign::get_lastest_record($formKey, $backFlowCode);
+ if (empty($backFlowCode)) continue;
+ Flow::updateFlowCode($formKey, $backAssign['flow_code']);
+ }
+ Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner());
+ }
+
+ /**
+ * 处理AssignStatus=B7 退回申请人
+ */
+ private function processAssignStatusB7()
+ {
+
+ $formKey = $this->flowContext->getFormKey();
+
+
+ #删除当前节点上的所有任务
+ $task = new NodeTask();
+ $task->setFormKey($formKey)
+ ->setFlowCode($this->flowContext->getCurrentNode()->getFlowCode())
+ ->setState("OPEN");
+
+ $closeTasks = TaskManager::getTasks($task);
+ foreach ($closeTasks as $task) {
+ $task->setState(NodeTask::TASK_FINISH_STATE)->update();
+ }
+
+ $startNode = $this->flowContext->getWorkFLowParser()->getFirstNode();
+
+ Flow::updateFlowCode($formKey, $startNode->getFlowCode());
+ Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner());
+ }
+
+ private function processAssignStatusF4()
+ {
+ $formKey = $this->flowContext->getFormKey();
+ Flow::updateFlowCode($formKey, $this->currentNode->getFlowCode());
+ Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner());
+ }
+
+ /**
+ * 处理异常
+ * @param $function
+ * @return string
+ */
+ private function processUndefined($function)
+ {
+ return "调用的不存在方法" . $function;
+ }
+}
diff --git a/workflow/Handler/LogicNodeHandler.php b/workflow/Handler/LogicNodeHandler.php
new file mode 100644
index 00000000..b1ceaddb
--- /dev/null
+++ b/workflow/Handler/LogicNodeHandler.php
@@ -0,0 +1,76 @@
+currentNode = $node;
+ $this->flowContext = $Context;
+ $this->formData = $formData;
+ }
+
+ /**
+ * 判断传入的assignStatus,在下层节点中找出含有该assignStatus的节点
+ */
+ function doWork()
+ {
+
+ #停留在当前节点
+ if (
+ in_array($this->flowContext->assignStatus, AssignStatus::$same_level_status)
+ or in_array($this->flowContext->assignStatus, AssignStatus::$back_status)
+ ) {
+ $flowHandler = new FlowNodeHandler($this->currentNode, $this->flowContext, $this->formData);
+ $flowHandler->doWork();
+ return;
+ }
+ $formKey = $this->flowContext->getFormKey();
+ #检查是否有下节点是否定routeMethod
+ $routeMethod = $this->currentNode->getRouteMethod();
+ $nextFlowCode = "";
+ $assignClass = $this->flowContext->getCurrentNode()->getAssignClass();
+ if (!empty($routeMethod)) {
+ $nextFlowCode = $routeMethod->invokeMethod($this->flowContext, $this->formData);
+ } else {
+ #根据下层节点的assign_status 匹配
+
+ $workFlowParser = $this->flowContext->getWorkFLowParser();
+ //解析下层节点\WorkFlowParser::getNextLevelNodes
+ $nextFlowNodes = $workFlowParser->getNextLevelNodes($this->currentNode->getNodeId());
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nextFlowNodes)) continue;
+ foreach ($nextFlowNodes[$type] as $node) {
+ if (method_exists($node, 'getAssignerList')) {
+ $assigner = $node->getAssignerList($workFlowParser);
+ $assign_status = $assigner[0][0];
+ if ($assign_status == $this->flowContext->getAssignStatus()) {
+ $nextFlowCode = $node->getFlowCode();
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+
+ #当前签核者
+ $currentAssignerId = $this->flowContext->getCurrentUser();
+
+ if ($this->flowContext->currentNode->checkTrust($assignClass, Employee::lead_code($currentAssignerId))) {
+ Flow::updateFlowCode($formKey, $nextFlowCode);
+ }
+
+ Subflow::updateCurrentUser($formKey, $this->flowContext->getNextAssigner());
+ }
+}
diff --git a/workflow/Handler/MergeNodeHandler.php b/workflow/Handler/MergeNodeHandler.php
new file mode 100644
index 00000000..15f67361
--- /dev/null
+++ b/workflow/Handler/MergeNodeHandler.php
@@ -0,0 +1,108 @@
+currentNode = $node;
+ $this->flowContext = $Context;
+ }
+
+ /**
+ * 1.从流程图中解析出下个节点的Code 更新
+ */
+ function doWork()
+ {
+
+ $flow = new Flow($this->flowContext->getFormKey());
+
+ $sm = new SubflowManager(new Flow($flow->getParentKey()));
+ $flag = $this->flowContext->assignStatus == AssignStatus::ACCEPT_STATUS ? 'Y' : 'N';
+ SubflowManager::updateReplyFlag($flow->getFormKey(), $flag);
+
+ $unReplyCount = $sm->getUnReplyCount(SubflowManager::getSeqByFormKey($flow->getFormKey()));
+ if ($unReplyCount == 0) {
+ $mergeOption = $this->currentNode->getMergeOption();
+ $mergeOption = empty($mergeOption) ? self::DEFAULT_MERGE_OPTION : $mergeOption;
+ $function = "cond" . strtoupper($mergeOption);
+ $this->$function($sm);
+ Subflow::delete($flow->getFormKey());
+ }
+
+ /**
+ *遍历所有下层节点 ,执行对应Handler类doWork方法
+ */
+ }
+
+ /**
+ * 同意一个即可
+ * @param SubflowManager $sm
+ */
+ private function condOR(SubflowManager $sm)
+ {
+ $cnt = $sm->getAcceptOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ if ($cnt >= 1) {
+ $this->nextAssign();
+ } else {
+ $this->backAssign();
+ }
+ }
+
+ /**
+ * 全部同意
+ * @param SubflowManager $sm
+ */
+ private function condAND(SubflowManager $sm)
+ {
+ $cnt = $sm->getRejectOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ if ($cnt == 0) {
+ $this->nextAssign();
+ } else {
+ $this->backAssign();
+ }
+ }
+
+ /**
+ *同意的占多数
+ * @param SubflowManager $sm
+ */
+ private function condVOTE(SubflowManager $sm)
+ {
+ $reject = $sm->getRejectOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ $accept = $sm->getAcceptOpinionCount(SubflowManager::getSeqByFormKey($this->flowContext->formKey));
+ if ($accept >= $reject) {
+ $this->nextAssign();
+ } else {
+ $this->backAssign();
+ }
+ }
+
+ private function backAssign()
+ {
+ $code = SubflowManager::getCurrentParentFlowCode($this->flowContext->formKey);
+ $node = $this->flowContext->workFlowParser->getNodeByCode($code);
+ $handleClass = get_class($node) . "Handler";
+ $obj = new $handleClass($node, $this->flowContext, $this->formData);
+ $obj->doWork();
+ }
+
+ private function nextAssign()
+ {
+ $nextAssigner = $this->flowContext->nextAssigner;
+ $nextFlowNodes = $this->flowContext->workFlowParser->getNextLevelNodes($this->currentNode->getNodeId());
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nextFlowNodes)) continue;
+ foreach ($nextFlowNodes[$type] as $node) {
+ $nextFlowCode = $node->getFlowCode();
+ break 2;
+ }
+ }
+ $currentFlow = new Flow($this->flowContext->formKey);
+ Flow::updateFlowCode($currentFlow->getParentKey(), $nextFlowCode);
+ // Subflow::updateCurrentUser($currentFlow->getParentKey(), $nextAssigner);
+ }
+}
diff --git a/workflow/Handler/NextAssignerModifyTaskHandler.php b/workflow/Handler/NextAssignerModifyTaskHandler.php
new file mode 100644
index 00000000..fc8a0eea
--- /dev/null
+++ b/workflow/Handler/NextAssignerModifyTaskHandler.php
@@ -0,0 +1,52 @@
+parseRole();
+ $newNextAssigners = array();
+ foreach ($nextAssigners as $row) {
+ array_push($newNextAssigners, array(0 => $row['assign_status'], 1 => $row['assigner_string']));
+ }
+
+ return $newNextAssigners;
+
+ }
+ /* public function setNextAssignerList(array $assigners, NodeTask $task)
+ {
+ $nextAssigners = $task->parseRole();
+ foreach ($nextAssigners as $row) {
+
+ foreach ($assigners as $key => $assigner) {
+
+ if ($assigners[$key][0] == $row['assign_status']) {
+ $assigners[$key][1] = $row['assigner_string'];
+ } else {
+ array_push($assigners, array(0 => $row['assign_status'], 1 => $row['assigner_string']));
+ }
+
+ }
+
+ }
+
+ return $assigners;
+ }*/
+}
\ No newline at end of file
diff --git a/workflow/Handler/SplitNodeHandler.php b/workflow/Handler/SplitNodeHandler.php
new file mode 100644
index 00000000..ec7d619e
--- /dev/null
+++ b/workflow/Handler/SplitNodeHandler.php
@@ -0,0 +1,58 @@
+currentNode = $node;
+ $this->flowContext = $flowContext;
+ }
+
+ /**
+ * 1.从流程图中解析出下个节点的Code 更新
+ *$assigners 数组结构: array(1) { [0]=> array(2) { [0]=> string(2) "F1" [1]=> string(15) "73502-包 博," } }
+ */
+ function doWork()
+ {
+
+ //解析下层节点\WorkFlowParser::getNextLevelNodes
+ $nextFlowNodes = $this->flowContext->getWorkFLowParser()
+ ->getNextLevelNodes($this->currentNode->getNodeId());
+ $sm = new SubflowManager(new Flow($this->flowContext->getFormKey()));
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nextFlowNodes)) continue;
+ $seq = 0;
+ foreach ($nextFlowNodes[$type] as $node) {
+ if (method_exists($node, 'getAssignerList')) {
+ $assigners = $node->getAssignerList($this->flowContext->getWorkFLowParser());
+ $tmp = (array)(explode('-', $assigners[0][1]));
+ $emp = $tmp[0];
+ $nextFlowCode = $node->getFlowCode();
+ $childFlow = new Flow();
+ $childFlow->setSystemId($this->flowContext->systemId)
+ ->setFlowId($this->flowContext->flowId)
+ ->setFormId($this->flowContext->formId)
+ ->setFlowCode($nextFlowCode)
+ ->insert();
+ $subflow = new Subflow($childFlow);
+ $subflow->setCurrentUser($emp)->insert();
+ $sm->append($subflow, $this->flowContext->getCurrentUser());
+
+ echo "会签 " . $seq++ . ":查看下笔链接" . "
";
+ }
+ }
+ }
+ $nextAssigner = $this->flowContext->getNextAssigner();
+ $currentFlow = new Flow($this->flowContext->getFormKey());
+ Subflow::updateCurrentUser($currentFlow->getParentKey(), $nextAssigner);
+ //exit();
+
+ /**
+ *遍历所有下层节点 ,执行对应Handler类doWork方法
+ */
+ }
+}
diff --git a/workflow/Handler/StartNodeHandler.php b/workflow/Handler/StartNodeHandler.php
new file mode 100644
index 00000000..d7efb6f7
--- /dev/null
+++ b/workflow/Handler/StartNodeHandler.php
@@ -0,0 +1,28 @@
+currentNode = $node;
+ $this->flowContext = $Context;
+ }
+
+ /**
+ * 根据传入FlowNode节点的中的Code 更新Flow表
+ */
+ function doWork()
+ {
+ # echo " StartNodeHandler 31:".$this->flowContext->getFormKey();
+ $flow = new Flow ($this->flowContext->getFormKey());
+ $flow->setFlowCode($this->currentNode->getFlowCode())->save();
+ $subflow = new Subflow($flow);
+ $subflow->setCurrentUser($this->flowContext->getNextAssigner())->insert();
+
+ }
+
+}
\ No newline at end of file
diff --git a/workflow/WorkFlow.php b/workflow/WorkFlow.php
new file mode 100644
index 00000000..7ef6f0bd
--- /dev/null
+++ b/workflow/WorkFlow.php
@@ -0,0 +1,445 @@
+log = new Logger(dirname(__FILE__) . "/"
+ . (self::$logPath), Logger::DEBUG);
+
+ $this->systemId = $systemId;
+ $this->flowId = $flowId;
+ $this->formId = $formId;
+
+ $this->currentFlow = new Flow($formKey);
+
+ $_parentKey = $this->currentFlow->getParentKey();
+ //当流程不是处 于会签和子流程状态时 $mainFlow 和 $currentFlow是一个对象
+ $this->mainFlow = ($_parentKey == null or empty($_parentKey))
+ ? $this->currentFlow : new Flow($_parentKey);
+ $this->workFlowParser = new WorkFlowParser($systemId, $flowId);
+ $this->flowContext = new FlowContext();
+ # var_dump( $this->flowContext);
+ // echo " WorkFLow 31:".$this->currentFlow->getFormKey();
+
+ $this->flowContext->setFormKey($this->currentFlow->getFormKey())
+ ->setSystemId($this->systemId)
+ ->setFlowId($this->flowId)
+ ->setFormId($this->formId)
+ ->setWorkFLowParser($this->workFlowParser);
+
+ $_SESSION['flowContext'] = serialize($this->flowContext);
+ // var_dump($this);
+ }
+
+ /**
+ *
+ * @param $userId 流程初始化人员
+ */
+ public function initWorkFlow($userId)
+ { //var_dump($this->formId);
+
+ // var_dump($this);
+ $this->currentFlow->setSystemId($this->systemId)
+ ->setFlowId($this->flowId)
+ ->setFormId($this->formId)
+ ->setFlowCode($this->getFirstFlowCode())
+ ->save();
+ // var_dump($userId);
+ $this->flowContext->setNextAssigner($userId)
+ ->setAssignStatus('S');
+
+ $start = new StartNodeHandler($this->workFlowParser->getFirstNode(), $this->flowContext, $this->formData);
+ // var_dump( $this->flowContext);
+ #执行开始节点预置的操作
+ $start->doWork();
+ #写入日志
+ // $this->log->logInfo("$userId 启动了流程 system:'" . $this->systemId . ";flow:" . $this->formId);
+ }
+
+ /**
+ * 设置多个签核接受人员
+ * @param array $members
+ */
+ function setSplitMembers($members = array())
+ {
+ }
+
+ /**
+ *1.先检查是否满足签核下
+ */
+ public function submit()
+ {
+ #获取FlowContext的值
+ $nextAssigner = $this->flowContext->getNextAssigner();
+ $assignStatus = $this->flowContext->getAssignStatus();
+ $assignOpinion = $this->flowContext->getAssignOpinion();
+ #获取所有下层Node数组
+ $nodes = $this->workFlowParser
+ ->getNextNodes($this->currentFlow->getFlowCode());
+ #设置当前节点数据
+ $this->flowContext->setCurrentNode($this->workFlowParser
+ ->getNodeByCode($this->currentFlow->getFlowCode()));
+ #设置要传入 Handler实例的Context 实例
+
+ $this->flowContext->getCurrentNode()->setFlow($this->flowContext)
+ ->setformData($this->formData);
+ // $this->flowContext->getCurrentNode()->setformData($this->formData);
+
+ $asg = new Assign($this->currentFlow->getFormKey());
+ if (
+ $this->flowContext->getCurrentNode()->getType() == 'start_node'
+ and $asg->getSeq() == '0'
+ ) {
+ $this->flowContext->setAssignStatus('S');
+ }
+ //var_dump(Subflow::getCurrentUser($this->currentFlow->getFormKey()));
+ $asg->setAssigner(Subflow::getCurrentUser($this->currentFlow->getFormKey()))
+ ->setAssignStatus($this->flowContext->getAssignStatus())
+ ->setAssignOpinion($assignOpinion)
+ ->setFlowCode($this->currentFlow->getFlowCode())
+ ->setFlowCodeSeq(0)->insert();
+
+ #记录日志
+ $_log_array = array(
+ "nextAssigner" => $nextAssigner,
+ "assignStatus" => $assignStatus,
+ "nextAssigner" => $nextAssigner,
+ "currentAssigner" => Subflow::getCurrentUser($this->currentFlow->getFormKey()),
+ "flow_code" => $this->currentFlow->getFlowCode()
+ );
+ $this->log->logInfo("" . ID . " 提交了流程 system:'" . $this->systemId . ";flow:" . $this->flowId, $_log_array);
+
+ #插入assign表信息
+
+ $_SESSION['flowContext'] = serialize($this->flowContext);
+ // var_dump($nodes);
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nodes)) continue;
+ foreach ($nodes[$type] as $node) {
+ $handleClass = get_class($node) . "Handler";
+ $obj = new $handleClass($node, $this->flowContext, $this->formData);
+ $obj->doWork();
+ }
+ }
+ }
+
+ /*
+ *获取签核人员列表
+ */
+ public function getAssignerList()
+ {
+ $currentNode = $this->workFlowParser
+ ->getNodeByCode($this->currentFlow->getFlowCode());
+ #获取当前签核者
+ $currentFormKey = $this->currentFlow->getFormKey();
+ $currentAssigner = Subflow::getCurrentUser($currentFormKey);
+ #读取签核类别 A是专人的签核
+
+ #遍历下层节点读取下层节点的签核人员
+ $currentNode->setFlow($this->flowContext)
+ ->setFormData($this->formData);
+ $assignClass = $currentNode->getAssignClass();
+
+ if ($currentNode->checkTrust($assignClass, Employee::lead_code($currentAssigner))) {
+
+ #获取所有下层Node数组,并遍历,调用其中getAssignerList 方法
+ $nodes = $this->workFlowParser->getNextNodes($this->currentFlow->getFlowCode());
+ // var_dump($nodes);
+
+ $assigner = array();
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nodes)) continue;
+ foreach ($nodes[$type] as $node) {
+ if (method_exists($node, 'getAssignerList')) {
+ $assigner = array_merge(
+ (array)$assigner,
+ $node->getAssignerList($this->workFlowParser)
+ );
+ }
+ }
+ }
+
+ #检查退回选项
+ $backOption = $currentNode->getBackOption();
+ //B4 退回上一个节点
+ if ($backOption == 'B4') {
+ $prevNodes = $this->flowContext->workFlowParser->getPrevLevelNodes(
+ $currentNode->getNodeId(),
+ [Node::FLOW_NODE, Node::LOGIC_NODE]
+ );
+ foreach ($prevNodes as $key => $prevNode) {
+ $tmpNode = $prevNode[0];
+ $backAssign = Assign::get_lastest_record($currentFormKey, $tmpNode->getFlowCode());
+ $backUser = $backAssign['assigner'];
+ if (empty($backUser)) continue;
+ $nextAssignerStr = "";
+ $nextAssignerStr .= Employee::get_employee($backUser, $format = "employee_no-name") . ',';
+ array_push($assigner, array(0 => 'B4', 1 => $nextAssignerStr));
+ }
+ }
+ #B7 退回申请人
+ if ($backOption == 'B7') {
+ $assign = Assign::get_records($currentFormKey, true, '%', 'S');
+ // var_dump($assign);
+ $applicant = $assign[0]['assigner'];
+ $nextAssignerStr = "";
+ $nextAssignerStr .= Employee::get_employee($applicant, $format = "employee_no-name") . ',';
+ array_push($assigner, array(0 => 'B7', 1 => $nextAssignerStr));
+ }
+
+ #获取任务节点,查看是否有修改签核者的的任务
+ $task = new NodeTask();
+ $task->setFormKey($this->currentFlow->getFormKey())
+ ->setFlowCode($this->currentFlow->getFlowCode())
+ ->setState("OPEN")
+ ->setPhase("LOAD");
+ $tasks = TaskManager::getTasks($task);
+ if (count($tasks) > 0) {
+ foreach ($tasks as $task) {
+ $handlerClass = NodeTask::$handlerClasses[constant("NodeTask::" . $task->getTaskType())];
+ $handler = new $handlerClass($this->flowContext, $this->formData);
+ if (method_exists($handler, 'setNextAssignerList')) {
+
+ $assigner = $handler->setNextAssignerList($assigner, $task);
+ }
+ }
+ }
+
+ #也可以指派给自己的下属
+ $subordinates = Employee::subordinates($currentAssigner);
+ if (count($subordinates) > 0) {
+ $nextAssignerStr = "";
+ foreach ($subordinates as $emp) {
+ $nextAssignerStr .= Employee::get_employee($emp, $format = "employee_no-name") . ',';
+ }
+ array_push($assigner, array(0 => 'FH', 1 => $nextAssignerStr));
+ }
+
+ $nextAssigner = $assigner;
+ } else {
+ #需要签给上级领导审
+ $nextAssigner = $currentNode->getDepartmentalAssignerList($currentAssigner);
+ # 获取任务节点,查看是否有修改签核者的的任务
+ $task = new NodeTask();
+ $task->setFormKey($this->currentFlow->getFormKey())
+ ->setFlowCode($this->currentFlow->getFlowCode())
+ ->setState("OPEN")
+ ->setPhase("LOAD")
+ ->setWfCondition('SAME');
+ $tasks = TaskManager::getTasks($task);
+ if (count($tasks) > 0) {
+ foreach ($tasks as $task) {
+ $handlerClass = NodeTask::$handlerClasses[constant("NodeTask::" . $task->getTaskType())];
+ $handler = new $handlerClass($this->flowContext, $this->formData);
+ if (method_exists($handler, 'setNextAssignerList')) {
+ $nextAssigner = $handler->setNextAssignerList($nextAssigner, $task);
+ }
+ }
+ }
+ }
+
+ $this->nextAssignList = $nextAssigner;
+
+ return $nextAssigner;
+ }
+
+ /**
+ *提交前测试表单数据是否满足表达提交条件
+ * 1.检测FlowContext对象的以下属性,为空不可提交
+ */
+ public function submitTest()
+ {
+ $errorArray = array();
+ #1.检查FlowContext的属性是否都被设置
+ $flowContextRequiredProperty = array(
+ "systemId", "flowId", "formId", "currentAssigner", "flowCode", "nextAssigner", "assignStatus", "assignOpinion", "formKey"
+ );
+ foreach ($this->flowContext as $key => $value) {
+ if (in_array($key, $flowContextRequiredProperty) and empty($value)) {
+ array_push($errorArray, "FlowContext:" . $key . " 属性异常. Value:" . $value);
+ }
+ }
+ #2. 当前登陆人员与Sublfow:Current_user 不符合时,不允许提交
+
+ $currentAssignerId = $this->flowContext->getCurrentUser();
+ if (!empty($currentAssignerId) and ID == $currentAssignerId) {
+ array_push($errorArray, "签核已提交,请勿重复操作.");
+ }
+ return $errorArray;
+ }
+
+ /**
+ *返回assignStatus
+ * @param $nextAssigner
+ * @return string
+ */
+ public function getAssignStatus($nextAssigner)
+ {
+
+ $htmlOption = "''";
+ foreach ($nextAssigner as $assigner) {
+
+ $htmlOption .= "";
+ }
+
+ return $htmlOption;
+ }
+
+ /**
+ *获取会签部门
+ * @param null $flowCode 当前流程的流程码
+ * @return array
+ */
+ public function getCounterSignDepart($flowCode = null)
+ {
+ $flowCode = empty($flowCode) ? $this->flowContext->getFlowCode() : $flowCode;
+ /* TODO 从会签节点读取配置的会签属性,并返回成员数组*/
+ return null;
+ }
+
+ /**
+ * 是否允许拆分
+ * @return bool
+ */
+ public function isSplitable()
+ {
+ $nodes = $this->workFlowParser->getNextNodes(
+ $this->currentFlow->getFlowCode(),
+ [Node::COUNTER_SIGN_TASK]
+ );
+ if (count($nodes) == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ *1.检查下个节点的类型,为Split节点时 ,返回Split节点下各层节点人员
+ */
+ public function getSubflowMembers()
+ {
+ $nodes = $this->workFlowParser->getNextNodes(
+ $this->currentFlow->getFlowCode(),
+ [Node::SPLIT_NODE]
+ );
+ if (count($nodes) == 0) {
+ return null;
+ }
+ $splitNode = $nodes[Node::SPLIT_NODE][0];
+ $assigner = $splitNode->getSplitMembers($this->workFlowParser);
+ return $assigner;
+ }
+
+ /**
+ * 获取第一个流程节点
+ * @return mixed
+ */
+ public function getFirstFlowCode()
+ {
+
+ $node = $this->workFlowParser->getFirstNode();
+ return $node->getFlowCode();
+ }
+
+ /**
+ * 获取流程的名称
+ * @return mixed
+ */
+ public function getFlowName()
+ {
+ $flowInfo = $this->workFlowParser->getFlowInfo();
+ return $flowInfo['flowName'];
+ }
+
+ /**
+ *获取流程版本
+ */
+ function getFlowVersion()
+ {
+ $flowInfo = $this->workFlowParser->getFlowInfo();
+ return $flowInfo['version'];
+ }
+
+ /**
+ * 获取流程需要的调单数据
+ * @return mixed
+ */
+ public function getFormData()
+ {
+ return $this->formData;
+ }
+
+ /**
+ * 设置表单里面的值
+ * @param mixed $formData
+ */
+ public function setFormData($formData)
+ {
+ $this->formData = $formData;
+ $nextUser = empty($formData['next_users']) ? "" : $formData['next_users'];
+ $assignStatus = empty($formData['assign_status']) ? "" : $formData['assign_status'];
+ $assignOpinion = empty($formData['assign_opinion']) ? "" : $formData['assign_opinion'];
+ $currentAssignerId = empty($formData['current_assigner']) ? ID : $formData['current_assigner'];
+ $this->flowContext->setAssignOpinion($assignOpinion)
+ ->setNextAssigner($nextUser)
+ ->setAssignStatus($assignStatus)
+ ->setFormKey($this->currentFlow->getFormKey())
+ ->setFlowCode($this->currentFlow->getFlowCode())
+ ->setCurrentUser($currentAssignerId);
+ }
+
+ /**
+ * 获取节点的
+ * @param $flowCode
+ * @return String
+ */
+ public function getNodeDescriptions($flowCode)
+ {
+ $node = $this->workFlowParser->getNodeByCode($flowCode);
+ return $node->getNodeDescription();
+ }
+
+ /**
+ * 获取节点的节点
+ * @param $flowCode
+ * @return String
+ */
+ public function getCurrentNode($flowCode = null)
+ {
+ $flowCode = empty($flowCode) ? $this->currentFlow->getFlowCode() : $flowCode;
+ $node = $this->workFlowParser->getNodeByCode($flowCode);
+ return $node;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTester()
+ {
+ return $this->tester;
+ }
+
+ /**
+ * @param mixed $tester
+ */
+ public function setTester($tester)
+ {
+ $this->tester = $tester;
+ }
+}
diff --git a/workflow/WorkFlowParser.php b/workflow/WorkFlowParser.php
new file mode 100644
index 00000000..93e3007e
--- /dev/null
+++ b/workflow/WorkFlowParser.php
@@ -0,0 +1,464 @@
+flowList = $flowchart['flowList'];
+ $this->flowInfo = array(
+ 'flowName' => $flowchart['flowName'],
+ 'systemId' => $flowchart['systemId'],
+ 'flowId' => $flowchart['flowId'],
+ 'version' => $flowchart['version']
+ );
+ foreach ($this->flowList as $key => $val) {
+
+ $this->edgeTo[$key] = 0;
+ $this->traversalMark[$key] = false;
+ }
+ }
+
+ /**
+ * 获取第一个节点
+ */
+ public function getFirstNode()
+ {
+ $firstNodeId = $this->_getFirstNodeId();
+ if (empty($firstNodeId)) {
+ return null;
+ }
+ $nodeClass = Node::$nodeClasses[strtoupper($this->flowList[$firstNodeId]['nodeType'])];
+ return new $nodeClass($this->flowList[$firstNodeId]);
+ }
+
+ /**
+ *
+ */
+ private function _getFirstNodeId()
+ {
+ if (empty($this->flowList)) {
+ return null;
+ }
+ foreach ($this->flowList as $domId => $node) {
+ if (substr($domId, 0, 5) == 'start') {
+
+ return $domId;
+ }
+ }
+ }
+
+ /***
+ * 获取某节点的父节点数组
+ *
+ *
+ */
+ function getParentNodes($nodeId)
+ {
+ $_nodes = array();
+ if (empty($this->flowList)) {
+ return $_nodes;
+ }
+ foreach ($this->flowList as $domId => $node) {
+ if (in_array($node['targetId'], $nodeId)) {
+ array_push($_nodes, $this->getNode($node));
+ }
+ }
+ return $_nodes;
+ }
+
+ /**
+ * 获取前一层所有节点
+ * @param String nodeId 节点ID
+ * @param String nodeType 节点类型
+ * @return Array [TASK_NODE=>['',.....],
+ * LOGIC_NODE=>['',.....],
+ * SPLIT_NODE=>['',.....]
+ * ]
+ */
+ public function getPrevLevelNodes($nodeId, $nodeType = Node::ALL_NODE)
+ {
+ $_nodes = array();
+ if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) {
+ return $_nodes;
+ }
+ foreach ($this->flowList as $domId => $node) {
+ //如果表中节点的目标节点中包含参数节点
+ if (in_array($nodeId, $node['targetId'])) {
+ //获取节点类型
+ $currentNodeType = array_search(ucfirst($node['nodeType']), Node::$nodeClasses);
+ foreach (Node::$nodeTypes as $types) {
+ //如果匹配到上层有匹配的节点
+ if (($currentNodeType == ($nodeType & $types))) {
+ $_nodes[$currentNodeType][] = $this->getNode($node);
+ }
+ }
+ }
+ }
+ return $_nodes;
+ }
+
+ /**
+ * 获取同一层的所有节点
+ * @param String nodeId 节点ID
+ * @param String nodeType 节点类型
+ * @return Array [TASK_NODE=>['',.....],
+ * LOGIC_NODE=>['',.....],
+ * SPLIT_NODE=>['',.....]
+ * ]
+ */
+ private function getSameLevelNodes($nodeId, $nodeType = Node::ALL_NODE)
+ {
+ $_nodes = array();
+ if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) {
+ return _nodes;
+ }
+ $_parentNodes = $this->getPrevLevelNodes($nodeId, $nodeType);
+ if (count($_parentNodes) == 0) {
+ return $_nodes;
+ }
+ //如果有多个父节点,说明当前这层只有一个节点
+ if (count($_parentNodes) >= 2) {
+ $currentNodeType = array_search(
+ ucfirst($this->flowList[$nodeId]['nodeType']),
+ Node::$nodeClasses
+ );
+ foreach (Node::$nodeTypes as $types) {
+ if (($currentNodeType == ($nodeType & $types))) {
+ $_nodes[$currentNodeType][] = $this->getNode($this->flowList[$nodeId]);
+ }
+ }
+ return $_nodes;
+ }
+ //如果只有一个父节点,遍历该父节点的所有节点
+ $pNode = $_parentNodes[0];
+ return $this->getNextLevelNodes($pNode->getNodeId(), $nodeType);
+ }
+
+ /**
+ * 获取下一层的所有节点
+ * @param String nodeId 节点ID
+ * @param String nodeType 节点类型
+ * @return Array [TASK_NODE=>['',.....],
+ * LOGIC_NODE=>['',.....],
+ * SPLIT_NODE=>['',.....]
+ * ]
+ */
+ public function getNextLevelNodes($nodeId, $nodeType = Node::ALL_NODE)
+ {
+
+ if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) {
+ return null;
+ }
+
+ $_nodes = array();
+ $nextLevelIDs = $this->flowList[$nodeId]["targetId"];
+
+ foreach ($nextLevelIDs as $nextId) {
+ $currentNodeType = array_search(
+ strtoupper($this->flowList[$nextId]['nodeType']),
+ Node::$nodeTypes
+ );
+ // echo " nextId :" . var_dump( $currentNodeType);
+ // var_dump(strtoupper ($this->flowList[$nextId]['nodeType']));
+ // var_dump($currentNodeType);
+ $nodeType = is_array($nodeType) ? $nodeType : [$nodeType];
+ if ($currentNodeType && in_array(strtoupper(Node::$nodeTypes[$currentNodeType]), $nodeType)) {
+ $_nodes[strtoupper(Node::$nodeTypes[$currentNodeType])][] = $this->getNode($this->flowList[$nextId]);
+ }
+ }
+
+ return $_nodes;
+ }
+
+ /**
+ * @param String code 节点flowCode
+ * @param String nodeType 节点类型
+ * @return Array [TASK_NODE=>['',.....],
+ * LOGIC_NODE=>['',.....],
+ * SPLIT_NODE=>['',.....]
+ * ]
+ */
+ function getNextNodes($code, $nodeType = Node::ALL_NODE)
+ {
+
+ $node = $this->getNodeByCode($code);
+ // var_dump($node);
+ // var_dump($this->getNextLevelNodes($node->getNodeId(), $nodeType));
+ return $this->getNextLevelNodes($node->getNodeId(), $nodeType);
+ }
+
+ /**
+ * 获取最后节点,如果nodeId不未 空,则获取nodeId所在流程的所有结案节点
+ * @param String nodeId
+ * @return Array 结案节点的集合
+ */
+ function getFinalCodes()
+ {
+ $arrNode = array();
+ if (empty($this->flowList)) {
+ return null;
+ }
+ foreach ($this->flowList as $domId => $node) {
+ if (substr($domId, 0, 3) == 'end') {
+ array_push($arrNode, $node['flowCode']);
+ }
+ }
+ return $arrNode;
+ }
+
+ public function getNodeIdByCode($code)
+ {
+ $node = $this->getNodeByCode($code);
+ if (!empty($node)) {
+ return $node->getNodeId();
+ }
+ return null;
+ }
+
+ /***
+ * 根据nodeId 获取Code
+ *
+ * @param $nodeId
+ * @return null|*Node
+ */
+ public function getNodeCodeByKey($nodeId)
+ {
+ if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) {
+ return null;
+ }
+ return $this->flowList[$nodeId]['flowCode'];
+ }
+
+ private function loadGraphByJson()
+ {
+ }
+
+ /**
+ * 根据nodeId获取对应的节点
+ * @param $node
+ * @return mixed
+ */
+ public function getNode($node)
+ {
+ try {
+ // var_dump($node);
+ // var_dump($node['nodeType']);
+ $_nodeClass = Node::$nodeClasses[strtoupper($node['nodeType'])];
+ // var_dump(strtoupper(Node::$nodeClasses[$node['nodeType']]));
+ return new $_nodeClass($node);
+ // exit();
+ } catch (Exception $exception) {
+ // var_dump(strtoupper(Node::$nodeClasses[$node['nodeType']]));
+ echo $exception->getMessage();
+ }
+ }
+
+ /***
+ *根据Key值获取节点对象
+ * @param $nodeId
+ * @return mixed|null
+ */
+ public function getNodeByNodeId($nodeId)
+ {
+ if (empty($this->flowList) || !array_key_exists($nodeId, $this->flowList)) {
+ return null;
+ }
+ $_node = $this->flowList[$nodeId];
+ return $this->getNode($_node);
+ }
+
+ /***
+ *根据Code值获取节点对象
+ * @param $code
+ * @return mixed|null
+ */
+ public function getNodeByCode($code)
+ {
+ if (empty($this->flowList)) {
+ return null;
+ }
+ foreach ($this->flowList as $domId => $node) {
+ if (array_key_exists('flowCode', $node) and $node['flowCode'] == $code) {
+
+ return $this->getNodeByNodeId($node['nodeId']);
+ }
+ }
+ return null;
+ }
+
+ public function getAllNode($nodeType = Node::ALL_NODE)
+ {
+ if (empty($this->flowList)) {
+
+ return null;
+ }
+ $_nodes = array();
+ foreach ($this->flowList as $domId => $node) {
+ $currentNodeType = array_search(
+ strtoupper($node['nodeType']),
+ Node::$nodeClasses
+ );
+ // var_dump($currentNodeType);
+ if ($currentNodeType && !empty($currentNodeType)) {
+
+ $_nodes[Node::$nodeTypes[strtoupper($currentNodeType)]][] = $this->getNode($node);
+ }
+ }
+ return $_nodes;
+ }
+
+ /**
+ * 获取流程的信息
+ * @return array
+ */
+ public function getFlowInfo()
+ {
+
+ return $this->flowInfo;
+ }
+
+
+ /**
+ * 获取两个节点之间的最短 长度
+ * @param null $targetId
+ * @param null $sourceId
+ * @return array|null
+ */
+ public function getMinLengthBetweenNode($targetId = null, $sourceId = null)
+ {
+
+ if (empty($targetId)) return null;
+
+ $this->sourceId = (empty($sourceId) ? $this->_getFirstNodeId() : $sourceId);
+
+ $this->BreadthFirstSearchPaths();
+
+ return $this->pathTo($targetId);
+ }
+
+ /**
+ * 使用深度优先获取路径
+ */
+
+ function DepthFirstSearchPaths()
+ {
+ //重置计数
+ $this->traversalMark = array();
+ $this->count = 0;
+ foreach ($this->flowList as $key => $val) {
+ $this->traversalMark[$key] = false;
+ $this->edgeTo[$key] = 0;
+ }
+ $_id = empty($this->sourceId) ? $this->_getFirstNodeId() : $this->sourceId; //$edgeTo
+ $this->dfs($_id);
+ }
+
+ /**
+ * 使用广度优先获取路径
+ */
+ function BreadthFirstSearchPaths()
+ {
+ //重置计数
+ $this->traversalMark = array();
+ $this->count = 0;
+ foreach ($this->flowList as $key => $val) {
+ $this->traversalMark[$key] = false;
+ $this->edgeTo[$key] = 0;
+ }
+ $_id = empty($this->sourceId) ? $this->_getFirstNodeId() : $this->sourceId; //$edgeTo
+ $this->bfs($_id);
+ }
+
+ /**
+ * 深度优先遍历
+ * @param $v
+ */
+
+ private function dfs($v)
+ {
+ $this->count++;
+
+ $this->traversalMark[$v] = true;
+ $target = $this->flowList[$v]["targetId"];
+
+ foreach ($target as $_id) {
+
+ if (empty($this->traversalMark[$_id])) {
+ $this->edgeTo[$_id] = $v;
+ $this->dfs($_id);
+ }
+ }
+ }
+
+ /**
+ * 广度优先遍历
+ */
+ private function bfs($v)
+ {
+ $queue = array();
+ array_push($queue, $v);
+ $this->traversalMark[$v] = true;
+ while (count($queue) > 0) {
+ $_id = array_shift($queue);
+ $target = $this->flowList[$_id]["targetId"];
+ foreach ($target as $n_id) {
+ if (empty($this->traversalMark[$n_id])) {
+
+ $this->edgeTo[$n_id] = $_id;
+ $this->traversalMark[$n_id] = true;
+ array_push($queue, $n_id);
+ }
+ }
+ }
+ }
+
+ /**
+ * 判断是否有路径
+ * @param $v
+ * @return mixed
+ */
+ private function hasPathTo($v)
+ {
+ return $this->traversalMark[$v];
+ }
+
+ function pathTo($v)
+ {
+ if (!$this->hasPathTo($v)) {
+ return array();
+ }
+ $stack = array();
+ try {
+
+ for ($x = $v; $x != $this->sourceId; $x = $this->edgeTo[$x]) {
+ array_push($stack, $x);
+ }
+ } catch (Exception $exception) {
+ echo $exception->getMessage();
+ }
+
+ // array_push($stack, $this->sourceId);
+ return $stack;
+ }
+}
diff --git a/workflow/impl/CommonFlowNode.php b/workflow/impl/CommonFlowNode.php
new file mode 100644
index 00000000..30e9b631
--- /dev/null
+++ b/workflow/impl/CommonFlowNode.php
@@ -0,0 +1,157 @@
+nodeProperty['flowCode'];
+ }
+
+ /**
+ * 获取节点内设置的签核人员列表
+ * @return mixed
+ */
+ public function getAssigner()
+ {
+ return $this->nodeProperty['assigner'];
+ }
+
+ /**
+ * 获取代理人设置
+ * @return mixed
+ */
+ public function getAgentSetting()
+ {
+ return $this->nodeProperty['agentSetting'];
+ }
+
+ /**
+ * 获取签核类别
+ * @return mixed
+ */
+ public function getAssignClass()
+ {
+ return $this->nodeProperty['assignClass'];
+ }
+
+ public function getAssignClassMethod()
+ {
+ return $this->nodeProperty['assignClassMethod'];
+ }
+
+ /**
+ * 获取退回选项
+ * @return mixed
+ */
+ public function getBackOption()
+ {
+ return $this->nodeProperty['backOption'];
+ }
+
+ /**
+ * 获取流程实例
+ * @return mixed
+ */
+ public function getFlow()
+ {
+ return $this->flow;
+ }
+
+ /**
+ * @param mixed $flow
+ * @return CommonFlowNode
+ */
+ public function setFlow($flow)
+ {
+ $this->flow = $flow;
+ return $this;
+ }
+
+ /**
+ * 设置FLow实例
+ * @return mixed
+ */
+ public function getFormData()
+ {
+ return $this->formData;
+ }
+
+ /**
+ * 设置表单数据
+ * @param mixed $formData
+ * @return CommonFlowNode
+ */
+ public function setFormData($formData)
+ {
+ $this->formData = $formData;
+ return $this;
+ }
+
+ /**
+ * 检查是否满足流转下一关条件
+ * @param $assignClass
+ * @param $leadCode
+ * @return bool
+ */
+ function checkTrust($assignClass, $leadCode)
+ {
+ $_flag = false;
+ $flowContext = unserialize($_SESSION['flowContext']);
+ $assignStatus = $flowContext->getAssignStatus();
+ #如果签核节点assign_status 在定义的同层签核节点当中则不可签回
+ if (in_array($assignStatus, AssignStatus::$same_level_status)) {
+ return $_flag;
+ }
+ switch ($assignClass) {
+ case 'A': //无需审核
+ $_flag = true;
+ break;
+ case 'B': //审核至科长
+ $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10')) ? true : false);
+
+ break;
+ case 'C': //审核至经理
+ $_flag = in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10')) ? true : false;
+ break;
+ case 'D': //审核至 协理/厂长/总监
+ $_flag = in_array($leadCode, array('19', '18', '17', '16', '12', '10')) ? true : false;
+ break;
+ case 'E': //审核至副总
+ $_flag = in_array($leadCode, array('12', '10')) ? true : false;
+ break;
+ case 'F': //审核至总经理
+ $_flag = substr($leadCode, 0, 2) == '10' ? true : false;
+ break;
+ case 'X':
+ $method = MethodLoader::getInstanceByMethodString(strip_tags($this->getAssignClassMethod()));
+ $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData());
+ $_flag = $this->checkTrust($_assignClass, $leadCode);
+ break;
+ default:
+ $_flag = false;
+ break;
+ }
+
+
+ return $_flag;
+ }
+}
diff --git a/workflow/impl/CounterSignTask.php b/workflow/impl/CounterSignTask.php
new file mode 100644
index 00000000..f9e371dc
--- /dev/null
+++ b/workflow/impl/CounterSignTask.php
@@ -0,0 +1,199 @@
+nodeProperty['allowAssign'];
+ }
+
+ /**
+ * 转交属性
+ */
+ public function getPropertyAllowPassTo()
+ {
+ return $this->nodeProperty['allowPassTo'];
+ }
+
+ public function getFlowCode()
+ {
+ return $this->nodeProperty['flowCode'];
+ }
+
+ public function getAssigner()
+ {
+ return $this->nodeProperty['assigner'];
+ }
+
+ public function getMergeOption()
+ {
+ return $this->nodeProperty['mergeOption'];
+ }
+
+ public function getBackOption()
+ {
+ return null;
+ }
+
+ /**
+ * 1.获取拆分人员
+ * @return array
+ */
+
+ function getSplitMemers($workFlowParser)
+ {
+ $strAssign = $this->getAssigner();
+ $assignEmps = array();
+ $arr_a = explode('|', $strAssign);
+ foreach ($arr_a as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ $arr_b = explode(':', $value);
+ $val = explode('-', $arr_b[0]);
+ $arr_c = explode(',', $arr_b[1]);
+ $str_next_user = "";
+ foreach ($arr_c as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ $str_next_user .= AssignerStringParser::process($value);
+ }
+ array_push($assignEmps, array(
+ $val[0], //assign_status
+ $str_next_user
+ ));
+ }
+ return $assignEmps;
+ }
+
+ /**
+ * 获取签核类别
+ */
+ public function getAssignClass()
+ {
+ $childFlow = SubflowManager::getChildNode($this->flow->formKey);
+ $leadCode = Employee::lead_code($childFlow['leader_no']);
+ if ($leadCode >= '80') return 'A';
+ if (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10'))) return 'B';
+ if (in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10'))) return 'C';
+ if (in_array($leadCode, array('19', '18', '17', '16', '12', '10'))) return 'D';
+ if (in_array($leadCode, array('12', '10'))) return 'E';
+ if (substr($leadCode, 0, 2) == '10') return 'F';
+ }
+
+ /**
+ * 检查是否满足流转下一关条件
+ * @param $assignClass
+ * @param $leadCode
+ * @return bool
+ */
+ function checkTrust($assignClass, $leadCode)
+ {
+
+ # 默认不可签回
+ $flowContext = unserialize($_SESSION['flowContext']);
+ $_flag = false;
+ $assignStatus = $flowContext->getAssignStatus();
+ #如果签核节点assign_status 在定义的同层签核节点当中则不可签回
+ if (in_array($assignStatus, AssignStatus::$same_level_status)) {
+ return $_flag;
+ }
+ #获取当前签核者字符串
+ $childFlow = SubflowManager::getChildNode($this->flow->formKey);
+ $currentAssigner = Subflow::getCurrentUser($this->flow->formKey);
+ if ($currentAssigner == $childFlow['leader_no']) {
+ #当前人员是被会签人员,可签回
+ $_flag = true;
+ } elseif ($leadCode < Employee::lead_code($currentAssigner)) {
+ #当前人员的岗位比被会签人员职位高,可签回
+ $_flag = true;
+ }
+
+ return $_flag;
+ }
+
+ public function getAssignerList(WorkFlowParser $fc)
+ {
+ $str_next_user = "00000-各部门,";
+ $assigner = array();
+ array_push($assigner, array(
+ "X3", //assign_status
+ $str_next_user
+ ));
+ return $assigner;
+ }
+
+ /**
+ * 获取部门的签核人员
+ * @param $userId
+ * @return array
+ */
+ public function getDepartmentalAssignerList($userId)
+ {
+
+ $leader = Employee::leader($userId);
+
+ $nextAssignerStr = Employee::get_employee($leader, $format = "employee_no-name");
+ $nextAssigner = array(0 => array(0 => "F6", 1 => $nextAssignerStr));
+
+ $subordinates = Employee::subordinates($userId);
+
+ if (count($subordinates) > 0) {
+ $nextAssignerStr = "";
+ foreach ($subordinates as $empl) {
+ $nextAssignerStr .= Employee::get_employee($empl, $format = "employee_no-name") . ',';
+ }
+ array_push($nextAssigner, array(0 => 'FH', 1 => $nextAssignerStr));
+ }
+ return $nextAssigner;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlow()
+ {
+ return $this->flow;
+ }
+
+ /**
+ * @param mixed $flow
+ * @return CounterSignTask
+ */
+ public function setFlow($flow)
+ {
+ $this->flow = $flow;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFormData()
+ {
+ return $this->formData;
+ }
+
+ /**
+ * @param mixed $formData
+ * @return CounterSignTask
+ */
+ public function setFormData($formData)
+ {
+ $this->formData = $formData;
+
+ return $this;
+ }
+}
diff --git a/workflow/impl/EndNode.php b/workflow/impl/EndNode.php
new file mode 100644
index 00000000..f540fbd6
--- /dev/null
+++ b/workflow/impl/EndNode.php
@@ -0,0 +1,78 @@
+请选择'";
+
+ return $html;
+ }
+
+ /**
+ * 检查是否满足流转下一关条件
+ * @param $assignClass
+ * @param $leadCode
+ * @return bool
+ */
+ function checkTrust($assignClass, $leadCode)
+ {
+ $_flag = false;
+ switch ($assignClass) {
+ case 'A': //无需审核
+
+ $_flag = true;
+ break;
+ case 'B': //审核至科长
+ $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10')) ? true : false);
+ break;
+ case 'C': //审核至经理
+ $_flag = in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10')) ? true : false;
+ break;
+ case 'D': //审核至 协理/厂长/总监
+ $_flag = in_array($leadCode, array('19', '18', '17', '16', '12', '10')) ? true : false;
+ break;
+ case 'E': //审核至副总
+ $_flag = in_array($leadCode, array('12', '10')) ? true : false;
+ break;
+ case 'F': //审核至总经理
+ $_flag = substr($leadCode, 0, 2) == '10' ? true : false;
+ break;
+ case 'X':
+ $method = MethodLoader::getInstanceByMethodString(strip_tags($this->getAssignClassMethod()));
+ $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData());
+ $_flag = $this->checkTrust($_assignClass, $leadCode);
+
+ break;
+ default:
+ $_flag = false;
+ break;
+ }
+ return $_flag;
+ }
+
+}
diff --git a/workflow/impl/FlowNode.php b/workflow/impl/FlowNode.php
new file mode 100644
index 00000000..8962b231
--- /dev/null
+++ b/workflow/impl/FlowNode.php
@@ -0,0 +1,126 @@
+getAssigner();
+ $assignEmps = array();
+ $arr_a = explode('|', $strAssign);
+ foreach ($arr_a as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ $arr_b = explode(':', $value);
+ $val = explode('-', $arr_b[0]);
+ $arr_c = explode(',', $arr_b[1]);
+ $str_next_user = "";
+ foreach ($arr_c as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ if ($value == '00000') {
+ $str_next_user .= '00000' . '-' . "00000,";
+ } else {
+ $str_next_user .= AssignerStringParser::process($value);
+ }
+ }
+ array_push($assignEmps, array(
+ $val[0], //assign_status
+ $str_next_user
+ ));
+ }
+
+ return $assignEmps;
+ }
+
+ /**
+ * 检查是否满足流转下一关条件
+ * @param $assignClass
+ * @param $leadCode
+ * @return bool
+ */
+ function checkTrust($assignClass, $leadCode)
+ {
+ $_flag = false;
+ $flowContext = unserialize($_SESSION['flowContext']);
+ $assignStatus = $flowContext->getAssignStatus();
+ #如果签核节点assign_status 在定义的同层签核节点当中则不可签回
+ if (in_array($assignStatus, AssignStatus::$same_level_status)) {
+ return $_flag;
+ }
+ switch ($assignClass) {
+ case 'A': //无需审核
+
+ $_flag = true;
+ break;
+ case 'B': //审核至科长
+ $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10','15')) ? true : false);
+
+ break;
+ case 'C': //审核至经理
+ $_flag = in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10','15')) ? true : false;
+ break;
+ case 'D': //审核至 协理/厂长/总监
+ $_flag = in_array($leadCode, array('19', '18', '17', '16', '12', '10','15')) ? true : false;
+ break;
+ case 'E': //审核至副总
+ $_flag = in_array($leadCode, array('12', '10')) ? true : false;
+ break;
+ case 'F': //审核至总经理
+ $_flag = substr($leadCode, 0, 2) == '10' ? true : false;
+ break;
+ case 'X':
+ $method = MethodLoader::getInstanceByMethodString(strip_tags($this->getAssignClassMethod()));
+ $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData());
+ $_flag = $this->checkTrust($_assignClass, $leadCode);
+ break;
+ default:
+ $_flag = false;
+ break;
+ }
+
+
+ return $_flag;
+ }
+
+ /**
+ * 获取附加的签核人员
+ * @param string $userId
+ * @return array
+ */
+ public function getDepartmentalAssignerList($userId)
+ {
+
+ $leader = Employee::leader($userId);
+
+ $nextAssignerStr = Employee::get_employee($leader, $format = "employee_no-name");
+ $nextAssigner = array(0 => array(0 => "F6", 1 => $nextAssignerStr));
+
+ $subordinates = Employee::subordinates($userId);
+
+ if (count($subordinates) > 0) {
+ $nextAssignerStr = "";
+ foreach ($subordinates as $empl) {
+ $nextAssignerStr .= Employee::get_employee($empl, $format = "employee_no-name") . ',';
+
+ }
+ array_push($nextAssigner, array(0 => 'FH', 1 => $nextAssignerStr));
+ }
+ return $nextAssigner;
+
+ }
+
+}
diff --git a/workflow/impl/LogicNode.php b/workflow/impl/LogicNode.php
new file mode 100644
index 00000000..152aaf42
--- /dev/null
+++ b/workflow/impl/LogicNode.php
@@ -0,0 +1,125 @@
+nodeProperty['routeMethod'];
+ if (!empty($methodString)) {
+
+ return MethodLoader::getInstanceByMethodString($methodString);
+
+ }
+ return null;
+ }
+
+ /**
+ *获取流程FLowCode
+ * @return mixed
+ */
+ public function getFlowCode()
+ {
+ $flowContext = unserialize($_SESSION['flowContext']);
+ $workFlowParser = $flowContext->getWorkFLowParser();
+ $prevNodes = $workFlowParser->getPrevLevelNodes(parent::getNodeId(), Node::FLOW_NODE);
+ $tmpNode = $prevNodes[Node::FLOW_NODE][0];
+ $tmpNodeFlowCode = $tmpNode->getFlowCode();
+ return $tmpNodeFlowCode;
+ }
+
+ /**
+ * 1.检查逻辑节点下层节点,并获取下层节点的assigner
+ * @param $flowchart
+ * @return array
+ */
+ public function getAssignerList($flowchart)
+ {
+
+
+ $nodes = $flowchart->getNextLevelNodes(parent::getNodeId());
+ $assigner = array();
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nodes)) continue;
+ foreach ($nodes[$type] as $node) {
+ if (method_exists($node, 'getAssignerList')) {
+ $assigner = array_merge((array)$assigner, $node->getAssignerList($flowchart));
+ }
+ }
+ }
+ /* $methodString = $this->getMethod();
+ if (!empty($methodString)) {
+
+ $_methodInstance = MethodLoader::getInstanceByMethodString($methodString);
+
+ }*/
+ return $assigner;
+ }
+
+ /**
+ * 获取附加的签核人员
+ * @param $userId
+ * @return array
+ */
+ public function getDepartmentalAssignerList($userId)
+ {
+ $leader = Employee::leader($userId);
+ $nextAssignerStr = Employee::get_employee($leader, $format = "employee_no-name");
+ $nextAssigner = array(0 => array(0 => "F6", 1 => $nextAssignerStr));
+ return $nextAssigner;
+ }
+
+ /**
+ * 检查是否满足流转下一关条件
+ * @param $assignClass
+ * @param $leadCode
+ * @return bool
+ */
+ function checkTrust($assignClass, $leadCode)
+ {
+ $_flag = false;
+ switch ($assignClass) {
+ case 'A': //无需审核
+ $_flag = true;
+ break;
+ case 'B': //审核至科长
+ $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '12', '10')) ? true : false);
+
+ break;
+ case 'C': //审核至经理
+ $_flag = in_array($leadCode, array('20', '19', '18', '17', '16', '12', '10')) ? true : false;
+ break;
+ case 'D': //审核至 协理/厂长/总监
+ $_flag = in_array($leadCode, array('19', '18', '17', '16', '12', '10')) ? true : false;
+ break;
+ case 'E': //审核至副总
+ $_flag = in_array($leadCode, array('12', '10')) ? true : false;
+ break;
+ case 'F': //审核至总经理
+ $_flag = substr($leadCode, 0, 2) == '10' ? true : false;
+ break;
+ case 'X':
+
+ $method = MethodLoader::getInstanceByMethodString(strip_tags($this->getAssignClassMethod()));
+ $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData());
+ $_flag = $this->checkTrust($_assignClass, $leadCode);
+ break;
+ default:
+ $_flag = false;
+ break;
+ }
+ return $_flag;
+ }
+}
diff --git a/workflow/impl/MailTask.php b/workflow/impl/MailTask.php
new file mode 100644
index 00000000..145448aa
--- /dev/null
+++ b/workflow/impl/MailTask.php
@@ -0,0 +1,109 @@
+mailTo = $param["mailTo"];
+ $this->mailSubject = $param["mailSubject"];
+ $this->mailContent = $param["mailContent"];
+ }
+
+ public function doTask()
+ {
+
+ $mailString = "echo '" . $this->mailContent . "'"
+ . '| mail -s "$(echo -e " ' . $this->mailSubject . '\nContent-Type: text/html")" ' . $this->mailTo . '@yungtay.com.cn';
+ system($mailString);
+ }
+ /**
+ * @return mixed
+ */
+ public function getMailFrom()
+ {
+ return $this->mailFrom;
+ }
+
+ /**
+ * @param mixed $mailFrom
+ * @return MailTask
+ */
+ public function setMailFrom($mailFrom)
+ {
+ $this->mailFrom = $mailFrom;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMailTo()
+ {
+ return $this->mailTo;
+ }
+
+ /**
+ * @param mixed $mailTo
+ * @return MailTask
+ */
+ public function setMailTo($mailTo)
+ {
+ $this->mailTo = $mailTo;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMailSubject()
+ {
+ return $this->mailSubject;
+ }
+
+ /**
+ * @param mixed $mailSubject
+ * @return MailTask
+ */
+ public function setMailSubject($mailSubject)
+ {
+ $this->mailSubject = $mailSubject;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMailContent()
+ {
+ return $this->mailContent;
+ }
+
+ /**
+ * @param mixed $mailContent
+ * @return MailTask
+ */
+ public function setMailContent($mailContent)
+ {
+ $this->mailContent = $mailContent;
+ return $this;
+ }
+}
diff --git a/workflow/impl/MergeNode.php b/workflow/impl/MergeNode.php
new file mode 100644
index 00000000..7cf2c415
--- /dev/null
+++ b/workflow/impl/MergeNode.php
@@ -0,0 +1,43 @@
+nodeProperty['mergeOption'];
+ }
+
+ /**
+ * 1.检查逻辑节点下层节点,并获取下层节点的assigner
+ * @param WorkFlowParser $workFlowParser
+ * @return array
+ */
+ public function getAssignerList(WorkFlowParser $workFlowParser)
+ {
+
+ $nodes = $workFlowParser->getNextLevelNodes(parent::getNodeId());
+ $assigner = array();
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nodes)) continue;
+ foreach ($nodes[$type] as $node) {
+ if (method_exists($node, 'getAssignerList')) {
+ $assigner = array_merge((array)$assigner, $node->getAssignerList($workFlowParser));
+ }
+ }
+ }
+ return $assigner;
+ }
+
+
+}
\ No newline at end of file
diff --git a/workflow/impl/Node.php b/workflow/impl/Node.php
new file mode 100644
index 00000000..f031c7e1
--- /dev/null
+++ b/workflow/impl/Node.php
@@ -0,0 +1,84 @@
+"StartNode",
+ self::TASK_NODE => "TaskNode",
+ self::LOGIC_NODE => "LogicNode",
+ self::SPLIT_NODE => "SplitNode",
+ self::FLOW_NODE => "FlowNode",
+ self::MERGE_NODE => "MergeNode",
+ self::END_NODE => "EndNode",
+ self::COUNTER_SIGN_TASK => "CounterSignTask",
+ self::COUNTER_SIGN_SUBTASK => "CounterSignSubtask"
+ );
+ static $nodeTypes = array(
+ self::START_NODE,
+ self::TASK_NODE,
+ self::LOGIC_NODE,
+ self::SPLIT_NODE,
+ self::FLOW_NODE,
+ self::MERGE_NODE,
+ self::END_NODE,
+ self::COUNTER_SIGN_TASK,
+ self::COUNTER_SIGN_SUBTASK
+ );
+ static $handlerClasses = array(
+ self::START_NODE=>"StartNodeHandler",
+ self::TASK_NODE => "TaskNodeHandler",
+ self::LOGIC_NODE => "LogicNodeHandler",
+ self::SPLIT_NODE => "SplitNodeHandler",
+ self::FLOW_NODE => "FlowNodeHandler",
+ self::MERGE_NODE => "MergeNodeHandler",
+ self::END_NODE => "EndNodeHandler",
+ self::COUNTER_SIGN_TASK => "CounterSignTaskHandler",
+ self::COUNTER_SIGN_SUBTASK => "CounterSignSubtaskHandler"
+ );
+ protected $nodeProperty;
+
+ /**
+ *返回节点类型
+ * @param $param
+ */
+ function __construct($param)
+ {
+ $this->nodeProperty = $param;
+ }
+
+ public function getType()
+ {
+ return $this->nodeProperty['nodeType'];
+ }
+ public function getNodeId()
+ {
+ return $this->nodeProperty['nodeId'];
+ }
+ public function getNodeDescription()
+ {
+ return $this->nodeProperty['desc'];
+ }
+}
diff --git a/workflow/impl/NoticeTask.php b/workflow/impl/NoticeTask.php
new file mode 100644
index 00000000..6041b894
--- /dev/null
+++ b/workflow/impl/NoticeTask.php
@@ -0,0 +1,54 @@
+noticeList = $param["noticeList"];
+ $this->noticeTitle = $param["noticeTitle"];
+ $this->noticeUrl = $param["noticeUrl"];
+ }
+
+ public function doTask()
+ {
+
+ return 0;
+ // return $mailString;
+ }
+
+ /**
+ * 设置任务的属性
+ * @param $objProperty
+ */
+ public function setTaskProperty($objProperty)
+ {
+ }
+
+ /**
+ * 任务执行之前
+ */
+ public function beforeDoTask()
+ {
+ }
+
+ /**
+ * 任务执行之后
+ */
+ public function afterDoTask()
+ {
+ }
+}
diff --git a/workflow/impl/SplitNode.php b/workflow/impl/SplitNode.php
new file mode 100644
index 00000000..510d1529
--- /dev/null
+++ b/workflow/impl/SplitNode.php
@@ -0,0 +1,87 @@
+getAllNode(Node::MERGE_NODE);
+ if (count($mergeNodes) == 0) return $assigners;
+ $subFlowNodes = $workFlowParser->getNextLevelNodes(parent::getNodeId(), Node::FLOW_NODE);
+ if (count($subFlowNodes) == 0) return $assigners;
+ foreach ($mergeNodes[Node::MERGE_NODE] as $mergeNode) {
+
+ $pathLength[$mergeNode->getNodeId()] = 0;
+ foreach ($subFlowNodes[Node::FLOW_NODE] as $flowNode) {
+ $path = $workFlowParser->getMinLengthBetweenNode($mergeNode->getNodeId(), $flowNode->getNodeId());
+
+ if (count($path) == 0) { //不存在路径,设置为极大值
+ $pathLength[$mergeNode->getNodeId()] = PHP_INT_MAX;
+ break;
+ }
+ $pathLength[$mergeNode->getNodeId()] += count($pathLength[$mergeNode->getNodeId()]) + 1;
+ }
+
+ }
+ if (min($pathLength) == PHP_INT_MAX) return $assigners;
+ $MinLengthPathNode = $workFlowParser->getNodeByNodeId(array_search(min($pathLength), $pathLength));
+ $SecondAssigners = $MinLengthPathNode->getAssignerList($workFlowParser);
+ if (count($SecondAssigners) == 0) return $assigners;
+ return $SecondAssigners;
+
+ }
+
+ /**
+ * 1.检查逻辑节点下层节点,并获取下层节点的assigner
+ * @param WorkFlowParser $workFlowParser
+ * @return array
+ */
+
+ function getSplitMembers(WorkFlowParser $workFlowParser)
+ {
+
+ $assigners = $this->getNextAssignerList($workFlowParser);
+ foreach ($assigners as $key => $assigner) {
+ $arr = explode('-', $assigner[1]);
+ $_depart = Depart::depart_name(Employee::f_return_depart($arr[0]));
+ $assigners[$key] = $_depart . '-' . $arr[1];
+ }
+ return $assigners;
+ }
+
+ /**
+ * @param WorkFlowParser $workFlowParser
+ * @return array
+ */
+ function getNextAssignerList(WorkFlowParser $workFlowParser)
+ {
+ $nodes = $workFlowParser->getNextLevelNodes(parent::getNodeId());
+ $assigners = array();
+ foreach (Node::$nodeTypes as $type) {
+ if (!array_key_exists($type, $nodes)) continue;
+ foreach ($nodes[$type] as $node) {
+ if (method_exists($node, 'getAssignerList')) {
+ $assigners = array_merge((array)$assigners, $node->getAssignerList($workFlowParser));
+ }
+ }
+ }
+ return $assigners;
+ }
+
+}
diff --git a/workflow/impl/StartNode.php b/workflow/impl/StartNode.php
new file mode 100644
index 00000000..469e62cb
--- /dev/null
+++ b/workflow/impl/StartNode.php
@@ -0,0 +1,128 @@
+nodeProperty['backOption'])
+ ? null : $this->nodeProperty['backOption'];
+ }
+
+ public function getAssignerList()
+ {
+ $strAssigner = $this->getAssigner();
+ //B4-退回:73376,73502,73396|A4-待评估:73376,73502|
+ $assignerList = array();
+ $arr_a = explode('|', $strAssigner);
+ foreach ($arr_a as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ $arr_b = explode(':', $value);
+ $val = explode('-', $arr_b[0]);
+ $arr_c = explode(',', $arr_b[1]);
+ $strNextUser = "";
+ foreach ($arr_c as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ if ($value == '00000') {
+ $strNextUser .= "00000" . '-' . "00000,";
+ } else {
+ $strNextUser .= AssignerStringParser::process($value);
+ }
+ }
+ array_push($assignerList, array($val[0], $strNextUser));
+ }
+ return $assignerList;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAssignStatus()
+ {
+ //B4-退回:73376,73502,73396|A4-待评估:73376,73502|
+ $strAssigner = $this->getAssigner();
+ $html = "''";
+ $arr_a = explode('|', $strAssigner);
+ foreach ($arr_a as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ $arr_b = explode(':', $value); //B4-退回:73376,73502,73396
+ $val = explode('-', $arr_b[0]);
+
+ $html .= "";
+ }
+ return $html;
+ }
+
+ /**
+ * 获取附加的签核人员
+ * @param $userId
+ * @return array
+ */
+ public function getDepartmentalAssignerList($userId)
+ {
+ $leader = Employee::leader($userId);
+ $nextAssignerStr = Employee::get_employee($leader, $format = "employee_no-name");
+ $nextAssigner = array(0 => array(0 => "F6", 1 => $nextAssignerStr));
+ return $nextAssigner;
+ }
+
+ /**
+ * 检查是否满足流转下一关条件
+ * @param $assignClass
+ * @param $leadCode
+ * @return bool
+ */
+ function checkTrust($assignClass, $leadCode)
+ {
+ $_flag = false;
+ switch ($assignClass) {
+ case 'A': //无需审核
+
+ $_flag = true;
+ break;
+ case 'B': //审核至科长
+ $_flag = (in_array($leadCode, array('50', '20', '19', '18', '17', '16', '15', '12', '11', '10')) ? true : false);
+
+ break;
+ case 'C': //审核至经理
+ $_flag = in_array($leadCode, array('20', '19', '18', '17', '15', '16', '12', '11', '10')) ? true : false;
+ break;
+ case 'D': //审核至 协理/厂长/总监
+ $_flag = in_array($leadCode, array('19', '18', '17', '16', '15', '12', '11', '10')) ? true : false;
+ break;
+ case 'E': //审核至副总
+ $_flag = in_array($leadCode, array('12', '10')) ? true : false;
+ break;
+ case 'F': //审核至总经理
+ $_flag = substr($leadCode, 0, 2) == '10' ? true : false;
+ break;
+ case 'X':
+ $method = MethodLoader::getInstanceByMethodString(strip_tags(html_entity_decode($this->getAssignClassMethod())));
+ // var_dump($this->getFormData());
+ $_assignClass = $method->invokeMethod($this->getFlow(), $this->getFormData());
+ $_flag = $this->checkTrust($_assignClass, $leadCode);
+
+ break;
+ default:
+ $_flag = false;
+ break;
+ }
+ return $_flag;
+ }
+}
diff --git a/workflow/interface/IFlow.php b/workflow/interface/IFlow.php
new file mode 100644
index 00000000..1d3d51e3
--- /dev/null
+++ b/workflow/interface/IFlow.php
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/workflow/interface/IRouter.php b/workflow/interface/IRouter.php
new file mode 100644
index 00000000..a7fa856f
--- /dev/null
+++ b/workflow/interface/IRouter.php
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/workflow/lib/AssignStatus.php b/workflow/lib/AssignStatus.php
new file mode 100644
index 00000000..6fc00e2c
--- /dev/null
+++ b/workflow/lib/AssignStatus.php
@@ -0,0 +1,29 @@
+getFormKey(), $as_array = true, $code);
+ $str_next_user = "";
+ foreach ($records as $record) {
+ $tmp_str = Employee::get_employee($record['assigner'], $format);
+ $str_next_user .= $tmp_str . $delimiter;
+ }
+ return $str_next_user;
+
+ }
+
+ /**
+ * 处理未定义的情况
+ * @return string
+ */
+ public static function processUndefined($function)
+ {
+ return "调用了不存在的处理函数:" . $function;
+ }
+
+}
\ No newline at end of file
diff --git a/workflow/lib/DB.php b/workflow/lib/DB.php
new file mode 100644
index 00000000..85459c13
--- /dev/null
+++ b/workflow/lib/DB.php
@@ -0,0 +1,209 @@
+ array('host' => 'db-104.coowo.com', 'db_name' => 'appwms', 'user' => 'masadaroot', 'pwd' => 'x6h5E5p#u8y')
+ );
+ public static $instance;
+ /**
+ * ?
+ *
+ * @param string $db
+ * @return object
+ */
+ public static function instance($db = 'default')
+ {
+
+ $dbh = new PDO("mysql:host=" . self::$ds[$db]['host'] . ";dbname=appwms" . ";charset=utf8", self::$ds[$db]['user'], self::$ds[$db]['pwd']);
+ $dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
+ return $dbh;
+ }
+ /**
+ * ?insert
+ *
+ * @param [String] $table_name
+ * @param [Array] $cols
+ * @param [Array] $values
+ * @param string $db
+ * @return void
+ */
+ public static function insert_batch($table_name, $cols, $values, $db = 'default')
+ {
+ $_sql = 'insert into ' . $table_name . '(' . implode(",", $cols) . ')';
+ $_vsql = array();
+ foreach ($values as $value) {
+ $_vsql[] = 'select ' . implode(",", $value) . 'from dual';
+ }
+ $_sql .= implode(' Union All ', $_vsql);
+ // self::query($_sql, $db);
+ self::instance($db)->exec($_sql);
+ }
+ /**
+ * insert
+ *
+ * @param [type] $table_name
+ * @param [type] $data
+ * @param string $db
+ * @return void
+ */
+ public static function insert_table($table_name, $data, $db = 'default')
+ {
+
+
+ // $stmt->debugDumpParams();
+
+ $fields = array_keys($data);
+
+ $meta = self::metadata($table_name, array_keys($data), $db);
+ // var_dump( $meta);
+
+ foreach ($fields as $f) {
+
+ if ($meta[$f] == 'LONG' || $meta[$f] == 'NEWDECIMAL') {
+ $data[$f] = (int) $data[$f];
+ } elseif ($meta[$f] == 'DATETIME' && empty($data[$f])) {
+ $data[$f] = 'NULL';
+ } else {
+ // var_dump( $data[$f]);
+ // if( is_array($data[$f])){ echo "$table_name " ; echo "$f ";};
+
+ $data[$f] = "'" . $data[$f] . "'";
+ $data[$f] = $data[$f];
+ }
+ }
+
+ //foreach ($fields as $f) {
+
+ $_sql = "insert into " . $table_name . "(" . implode(",", array_keys($data)) . ") values (" . implode(",", array_values($data)) . " )";
+//echo $_sql;
+ self::instance($db)->exec($_sql);
+ // $stmt->debugDumpParams();
+
+
+
+ }
+ /**
+ *
+ *
+ * @param [String] $table_name
+ * @param [Array] $data
+ * @param [String] $data
+ * @param string $db
+ * @return void
+ */
+ public static function update_table($table_name, $data, $where, $db = 'default')
+ {
+ $fields = array_keys($data);
+
+ $meta = self::metadata($table_name, array_keys($data), $db);
+ // var_dump( $meta);
+
+ foreach ($fields as $f) {
+
+ if ($meta[$f] == 'LONG') {
+ $data[$f] = (int) $data[$f];
+ } else if ($meta[$f] == 'NEWDECIMAL') {
+ $data[$f] = (float) $data[$f];
+ } elseif ($meta[$f] == 'DATETIME' && empty($data[$f])) {
+ $data[$f] = NULL;
+ } else {
+ $data[$f] = $data[$f];
+ $data[$f] = $data[$f];
+ }
+ }
+
+
+
+ if (empty($where)) {
+ return false;
+ }
+ $sql = "update $table_name set ";
+ $i = 0;
+ foreach ($data as $key => $val) {
+ $sql .= $i++ > 0 ? " , $key=:$key " : " $key=:$key ";
+ $value[$key] = $val;
+ }
+ // var_dump($value);
+ $sql .= " where " . $where;
+ $stmt = self::instance($db)->prepare($sql);
+
+ $stmt->execute($value);
+ // $stmt->debugDumpParams();
+ }
+
+ /**
+ * sql
+ *
+ * @param [String] $sql
+ * @param string $db
+ * @return void
+ */
+ public static function fields($sql, $db = 'default')
+ {
+ return self::query($sql)->fetch(PDO::FETCH_BOTH);
+ }
+ /**
+ * ?,as_array array?
+ *
+ * @param [String] $sql
+ * @param boolean $as_array
+ * @param string $db
+ * @return mixed
+ */
+ public static function result($sql, $as_array = true, $db = 'default')
+ {
+ // echo $sql;
+ $resource = self::query($sql, $db);
+
+ return $as_array == false ? $resource->fetchAll(PDO::FETCH_OBJ) : $resource->fetchAll(PDO::FETCH_BOTH);
+ }
+ /**
+ *sql?
+ *
+ * @param [String] $sql
+ * @return [int]
+ */
+ public static function effect_num($sql, $db = 'default')
+ {
+ return count(self::query($sql, $db)->fetchAll());
+ }
+ public static function query($sql, $db = 'default')
+ {
+
+ // echo $sql;
+ $res = self::instance($db)->prepare($sql);
+
+ if (!$res) {
+ // var_dump($res->errorInfo());
+ } else {
+ $res->execute();
+
+ return $res;
+ }
+ }
+ public function escape($filed)
+ {
+ }
+
+ /*
+ * 获取列的元数据
+ *
+ * @param [type] $tablename
+ * @return void
+ */
+ public static function metadata($tablename = null, $col = array(), $db = 'default')
+ {
+ $column_types = array();
+
+ $stmt = self::query("SELECT " . implode(",", array_values($col)) . " FROM " . $tablename . " limit 0,1");
+ for ($i = 0; $i < $stmt->columnCount(); $i++) {
+ $meta[$i] = $stmt->getColumnMeta($i);
+
+ $column_types[$meta[$i]['name']] = $meta[$i]['native_type'];
+ }
+
+ return $column_types;
+ }
+}
diff --git a/workflow/lib/Depart.php b/workflow/lib/Depart.php
new file mode 100644
index 00000000..e1496055
--- /dev/null
+++ b/workflow/lib/Depart.php
@@ -0,0 +1,68 @@
+employee_no,
+ $this->depart_no,
+ $this->name,
+ $this->lead_code,
+ $this->position_code,
+ $this->mail,
+ $this->mail_server
+ ) = DB::fields("SELECT EMPLOYEE_NO,DEPART_NO,NAME,LEAD_CODE,POSITION_CODE,MAIL,MAIL_SERVER
+ FROM employee
+ WHERE EMPLOYEE_NO='" . $employee_no . "'
+ ");
+ }
+
+ static $allowFormatWord = array(
+ "employee_no",
+ "name",
+ "depart_no",
+ "position",
+ "depart_name"
+ );
+
+ /**
+ * 获取领导
+ *
+ * @param String $employee_no
+ * @return void
+ */
+ public static function leader($employee_no)
+ {
+ $_sql = "select f_return_leader('" . $employee_no . "') LEADER from dual";
+ list($_leader) = DB::fields($_sql);
+ return $_leader;
+ }
+
+ /**
+ * 获取lead_code
+ *
+ * @param String $employee_no
+ * @return void
+ */
+ public static function lead_code($employee_no)
+ {
+ $_sql = "select lead_code from employee where employee_no='" . $employee_no . "'";
+ list($_lead_code) = DB::fields($_sql);
+ return $_lead_code;
+ }
+
+ /**
+ * 姓名
+ *
+ * @param String $employee_no
+ * @return void
+ */
+ public static function name($employee_no)
+ {
+ $_sql = "select name from employee where employee_no='" . $employee_no . "'";
+ list($_name) = DB::fields($_sql, 'ibmora');
+
+ return $_name;
+ }
+
+ /**
+ * 员工号
+ *
+ * @param String $employee_no
+ * @return void
+ */
+ public static function get_employee_no($employee_no)
+ {
+
+ return $employee_no;
+ }
+
+ public static function get_position_name($employee_no)
+ {
+ if (Employee::lead_code($employee_no) == '90') return "";
+ return Code::getContent("lead_code", Employee::lead_code($employee_no));
+ }
+
+ /**
+ * 获取员工部门
+ *
+ * @return void
+ */
+ public static function f_return_depart($employee_no)
+ {
+ $_sql = "select depart_no from employee where employee_no='" . $employee_no . "'";
+ list($_depart) = DB::fields($_sql);
+ return $_depart;
+ }
+
+ /**
+ * 获取员工部门名称
+ *
+ * @return void
+ */
+ public static function f_return_depart_name($employee_no)
+ {
+ $_depart = self::f_return_depart($employee_no);
+
+ return Depart::depart_name($_depart);
+ }
+
+ /**
+ * 获取下属
+ *
+ * @param String $employee_no
+ * @return void|array
+ */
+ public static function subordinates($employee_no)
+ {
+ $depart = self::f_return_depart($employee_no);
+ $depart = rtrim($depart, 0);
+ $_sql = "select employee_no from employee where
+ depart_no like '" . $depart . "%'
+ and employee_no!='" . $employee_no . "'
+ and lead_code >'" . self::lead_code($employee_no) . "' ";
+ // echo $_sql;
+ $_arr = array();
+ $result = DB::result($_sql, true);
+
+ foreach ($result as $row) {
+ if (!empty($row['employee_no'])) {
+ array_push($_arr, $row['employee_no']);
+ }
+ }
+ return $_arr;
+ }
+
+ /**
+ * @param $employee_no
+ * @param string $format
+ * @return mixed|string
+ */
+ public static function get_employee($employee_no, $format = "employee_no-name position")
+ {
+ $tmp_str = $format;
+ if ($employee_no == '00000' or empty($employee_no)) {
+ return '00000';
+ }
+ $_sql = " select employee_no,name,depart_no,f_return_depart_name(depart_no) depart_name,
+ f_return_content('lead_code',lead_code) position from employee where employee_no='" . $employee_no . "'";
+
+ $result = DB::result($_sql, true);
+
+ foreach (self::$allowFormatWord as $word) {
+ $tmp_str = str_replace($word, $result[0][$word], $tmp_str);
+ }
+ return $tmp_str;
+ }
+}
diff --git a/workflow/lib/Logger.php b/workflow/lib/Logger.php
new file mode 100644
index 00000000..809e5294
--- /dev/null
+++ b/workflow/lib/Logger.php
@@ -0,0 +1,400 @@
+logInfo('Returned a million search results'); //Prints to the log file
+ * $log->logFatal('Oh dear.'); //Prints to the log file
+ * $log->logDebug('x = 5'); //Prints nothing due to current severity threshhold
+ */
+
+/**
+ * Class documentation
+ */
+class Logger
+{
+
+ const EMERG = 0; // Emergency: system is unusable
+ const ALERT = 1; // Alert: action must be taken immediately
+ const CRIT = 2; // Critical: critical conditions
+ const ERR = 3; // Error: error conditions
+ const WARN = 4; // Warning: warning conditions
+ const NOTICE = 5; // Notice: normal but significant condition
+ const INFO = 6; // Informational: informational messages
+ const DEBUG = 7; // Debug: debug messages
+
+ //custom logging level
+ /**
+ * Log nothing at all
+ */
+ const OFF = 8;
+ /**
+ * Alias for CRIT
+ * @deprecated
+ */
+ const FATAL = 2;
+
+ /**
+ * Internal status codes
+ */
+ const STATUS_LOG_OPEN = 1;
+ const STATUS_OPEN_FAILED = 2;
+ const STATUS_LOG_CLOSED = 3;
+
+ /**
+ * We need a default argument value in order to add the ability to easily
+ * print out objects etc. But we can't use NULL, 0, FALSE, etc, because those
+ * are often the values the developers will test for. So we'll make one up.
+ */
+ const NO_ARGUMENTS = 'Logger::NO_ARGUMENTS';
+
+ /**
+ * Current status of the log file
+ * @var integer
+ */
+ private $_logStatus = self::STATUS_LOG_CLOSED;
+ /**
+ * Holds messages generated by the class
+ * @var array
+ */
+ private $_messageQueue = array();
+ /**
+ * Path to the log file
+ * @var string
+ */
+ private $_logFilePath = null;
+ /**
+ * Current minimum logging threshold
+ * @var integer
+ */
+ private $_severityThreshold = self::INFO;
+ /**
+ * This holds the file handle for this instance's log file
+ * @var resource
+ */
+ private $_fileHandle = null;
+
+ /**
+ * Standard messages produced by the class. Can be modified for il8n
+ * @var array
+ */
+ private $_messages = array(
+ //'writefail' => 'The file exists, but could not be opened for writing. Check that appropriate permissions have been set.',
+ 'writefail' => 'The file could not be written to. Check that appropriate permissions have been set.',
+ 'opensuccess' => 'The log file was opened successfully.',
+ 'openfail' => 'The file could not be opened. Check permissions.',
+ );
+
+ /**
+ * Default severity of log messages, if not specified
+ * @var integer
+ */
+ private static $_defaultSeverity = self::DEBUG;
+ /**
+ * Valid PHP date() format string for log timestamps
+ * @var string
+ */
+ private static $_dateFormat = 'Y-m-d G:i:s';
+ /**
+ * Octal notation for default permissions of the log file
+ * @var integer
+ */
+ private static $_defaultPermissions = 0777;
+ /**
+ * Array of Logger instances, part of Singleton pattern
+ * @var array
+ */
+ private static $instances = array();
+
+ /**
+ * Partially implements the Singleton pattern. Each $logDirectory gets one
+ * instance.
+ *
+ * @param string $logDirectory File path to the logging directory
+ * @param integer $severity One of the pre-defined severity constants
+ * @return Logger
+ */
+ public static function instance($logDirectory = false, $severity = false)
+ {
+ if ($severity === false) {
+ $severity = self::$_defaultSeverity;
+ }
+
+ if ($logDirectory === false) {
+ if (count(self::$instances) > 0) {
+ return current(self::$instances);
+ } else {
+ $logDirectory = dirname(__FILE__);
+ }
+ }
+
+ if (in_array($logDirectory, self::$instances)) {
+ return self::$instances[$logDirectory];
+ }
+
+ self::$instances[$logDirectory] = new self($logDirectory, $severity);
+
+ return self::$instances[$logDirectory];
+ }
+
+ /**
+ * Class constructor
+ *
+ * @param string $logDirectory File path to the logging directory
+ * @param integer $severity One of the pre-defined severity constants
+ * @return void
+ */
+ public function __construct($logDirectory, $severity)
+ {
+ $logDirectory = rtrim($logDirectory, '\\/');
+
+ if ($severity === self::OFF) {
+ return;
+ }
+
+ $this->_logFilePath = $logDirectory
+ . DIRECTORY_SEPARATOR
+ . 'log_'
+ . date('Y-m-d')
+ . '.txt';
+
+ $this->_severityThreshold = $severity;
+ if (!file_exists($logDirectory)) {
+ mkdir($logDirectory, self::$_defaultPermissions, true);
+ }
+
+ if (file_exists($this->_logFilePath) && !is_writable($this->_logFilePath)) {
+ $this->_logStatus = self::STATUS_OPEN_FAILED;
+ $this->_messageQueue[] = $this->_messages['writefail'];
+ return;
+ }
+
+ if (($this->_fileHandle = fopen($this->_logFilePath, 'a'))) {
+ $this->_logStatus = self::STATUS_LOG_OPEN;
+ $this->_messageQueue[] = $this->_messages['opensuccess'];
+ } else {
+ $this->_logStatus = self::STATUS_OPEN_FAILED;
+ $this->_messageQueue[] = $this->_messages['openfail'];
+ }
+ }
+
+ /**
+ * Class destructor
+ */
+ public function __destruct()
+ {
+ if ($this->_fileHandle) {
+ fclose($this->_fileHandle);
+ }
+ }
+ /**
+ * Writes a $line to the log with a severity level of DEBUG
+ *
+ * @param string $line Information to log
+ * @return void
+ */
+ public function logDebug($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::DEBUG);
+ }
+
+ /**
+ * Returns (and removes) the last message from the queue.
+ * @return string
+ */
+ public function getMessage()
+ {
+ return array_pop($this->_messageQueue);
+ }
+
+ /**
+ * Returns the entire message queue (leaving it intact)
+ * @return array
+ */
+ public function getMessages()
+ {
+ return $this->_messageQueue;
+ }
+
+ /**
+ * Empties the message queue
+ * @return void
+ */
+ public function clearMessages()
+ {
+ $this->_messageQueue = array();
+ }
+
+ /**
+ * Sets the date format used by all instances of Logger
+ *
+ * @param string $dateFormat Valid format string for date()
+ */
+ public static function setDateFormat($dateFormat)
+ {
+ self::$_dateFormat = $dateFormat;
+ }
+
+ /**
+ * Writes a $line to the log with a severity level of INFO. Any information
+ * can be used here, or it could be used with E_STRICT errors
+ *
+ * @param string $line Information to log
+ * @return void
+ */
+ public function logInfo($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::INFO, $args);
+ }
+
+ /**
+ * Writes a $line to the log with a severity level of NOTICE. Generally
+ * corresponds to E_STRICT, E_NOTICE, or E_USER_NOTICE errors
+ *
+ * @param string $line Information to log
+ * @return void
+ */
+ public function logNotice($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::NOTICE, $args);
+ }
+
+ /**
+ * Writes a $line to the log with a severity level of WARN. Generally
+ * corresponds to E_WARNING, E_USER_WARNING, E_CORE_WARNING, or
+ * E_COMPILE_WARNING
+ *
+ * @param string $line Information to log
+ * @return void
+ */
+ public function logWarn($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::WARN, $args);
+ }
+
+ /**
+ * Writes a $line to the log with a severity level of ERR. Most likely used
+ * with E_RECOVERABLE_ERROR
+ *
+ * @param string $line Information to log
+ * @return void
+ */
+ public function logError($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::ERR, $args);
+ }
+
+ /**
+ * Writes a $line to the log with a severity level of FATAL. Generally
+ * corresponds to E_ERROR, E_USER_ERROR, E_CORE_ERROR, or E_COMPILE_ERROR
+ *
+ * @param string $line Information to log
+ * @return void
+ * @deprecated Use logCrit
+ */
+ public function logFatal($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::FATAL, $args);
+ }
+
+ /**
+ * Writes a $line to the log with a severity level of ALERT.
+ *
+ * @param string $line Information to log
+ * @return void
+ */
+ public function logAlert($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::ALERT, $args);
+ }
+
+ /**
+ * Writes a $line to the log with a severity level of CRIT.
+ *
+ * @param string $line Information to log
+ * @return void
+ */
+ public function logCrit($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::CRIT, $args);
+ }
+
+ /**
+ * Writes a $line to the log with a severity level of EMERG.
+ *
+ * @param string $line Information to log
+ * @return void
+ */
+ public function logEmerg($line, $args = self::NO_ARGUMENTS)
+ {
+ $this->log($line, self::EMERG, $args);
+ }
+
+ /**
+ * Writes a $line to the log with the given severity
+ *
+ * @param string $line Text to add to the log
+ * @param integer $severity Severity level of log message (use constants)
+ */
+ public function log($line, $severity, $args = self::NO_ARGUMENTS)
+ {
+ if ($this->_severityThreshold >= $severity) {
+ $status = $this->_getTimeLine($severity);
+
+ $line = "$status $line";
+
+ if ($args !== self::NO_ARGUMENTS) {
+ /* Print the passed object value */
+ $line = $line . '; ' . var_export($args, true);
+ }
+
+ $this->writeFreeFormLine($line . PHP_EOL);
+ }
+ }
+
+ /**
+ * Writes a line to the log without prepending a status or timestamp
+ *
+ * @param string $line Line to write to the log
+ * @return void
+ */
+ public function writeFreeFormLine($line)
+ {
+ if (
+ $this->_logStatus == self::STATUS_LOG_OPEN
+ && $this->_severityThreshold != self::OFF
+ ) {
+ if (fwrite($this->_fileHandle, $line) === false) {
+ $this->_messageQueue[] = $this->_messages['writefail'];
+ }
+ }
+ }
+
+ private function _getTimeLine($level)
+ {
+ $time = date(self::$_dateFormat);
+
+ switch ($level) {
+ case self::EMERG:
+ return "$time - EMERG -->";
+ case self::ALERT:
+ return "$time - ALERT -->";
+ case self::CRIT:
+ return "$time - CRIT -->";
+ case self::FATAL: # FATAL is an alias of CRIT
+ return "$time - FATAL -->";
+ case self::NOTICE:
+ return "$time - NOTICE -->";
+ case self::INFO:
+ return "$time - INFO -->";
+ case self::WARN:
+ return "$time - WARN -->";
+ case self::DEBUG:
+ return "$time - DEBUG -->";
+ case self::ERR:
+ return "$time - ERROR -->";
+ default:
+ return "$time - LOG -->";
+ }
+ }
+}
diff --git a/workflow/lib/MethodLoader.php b/workflow/lib/MethodLoader.php
new file mode 100644
index 00000000..275fc8d4
--- /dev/null
+++ b/workflow/lib/MethodLoader.php
@@ -0,0 +1,41 @@
+methodString = $methodString;
+ }
+ public function invokeMethod($flow, $form)
+ {
+ //function[\s\n]+(\S+)[\s\n]*\(
+ preg_match_all("/function[\s\n]+(\S+)[\s\n]*\(/", $this->methodString, $arr);
+ eval($this->methodString . ";");
+ $func=$arr[1][0];
+ return $func($flow, $form);
+ }
+ };
+
+ return $obj;
+ }
+}
diff --git a/workflow/model/Assign.php b/workflow/model/Assign.php
new file mode 100644
index 00000000..c434bbfd
--- /dev/null
+++ b/workflow/model/Assign.php
@@ -0,0 +1,254 @@
+form_key;
+ }
+
+ /**
+ * @param null $form_key
+ * @return Assign
+ */
+ public function setFormKey($form_key)
+ {
+ $this->form_key = $form_key;
+ return $this;
+ }
+
+ /**
+ * @return int
+ */
+ public function getSeq()
+ {
+ return $this->seq;
+ }
+
+ /**
+ * @param int $seq
+ * @return Assign
+ */
+ public function setSeq($seq)
+ {
+ $this->seq = $seq;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAssigner()
+ {
+ return $this->assigner;
+ }
+
+ /**
+ * @param mixed $assigner
+ * @return Assign
+ */
+ public function setAssigner($assigner)
+ {
+ $this->assigner = $assigner;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAssignStatus()
+ {
+ return $this->assign_status;
+ }
+
+ /**
+ * @param mixed $assign_status
+ * @return Assign
+ */
+ public function setAssignStatus($assign_status)
+ {
+ $this->assign_status = $assign_status;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAssignDate()
+ {
+ return $this->assign_date;
+ }
+
+ /**
+ * @param mixed $assign_date
+ * @return Assign
+ */
+ public function setAssignDate($assign_date)
+ {
+ $this->assign_date = $assign_date;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAssignOpinion()
+ {
+ return $this->assign_opinion;
+ }
+
+ /**
+ * @param mixed $assign_opinion
+ * @return Assign
+ */
+ public function setAssignOpinion($assign_opinion)
+ {
+ $this->assign_opinion = $assign_opinion;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlowCode()
+ {
+ return $this->flow_code;
+ }
+
+ /**
+ * @param mixed $flow_code
+ * @return Assign
+ */
+ public function setFlowCode($flow_code)
+ {
+ $this->flow_code = $flow_code;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlowCodeSeq()
+ {
+ return $this->flow_code_seq;
+ }
+
+ /**
+ * @param mixed $flow_code_seq
+ * @return Assign
+ */
+ public function setFlowCodeSeq($flow_code_seq)
+ {
+ $this->flow_code_seq = $flow_code_seq;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRealAssigner()
+ {
+ return $this->real_assigner;
+ }
+
+ /**
+ * @param mixed $real_assigner
+ * @return Assign
+ */
+ public function setRealAssigner($real_assigner)
+ {
+ $this->real_assigner = $real_assigner;
+ return $this;
+ }
+
+
+ /**
+ * @param null $formKey
+ */
+ public function __construct($formKey = null)
+ {
+
+ $this->form_key = $formKey;
+
+ list($seq) = DB::fields("SELECT max(seq) FROM assign
+ where form_key ='$formKey'");
+ $this->seq = empty($seq) ? 0 : $seq;
+ }
+
+ /**
+ * @param null $formKey
+ * @param string $as_array
+ * @param string $code
+ * @param string $assign_status
+ * @return array
+ */
+ public static function get_records($formKey = null, $as_array = "true", $code = '%', $assign_status = '%')
+ {
+ try {
+ $sql = "select seq,assigner,assign_opinion, assign_date assign_date
+ ,lead_code,f_return_content('lead_code',lead_code) position_name,assign_status,flow_code,
+ f_return_depart(assigner) assign_depart ,f_return_depart_name(f_return_depart(assigner)) assign_depart_name
+ from
+ assign a,employee b where
+ a.assigner =b.employee_no
+ and assign_status like '" . $assign_status . "%'
+ and form_key = '" . $formKey . "' and flow_code like '" . $code . "%' order by assign_date asc";
+ // echo $sql;
+ return DB::result($sql, $as_array);
+
+ } catch (Exception $e) {
+ echo 'Caught exception: ', $e->getMessage(), "\n";
+ return null;
+ }
+
+ }
+
+ public static function get_lastest_record($formKey, $code)
+ {
+ try {
+ $sql = "select seq,assigner,assign_opinion, assign_date assign_date,lead_code,
+ f_return_content('lead_code',lead_code) position_name,assign_status,flow_code,
+ f_return_depart(assigner) assign_depart ,f_return_depart_name(f_return_depart(assigner)) assign_depart_name
+ from
+ assign a,employee b where
+ a.assigner =b.employee_no
+ and form_key = '" . $formKey . "' and seq in(
+ select max(seq) from assign where form_key = '" . $formKey . "'
+ and flow_code like '" . $code . "%'
+ ) ";
+ $result = DB::result($sql);
+ return $result[0];
+
+ } catch (Exception $e) {
+ echo 'Caught exception: ', $e->getMessage(), "\n";
+ return null;
+ }
+ }
+
+ public function insert()
+ {
+ DB::insert_table("assign", array(
+ "form_key" => $this->form_key,
+ "seq" => $this->seq + 1,
+ "assigner" => $this->assigner,
+ "assign_status" => $this->assign_status,
+ "assign_opinion" => $this->assign_opinion,
+ "flow_code" => $this->flow_code,
+ "flow_code_seq" => $this->flow_code_seq,
+ "real_assigner" => $this->real_assigner
+ ));
+ }
+}
\ No newline at end of file
diff --git a/workflow/model/Code.php b/workflow/model/Code.php
new file mode 100644
index 00000000..884af59d
--- /dev/null
+++ b/workflow/model/Code.php
@@ -0,0 +1,17 @@
+form_key = self::getNewFormKey();
+ } else {
+
+ list(
+ $this->system_id,
+ $this->flow_id,
+ $this->form_id,
+ $this->form_key,
+ $this->flow_code,
+ $this->flow_code_seq,
+ $this->back_code
+ )
+ = DB::fields("SELECT system_id,flow_id,form_id,form_key,flow_code,flow_code_seq,back_code
+ FROM flow where form_key ='$formKey'");
+ // echo " FLow 33:" . "SELECT system_id,flow_id,form_id,form_key,flow_code,flow_code_seq,back_code
+ // FROM flow where form_key ='$formKey'";
+ }
+ }
+
+ public function getParentKey()
+ {
+ list($parent_key) = DB::fields("select parent_key from workflow_subflow
+ where form_key='" . $this->form_key . "' ");
+ return $parent_key;
+ }
+ public static function getParentFormKey($formKey)
+ {
+ list($parent_key) = DB::fields("select parent_key from workflow_subflow
+ where form_key='" . $formKey . "' ");
+ return $parent_key;
+ }
+ public static function getSplitFlowCode()
+ {
+ }
+
+ /**
+ * @param $formKey
+ * @param $flowCode
+ */
+ static function updateFlowCode($formKey, $flowCode)
+ {
+ $where = "form_key = '" . $formKey . "'";
+ DB::update_table("flow", array(
+ "flow_code" => $flowCode
+ ), $where);
+ }
+ /**
+ * 生成新的formkey
+ * @return string
+ */
+ public static function getNewFormKey()
+ {
+ // list($curvalformKey) = DB::fields("SELECT appwms.currval('form_key') form_key");
+ // echo " curvalformKey line69 :" . $curvalformKey."
";
+ list($formKey) = DB::fields("SELECT appwms.nextval('form_key') form_key");
+ // echo " formKey line77:" . $formKey."
";
+ return $formKey;
+ }
+
+ public function insert()
+ {
+ DB::insert_table("flow", array(
+ "form_key" => $this->form_key,
+ "system_id" => $this->system_id,
+ "flow_id" => $this->flow_id,
+ "form_id" => $this->form_id,
+ "flow_code" => $this->flow_code,
+ "flow_code_seq" => $this->flow_code_seq,
+ "back_code" => $this->back_code
+ ));
+ }
+ public function save()
+ {
+ list($cnt) = DB::fields("select count(*) from flow where form_key='" . $this->form_key . "' ");
+
+ if ($cnt == 0) {
+ // echo "CNT : ".$cnt;
+ DB::insert_table("flow", array(
+ "form_key" => $this->form_key,
+ "system_id" => $this->system_id,
+ "flow_id" => $this->flow_id,
+ "form_id" => $this->form_id,
+ "flow_code" => $this->flow_code,
+ "flow_code_seq" => $this->flow_code_seq,
+ "back_code" => $this->back_code
+ ));
+ } else {
+ $where = "form_key = '" . $this->form_key . "'";
+ DB::update_table("flow", array(
+ "flow_code" => $this->flow_code ,
+ "flow_code_seq" => $this->flow_code_seq ,
+ "back_code" => $this->back_code
+ ), $where);
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function getFormKey()
+ {
+ return $this->form_key;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFormId()
+ {
+ return $this->form_id;
+ }
+ /**
+ * @return mixed
+ */
+ public function getFlowId()
+ {
+ return $this->flow_id;
+ }
+
+
+ /**
+ * @return mixed
+ */
+ public function getSystemId()
+ {
+ return $this->system_id;
+ }
+
+ /**
+ * @param mixed $system_id
+ * @return Flow
+ */
+ public function setSystemId($system_id)
+ {
+ $this->system_id = $system_id;
+ return $this;
+ }
+
+ /**
+ * @param mixed $flow_id
+ * @return Flow
+ */
+ public function setFormId($form_id)
+ {
+ $this->form_id = $form_id;
+ return $this;
+ }
+
+ /**
+ * @param mixed $flow_code
+ * @return Flow
+ */
+ public function setFlowCode($flow_code)
+ {
+ $this->flow_code = $flow_code;
+ return $this;
+ }
+ /**
+ * @return mixed
+ */
+ public function setFlowId($flow_id)
+ {
+ $this->flow_id = $flow_id;
+ return $this;
+ }
+ /**
+ * @return mixed
+ */
+ public function getFlowCode()
+ {
+ return $this->flow_code;
+ }
+}
diff --git a/workflow/model/NodeTask.php b/workflow/model/NodeTask.php
new file mode 100644
index 00000000..d3356d49
--- /dev/null
+++ b/workflow/model/NodeTask.php
@@ -0,0 +1,426 @@
+ "CounterSignSubtaskHandler",
+ self::NEXT_ASSIGNER_MODIFY_TASK => "NextAssignerModifyTaskHandler",
+ self::FH_TASK => "FhTaskHandler",
+ self::B4_TASK => "B4TaskHandler",
+ self::B7_TASK => "B7TaskHandler"
+ );
+
+ public function update()
+ {
+ $where = "task_id = '" . $this->task_id . "'";
+ DB::update_table("workflow_task", array(
+ "form_key" => $this->getFormKey(),
+ "flow_code" => $this->getFlowCode(),
+ "task_type" => $this->getTaskType(),
+ "completion_condition" => $this->getCompletionCondition(),
+ "state" => $this->getState(),
+ "join_role" => $this->getJoinRole(),
+ "role_type" => $this->getRoleType(),
+ "necessary" => $this->getNecessary(),
+ "creator" => $this->getCreator(),
+ "error_info" => $this->getErrorInfo(),
+ "create_code" => $this->getCreateCode(),
+ "wf_condition" => $this->getWfCondition(),
+ "remark" => $this->getRemark()
+ ), $where);
+ }
+
+ public function delete()
+ {
+ DB::query("delete from workflow_task where task_id='" . $this->task_id . "' ", $db = 'default');
+ }
+
+ function parseRole()
+ {
+ $function = "_roleIs" . $this->getRoleType();
+ if (!method_exists('NodeTask', $function)) {
+ return self::processUndefined($function);
+ }
+ return $this->$function();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCreator()
+ {
+ return $this->creator;
+ }
+
+ /**
+ * @param mixed $creator
+ * @return NodeTask
+ */
+ public function setCreator($creator)
+ {
+ $this->creator = $creator;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCreateCode()
+ {
+ return $this->create_code;
+ }
+
+ /**
+ * @param mixed $create_code
+ * @return NodeTask
+ */
+ public function setCreateCode($create_code)
+ {
+ $this->create_code = $create_code;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWfCondition()
+ {
+ return $this->wf_condition;
+ }
+
+ /**
+ * @param mixed $condition
+ * @return NodeTask
+ */
+ public function setWfCondition($condition)
+ {
+ $this->wf_condition = $condition;
+ return $this;
+ }
+
+ private function _roleIsString()
+ {
+ #以下为专人
+ $strAssign = $this->getJoinRole();
+ $assignEmps = array();
+ $arr_a = explode('|', $strAssign);
+ foreach ($arr_a as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ $arr_b = explode(':', $value);
+ $val = explode('-', $arr_b[0]);
+ $arr_c = explode(',', $arr_b[1]);
+ $str_next_user = "";
+ foreach ($arr_c as $key => $value) {
+ if (empty($value)) {
+ continue;
+ }
+ if ($value == '00000') {
+ $str_next_user .= '00000' . '-' . "00000,";
+ } else {
+ $str_next_user .= AssignerStringParser::process($value);
+ }
+ }
+ array_push($assignEmps, array(
+ 'assign_status' => $val[0], //assign_status
+ 'assigner_string' => $str_next_user
+ ));
+ }
+ return $assignEmps;
+ }
+
+ private function _roleIsSQL()
+ {
+ return DB::result($this->getJoinRole());
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTaskId()
+ {
+ return $this->task_id;
+ }
+
+ /**
+ * @param mixed $task_id
+ * @return NodeTask
+ */
+ public function setTaskId($task_id)
+ {
+ $this->task_id = $task_id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTaskType()
+ {
+ return $this->task_type;
+ }
+
+ /**
+ * @param mixed $task_type
+ * @return NodeTask
+ */
+ public function setTaskType($task_type)
+ {
+ $this->task_type = $task_type;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlowCode()
+ {
+ return $this->flow_code;
+ }
+
+ /**
+ * @param mixed $flow_code
+ * @return NodeTask
+ */
+ public function setFlowCode($flow_code)
+ {
+ $this->flow_code = $flow_code;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFormKey()
+ {
+ return $this->form_key;
+ }
+
+ /**
+ * @param mixed $form_key
+ * @return NodeTask
+ */
+ public function setFormKey($form_key)
+ {
+ $this->form_key = $form_key;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getNecessary()
+ {
+ return $this->necessary;
+ }
+
+ /**
+ * @param mixed $necessary
+ * @return NodeTask
+ */
+ public function setNecessary($necessary)
+ {
+ $this->necessary = $necessary;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCompletionCondition()
+ {
+ return $this->completion_condition;
+ }
+
+ /**
+ * @param mixed $completion_condition
+ * @return NodeTask
+ */
+ public function setCompletionCondition($completion_condition)
+ {
+ $this->completion_condition = $completion_condition;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+
+ /**
+ * @param mixed $state
+ * @return NodeTask
+ */
+ public function setState($state)
+ {
+ $this->state = $state;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getJoinRole()
+ {
+ return $this->join_role;
+ }
+
+ /**
+ * @param mixed $join_role
+ * @return NodeTask
+ */
+ public function setJoinRole($join_role)
+ {
+ $this->join_role = $join_role;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getErrorInfo()
+ {
+ return $this->error_info;
+ }
+
+ /**
+ * @param mixed $error_info
+ * @return NodeTask
+ */
+ public function setErrorInfo($error_info)
+ {
+ $this->error_info = $error_info;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRemark()
+ {
+ return $this->remark;
+ }
+
+ /**
+ * @param mixed $remark
+ * @return NodeTask
+ */
+ public function setRemark($remark)
+ {
+ $this->remark = $remark;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCreateDate()
+ {
+ return $this->create_date;
+ }
+
+ /**
+ * @param mixed $create_date
+ * @return NodeTask
+ */
+ public function setCreateDate($create_date)
+ {
+ $this->create_date = $create_date;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFinishDate()
+ {
+ return $this->finish_date;
+ }
+
+ /**
+ * @param mixed $finish_date
+ * @return NodeTask
+ */
+ public function setFinishDate($finish_date)
+ {
+ $this->finish_date = $finish_date;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getPhase()
+ {
+ return $this->phase;
+ }
+
+ /**
+ * @param mixed $phase
+ * @return NodeTask
+ */
+ public function setPhase($phase)
+ {
+ $this->phase = $phase;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getRoleType()
+ {
+ return $this->role_type;
+ }
+
+ /**
+ * @param mixed $role_type
+ * @return NodeTask
+ */
+ public function setRoleType($role_type)
+ {
+ $this->role_type = $role_type;
+ return $this;
+ }
+}
diff --git a/workflow/model/Subflow.php b/workflow/model/Subflow.php
new file mode 100644
index 00000000..5a6e8f72
--- /dev/null
+++ b/workflow/model/Subflow.php
@@ -0,0 +1,150 @@
+getFormKey() == null) {
+ $this->form_key = Flow::getNewFormKey();
+ } else {
+ $this->form_key = $flow->getFormKey();
+ }
+ }
+
+ function getFormKey()
+ {
+ return $this->form_key;
+ }
+
+ public static function delete($formKey = null)
+ {
+ DB::query("DELETE subflow WHERE Form_Key = '" . $formKey . "'");
+ }
+
+ /**
+ * @param $userId
+ * @return $this
+ */
+ public function setCurrentUser($userId)
+ {
+ $this->current_assigner = $userId;
+ return $this;
+ }
+
+ /**
+ *变更当前签核人员
+ * @param $formKey
+ * @param $userId
+ */
+ public static function updateCurrentUser($formKey, $userId)
+ {
+ $where = "form_key = '" . $formKey . "'";;
+ DB::update_table("subflow", array(
+ "current_assigner" => $userId,
+ ), $where);
+
+ }
+
+ /**
+ * 获取当前签核者
+ * @param $formKey
+ * @return userId
+ */
+ public static function getCurrentUser($formKey)
+ {
+ list($currentAssigner) = DB::fields("SELECT current_assigner
+ FROM subflow where form_key ='$formKey'");
+
+ return $currentAssigner;
+ }
+
+ /***
+ *
+ *关闭签核
+ * @param null $formKey
+ */
+ public static function close($formKey = null)
+ {
+ $where = "form_key = '" . $formKey . "'";;
+ DB::update_table("subflow", array(
+ "current_assigner" => '00000'
+ ), $where);
+ }
+
+ /**
+ *
+ * @param null $formKey
+ */
+ public static function suspend($formKey = null)
+ {
+
+ self::updateRealId($formKey, self::getCurrentUser($formKey));
+ $where = "form_key = '" . $formKey . "'";
+ DB::update_table("subflow", array(
+ "current_assigner" => self::SUSPEND_STATE,
+
+ ), $where);
+ }
+
+ /**
+ *
+ * @param $formKey
+ * @param $userId
+ */
+ public static function updateRealId($formKey, $userId)
+ {
+ $where = "form_key = '" . $formKey . "'";;
+ DB::update_table("subflow", array(
+ "real_id" => $userId,
+ ), $where);
+ }
+
+ /**
+ *
+ * @param $formKey
+ * @param $userId
+ * @return
+ */
+ public static function getRealId($formKey)
+ {
+ list($real_id) = DB::fields("SELECT real_id
+ FROM subflow where form_key ='$formKey'");
+ return $real_id;
+
+ }
+
+ /**
+ * 插入记录
+ * @return int
+ */
+ public function insert()
+ {
+ list($cnt) = DB::fields("select count(*) from subflow where from_key='" . $this->form_key . "' ");
+ if ($cnt == 0) {
+ DB::insert_table("subflow", array(
+ "form_key" => $this->form_key,
+ "seq" => $this->seq + 1,
+ "current_assigner" => $this->current_assigner,
+ "real_id" => $this->real_id
+ ));
+ return 1;
+ }
+ return -1;
+
+ }
+
+ public function __toString()
+ {
+ return json_encode($this);
+ }
+}
+
diff --git a/workflow/model/SubflowManager.php b/workflow/model/SubflowManager.php
new file mode 100644
index 00000000..619ce9d5
--- /dev/null
+++ b/workflow/model/SubflowManager.php
@@ -0,0 +1,242 @@
+parent_key = $parentFlow->getFormKey();
+ }
+ $this->seq = $this->_getSeq();
+ }
+
+ public function __toString()
+ {
+ return json_encode($this);
+ }
+
+ public static function getDetail($parentKey, $seq = 0)
+ {
+ $detail = DB::result("select * from workflow_subflow where
+ seq='" . $seq . "' and parent_key ='" . $parentKey . "'");
+ return $detail;
+
+ }
+
+ /**
+ * @desc workflow_sublow 新增一条记录
+ * @param Subflow $subflow
+ * @param $sender
+ * @param int $seq
+ */
+ public function append(Subflow $subflow, $sender, $seq = null)
+ {
+ DB::query("insert into workflow_subflow (FORM_KEY, SEQ, PARENT_KEY, LEADER_NO, CREATE_DATE, SENDER)
+ values ('" . $subflow->getFormKey() . "',
+ '" . $this->seq . "',
+ '" . $this->parent_key . "',
+ '" . $subflow->current_assigner . "',
+ now(),
+ '" . $sender . "' ) ");
+
+ }
+
+ static function getChildNode($childFormKey)
+ {
+
+
+ $node = DB::result("select * from workflow_subflow where form_key
+ ='" . $childFormKey . "'");
+ return $node[0];
+ }
+
+ /**
+ * 未回复统计
+ * @return integer|null
+ */
+ public function getUnReplyCount($seq = null)
+ {
+ if ($seq == null) {
+ return null;
+ }
+ list($cnt) = DB::fields("select count(*) from workflow_subflow where
+ reply_flag is null and seq='" . $seq . "' and parent_key ='" . $this->parent_key . "'");
+ return $cnt;
+ }
+
+ /**
+ * 未回复明细
+ * @return array|void
+ */
+ public function getUnReplyDetail($seq = null)
+ {
+ if ($seq == null) {
+ return null;
+ }
+ list($detail) = DB::fields("select * from workflow_subflow where
+ reply_flag is null and seq='" . $seq . "' and parent_key ='" . $this->parent_key . "'");
+ return $detail;
+ }
+
+ /**
+ * 已回复统计
+ * @param null $seq
+ * @return integer
+ */
+ public function getReplyCount($seq = null)
+ {
+ if ($seq == null) {
+ return null;
+ }
+ list($cnt) = DB::fields("select count(*) from workflow_subflow where
+ reply_flag is not null and seq='" . $seq . "' and parent_key ='" . $this->parent_key . "'");
+ return $cnt;
+ }
+
+ /**
+ * 已回复明细
+ * @param null $seq 会签的序号
+ * @return integer
+ */
+ public function getReplyDetail($seq = null)
+ {
+ if ($seq == null) {
+ return null;
+ }
+ $detail = DB::result("select * from workflow_subflow where
+ reply_flag is not null and seq='" . $seq . "' and parent_key ='" . $this->parent_key . "'");
+ return $detail;
+ }
+
+ /**
+ * 获取$parentKey 已经会签或拆分的次数
+ * @return integer
+ */
+ private function _getSeq()
+ {
+ list($cnt) = DB::fields("select nvl(max(seq),-1)+1 from workflow_subflow where
+ parent_key ='" . $this->parent_key . "'");
+ return $cnt;
+ }
+
+ /**
+ * 获取$parentKey已经会签或拆分的次数
+ * @return integer
+ */
+ public static function getSeqByFormKey($formKey)
+ {
+ list($seq) = DB::fields("select seq from workflow_subflow where
+ form_key ='" . $formKey . "'");
+ return $seq;
+ }
+
+ /**
+ * 获取该节点
+ * @param $formKey
+ * @return integer
+ */
+ public static function getCurrentParentFlowCode($formKey)
+ {
+ $flow = new Flow($formKey);
+ list($flow_code) = DB::fields("select flow_code from flow where
+ form_key ='" . $flow->getParentKey() . "'");
+ return $flow_code;
+ }
+
+ /**
+ * @param $formKey
+ * @param $flag REPLY_FLAG
+ */
+ public static function updateReplyFlag($formKey, $flag)
+ {
+ $where = "form_key = '" . $formKey . "'";
+ DB::update_table("workflow_subflow", array(
+ "REPLY_FLAG" => "'" . $flag . "'"
+ ), $where);
+
+ }
+
+ /**
+ *
+ * 获取会签中不同意的数量
+ * @param $seq
+ * @return null
+ */
+ public function getRejectOpinionCount($seq)
+ {
+ if ($seq == null) {
+ return null;
+ }
+ $details = $this->getReplyDetail($seq);
+ $cnt = 0;
+ foreach ($details as $row) {
+ if ($row['reply_flag'] == 'N') {
+ $cnt++;
+ }
+ }
+ return $cnt;
+
+ }
+
+ /**
+ *
+ * 获取会签中不同意的数量
+ */
+ public function getAcceptOpinionCount($seq)
+ {
+ if ($seq == null) {
+ return null;
+ }
+ $details = $this->getReplyDetail($seq);
+ $cnt = 0;
+ foreach ($details as $row) {
+ if ($row['reply_flag'] == 'Y') {
+ $cnt++;
+ }
+ }
+ return $cnt;
+
+ }
+
+ public static function updateReplyComment($formKey, $comment)
+ {
+ $where = "form_key = '" . $formKey . "'";
+ DB::update_table("workflow_subflow", array(
+ "REPLY_COMMENT" => "'" . $comment . "'"
+ ), $where);
+ self::updateChangeDate($formKey);
+ }
+
+ public static function getReplyComment($formKey)
+ {
+
+ $detail = DB::result("select reply_comment from workflow_subflow where
+ form_key='" . $formKey . "'");
+ return $detail;
+ }
+
+ public static function getCounterSignComments($parentKey)
+ {
+ $sql = "select rownum seq ,seq CS_SEQ ,LEADER_NO ASSIGNER,reply_comment ASSIGN_OPINION ,change_date ASSIGN_DATE , LEAD_CODE,
+ f_return_content('lead_code',LEAD_CODE) POSITION_NAME,case Reply_flag when 'Y' then 'F1'
+ when 'N' then 'Y1' else 'A4' end ASSIGN_STATUS,'' FLOW_CODE from workflow_subflow a,employee b
+ where parent_key='" . $parentKey . "' and a.leader_no=b.employee_no";
+ return DB::result($sql);
+ }
+
+ public static function updateChangeDate($formKey)
+ {
+ $sql = "update workflow_subflow set change_date=sysdate where form_key='" . $formKey . "'";
+ DB::query($sql);
+ }
+
+}
\ No newline at end of file
diff --git a/workflow/model/TaskManager.php b/workflow/model/TaskManager.php
new file mode 100644
index 00000000..afd715a1
--- /dev/null
+++ b/workflow/model/TaskManager.php
@@ -0,0 +1,122 @@
+setTaskId($row['task_id'])
+ ->setFormKey($row['form_key'])
+ ->setNecessary($row['necessary'])
+ ->setTaskType($row['task_type'])
+ ->setErrorInfo($row['error_info'])
+ ->setRemark($row['remark'])
+ ->setFlowCode($row['flow_code'])
+ ->setCompletionCondition($row['completion_condition'])
+ ->setState($row['state'])
+ ->setCreator($row['creator'])
+ ->setJoinRole($row['join_role'])
+ ->setRoleType($row['role_type'])
+ ->setTaskType($row['task_type'])
+ ->setWfCondition($row['wf_condition'])
+ ->setCreateCode($row['create_code']);
+
+ array_push($tasks, $task);
+ }
+ return $tasks;
+ }
+
+ public static function getTasks(NodeTask $task)
+ {
+ $taskClass = new ReflectionClass('NodeTask');
+ $props = $taskClass->getProperties();
+
+ $condition = array();
+ $sql = "select * From workflow_task where 1=1 ";
+ foreach ($props as $prop) {
+ $val = $prop->getValue($task);
+ $name = $prop->getName();
+ if (is_null($val) || empty($val) || $prop->isStatic()) continue;
+ $condition[$name] = $val;
+ $sql .= " and $name = '$val' ";
+ }
+ $tasks = array();
+ //return $tasks;
+ $result = DB::result($sql, true);
+ $tasks = array();
+ // var_dump( $result);
+ foreach ($result as $row) {
+ $task = new NodeTask();
+ $task->setTaskId($row['task_id'])
+ ->setFormKey($row['form_key'])
+ ->setNecessary($row['necessary'])
+ ->setTaskType($row['task_type'])
+ ->setErrorInfo($row['error_info'])
+ ->setRemark($row['remark'])
+ ->setFlowCode($row['flow_code'])
+ ->setCompletionCondition($row['completion_condition'])
+ ->setState($row['state'])
+ ->setJoinRole($row['join_role'])
+ ->setCreator($row['creator'])
+ ->setRoleType($row['role_type'])
+ ->setWfCondition($row['wf_condition'])
+ ->setTaskType($row['task_type'])
+ ->setCreateCode($row['create_code']);
+ array_push($tasks, $task);
+ }
+ return $tasks;
+ }
+
+ static function closeTaskByFormKey($formKey, $flowCode = "")
+ {
+ return null;
+ }
+
+ public static function insertTask(NodeTask $task)
+ {
+ $task_id = self::getNewTaskId();
+ //var_dump( $task_id);
+ DB::insert_table("workflow_task", array(
+ "task_id" => $task_id,
+ "form_key" => $task->getFormKey(),
+ "flow_code" => $task->getFlowCode(),
+ "task_type" => $task->getTaskType(),
+ "completion_condition" => $task->getCompletionCondition(),
+ "state" => $task->getState(),
+ "necessary" => $task->getNecessary(),
+ "error_info" => $task->getErrorInfo(),
+ "join_role" => $task->getJoinRole(),
+ "creator" => $task->getCreator(),
+ "role_type" => $task->getRoleType(),
+ "remark" => $task->getRemark(),
+ "phase" => $task->getPhase(),
+ "wf_condition" => $task->getWfCondition(),
+ 'create_code' => $task->getCreateCode(),
+ ));
+ return $task_id;
+ }
+
+ static function getNewTaskId()
+ {
+ list($msec, $sec) = explode(' ', microtime());
+ return date('YmdHis') . str_pad((sprintf("%0.4f", $msec) * 10000), 4, STR_PAD_LEFT);
+ }
+}
diff --git a/workflow/model/WorkFLowItems.php b/workflow/model/WorkFLowItems.php
new file mode 100644
index 00000000..c7b942eb
--- /dev/null
+++ b/workflow/model/WorkFLowItems.php
@@ -0,0 +1,240 @@
+setSystemId($systemId)
+ ->setFlowId($flowId);
+ }
+
+ /**
+ * @param string $systemId
+ * @param string $flowId
+ * @return array|void
+ */
+ public static function get_records($systemId = "", $flowId = "")
+ {
+ // var_dump($_SERVER['DOCUMENT_ROOT']);
+
+ $where = " ";
+ $where .= !empty($systemId) ? (" and system_id like '" . $systemId . "%'") : "";
+ $where .= !empty($flowId) ? (" and flow_id like '" . $flowId . "%'") : "";
+ $where = $where == "where " ? "" : $where;
+
+ return DB::result("SELECT system_id,flow_id,creator,create_date,
+ wf_file,wf_layout,wf_version,wf_name
+ FROM workflow_items where 1=1 " . $where, false);
+ }
+
+ public function save()
+ {
+
+ #这里针对主机
+ $directory = self::PREFIX_SAVE_DIR . $this->getSystemId();
+ if (!file_exists($directory)) {
+ mkdir($directory, 0777, true);
+ chmod($directory, 0777);
+ }
+ $this->setWfFile($this->getFlowId() . ".json");
+ $path = $directory . "/" . $this->getWfFile();
+ echo $path;
+ DB::query("delete from workflow_items where
+ system_id='" . $this->getSystemId() . "' and flow_id='" . $this->getFlowId() . "'");
+
+ DB::insert_table("workflow_items", array(
+ 'system_id' => $this->getsystemid(),
+ 'flow_id' => $this->getflowid(),
+ 'creator' => $this->getcreator(),
+ 'wf_name' => $this->getwffile(),
+ 'wf_version' => $this->getwfversion(),
+ 'wf_layout' => "null",
+ 'wf_file' => $path
+ ));
+ file_put_contents($path, $this->getFlowChart());
+ }
+
+ public function parseFcToFields($flowChart = null)
+ {
+
+ $flowChart = empty($flowChart) ? $this->getFlowChart() : $flowChart;
+ $_flowChart = json_decode($flowChart, true);
+ $this->setWfVersion($_flowChart['version'])->setSystemId($_flowChart['systemId'])
+ ->setFlowChart($flowChart)->setFlowId($_flowChart['flowId'])->setWfName($_flowChart['flowName']);
+ return $this;
+ }
+
+ public function setFlowChart($flowChart)
+ {
+ $this->flow_chart = $flowChart;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getSystemId()
+ {
+ return $this->system_id;
+ }
+
+ /**
+ * @param mixed $system_id
+ * @return WorkFLowItems
+ */
+ public function setSystemId($system_id)
+ {
+ $this->system_id = $system_id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlowId()
+ {
+ return $this->flow_id;
+ }
+
+ /**
+ * @param mixed $flow_id
+ * @return WorkFLowItems
+ */
+ public function setFlowId($flow_id)
+ {
+ $this->flow_id = $flow_id;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCreator()
+ {
+ return $this->creator;
+ }
+
+ /**
+ * @param mixed $creator
+ * @return WorkFLowItems
+ */
+ public function setCreator($creator)
+ {
+ $this->creator = $creator;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCreateDate()
+ {
+ return $this->create_date;
+ }
+
+ /**
+ * @param mixed $create_date
+ * @return WorkFLowItems
+ */
+ public function setCreateDate($create_date)
+ {
+ $this->create_date = $create_date;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWfFile()
+ {
+ return $this->wf_file;
+ }
+
+ /**
+ * @param mixed $wf_file
+ * @return WorkFLowItems
+ */
+ public function setWfFile($wf_file)
+ {
+ $this->wf_file = $wf_file;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWfLayout()
+ {
+ return $this->wf_layout;
+ }
+
+ /**
+ * @param mixed $wf_layout
+ * @return WorkFLowItems
+ */
+ public function setWfLayout($wf_layout)
+ {
+ $this->wf_layout = $wf_layout;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWfVersion()
+ {
+ return $this->wf_version;
+ }
+
+ /**
+ * @param mixed $wf_version
+ * @return WorkFLowItems
+ */
+ public function setWfVersion($wf_version)
+ {
+ $this->wf_version = $wf_version;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWfName()
+ {
+ return $this->wf_name;
+ }
+
+ /**
+ * @param mixed $wf_name
+ * @return WorkFLowItems
+ */
+ public function setWfName($wf_name)
+ {
+ $this->wf_name = $wf_name;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFlowChart()
+ {
+ return $this->flow_chart;
+ }
+}