Files
fdesk/app/common/utils/approval/traits/ApprovalNotificationTrait.php
T

165 lines
6.8 KiB
PHP
Raw Normal View History

2025-12-09 07:33:04 +00:00
<?php
2026-01-07 17:23:03 +08:00
namespace app\common\utils\approval\traits;
2025-12-09 07:33:04 +00:00
use support\Db;
use support\Log;
trait ApprovalNotificationTrait
{
/** 发送通知 */
private function sendNotification(array $userIds, object $instance, string $action, bool $isCC, array $extra = []): void
{
$map = [
'pending' => '待审批',
'approve' => '已通过',
'reject' => '已拒绝',
'revoked' => '已撤回',
'voided' => '已作废',
];
$prefix = $isCC ? '【抄送】' : '【审批】';
$text = $map[$action] ?? $action;
// 业务标题/内容
$approvalType = array_flip(\app\common\service\SysDictService::pluckKeyValueByCode('approval_type'));
$flowTxt = $approvalType[$instance->flow_type] ?? (string)$instance->flow_type;
$title = $prefix.'审批通知';
$content = "{$prefix}你有一条审批 {$text}:类型 {$flowTxt},业务标识 {$instance->biz_id}";
switch ($instance->flow_type) {
case 'stock_orders':
// 备货单
$stockOrder = \app\common\model\StockOrders::find($instance->biz_id);
if ($stockOrder) {
$title = $prefix."备货单:{$stockOrder->order_no}";
$flowTxt = $approvalType[$instance->flow_type] ?? $instance->flow_type;
$content = "{$prefix}你有一条审批 {$text}:类型 {$flowTxt},业务单号 {$stockOrder->order_no}";
}
break;
case 'stock_orders_nullify':
// 备货单作废
$stockOrder = \app\common\model\StockOrders::find($instance->biz_id);
if ($stockOrder) {
$title = $prefix."备货单作废:{$stockOrder->order_no}";
$flowTxt = $approvalType[$instance->flow_type] ?? '备货单作废';
$content = "{$prefix}你有一条审批 {$text}:类型 {$flowTxt},业务单号 {$stockOrder->order_no}";
// 把作废原因附带展示更清晰(也可依赖 $extra['note'])
$fd = json_decode($instance->form_data ?? '{}', true) ?: [];
if (!empty($fd['_nullify_reason'])) {
$content .= ';原因:'.(function_exists('mb_strimwidth') ? mb_strimwidth($fd['_nullify_reason'], 0, 120, '...', 'UTF-8') : $fd['_nullify_reason']);
}
}
break;
case 'purchase_orders':
// 采购单
$purchaseOrder = \app\common\model\PurchaseOrders::find($instance->biz_id);
if ($purchaseOrder) {
$title = $prefix."采购单:{$purchaseOrder->order_no}";
$flowTxt = $approvalType[$instance->flow_type] ?? $instance->flow_type;
$content = "{$prefix}你有一条审批 {$text}:类型 {$flowTxt},业务单号 {$purchaseOrder->order_no}";
}
break;
case 'purchase_order':
// 采购单
break;
2026-01-07 17:23:03 +08:00
case 'inv_requisition':
// 备货单
$invRequisition = \app\common\model\InvRequisition::find($instance->biz_id);
if ($invRequisition) {
$title = $prefix."物品借用:{$invRequisition->order_no}";
$flowTxt = $approvalType[$instance->flow_type] ?? $instance->flow_type;
$content = "{$prefix}你有一条审批 {$text}:类型 {$flowTxt},业务单号 {$invRequisition->order_no}";
}
break;
2025-12-09 07:33:04 +00:00
}
// 附加说明(提交说明/申诉/讨论摘要)
$append = $extra['appeal'] ?? ($extra['note'] ?? null);
if ($append) {
if (function_exists('mb_strimwidth')) {
$append = mb_strimwidth($append, 0, 120, '...', 'UTF-8');
}
$content .= ";说明:{$append}";
}
noticePush([
'title' => $title,
'content' => $content,
'recipient' => $userIds,
'email' => 1,
]);
}
private function notifyInitiator(object $instance, string $result): void
{
$this->sendNotification([(int)$instance->initiator_id], $instance, $result, false);
}
/** WebSocket:把一组用户的“待办数量”推送给前端(旧版) */
private function pushTodoChanged22(array $userIds): void
{
$userIds = array_values(array_unique(array_map('intval', $userIds)));
if (empty($userIds)) return;
// 统计这些用户当前的待办数量(以 approval_records.status = 'pending' 为准)
$rows = Db::table('approval_records')
->whereIn('approver_id', $userIds)
->where('status', 'pending')
->groupBy('approver_id')
->select('approver_id', Db::raw('COUNT(*) as cnt'))
->get();
// 默认都置 0,再填充真实值
$payload = array_fill_keys($userIds, 0);
foreach ($rows as $r) {
$payload[(int)$r->approver_id] = (int)$r->cnt;
}
try {
foreach ($payload as $uid => $cnt) {
$data = [
'event' => 'approval.todo.counts',
'user_id' => $uid,
'num' => $cnt,
];
\Webman\RedisQueue\Redis::send('ws-msg', $data);
}
} catch (\Throwable $e) {
Log::error('ws todo push error: '.$e->getMessage());
}
}
/** WebSocket:把一组用户的“待办数量”推送给前端(统一口径) */
private function pushTodoChanged(array $userIds): void
{
$userIds = array_values(array_unique(array_map('intval', $userIds)));
if (empty($userIds)) return;
// 只统计:实例进行中 + 当前轮次 + 当前步骤 的 pending
$rows = Db::table('approval_records as ar')
->join('approval_instances as ai', 'ai.id', '=', 'ar.instance_id')
->whereIn('ar.approver_id', $userIds)
->where('ar.status', 'pending')
->where('ai.status', 'processing')
->whereRaw('ar.round = ai.round')
->whereRaw('ar.step_index = ai.current_step')
->groupBy('ar.approver_id')
->select('ar.approver_id', Db::raw('COUNT(*) as cnt'))
->get();
// 默认置 0,再填充真实值
$payload = array_fill_keys($userIds, 0);
foreach ($rows as $r) {
$payload[(int)$r->approver_id] = (int)$r->cnt;
}
try {
foreach ($payload as $uid => $cnt) {
(new \app\common\utils\WsEvents())->todoCounts($uid, $cnt);
}
} catch (\Throwable $e) {
Log::error('ws todo push error: '.$e->getMessage());
}
}
}