fix: 修复审批消息推送问题
问题1:BusinessTripService 数据格式兼容性
- 后端期望对象数组 [{id:1, name:'...'}],前端传纯 ID 数组 [1,2,3]
- 修复:兼容两种格式,自动提取 id
问题2:ApprovalService 没有消息推送
- 添加 FeishuNotificationService 集成
- approve() 方法:节点完成后通知下一节点审批人,流程完成后通知申请人
- reject() 方法:审批拒绝时通知申请人
问题3:修复重复类定义导致的语法错误
相关文件:
- backend/app/service/BusinessTripService.php
- backend/app/service/ApprovalService.php
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ use Illuminate\Database\Connection;
|
||||
class ApprovalService
|
||||
{
|
||||
private Connection $db;
|
||||
private ?FeishuNotificationService $notificationService = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -96,6 +97,9 @@ class ApprovalService
|
||||
// 没有下一节点,审批完成
|
||||
$order->status = ApprovalOrder::STATUS_APPROVED;
|
||||
$order->current_nodes = [];
|
||||
|
||||
// 通知申请人审批通过
|
||||
$this->notifyApplicant($order, 'approve');
|
||||
} else {
|
||||
// 检查第一个下一节点
|
||||
$firstNextNode = $nextNodes[0] ?? null;
|
||||
@@ -103,9 +107,15 @@ class ApprovalService
|
||||
// 下一个是抄送节点,跳过并完成流程
|
||||
$order->status = ApprovalOrder::STATUS_APPROVED;
|
||||
$order->current_nodes = [];
|
||||
|
||||
// 通知申请人审批通过
|
||||
$this->notifyApplicant($order, 'approve');
|
||||
} else {
|
||||
// 下一个是审批节点,移动到该节点
|
||||
$order->current_nodes = collect($nextNodes)->pluck('id')->toArray();
|
||||
|
||||
// 通知下一节点的审批人
|
||||
$this->notifyNextApprovers($order, $nextNodes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +156,9 @@ class ApprovalService
|
||||
$order->current_nodes = [];
|
||||
$order->save();
|
||||
|
||||
// 通知申请人审批被拒绝
|
||||
$this->notifyApplicant($order, 'reject', $comment);
|
||||
|
||||
return $order->fresh(['flow', 'applicant', 'records']);
|
||||
});
|
||||
}
|
||||
@@ -381,4 +394,138 @@ class ApprovalService
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知申请人
|
||||
*/
|
||||
private function notifyApplicant(ApprovalOrder $order, string $action, ?string $comment = null): void
|
||||
{
|
||||
try {
|
||||
if (!$this->notificationService) {
|
||||
$this->notificationService = new FeishuNotificationService();
|
||||
}
|
||||
|
||||
$applicant = User::find($order->applicant_id);
|
||||
if (!$applicant) {
|
||||
error_log("❌ notifyApplicant: 申请人不存在, applicant_id={$order->applicant_id}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据业务类型获取详情链接
|
||||
$detailUrl = $this->getDetailUrl($order);
|
||||
|
||||
// 构建消息内容
|
||||
$title = $action === 'approve' ? '您的申请已通过' : '您的申请已被拒绝';
|
||||
$content = "**申请标题**: {$order->title}\n";
|
||||
$content .= "**申请类型**: {$this->getBusinessTypeName($order->business_type)}\n";
|
||||
|
||||
if ($comment) {
|
||||
$content .= "**审批意见**: {$comment}\n";
|
||||
}
|
||||
|
||||
error_log("🔔 通知申请人: applicant_id={$applicant->id}, action={$action}");
|
||||
|
||||
$this->notificationService->setAppByUser($applicant->id)
|
||||
->sendSystemNotification([
|
||||
'user_ids' => [$applicant->id],
|
||||
'title' => $title,
|
||||
'content' => $content,
|
||||
'url' => $detailUrl,
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
error_log('❌ notifyApplicant 失败: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知下一节点的审批人
|
||||
*/
|
||||
private function notifyNextApprovers(ApprovalOrder $order, array $nextNodes): void
|
||||
{
|
||||
try {
|
||||
if (!$this->notificationService) {
|
||||
$this->notificationService = new FeishuNotificationService();
|
||||
}
|
||||
|
||||
// 从 form_data 获取审批人列表
|
||||
$formData = $order->form_data ?? [];
|
||||
$approvers = $formData['approvers'] ?? [];
|
||||
|
||||
// 兼容两种格式
|
||||
if (!empty($approvers) && is_array($approvers[0] ?? null) && isset($approvers[0]['id'])) {
|
||||
$approverIds = array_column($approvers, 'id');
|
||||
} else {
|
||||
$approverIds = $approvers;
|
||||
}
|
||||
|
||||
if (empty($approverIds)) {
|
||||
error_log("⚠️ notifyNextApprovers: 没有找到审批人, order_id={$order->id}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取详情链接
|
||||
$detailUrl = $this->getDetailUrl($order);
|
||||
|
||||
// 业务类型名称
|
||||
$businessTypeName = $this->getBusinessTypeName($order->business_type);
|
||||
|
||||
error_log("🔔 通知下一节点审批人: order_id={$order->id}, approverIds=" . json_encode($approverIds));
|
||||
|
||||
// 为每个审批人发送通知
|
||||
foreach ($approverIds as $approverId) {
|
||||
try {
|
||||
$this->notificationService->setAppByUser($approverId)
|
||||
->sendApprovalNotification([
|
||||
'user_id' => $approverId,
|
||||
'title' => '新的审批待办',
|
||||
'applicant' => $order->applicant->name,
|
||||
'type' => $businessTypeName,
|
||||
'content' => "**申请标题**: {$order->title}\n**申请人**: {$order->applicant->name}",
|
||||
'url' => $detailUrl,
|
||||
]);
|
||||
error_log("✅ 审批人通知成功: approver_id={$approverId}");
|
||||
} catch (\Exception $e) {
|
||||
error_log("❌ 发送审批通知失败: approver_id={$approverId}, error=" . $e->getMessage());
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
error_log('❌ notifyNextApprovers 失败: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取详情链接
|
||||
*/
|
||||
private function getDetailUrl(ApprovalOrder $order): string
|
||||
{
|
||||
$baseUrl = 'https://xsm.dev.hnxinyouhe.com';
|
||||
|
||||
switch ($order->business_type) {
|
||||
case 'business_trip':
|
||||
return "{$baseUrl}/business-trip/detail/{$order->business_id}";
|
||||
case 'expense':
|
||||
return "{$baseUrl}/expense/detail/{$order->business_id}";
|
||||
case 'leave':
|
||||
return "{$baseUrl}/leave/detail/{$order->business_id}";
|
||||
case 'purchase':
|
||||
return "{$baseUrl}/purchase/detail/{$order->business_id}";
|
||||
default:
|
||||
return "{$baseUrl}/approval/detail/{$order->id}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取业务类型名称
|
||||
*/
|
||||
private function getBusinessTypeName(string $businessType): string
|
||||
{
|
||||
$typeNames = [
|
||||
'business_trip' => '出差申请',
|
||||
'expense' => '费用报销',
|
||||
'leave' => '请假申请',
|
||||
'purchase' => '采购申请',
|
||||
];
|
||||
|
||||
return $typeNames[$businessType] ?? $businessType;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user