|
@@ -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];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|