alias("a") ->join(['school_personnel' => 'b'],'a.applicant_id = b.id','left') ->join(['school_personnel' => 'c'],'a.current_approver_id = c.id','left') ->where($where) ->field($field) ->order($order) ->page($page, $limit) ->select() ->toArray(); $count = (new SchoolApprovalProcess())->where($where)->count(); return [ 'list' => $list, 'count' => $count ]; } /** * 获取审批流程详情 * @param int $id * @return array */ public function getInfo(int $id): array { $info = (new SchoolApprovalProcess()) ->alias("a") ->join(['school_personnel' => 'b'],'a.applicant_id = b.id','left') ->join(['school_personnel' => 'c'],'a.current_approver_id = c.id','left') ->with(['participants']) ->where(['a.id' => $id]) ->field('a.*,b.name as applicant_name,c.name as current_approver_name') ->find(); if (empty($info)) { return []; } $info = $info->toArray(); $Personnel = new Personnel(); foreach ($info['participants'] as $key => $value) { $info['participants'][$key]['name'] = $Personnel->where(['id' => $value['participant_id']])->value('name'); } return $info; } /** * 创建审批流程 * @param array $data * @param int $config_id 审批配置ID * @return int * @throws \Exception */ public function create(array $data, int $config_id): int { Db::startTrans(); try { // 获取审批配置详情 $config_info = (new SchoolApprovalConfigService())->getInfo($config_id); if (empty($config_info)) { throw new Exception('审批配置不存在'); } // 创建审批流程 $process = [ 'process_name' => $data['process_name'], 'applicant_id' => $data['applicant_id'], 'application_time' => date("Y-m-d H:i:s"), 'current_approver_id' => 0, // 初始时为0,后面会更新 'approval_status' => SchoolApprovalProcess::STATUS_PENDING, 'remarks' => $data['remarks'] ?? '', 'business_type' => $data['business_type'] ?? '', 'business_id' => $data['business_id'] ?? 0, 'business_data' => isset($data['business_data']) ? json_encode($data['business_data']) : '' ]; $process_id = (new SchoolApprovalProcess())->insertGetId($process); // 创建审批参与人 $participants = []; foreach ($config_info['nodes'] as $sequence => $node) { $approver_ids = explode(',', $node['approver_ids']); foreach ($approver_ids as $approver_id) { $participants[] = [ 'process_id' => $process_id, 'participant_id' => $approver_id, 'sequence' => $node['sequence'], 'status' => SchoolApprovalParticipants::STATUS_PENDING, 'sign_type' => $node['sign_type'] ]; } } if (!empty($participants)) { (new SchoolApprovalParticipants())->insertAll($participants); // 更新当前审批人为第一个审批人 $first_participant = (new SchoolApprovalParticipants()) ->where(['process_id' => $process_id]) ->order('sequence', 'asc') ->find(); if (!empty($first_participant)) { (new SchoolApprovalProcess())->where(['id' => $process_id]) ->update(['current_approver_id' => $first_participant['participant_id']]); } } Db::commit(); return $process_id; } catch (\Exception $e) { Db::rollback(); throw new Exception($e->getMessage()); } } /** * 创建人员添加审批流程 * @param array $personnelData 人员数据 * @param int $applicantId 申请人ID * @param int $configId 审批配置ID * @return int * @throws \Exception */ public function createPersonnelApproval(array $personnelData, int $applicantId, int $configId): int { // 创建审批流程数据 $processData = [ 'process_name' => '人员添加申请 - ' . $personnelData['name'], 'applicant_id' => $applicantId, 'remarks' => '申请添加新员工:' . $personnelData['name'] . ',职位:' . ($personnelData['position'] ?? '未指定'), 'business_type' => 'personnel_add', 'business_id' => 0, // 暂时为0,等人员创建后更新 'business_data' => $personnelData ]; return $this->create($processData, $configId); } /** * 审批 * @param int $process_id 流程ID * @param int $approver_id 审批人ID * @param string $status 审批状态 * @param string $remarks 备注 * @return bool * @throws \Exception */ public function approve(int $process_id, int $approver_id, string $status, string $remarks = ''): bool { Db::startTrans(); try { // 获取审批流程 $process_info = (new SchoolApprovalProcess())->where(['id' => $process_id])->find(); if (empty($process_info)) { throw new Exception('审批流程不存在'); } // 检查是否当前审批人 if ($process_info['current_approver_id'] != $approver_id) { throw new Exception('您不是当前审批人'); } // 检查流程状态 if ($process_info['approval_status'] != SchoolApprovalProcess::STATUS_PENDING) { throw new Exception('该审批流程已完成'); } // 获取当前审批节点 $current_participant = (new SchoolApprovalParticipants()) ->where([ 'process_id' => $process_id, 'participant_id' => $approver_id, 'status' => SchoolApprovalParticipants::STATUS_PENDING ]) ->find(); if (empty($current_participant)) { throw new Exception('审批节点信息错误'); } // 更新当前审批人状态 (new SchoolApprovalParticipants())->where(['id' => $current_participant['id']]) ->update([ 'status' => $status, 'remarks' => $remarks ]); // 如果拒绝,直接更新整个流程状态为拒绝 if ($status == SchoolApprovalParticipants::STATUS_REJECTED) { (new SchoolApprovalProcess())->where(['id' => $process_id]) ->update([ 'approval_status' => SchoolApprovalProcess::STATUS_REJECTED, 'approval_time' => time(), 'remarks' => $remarks ]); // 处理拒绝后的业务逻辑 $this->handleApprovalRejected($process_id); Db::commit(); return true; } // 检查当前节点是否需要会签 $same_sequence_participants = (new SchoolApprovalParticipants()) ->where([ 'process_id' => $process_id, 'sequence' => $current_participant['sequence'], 'status' => SchoolApprovalParticipants::STATUS_PENDING ]) ->select(); // 如果是会签且还有其他人未审批,则等待 if ($current_participant['sign_type'] == SchoolApprovalParticipants::SIGN_TYPE_AND && !$same_sequence_participants->isEmpty()) { // 不做任何处理,等待其他人审批 Db::commit(); return true; } // 获取下一个审批节点 $next_participant = (new SchoolApprovalParticipants()) ->where([ 'process_id' => $process_id, 'status' => SchoolApprovalParticipants::STATUS_PENDING ]) ->order('sequence', 'asc') ->find(); if (empty($next_participant)) { // 没有下一个审批人,流程结束,标记为已通过 (new SchoolApprovalProcess())->where(['id' => $process_id]) ->update([ 'approval_status' => SchoolApprovalProcess::STATUS_APPROVED, 'approval_time' => time() ]); // 处理业务逻辑 $this->handleApprovalCompleted($process_id); } else { // 更新当前审批人为下一个审批人 (new SchoolApprovalProcess())->where(['id' => $process_id]) ->update(['current_approver_id' => $next_participant['participant_id']]); } Db::commit(); return true; } catch (\Exception $e) { Db::rollback(); throw new Exception($e->getMessage()); } } /** * 撤销审批流程 * @param int $process_id 流程ID * @param int $applicant_id 申请人ID * @return bool * @throws \Exception */ public function cancel(int $process_id, int $applicant_id): bool { Db::startTrans(); try { // 获取审批流程 $process_info = (new SchoolApprovalProcess())->where(['id' => $process_id])->find(); if (empty($process_info)) { throw new Exception('审批流程不存在'); } // 检查是否申请人 if ($process_info['applicant_id'] != $applicant_id) { throw new Exception('您不是该流程的申请人'); } // 检查流程状态 if ($process_info['approval_status'] != SchoolApprovalProcess::STATUS_PENDING) { throw new Exception('该审批流程已完成,无法撤销'); } // 更新流程状态为已拒绝(撤销) (new SchoolApprovalProcess())->where(['id' => $process_id]) ->update([ 'approval_status' => SchoolApprovalProcess::STATUS_REJECTED, 'approval_time' => time(), 'remarks' => '申请人撤销' ]); // 更新所有待审批节点为已拒绝 (new SchoolApprovalParticipants())->where([ 'process_id' => $process_id, 'status' => SchoolApprovalParticipants::STATUS_PENDING ])->update([ 'status' => SchoolApprovalParticipants::STATUS_REJECTED, 'remarks' => '申请人撤销' ]); Db::commit(); return true; } catch (\Exception $e) { Db::rollback(); throw new Exception($e->getMessage()); } } /** * 处理审批完成后的业务逻辑 * @param int $process_id * @throws \Exception */ private function handleApprovalCompleted(int $process_id): void { // 获取流程信息 $process = (new SchoolApprovalProcess())->where(['id' => $process_id])->find(); if (empty($process)) { throw new Exception('流程信息不存在'); } // 根据业务类型处理 switch ($process['business_type']) { case 'personnel_add': $this->handlePersonnelAddApproval($process); break; default: // 其他业务类型的处理逻辑 break; } } /** * 处理人员添加审批完成 * @param $process * @throws \Exception */ private function handlePersonnelAddApproval($process): void { if (empty($process['business_data'])) { throw new Exception('人员数据不存在'); } $personnelData = json_decode($process['business_data'], true); if (empty($personnelData)) { throw new Exception('人员数据格式错误'); } try { // 调用人员服务创建正式人员记录 $personnelService = new \app\service\admin\personnel\PersonnelService(); // 准备人员数据 $createData = $personnelData; $createData['status'] = 1; // 设置为正常状态 // 创建人员记录 $personnelId = $personnelService->add($createData); // 更新流程的business_id为实际创建的人员ID (new SchoolApprovalProcess())->where(['id' => $process['id']]) ->update(['business_id' => $personnelId]); } catch (\Exception $e) { throw new Exception('创建人员记录失败:' . $e->getMessage()); } } /** * 处理审批拒绝后的业务逻辑 * @param int $process_id * @throws \Exception */ private function handleApprovalRejected(int $process_id): void { // 获取流程信息 $process = (new SchoolApprovalProcess())->where(['id' => $process_id])->find(); if (empty($process)) { return; } // 根据业务类型处理 switch ($process['business_type']) { case 'personnel_add': // 人员添加被拒绝,不需要特殊处理 break; default: // 其他业务类型的处理逻辑 break; } } }