cqp 4 tygodni temu
rodzic
commit
226029d159

+ 76 - 0
app/Http/Controllers/Api/WorkFlowController.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Service\WorkFlowService;
+use Illuminate\Http\Request;
+
+class WorkFlowController extends BaseController
+{
+    public function workFlowEdit(Request $request)
+    {
+        $service = new WorkFlowService();
+        $user = $request->userData;
+        list($status,$data) = $service->workFlowEdit($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function workFlowAdd(Request $request)
+    {
+        $service = new WorkFlowService();
+        $user = $request->userData;
+        list($status,$data) = $service->workFlowAdd($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+
+    }
+
+    public function workFlowDel(Request $request)
+    {
+        $service = new WorkFlowService();
+        $user = $request->userData;
+        list($status,$data) = $service->workFlowDel($request->all());
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+
+    }
+
+    public function workFlowList(Request $request)
+    {
+        $service = new WorkFlowService();
+        $user = $request->userData;
+        list($status,$data) = $service->workFlowList($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function workFlowDetail(Request $request)
+    {
+        $service = new WorkFlowService();
+        $user = $request->userData;
+        list($status,$data) = $service->workFlowDetail($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+}

+ 16 - 0
app/Model/WorkFlowInstances.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+//流程实例表
+class WorkFlowInstances extends DataScopeBaseModel
+{
+    protected $guarded = [];
+    protected $table = "work_flow_instances"; //指定表
+    const CREATED_AT = 'crt_time';
+    const UPDATED_AT = 'upd_time';
+    protected $dateFormat = 'U';
+    public static $field = ['id', 'template_id', 'document_id', 'document_type', 'status', 'crt_id', 'crt_time', 'upd_time'];
+}

+ 16 - 0
app/Model/WorkFlowInstancesNodes.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+//流程节点实例表
+class WorkFlowInstancesNodes extends DataScopeBaseModel
+{
+    protected $guarded = [];
+    protected $table = "work_flow_instance_nodes"; //指定表
+    const CREATED_AT = 'crt_time';
+    const UPDATED_AT = 'upd_time';
+    protected $dateFormat = 'U';
+    public static $field = ['id', 'instance_id', 'node_key', 'label', 'prev_node_key', 'next_node_key', 'assignees', 'approval_type', 'status', 'handled_time', 'crt_time', 'upd_time', 'crt_id'];
+}

+ 16 - 0
app/Model/WorkFlowTemplates.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+//审批流模板表
+class WorkFlowTemplates extends DataScopeBaseModel
+{
+    protected $guarded = [];
+    protected $table = "work_flow_templates"; //指定表
+    const CREATED_AT = 'crt_time';
+    const UPDATED_AT = 'upd_time';
+    protected $dateFormat = 'U';
+    public static $field = ['id', 'code', 'title', 'crt_id', 'crt_time', 'upd_time'];
+}

+ 222 - 0
app/Service/WorkFLowService.php

@@ -0,0 +1,222 @@
+<?php
+
+namespace App\Service;
+
+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 = $data['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 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)信息'];
+        }
+
+        // 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($templateCode, $documentId, $documentType, $user)
+    {
+        // 1. 获取对应的审批流模板
+        $template = WorkFlowTemplates::where('code', $templateCode)
+            ->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'        => 'processing',
+            '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();
+
+            $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($node['data']['assignees'] ?? []),
+
+                // 审批类型: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];
+    }
+}

+ 7 - 0
routes/api.php

@@ -139,6 +139,13 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('teamDel', 'Api\TeamController@teamDel');
     $route->any('teamDetail', 'Api\TeamController@teamDetail');
 
+    //审批流模板
+    $route->any('workFlowList', 'Api\WorkFlowController@workFlowList');
+    $route->any('workFlowEdit', 'Api\WorkFlowController@workFlowEdit');
+    $route->any('workFlowAdd', 'Api\WorkFlowController@workFlowAdd');
+    $route->any('workFlowDel', 'Api\WorkFlowController@workFlowDel');
+    $route->any('workFlowDetail', 'Api\WorkFlowController@workFlowDetail');
+
     //费用类型
     $route->any('feeAdd', 'Api\FeeController@feeAdd')->name('fee.add');
     $route->any('feeEdit', 'Api\FeeController@feeEdit')->name('fee.edit');