Kaynağa Gözat

通知列表解析操作数据和数据对象

moell 8 ay önce
ebeveyn
işleme
0e42c2e43d

+ 3 - 2
app/Http/Controllers/API/NotificationController.php

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers\API;
 
 use App\Http\Controllers\Controller;
+use App\Http\Resources\API\NotificationCollection;
 use App\Http\Resources\API\NotificationResource;
 use App\Models\Enums\NotificationStatus;
 use App\Models\Notification;
@@ -17,7 +18,7 @@ class NotificationController extends Controller
      * 用户通知列表
      *
      * @param Request $request
-     * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
+     * @return NotificationCollection
      */
     public function index(Request $request)
     {
@@ -29,7 +30,7 @@ class NotificationController extends Controller
             ->orderByDesc("created_at")
             ->paginate();
 
-        return NotificationResource::collection($notifications);
+        return new NotificationCollection($notifications);
     }
 
     /**

+ 75 - 0
app/Http/Resources/API/NotificationCollection.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace App\Http\Resources\API;
+
+use App\Models\Action;
+use App\Models\Enums\ApprovalObjectType;
+use App\Models\Enums\NotificationObjectType;
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\ResourceCollection;
+
+class NotificationCollection extends ResourceCollection
+{
+    /**
+     * Transform the resource collection into an array.
+     *
+     * @return array<int|string, mixed>
+     */
+    public function toArray(Request $request): array
+    {
+        list ($actions, $actionGroupObjects) = $this->widthActionObjects();
+
+        $items = [];
+        foreach ($this->resource->items() as $item) {
+            $object = null;
+            if ($item->object_type == NotificationObjectType::ACTION->value) {
+                $action = $actions[$item->object_id];
+
+                $objectAction = $item->extra_fields['action'] ?? $action->action;
+
+                $object = [
+                    'id' => $action->id,
+                    'action' => $objectAction,
+                    'action_label' => __(sprintf("action-labels.label.%s", $objectAction)),
+                    'created_by' => new UserProfileResource($action->createdBy),
+                    'comment' => $action->commtent,
+                    'object_type' => $action->object_type,
+                    'object' => [
+                        'id' => $action->object_id,
+                        'name' => data_get($actionGroupObjects, sprintf("%s.%s", $action->object_type, $action->object_id)),
+                    ]
+                ];
+            }
+            $row = [
+                'id' => $item->id,
+                'object_type' => $item->object_type,
+                'content' => $item->content,
+                'read_at' => (string)$item->read_at,
+                'read_status' => (bool)$item->read_at,
+                'object' => $object,
+            ];
+            $items[] = $row;
+        }
+
+        return $items;
+    }
+
+    protected function widthActionObjects(): array
+    {
+        $actionIDS = collect($this->resource->items())->where("object_type", NotificationObjectType::ACTION->value)->pluck("object_id");
+
+        $actions = Action::with(['createdBy'])->whereIn("id", $actionIDS->toArray())->get();
+
+        $actionGroupObjects = [];
+
+        foreach($actions->groupBy("object_type") as $objectType => $items) {
+            $approvalObjectType = ApprovalObjectType::from($objectType);
+            $actionGroupObjects[$objectType] = $approvalObjectType
+                ->modelBuilder()
+                ->whereIn("id", array_column($items->toArray(), "object_id"))
+                ->pluck($approvalObjectType->nameField(), "id");
+        };
+
+        return [$actions->keyBy("id"), $actionGroupObjects];
+    }
+}

+ 1 - 1
app/Models/Notification.php

@@ -13,6 +13,6 @@ class Notification extends Model
     protected $guarded = ['id'];
 
     protected $casts = [
-        'content' => 'array'
+        'extra_fields' => 'array'
     ];
 }

+ 16 - 13
app/Services/Notification/Abstracts/ActionBrowserNotificationAbstract.php

@@ -4,13 +4,11 @@ namespace App\Services\Notification\Abstracts;
 
 use App\Models\Action;
 use App\Models\Approval;
-use App\Models\Enums\ActionObjectType;
 use App\Models\Enums\NotificationObjectType;
 use App\Models\Enums\ObjectAction;
 use App\Models\Notification;
 use App\Models\NotificationRecord;
 use App\Services\Notification\Contacts\ActionBrowserNotificationContacts;
-use App\Services\Notification\NotificationContent;
 use Illuminate\Database\Eloquent\Model;
 
 abstract class ActionBrowserNotificationAbstract implements ActionBrowserNotificationContacts
@@ -41,21 +39,26 @@ abstract class ActionBrowserNotificationAbstract implements ActionBrowserNotific
         }
 
         match ($this->objectAction) {
-            ObjectAction::APPROVAL_REQUEST, ObjectAction::APPROVED_TO_NEXT_NODE => $this->notificationNextApprovalUsers($approval),
-            ObjectAction::APPROVAL_APPROVED, ObjectAction::APPROVAL_REJECTED => $this->handleByObjectAction([$approval->create_by]),
+            ObjectAction::APPROVAL_REQUEST => $this->notificationNextApprovalUsers($approval),
+            ObjectAction::APPROVED_TO_NEXT_NODE => $this->handleByApprovedToNextNode($approval),
+            ObjectAction::APPROVAL_APPROVED, ObjectAction::APPROVAL_REJECTED => $this->handleByObjectAction([$approval->created_by]),
             default => '',
         };
     }
 
+    protected function handleByApprovedToNextNode(Approval $approval)
+    {
+        $this->notificationNextApprovalUsers($approval);
+
+        $this->handleByObjectAction([$approval->created_by]);
+    }
+
     protected function handleByObjectAction(array $userIDs)
     {
-        $this->storeNotification(
-            new NotificationContent($this->objectAction->value),
-            $userIDs,
-        );
+        $this->storeNotification($userIDs);
     }
 
-    protected function storeNotification(NotificationContent $content, array $userIds)
+    protected function storeNotification(array $userIds, array $extraFields = [])
     {
         if (! $userIds) {
             return;
@@ -64,7 +67,7 @@ abstract class ActionBrowserNotificationAbstract implements ActionBrowserNotific
         $notification =  Notification::query()->create([
             'object_type' => NotificationObjectType::ACTION->value,
             'object_id' => $this->action->id,
-            'content' => $content->toArray()
+            'extra_fields' => $extraFields ?: null,
         ]);
 
         foreach ($userIds as $userId) {
@@ -84,8 +87,8 @@ abstract class ActionBrowserNotificationAbstract implements ActionBrowserNotific
 
         $userIds = $approvalFlow->nodes[$this->action->extra_fields['next']]['approval_users'] ?? [];
 
-        $content = new NotificationContent("waitingForMyApproval");
-
-        $this->storeNotification($content, $userIds);
+        $this->storeNotification($userIds, [
+            'action' => 'waitingForMyApproval'
+        ]);
     }
 }

+ 0 - 17
app/Services/Notification/NotificationContent.php

@@ -1,17 +0,0 @@
-<?php
-
-namespace App\Services\Notification;
-
-class NotificationContent
-{
-    public function __construct(protected string $action)
-    {
-    }
-
-    public function toArray()
-    {
-        return [
-            'action' => $this->action,
-        ];
-    }
-}

+ 2 - 2
database/migrations/2024_06_28_233556_change_content_to_notifications_tables.php → database/migrations/2024_06_29_095745_add_extra_fields_to_notifications_table.php

@@ -12,7 +12,7 @@ return new class extends Migration
     public function up(): void
     {
         Schema::table('notifications', function (Blueprint $table) {
-            $table->json("content")->nullable()->change();
+            $table->json("extra_fields")->nullable();
         });
     }
 
@@ -22,7 +22,7 @@ return new class extends Migration
     public function down(): void
     {
         Schema::table('notifications', function (Blueprint $table) {
-            $table->text('content')->nullable()->change();
+            $table->dropColumn(['extra_fields']);
         });
     }
 };