|
|
@@ -0,0 +1,592 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Service;
|
|
|
+
|
|
|
+use App\Model\Draft;
|
|
|
+use App\Model\Employee;
|
|
|
+use App\Model\WorkFlowInstances;
|
|
|
+use App\Model\WorkFlowInstancesNodes;
|
|
|
+use App\Model\WorkFlowTemplates;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+
|
|
|
+class WorkFlowService extends Service
|
|
|
+{
|
|
|
+ public function workFlowEdit($data,$user){
|
|
|
+ list($status,$msg) = $this->workFlowRule($data, $user, false);
|
|
|
+ if(!$status) return [$status,$msg];
|
|
|
+
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+
|
|
|
+ $model = WorkFlowTemplates::where('id', $data['id'])->first();
|
|
|
+ $model->code = $data['code'] ?? '';
|
|
|
+ $model->title = $data['title'] ?? '';
|
|
|
+ $model->content = $data['content'] ?? '';
|
|
|
+ $model->save();
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+ }catch (\Exception $exception){
|
|
|
+ DB::rollBack();
|
|
|
+ return [false,$exception->getMessage()];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function workFlowAdd($data,$user){
|
|
|
+ list($status,$msg) = $this->workFlowRule($data, $user);
|
|
|
+ if(!$status) return [$status,$msg];
|
|
|
+
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+
|
|
|
+ $model = new WorkFlowTemplates();
|
|
|
+ $model->code = $data['code'] ?? '';
|
|
|
+ $model->title = $data['title'] ?? '';
|
|
|
+ $model->content = $data['content'] ?? '';
|
|
|
+ $model->crt_id = $user['id'];
|
|
|
+ $model->top_depart_id = $user['top_depart_id'];
|
|
|
+ $model->save();
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+ }catch (\Exception $exception){
|
|
|
+ DB::rollBack();
|
|
|
+ return [false,$exception->getMessage()];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function workFlowDetail($data, $user){
|
|
|
+ if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
|
|
|
+ $customer = WorkFlowTemplates::where('del_time',0)
|
|
|
+ ->where('id',$data['id'])
|
|
|
+ ->first();
|
|
|
+ if(empty($customer)) return [false,'审批流不存在或已被删除'];
|
|
|
+ $customer = $customer->toArray();
|
|
|
+
|
|
|
+ $customer['crt_name'] = Employee::where('id',$customer['crt_id'])->value('title');
|
|
|
+ $customer['crt_time'] = $customer['crt_time'] ? date("Y-m-d H:i:s",$customer['crt_time']): '';
|
|
|
+
|
|
|
+ return [true, $customer];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function workFlowDel($data, $user){
|
|
|
+ if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
|
|
|
+ $customer = WorkFlowTemplates::where('del_time',0)
|
|
|
+ ->where('id',$data['id'])
|
|
|
+ ->first();
|
|
|
+ if(empty($customer)) return [false,'审批流不存在或已被删除'];
|
|
|
+ $customer->del_time = time();
|
|
|
+ $customer->save();
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function workFlowCommon($data,$user, $field = []){
|
|
|
+ if(empty($field)) $field = WorkFlowTemplates::$field;
|
|
|
+
|
|
|
+ $model = WorkFlowTemplates::TopClear($user,$data);
|
|
|
+ $model = $model->where('del_time',0)
|
|
|
+ ->select($field)
|
|
|
+ ->orderby('id', 'desc');
|
|
|
+
|
|
|
+ if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
|
|
|
+ if(! empty($data['code'])) $model->where('code', 'LIKE', '%'.$data['code'].'%');
|
|
|
+ if(! empty($data['id'])) $model->whereIn('id', $data['id']);
|
|
|
+ if(! empty($data['crt_time'][0]) && ! empty($data['crt_time'][1])) {
|
|
|
+ $return = $this->changeDateToTimeStampAboutRange($data['crt_time']);
|
|
|
+ $model->where('crt_time','>=',$return[0]);
|
|
|
+ $model->where('crt_time','<=',$return[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $model;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function workFlowList($data,$user){
|
|
|
+ $model = $this->workFlowCommon($data, $user);
|
|
|
+ $list = $this->limit($model,'',$data);
|
|
|
+ $list = $this->fillData($list);
|
|
|
+
|
|
|
+ return [true, $list];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function workFlowRule(&$data, $user, $is_add = true) {
|
|
|
+ if(empty($data['title'])) return [false, '审批流名称不能为空'];
|
|
|
+ if(empty($data['code'])) return [false, '审批流编码不能为空'];
|
|
|
+ if(empty($data['content'])) return [false, '审批流内容不能为空'];
|
|
|
+
|
|
|
+ // 1. JSON 格式校验与转换
|
|
|
+ $content = $data['content'];
|
|
|
+ if (is_string($content)) {
|
|
|
+ $content = json_decode($content, true);
|
|
|
+ if (json_last_error() !== JSON_ERROR_NONE) {
|
|
|
+ return [false, '审批流内容格式错误,不是有效的JSON'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 结构完整性校验
|
|
|
+ if (!isset($content['nodes']) || !is_array($content['nodes'])) {
|
|
|
+ return [false, '审批流配置缺少节点(nodes)信息'];
|
|
|
+ }
|
|
|
+ if (!isset($content['edges']) || !is_array($content['edges'])) {
|
|
|
+ return [false, '审批流配置缺少连线(edges)信息'];
|
|
|
+ }
|
|
|
+
|
|
|
+ $data['content'] = $content;
|
|
|
+
|
|
|
+ // 4. 业务唯一性校验
|
|
|
+ $query = WorkFlowTemplates::where('code', $data['code'])
|
|
|
+ ->where('top_depart_id', $user['top_depart_id'])
|
|
|
+ ->where('del_time', 0);
|
|
|
+
|
|
|
+ if (!$is_add) {
|
|
|
+ if (empty($data['id'])) return [false, 'ID不能为空'];
|
|
|
+ $query->where('id', '<>', $data['id']);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($query->exists()) return [false, '审批流编码已存在'];
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function fillData($data){
|
|
|
+ if(empty($data['data'])) return $data;
|
|
|
+
|
|
|
+ $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_merge_recursive(array_column($data['data'],'charge_id'), array_column($data['data'],'crt_id'))));
|
|
|
+ foreach ($data['data'] as $key => $value){
|
|
|
+ $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
|
|
|
+ $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
|
|
|
+ }
|
|
|
+
|
|
|
+ return $data;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 触发审批流实例
|
|
|
+ * * @param string $templateCode 审批流唯一编码
|
|
|
+ * @param int $documentId 业务单据ID
|
|
|
+ * @param string $documentType 业务模型类名
|
|
|
+ * @param array $user 当前操作用户信息
|
|
|
+ */
|
|
|
+ public function triggerWorkflow($templateID, $documentId, $documentType, $user)
|
|
|
+ {
|
|
|
+ // 1. 获取对应的审批流模板
|
|
|
+ $template = WorkFlowTemplates::where('id', $templateID)
|
|
|
+ ->where('top_depart_id', $user['top_depart_id'])
|
|
|
+ ->where('del_time', 0)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (!$template) return [false, '审批模板不存在'];
|
|
|
+
|
|
|
+ // 2. 创建流程主实例
|
|
|
+ $instance = WorkFlowInstances::create([
|
|
|
+ 'template_id' => $template->id,
|
|
|
+ 'document_id' => $documentId,
|
|
|
+ 'document_type' => $documentType,
|
|
|
+ 'status' => WorkFlowInstances::status_two, // 激活
|
|
|
+ 'crt_id' => $user['id'],
|
|
|
+ 'crt_time' => time(),
|
|
|
+ 'upd_time' => time(),
|
|
|
+ 'top_depart_id' => $user['top_depart_id']
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 获取前端原始 JSON 中的节点和连线 [cite: 1]
|
|
|
+ $nodes = $template->content['nodes'];
|
|
|
+ $edges = $template->content['edges'];
|
|
|
+
|
|
|
+ // 3. 准备批量插入的节点数据
|
|
|
+ $insertNodes = [];
|
|
|
+ foreach ($nodes as $node) {
|
|
|
+ $nodeKey = $node['id'];
|
|
|
+
|
|
|
+ // 从 edges 中寻找当前节点的前置 (source 为谁) 和 后置 (target 为谁) [cite: 1]
|
|
|
+ // 这里的 source 和 target 是 edges 顶层的字符串 ID
|
|
|
+ $prev = collect($edges)->where('target', $nodeKey)->pluck('source')->first();
|
|
|
+ $next = collect($edges)->where('source', $nodeKey)->pluck('target')->first();
|
|
|
+
|
|
|
+ $tempAssignees = $node['data']['assignees'] ?? [];
|
|
|
+ foreach($tempAssignees as $k => $person) {
|
|
|
+ $tempAssignees[$k]['is_pass'] = 0; // 0-未审,1-通过,2-驳回
|
|
|
+ $tempAssignees[$k]['mark'] = '';
|
|
|
+ $tempAssignees[$k]['pass_time'] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ $insertNodes[] = [
|
|
|
+ 'instance_id' => $instance->id,
|
|
|
+ 'node_key' => $nodeKey,
|
|
|
+ 'label' => $node['label'] ?? '未命名节点',
|
|
|
+ 'prev_node_key' => $prev, // 上级节点 ID
|
|
|
+ 'next_node_key' => $next, // 下级节点 ID
|
|
|
+
|
|
|
+ // 审批人快照存储 [cite: 1]
|
|
|
+ 'assignees' => json_encode($tempAssignees),
|
|
|
+
|
|
|
+ // 审批类型:1 会签,2 或签 [cite: 1]
|
|
|
+ 'approval_type' => $node['data']['type'] ?? 2,
|
|
|
+
|
|
|
+ // 初始状态逻辑:如果没有前置节点,说明是首节点,直接进入“审批中”状态
|
|
|
+ 'status' => $prev ? 0 : 1,
|
|
|
+
|
|
|
+ 'handled_time' => 0,
|
|
|
+ 'crt_time' => time(),
|
|
|
+ 'upd_time' => time(),
|
|
|
+ 'crt_id' => $user['id'],
|
|
|
+ 'top_depart_id' => $user['top_depart_id']
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 写入节点实例表
|
|
|
+ WorkFlowInstancesNodes::insert($insertNodes);
|
|
|
+
|
|
|
+ return [true, $instance->id];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前用户的已办(已处理)审核列表
|
|
|
+ */
|
|
|
+ public function getMyHandledApprovals($data, $user)
|
|
|
+ {
|
|
|
+ $userId = $user['id'];
|
|
|
+ $topDepartId = $user['top_depart_id'];
|
|
|
+
|
|
|
+ // 1. 构造查询对象
|
|
|
+ $model = WorkFlowInstancesNodes::where('del_time', 0)
|
|
|
+ ->where('top_depart_id', $topDepartId)
|
|
|
+ // 核心条件变更:
|
|
|
+ // 条件A:我是审批人之一
|
|
|
+ ->whereRaw('JSON_CONTAINS(assignees, JSON_OBJECT("id", ?))', [$userId])
|
|
|
+ // 条件B:包含我已经审批通过(1)或审批驳回(2)的情况
|
|
|
+ ->whereRaw('(JSON_CONTAINS(assignees, JSON_OBJECT("id", ?, "is_pass", 1)) OR JSON_CONTAINS(assignees, JSON_OBJECT("id", ?, "is_pass", 2)))', [$userId, $userId])
|
|
|
+ ->select('*')
|
|
|
+ ->orderBy('id', 'desc');
|
|
|
+
|
|
|
+ $pageData = $this->limit($model, '', $data);
|
|
|
+
|
|
|
+ if (empty($pageData['data'])) return [true, $pageData];
|
|
|
+
|
|
|
+ // 2. 提取当前页的所有流程实例 ID
|
|
|
+ $instanceIds = array_unique(array_column($pageData['data'], 'instance_id'));
|
|
|
+
|
|
|
+ // 3. 获取流程实例及其关联的模板
|
|
|
+ $instances = WorkFlowInstances::with(['template'])
|
|
|
+ ->whereIn('id', $instanceIds)
|
|
|
+ ->get()
|
|
|
+ ->keyBy('id');
|
|
|
+
|
|
|
+ // --- 处理动态业务单据数据 ---
|
|
|
+ // 4. 按业务类型分组,批量查出单据的 code 和 title
|
|
|
+ $documentGroups = [];
|
|
|
+ foreach ($instances as $ins) {
|
|
|
+ $documentGroups[$ins->document_type][] = $ins->document_id;
|
|
|
+ }
|
|
|
+
|
|
|
+ $documentDataMap = []; // 存储结构: [type][id] => ['code' => ..., 'title' => ...]
|
|
|
+ foreach ($documentGroups as $type => $ids) {
|
|
|
+ $docs = DB::table($type)
|
|
|
+ ->whereIn('id', array_unique($ids))
|
|
|
+ ->select('id', 'code', 'title')
|
|
|
+ ->get()
|
|
|
+ ->keyBy('id')
|
|
|
+ ->toArray();
|
|
|
+ $documentDataMap[$type] = $docs;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 组装最终返回数据
|
|
|
+ foreach ($pageData['data'] as $key => $node) {
|
|
|
+ $instance = $instances[$node['instance_id']] ?? null;
|
|
|
+
|
|
|
+ // 获取关联业务表的具体数据
|
|
|
+ $docDetail = null;
|
|
|
+ if ($instance) {
|
|
|
+ $docDetail = $documentDataMap[$instance->document_type][$instance->document_id] ?? null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析出我个人的审批意见和审批时间
|
|
|
+ $assignees = is_string($node['assignees']) ? json_decode($node['assignees'], true) : $node['assignees'];
|
|
|
+ $mySnapshot = collect($assignees)->firstWhere('id', $userId);
|
|
|
+
|
|
|
+ $pageData['data'][$key] = [
|
|
|
+ 'node_instance_id' => $node['id'],
|
|
|
+ 'instance_id' => $node['instance_id'],
|
|
|
+ 'node_label' => $node['label'],
|
|
|
+ 'document_id' => $instance->document_id ?? 0,
|
|
|
+ 'document_type' => $instance->document_type ?? '',
|
|
|
+ 'document_code' => $docDetail->code ?? '', // 业务单据编号
|
|
|
+ 'document_title' => $docDetail->title ?? '', // 业务单据标题
|
|
|
+ 'workflow_title' => $instance->template->title ?? '', // 审批模板名
|
|
|
+ 'crt_time' => !empty($instance->crt_time->timestamp) ? date('Y-m-d H:i:s', $instance->crt_time->timestamp) : '',
|
|
|
+ 'approval_type' => $node['approval_type'],
|
|
|
+ 'approval_type_title'=> WorkFlowInstancesNodes::approval_type[$node['approval_type']] ?? '',
|
|
|
+
|
|
|
+ // --- 已办列表额外返回:我当时的处理结果 ---
|
|
|
+ 'my_handle_status' => $mySnapshot['is_pass'] ?? 0, // 我个人的处理状态:1-通过,2-驳回
|
|
|
+ 'my_handle_status_title' => WorkFlowInstancesNodes::is_pass_title[$mySnapshot['is_pass']] ?? '', // 我个人的处理状态:1-通过,2-驳回
|
|
|
+ 'my_handle_remark' => $mySnapshot['mark'] ?? '', // 我写下的审批意见
|
|
|
+ 'my_handle_time_fmt' => !empty($mySnapshot['pass_time']) ? date('Y-m-d H:i:s', $mySnapshot['pass_time']) : '', // 我的审批时间
|
|
|
+
|
|
|
+ // 整个流程目前的整体状态(方便前端展示:审批中、已通过、已驳回)
|
|
|
+ 'instance_status' => $instance->status ?? 0,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, $pageData];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前用户的待办审核列表
|
|
|
+ */
|
|
|
+ public function getMyPendingApprovals($data, $user)
|
|
|
+ {
|
|
|
+ $userId = $user['id'];
|
|
|
+ $topDepartId = $user['top_depart_id'];
|
|
|
+
|
|
|
+ // 1. 构造查询对象
|
|
|
+ $model = WorkFlowInstancesNodes::where('del_time', 0)
|
|
|
+ ->where('top_depart_id', $topDepartId)
|
|
|
+ ->where('status', 1)
|
|
|
+ ->whereRaw('JSON_CONTAINS(assignees, JSON_OBJECT("id", ?))', [$userId])
|
|
|
+ ->whereRaw('NOT JSON_CONTAINS(assignees, JSON_OBJECT("id", ?, "is_pass", 1))', [$userId])
|
|
|
+ ->select('*')
|
|
|
+ ->orderBy('id', 'desc');
|
|
|
+
|
|
|
+ $pageData = $this->limit($model, '', $data);
|
|
|
+
|
|
|
+ if (empty($pageData['data'])) return [true, $pageData];
|
|
|
+
|
|
|
+ // 2. 提取当前页的所有流程实例 ID
|
|
|
+ $instanceIds = array_unique(array_column($pageData['data'], 'instance_id'));
|
|
|
+
|
|
|
+ // 3. 获取流程实例及其关联的模板
|
|
|
+ $instances = WorkFlowInstances::with(['template'])
|
|
|
+ ->whereIn('id', $instanceIds)
|
|
|
+ ->get()
|
|
|
+ ->keyBy('id');
|
|
|
+
|
|
|
+ // --- 处理动态业务单据数据 ---
|
|
|
+ // 4. 按业务类型分组,批量查出单据的 code 和 title
|
|
|
+ $documentGroups = [];
|
|
|
+ foreach ($instances as $ins) {
|
|
|
+ $documentGroups[$ins->document_type][] = $ins->document_id;
|
|
|
+ }
|
|
|
+
|
|
|
+ $documentDataMap = []; // 存储结构: [type][id] => ['code' => ..., 'title' => ...]
|
|
|
+ foreach ($documentGroups as $type => $ids) {
|
|
|
+ // 这里根据你的 document_type (如 'item') 动态查询
|
|
|
+ // 假设你的业务表都有 code 和 title 字段
|
|
|
+ $docs = DB::table($type)
|
|
|
+ ->whereIn('id', array_unique($ids))
|
|
|
+ ->select('id', 'code', 'title')
|
|
|
+ ->get()
|
|
|
+ ->keyBy('id')
|
|
|
+ ->toArray();
|
|
|
+ $documentDataMap[$type] = $docs;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 组装最终返回数据
|
|
|
+ foreach ($pageData['data'] as $key => $node) {
|
|
|
+ $instance = $instances[$node['instance_id']] ?? null;
|
|
|
+
|
|
|
+ // 获取关联业务表的具体数据
|
|
|
+ $docDetail = null;
|
|
|
+ if ($instance) {
|
|
|
+ $docDetail = $documentDataMap[$instance->document_type][$instance->document_id] ?? null;
|
|
|
+ }
|
|
|
+
|
|
|
+ $pageData['data'][$key] = [
|
|
|
+ 'node_instance_id' => $node['id'],
|
|
|
+ 'instance_id' => $node['instance_id'],
|
|
|
+ 'node_label' => $node['label'],
|
|
|
+ 'document_id' => $instance->document_id ?? 0,
|
|
|
+ 'document_type' => $instance->document_type ?? '',
|
|
|
+ // --- 新增字段 ---
|
|
|
+ 'document_code' => $docDetail->code ?? '', // 业务单据编号
|
|
|
+ 'document_title' => $docDetail->title ?? '', // 业务单据标题
|
|
|
+ 'workflow_title' => $instance->template->title ?? '', // 审批模板名
|
|
|
+ 'crt_time' => !empty($instance->crt_time->timestamp) ? date('Y-m-d H:i:s', $instance->crt_time->timestamp) : '',
|
|
|
+ 'approval_type' => $node['approval_type'],
|
|
|
+ 'approval_type_title' => WorkFlowInstancesNodes::approval_type[$node['approval_type']] ?? '',
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, $pageData];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function approval($data, $user)
|
|
|
+ {
|
|
|
+ DB::beginTransaction(); // 开启最外层事务
|
|
|
+ try {
|
|
|
+ // 1. 执行审批逻辑
|
|
|
+ list($status, $msg, $result) = $this->approve($data, $user);
|
|
|
+
|
|
|
+ if (!$status) {
|
|
|
+ DB::rollBack();
|
|
|
+ return [false, $msg];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 如果流程终结(通过或驳回),执行业务结算
|
|
|
+ if ($result == 1 || $result == 2) {
|
|
|
+ $instance_id = $msg;
|
|
|
+
|
|
|
+ $this->businessSettle($result, $instance_id);
|
|
|
+ }
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ return [false, "审批失败: " . $e->getMessage()];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param int $nodeInstanceId 节点实例ID
|
|
|
+ * @param int $status 结果:2-通过,3-驳回
|
|
|
+ * @param string $remark 意见
|
|
|
+ * @param array $user 当前操作人
|
|
|
+ *
|
|
|
+ * 业务结果说明:0-审批中(继续等待), 1-最终通过(业务单据可改为已完成), 2-已驳回(业务单据可改为已拒绝)
|
|
|
+ */
|
|
|
+ public function approve($data, $user)
|
|
|
+ {
|
|
|
+ $nodeInstanceId = $data['node_instance_id'] ?? 0;
|
|
|
+ $status = $data['status'] ?? 2;
|
|
|
+ $remark = $data['mark'] ?? '';
|
|
|
+
|
|
|
+ $currentNode = WorkFlowInstancesNodes::where('del_time',0)
|
|
|
+ ->where('id', $nodeInstanceId)
|
|
|
+ ->where('top_depart_id', $user['top_depart_id'])
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (!$currentNode || $currentNode->status != 1) return [false, '环节无效或已处理', 0];
|
|
|
+
|
|
|
+ $assignees = is_string($currentNode->assignees) ? json_decode($currentNode->assignees, true) : $currentNode->assignees;
|
|
|
+
|
|
|
+ $myIndex = collect($assignees)->search(fn($item) => $item['id'] == $user['id']);
|
|
|
+ if ($myIndex === false) return [false, '您不在审批人名单中', 0];
|
|
|
+
|
|
|
+ $time = time();
|
|
|
+ $assignees[$myIndex]['mark'] = $remark;
|
|
|
+ $assignees[$myIndex]['pass_time'] = $time;
|
|
|
+
|
|
|
+ // --- 情况 A:驳回 ---
|
|
|
+ if ($status == 3) {
|
|
|
+ $currentNode->status = 3;
|
|
|
+ $currentNode->handled_time = $time;
|
|
|
+ $assignees[$myIndex]['is_pass'] = 2;
|
|
|
+ $currentNode->assignees = $assignees;
|
|
|
+ $currentNode->save();
|
|
|
+
|
|
|
+ WorkFlowInstances::where('id', $currentNode->instance_id)->update(['status' => WorkFlowInstances::status_four]);
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+ return [true, $currentNode->instance_id, 2];
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- 情况 B:通过 ---
|
|
|
+ $assignees[$myIndex]['is_pass'] = 1;
|
|
|
+ $currentNode->assignees = $assignees;
|
|
|
+
|
|
|
+ $shouldMoveToNext = false;
|
|
|
+ if ($currentNode->approval_type == 2) {
|
|
|
+ $shouldMoveToNext = true;
|
|
|
+ } else {
|
|
|
+ $unPassedCount = collect($assignees)->where('is_pass', '!=', 1)->count();
|
|
|
+ if ($unPassedCount == 0) {
|
|
|
+ $shouldMoveToNext = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $finalResult = 0; // 默认:还在审批中
|
|
|
+
|
|
|
+ if ($shouldMoveToNext) {
|
|
|
+ $currentNode->status = 2;
|
|
|
+ $currentNode->handled_time = $time;
|
|
|
+ $currentNode->save();
|
|
|
+
|
|
|
+ if (!empty($currentNode->next_node_key)) {
|
|
|
+ $hasActiveNext = $this->activateNextNode($currentNode->instance_id, $currentNode->next_node_key);
|
|
|
+ if (!$hasActiveNext) {
|
|
|
+ // 如果逻辑上虽然有key但没找到下个节点,也视为终结
|
|
|
+ WorkFlowInstances::where('id', $currentNode->instance_id)->update(['status' => WorkFlowInstances::status_three]);
|
|
|
+ $finalResult = 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 没有下个节点,流程最终终结
|
|
|
+ WorkFlowInstances::where('id', $currentNode->instance_id)->update(['status' => WorkFlowInstances::status_three]);
|
|
|
+ $finalResult = 1; // 返回 1,表示业务层面可以执行“生效”动作
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 会签中,还有人没审
|
|
|
+ $currentNode->save();
|
|
|
+ $finalResult = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, $currentNode->instance_id, $finalResult];
|
|
|
+ }
|
|
|
+
|
|
|
+ private function activateNextNode($instanceId, $nextNodeKey)
|
|
|
+ {
|
|
|
+ $nextNode = WorkFlowInstancesNodes::where('instance_id', $instanceId)
|
|
|
+ ->where('node_key', $nextNodeKey)
|
|
|
+ ->where('del_time',0)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if ($nextNode) {
|
|
|
+ $nextNode->status = 1;
|
|
|
+ $nextNode->save();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 业务结算逻辑
|
|
|
+ */
|
|
|
+ public function businessSettle($result, $instance_id)
|
|
|
+ {
|
|
|
+ $w = WorkFlowInstances::where('id', $instance_id)->first();
|
|
|
+ if (empty($w)) throw new \Exception("未找到流程实例");
|
|
|
+
|
|
|
+ $draft = Draft::where('del_time', 0)
|
|
|
+ ->where('document_type', $w->document_type)
|
|
|
+ ->where('document_id', $w->document_id)
|
|
|
+ ->where('top_depart_id', $w->top_depart_id)
|
|
|
+ ->latest()
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ // 审核最终通过
|
|
|
+ if ($result == 1) {
|
|
|
+ if (!empty($draft)) {
|
|
|
+ if ($draft->opt_type == 1) {
|
|
|
+ // 执行覆盖逻辑
|
|
|
+ $status = false;
|
|
|
+ $resMsg = '';
|
|
|
+
|
|
|
+ // 动态调用
|
|
|
+ if ($draft->document_type == 'item') {
|
|
|
+ list($status, $resMsg) = (new ItemService())->itemEditSave($draft->content, $draft->opt_user);
|
|
|
+ } elseif ($draft->document_type == 'item_node') {
|
|
|
+ list($status, $resMsg) = (new ItemService())->itemNodeEditSave($draft->content, $draft->opt_user);
|
|
|
+ } elseif ($draft->document_type == 'item_node_mission') {
|
|
|
+ list($status, $resMsg) = (new ItemService())->itemNodeMissionEditSave($draft->content, $draft->opt_user);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!$status) throw new \Exception("业务数据更新失败: " . $resMsg);
|
|
|
+ }elseif ($draft->opt_type == 2){
|
|
|
+ DB::table($w->document_type)->where('id', $w->document_id)->update($draft->content);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 无论通过还是驳回,重置业务表状态
|
|
|
+ DB::table($w->document_type)->where('id', $w->document_id)->update(['approval_state' => 0]);
|
|
|
+
|
|
|
+ // 清理草稿
|
|
|
+ if (! empty($draft)) {
|
|
|
+ $draft->del_time = time();
|
|
|
+ $draft->save();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|