Ver Fonte

浏览产品

bianjunhui há 1 semana atrás
pai
commit
db13714fbb

+ 111 - 0
packages/Longyi/RewardPoints/src/Http/Controllers/RewardPointsController.php

@@ -12,6 +12,8 @@ use Carbon\Carbon;
 use Illuminate\Http\Request;
 use Illuminate\Routing\Controller;
 use Longyi\RewardPoints\Models\RewardPointHistory;
+use Illuminate\Support\Facades\Redis;
+
 class RewardPointsController extends Controller
 {
     protected $rewardPointRepository;
@@ -310,6 +312,113 @@ class RewardPointsController extends Controller
         return ApiResponse::success([], 'Reward points removed successfully');
     }
 
+    /**
+     * 浏览产品赠送积分(每个产品每天仅赠送一次)
+     *
+     * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function browseProduct(Request $request)
+    {
+        $customer = auth()->guard('customer')->user();
+
+        if (!$customer) {
+            return ApiResponse::unauthorized();
+        }
+
+        $productId = $request->input('categorys');
+
+        if (!$productId) {
+            return ApiResponse::validationError('categorys is required');
+        }
+
+        // 查询有效的浏览产品规则
+        $rule = RewardActiveRule::active()
+            ->ofType(RewardActiveRule::TYPE_BROWSE_PRODUCT)
+            ->first();
+
+        if (!$rule) {
+            return ApiResponse::forbidden('Browse product reward is not available');
+        }
+
+        // 检查规则是否适用于当前客户
+        if (!$rule->isApplicableToCustomer($customer)) {
+            return ApiResponse::forbidden('This reward is not applicable to your account');
+        }
+
+        // Redis Key: browse_product:{customer_id}:{date}:{product_id}
+        $today = Carbon::now()->format('Y-m-d');
+        $redisKey = "browse_product:{$customer->id}:{$today}:{$productId}";
+
+        // Redis 判断该产品今天是否已经浏览过
+        if (Redis::exists($redisKey)) {
+            return ApiResponse::error('You have already earned points for browsing this product today');
+        }
+
+        // 获取该客户应得的积分
+        $points = $rule->getPointsForCustomer($customer);
+        if ($points <= 0) {
+            $points = (int) $rule->reward_point;
+        }
+        if ($points <= 0) {
+            return ApiResponse::error('No points configured for browse product');
+        }
+
+        // 添加积分
+        $this->rewardPointRepository->addPoints(
+            $customer->id,
+            RewardActiveRule::TYPE_BROWSE_PRODUCT,
+            $points,
+            null,
+            "Browsed categorys #{$productId}",
+            $rule
+        );
+
+        // 写入 Redis,TTL = 到当天结束的剩余秒数
+        $endOfDay = Carbon::now()->endOfDay();
+        $ttl = Carbon::now()->diffInSeconds($endOfDay);
+        Redis::setex($redisKey, $ttl, 1);
+
+        // 同时记录到当天已浏览产品集合(方便 getBrowsedProducts 读取)
+        $setKey = "browse_product:{$customer->id}:{$today}:set";
+        Redis::sadd($setKey, $productId);
+        Redis::expire($setKey, $ttl);
+
+        $totalPoints = $this->rewardPointRepository->getCustomerPoints($customer->id);
+
+        return ApiResponse::success([
+            'categorys' => $productId,
+            'points' => $points,
+            'total_points' => $totalPoints
+        ], "You earned {$points} points for browsing this product!");
+    }
+
+    /**
+     * 获取今天已浏览并获得积分的产品列表
+     *
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function getBrowsedProducts()
+    {
+        $customer = auth()->guard('customer')->user();
+
+        if (!$customer) {
+            return ApiResponse::unauthorized();
+        }
+
+        $today = Carbon::now()->format('Y-m-d');
+        $setKey = "browse_product:{$customer->id}:{$today}:set";
+
+        // 从 Redis Set 中获取今天已浏览的产品ID列表
+        $browsedProductIds = Redis::smembers($setKey);
+        $browsedProductIds = array_map('intval', $browsedProductIds);
+
+        return ApiResponse::success([
+            'browsed_product_ids' => $browsedProductIds,
+            'browsed_count' => count($browsedProductIds)
+        ]);
+    }
+
     /**
      * Get points information for cart
      */
@@ -341,6 +450,8 @@ class RewardPointsController extends Controller
             7 => 'Share',
             8 => 'Subscription',
             9 => 'Login',
+            13 => 'Browse Product',
+            14 => 'Follow',
             99 => 'admin',
         ];
 

+ 9 - 5
packages/Longyi/RewardPoints/src/Listeners/ReviewEvents.php

@@ -49,8 +49,10 @@ class ReviewEvents
             return;
         }
 
-        // 【简化】使用统一方法获取积分值
-        $points = $rule->getPointsForCustomer($customer);
+        // 根据评价是否包含图片/视频决定积分数
+        // 纯文字评价 50 积分,带照片/视频评价 100 积分
+        $hasMedia = $review->images()->count() > 0;
+        $points = $hasMedia ? 100 : 50;
 
         if ($points <= 0) {
             // Log::info('Review points is 0, skipping', [
@@ -84,7 +86,7 @@ class ReviewEvents
             RewardActiveRule::TYPE_REVIEW,
             $points,
             null,
-            $this->getReviewPointsDescription($review),
+            $this->getReviewPointsDescription($review, $hasMedia),
             $rule
         );
 
@@ -161,12 +163,14 @@ class ReviewEvents
     /**
      * 获取评价积分描述
      */
-    protected function getReviewPointsDescription($review): string
+    protected function getReviewPointsDescription($review, bool $hasMedia = false): string
     {
         $productInfo = !empty($review->product_id)
             ? " for product #{$review->product_id}"
             : '';
 
-        return "Points earned for product review{$productInfo} (Review ID: {$review->id})";
+        $mediaLabel = $hasMedia ? ' (with photo/video)' : ' (text only)';
+
+        return "Points earned for product review{$productInfo}{$mediaLabel} (Review ID: {$review->id})";
     }
 }

+ 2 - 0
packages/Longyi/RewardPoints/src/Models/RewardActiveRule.php

@@ -22,6 +22,8 @@ class RewardActiveRule extends Model
     const TYPE_GIFT_CARD_REDEEM = TransactionType::GIFT_CARD_REDEEM;
     const TYPE_ADMIN_ACTION = TransactionType::ADMIN_ACTION;
     const TYPE_ORDER_CANCEL_REFUND = TransactionType::ORDER_CANCEL_REFUND;
+    const TYPE_BROWSE_PRODUCT = TransactionType::BROWSE_PRODUCT;
+    const TYPE_FOLLOW = TransactionType::FOLLOW;
 
     protected $table = 'mw_reward_active_rules';
     protected $primaryKey = 'rule_id';

+ 5 - 7
packages/Longyi/RewardPoints/src/Repositories/RewardPointRepository.php

@@ -271,16 +271,14 @@ class RewardPointRepository extends Repository
     {
         $query = $this->where('customer_id', $customerId)
             ->orderBy('transaction_time', 'desc');
-
-        if ($page) {
-            return $query->paginate($limit, ['*'], 'page', $page);
-        }
-// 根据视图类型筛选(仅获取或全部)
-       if ($amountType === 'earned') {
+        if ($amountType == 'earned') {
             $query->where('amount', '>', 0)->where('status',1);
-        } elseif ($amountType === 'redeemed') {
+        } elseif ($amountType == 'redeemed') {
             $query->where('amount', '<', 0);
         }
+        if ($page) {
+            return $query->paginate($limit, ['*'], 'page', $page);
+        }
         return $query->paginate($limit);
     }
 

+ 10 - 0
packages/Longyi/RewardPoints/src/Routes/routes.php

@@ -99,6 +99,16 @@ Route::group(['middleware' => ['api', ApiCustomerAuthenticate::class], 'prefix'
         'as' => 'api.checkout.reward-points-info',
         'uses' => 'Longyi\RewardPoints\Http\Controllers\RewardPointsController@getPointsInfo'
     ]);
+
+    Route::post('reward-points/browse-product', [
+        'as' => 'api.customer.reward-points.browse-product',
+        'uses' => 'Longyi\RewardPoints\Http\Controllers\RewardPointsController@browseProduct'
+    ]);
+
+    Route::get('reward-points/browsed-products', [
+        'as' => 'api.customer.reward-points.browsed-products',
+        'uses' => 'Longyi\RewardPoints\Http\Controllers\RewardPointsController@getBrowsedProducts'
+    ]);
 });
 
 // 后台路由