fix: 使用 form_data 存储运行时审批人,不修改 approval_node 模板
主要修改:
1. submit() 方法不再修改 approval_node 表,节点仅作为流程模板
2. getList() 的 pending 查询从 form_data.approvers 获取审批人列表
3. approve() 方法从 form_data.approvers 检查用户是否有权限
4. 兼容两种数据格式:[1,2,3] 或 [{id:1},{id:2},{id:3}]
修复问题:
- 之前每次提交申请都会修改 approval_node 表的 approvers 字段
- 这导致流程模板被污染,不同的申请共享同一个节点配置
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -129,9 +129,15 @@ class BusinessTripController extends BaseController
|
||||
$data = $request->post();
|
||||
$data = $data ?? [];
|
||||
|
||||
error_log("📝 提交申请 - 用户ID: {$userId}, 申请ID: {$id}");
|
||||
error_log("📦 接收到的数据: " . json_encode($data, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$approvers = $data['approvers'] ?? [];
|
||||
$ccUsers = $data['cc_users'] ?? [];
|
||||
|
||||
error_log("👥 审批人列表: " . json_encode($approvers, JSON_UNESCAPED_UNICODE));
|
||||
error_log("📨 抄送人列表: " . json_encode($ccUsers, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
if (empty($approvers)) {
|
||||
return $this->error('请选择审批人');
|
||||
}
|
||||
|
||||
@@ -138,47 +138,21 @@ class BusinessTripService
|
||||
]);
|
||||
}
|
||||
|
||||
// 根据审批人创建审批节点
|
||||
$approverIds = array_column($approvers, 'id');
|
||||
// approval_node 是流程模板,不应在提交时修改
|
||||
// 实际的审批人存储在 approval_order.form_data 中
|
||||
// 获取或创建第一个审批节点(仅用于流程结构)
|
||||
$node = ApprovalNode::where('flow_id', $flow->id)
|
||||
->where('order', 0)
|
||||
->first();
|
||||
|
||||
if (!$node) {
|
||||
// 创建第一个审批节点
|
||||
$node = ApprovalNode::create([
|
||||
'flow_id' => $flow->id,
|
||||
'type' => count($approverIds) > 1 ? 'and_approve' : 'approver',
|
||||
'type' => 'approver',
|
||||
'name' => '审批',
|
||||
'order' => 0,
|
||||
'approvers' => $approverIds,
|
||||
'approvers' => [], // 模板节点不存储具体审批人
|
||||
]);
|
||||
} else {
|
||||
// 更新现有节点的审批人
|
||||
$node->approvers = $approverIds;
|
||||
$node->save();
|
||||
}
|
||||
|
||||
// 创建抄送节点(如果有抄送人)
|
||||
$ccUserIds = array_column($ccUsers, 'id');
|
||||
if (!empty($ccUserIds)) {
|
||||
$ccNode = ApprovalNode::where('flow_id', $flow->id)
|
||||
->where('type', 'notify')
|
||||
->where('order', 1)
|
||||
->first();
|
||||
|
||||
if (!$ccNode) {
|
||||
ApprovalNode::create([
|
||||
'flow_id' => $flow->id,
|
||||
'type' => 'notify',
|
||||
'name' => '抄送',
|
||||
'order' => 1,
|
||||
'approvers' => $ccUserIds,
|
||||
]);
|
||||
} else {
|
||||
$ccNode->approvers = $ccUserIds;
|
||||
$ccNode->save();
|
||||
}
|
||||
}
|
||||
|
||||
// 创建审批单
|
||||
@@ -270,6 +244,8 @@ class BusinessTripService
|
||||
}
|
||||
|
||||
// 发送飞书通知给审批人
|
||||
error_log("🔔 准备发送审批通知,调用 sendApprovalNotification 方法");
|
||||
error_log("📋 传递的参数 - approverIds: " . json_encode($approverIds) . ", ccUserIds: " . json_encode($ccUserIds));
|
||||
$this->sendApprovalNotification($businessTrip, $approverIds, $ccUserIds);
|
||||
|
||||
return $businessTrip->fresh(['itineraries', 'approvalOrder']);
|
||||
@@ -282,6 +258,8 @@ class BusinessTripService
|
||||
private function sendApprovalNotification(BusinessTrip $businessTrip, array $approverIds, array $ccUserIds): void
|
||||
{
|
||||
try {
|
||||
error_log("🔔 准备发送审批通知: trip_id={$businessTrip->id}, approvers=" . json_encode($approverIds) . ", cc=" . json_encode($ccUserIds));
|
||||
|
||||
$notificationService = new \app\service\FeishuNotificationService();
|
||||
|
||||
// 构建详情链接
|
||||
@@ -295,6 +273,7 @@ class BusinessTripService
|
||||
// 通知审批人
|
||||
foreach ($approverIds as $approverId) {
|
||||
try {
|
||||
error_log("📧 通知审批人: approver_id={$approverId}");
|
||||
$notificationService->setAppByUser($approverId)
|
||||
->sendApprovalNotification([
|
||||
'user_id' => $approverId,
|
||||
@@ -304,14 +283,16 @@ class BusinessTripService
|
||||
'content' => $content,
|
||||
'url' => $detailUrl,
|
||||
]);
|
||||
error_log("✅ 审批人通知成功: approver_id={$approverId}");
|
||||
} catch (\Exception $e) {
|
||||
error_log("发送审批通知失败: approver_id={$approverId}, error=" . $e->getMessage());
|
||||
error_log("❌ 发送审批通知失败: approver_id={$approverId}, error=" . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 通知抄送人
|
||||
foreach ($ccUserIds as $ccUserId) {
|
||||
try {
|
||||
error_log("📧 通知抄送人: cc_user_id={$ccUserId}");
|
||||
$notificationService->setAppByUser($ccUserId)
|
||||
->sendSystemNotification([
|
||||
'user_ids' => [$ccUserId],
|
||||
@@ -319,12 +300,15 @@ class BusinessTripService
|
||||
'content' => "**申请人**: {$businessTrip->user->name}\n" . $content,
|
||||
'url' => $detailUrl,
|
||||
]);
|
||||
error_log("✅ 抄送人通知成功: cc_user_id={$ccUserId}");
|
||||
} catch (\Exception $e) {
|
||||
error_log("发送抄送通知失败: cc_user_id={$ccUserId}, error=" . $e->getMessage());
|
||||
error_log("❌ 发送抄送通知失败: cc_user_id={$ccUserId}, error=" . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
error_log("✅ 审批通知发送完成");
|
||||
} catch (\Exception $e) {
|
||||
error_log("发送飞书通知异常: " . $e->getMessage());
|
||||
error_log("❌ 发送飞书通知异常: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,10 +364,12 @@ class BusinessTripService
|
||||
break;
|
||||
case 'pending':
|
||||
// 待我审批:需要查询当前用户是审批人且还未审批的申请
|
||||
$pendingOrderIds = ApprovalOrder::where('status', ApprovalOrder::STATUS_PENDING)
|
||||
$allPendingOrders = ApprovalOrder::where('status', ApprovalOrder::STATUS_PENDING)
|
||||
->where('business_type', 'business_trip')
|
||||
->pluck('id')
|
||||
->toArray();
|
||||
->get();
|
||||
error_log("🔍 Pending query result: count=" . count($allPendingOrders));
|
||||
|
||||
$pendingOrderIds = $allPendingOrders->pluck('id')->toArray();
|
||||
|
||||
if (empty($pendingOrderIds)) {
|
||||
$query->whereRaw('1 = 0'); // 返回空结果
|
||||
@@ -393,18 +379,29 @@ class BusinessTripService
|
||||
$validOrderIds = [];
|
||||
|
||||
foreach ($pendingOrders as $order) {
|
||||
$currentNodes = $order->current_nodes ?? [];
|
||||
error_log("🔍 Checking order {$order->id}: form_data=" . json_encode($order->form_data));
|
||||
// 从 form_data 获取实际的审批人列表
|
||||
$formData = $order->form_data ?? [];
|
||||
$approvers = $formData['approvers'] ?? [];
|
||||
|
||||
// 检查用户是否在当前节点的审批人列表中
|
||||
$isApprover = false;
|
||||
foreach ($currentNodes as $nodeId) {
|
||||
$node = ApprovalNode::find($nodeId);
|
||||
if ($node && in_array($userId, $node->approvers ?? [])) {
|
||||
$isApprover = true;
|
||||
break;
|
||||
// 兼容两种格式:[1,2,3] 或 [{id:1},{id:2},{id:3}]
|
||||
if (!empty($approvers)) {
|
||||
if (is_array($approvers[0] ?? null) && isset($approvers[0]['id'])) {
|
||||
// 对象数组格式: [{id:1, name:'...'}]
|
||||
$approverIds = array_column($approvers, 'id');
|
||||
} else {
|
||||
// ID数组格式: [1, 2, 3]
|
||||
$approverIds = $approvers;
|
||||
}
|
||||
} else {
|
||||
$approverIds = [];
|
||||
}
|
||||
|
||||
error_log("🔍 Order {$order->id}: approverIds=" . json_encode($approverIds) . ", userId={$userId}");
|
||||
// 检查用户是否在审批人列表中
|
||||
$isApprover = in_array($userId, $approverIds);
|
||||
error_log("🔍 Order {$order->id}: isApprover=" . ($isApprover ? 'true' : 'false'));
|
||||
|
||||
// 如果用户是当前节点审批人,且未审批过,则加入列表
|
||||
if ($isApprover) {
|
||||
$hasApproved = ApprovalRecord::where('order_id', $order->id)
|
||||
@@ -674,27 +671,24 @@ class BusinessTripService
|
||||
}
|
||||
|
||||
// 检查用户是否是当前审批人
|
||||
$currentNodes = $approvalOrder->current_nodes ?? [];
|
||||
$isApprover = false;
|
||||
// 从 form_data 获取实际的审批人列表
|
||||
$formData = $approvalOrder->form_data ?? [];
|
||||
$approvers = $formData['approvers'] ?? [];
|
||||
|
||||
foreach ($currentNodes as $nodeId) {
|
||||
$node = ApprovalNode::where('flow_id', $approvalOrder->flow_id)
|
||||
->where('id', $nodeId)
|
||||
->first();
|
||||
|
||||
if (!$node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查用户是否在审批人列表中
|
||||
$approvers = $node->approvers ?? [];
|
||||
if (in_array($userId, $approvers)) {
|
||||
$isApprover = true;
|
||||
break;
|
||||
// 兼容两种格式:[1,2,3] 或 [{id:1},{id:2},{id:3}]
|
||||
if (!empty($approvers)) {
|
||||
if (is_array($approvers[0] ?? null) && isset($approvers[0]['id'])) {
|
||||
// 对象数组格式: [{id:1, name:'...'}]
|
||||
$approverIds = array_column($approvers, 'id');
|
||||
} else {
|
||||
// ID数组格式: [1, 2, 3]
|
||||
$approverIds = $approvers;
|
||||
}
|
||||
} else {
|
||||
$approverIds = [];
|
||||
}
|
||||
|
||||
if (!$isApprover) {
|
||||
if (!in_array($userId, $approverIds)) {
|
||||
throw new \Exception('您不是当前审批人');
|
||||
}
|
||||
|
||||
@@ -708,10 +702,14 @@ class BusinessTripService
|
||||
throw new \Exception('您已经审批过了');
|
||||
}
|
||||
|
||||
// 获取当前节点ID
|
||||
$currentNodes = $approvalOrder->current_nodes ?? [];
|
||||
$currentNodeId = $currentNodes[0] ?? null;
|
||||
|
||||
// 记录审批操作
|
||||
ApprovalRecord::create([
|
||||
'order_id' => $approvalOrder->id,
|
||||
'node_id' => $currentNodes[0] ?? 1,
|
||||
'node_id' => $currentNodeId,
|
||||
'node_type' => 'approver',
|
||||
'approver_id' => $userId,
|
||||
'action' => $action,
|
||||
@@ -726,7 +724,6 @@ class BusinessTripService
|
||||
$businessTrip->status = BusinessTrip::STATUS_REJECTED;
|
||||
} else {
|
||||
// 同意:检查当前节点是否完成,并处理流程流转
|
||||
$currentNodeId = $currentNodes[0] ?? null;
|
||||
$nodeCompleted = false;
|
||||
|
||||
if ($currentNodeId) {
|
||||
@@ -745,8 +742,7 @@ class BusinessTripService
|
||||
->where('node_id', $currentNodeId)
|
||||
->where('action', 'approve')
|
||||
->count();
|
||||
$allApprovers = $node->approvers ?? [];
|
||||
if ($approvedCount >= count($allApprovers)) {
|
||||
if ($approvedCount >= count($approverIds)) {
|
||||
$nodeCompleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user