Browse Source

Merge branch 'kuaiyingyong' into kuaiyingyong_push

Wang Chen 4 years ago
parent
commit
2b4ab967a2
34 changed files with 1443 additions and 561 deletions
  1. 3 1
      app/Cache/CacheKeys.php
  2. 112 0
      app/Cache/Push/PushCache.php
  3. 0 34
      app/Cache/PushCache.php
  4. 1 0
      app/Consts/ErrorConst.php
  5. 1 1
      app/Exceptions/Handler.php
  6. 1 1
      app/Http/Controllers/QuickApp/Activity/ActivityController.php
  7. 1 1
      app/Http/Controllers/QuickApp/Activity/Transformers/ReBuildData.php
  8. 28 6
      app/Http/Controllers/QuickApp/Book/BookController.php
  9. 72 8
      app/Http/Controllers/QuickApp/Book/ChapterController.php
  10. 10 10
      app/Http/Controllers/QuickApp/Book/Transformers/ChapterListTransformer.php
  11. 52 1
      app/Http/Controllers/QuickApp/Order/OrdersController.php
  12. 9 10
      app/Http/Controllers/QuickApp/User/ReadRecordController.php
  13. 6 5
      app/Http/Controllers/QuickApp/User/Transformers/ReadRecordTransformer.php
  14. 25 13
      app/Http/Controllers/QuickApp/User/UserShelfBooksController.php
  15. 16 5
      app/Http/Controllers/QuickApp/WelcomeController.php
  16. 3 3
      app/Http/Kernel.php
  17. 8 0
      app/Http/Middleware/QuickAppGetUserFromToken.php
  18. 53 23
      app/Modules/AdPosition/Services/AdPositionService.php
  19. 5 3
      app/Modules/Book/Models/BookConfig.php
  20. 21 4
      app/Modules/Book/Services/BookConfigService.php
  21. 2 1
      app/Modules/Push/Services/PushService.php
  22. 2 0
      app/Modules/Trade/Models/Order.php
  23. 2 2
      app/Modules/Trade/Pay/OrderArousePayFactory.php
  24. 12 0
      app/Modules/Trade/Pay/OrderPaySuccess.php
  25. 46 0
      app/Modules/Trade/Pay/QuarterOrderPaySuccess.php
  26. 10 10
      app/Modules/Trade/Pay/WxOrderArousePay.php
  27. 30 0
      app/Modules/User/Models/ReadLog.php
  28. 103 83
      app/Modules/User/Services/ReadRecordService.php
  29. 32 32
      config/app.php
  30. 5 1
      config/audit.php
  31. 13 0
      config/database.php
  32. 4 0
      config/option.php
  33. 403 0
      resources/views/qapp/start.blade.php
  34. 352 303
      resources/views/qapp/welcome.blade.php

+ 3 - 1
app/Cache/CacheKeys.php

@@ -23,7 +23,9 @@ class CacheKeys
             'token' => 'Lock:%s', // 锁,token
         ],
         'push'     => [
-            'user' => 'Push:%s'
+            'user'   => 'Push:%s',
+            'statPv' => 'Push:pv:%s:%s',
+            'statUv' => 'Push:uv:%s:%s',
         ],
         'ad'       => [
             'position' => 'Ad:position'

+ 112 - 0
app/Cache/Push/PushCache.php

@@ -0,0 +1,112 @@
+<?php
+
+
+namespace App\Cache\Push;
+
+
+use App\Consts\BaseConst;
+use App\Libs\Utils;
+use Illuminate\Support\Facades\Redis;
+
+class PushCache
+{
+    /**
+     * 获取用户reg id
+     * @param $uid
+     * @return mixed
+     */
+    public static function getUserPushRegId($uid)
+    {
+        $cacheKey = Utils::getCacheKey('push.user', [$uid]);
+        return Redis::get($cacheKey);
+    }
+
+    /**
+     * 设置用户reg id
+     * @param $uid
+     * @param $regId
+     * @return mixed
+     */
+    public static function setUserPushRegId($uid, $regId)
+    {
+        $cacheKey = Utils::getCacheKey('push.user', [$uid]);
+        return Redis::set($cacheKey, $regId);
+    }
+
+    /**
+     * 增加pv
+     * @param $pushId
+     * @param $date
+     * @return bool
+     */
+    public static function incrPushPv($pushId, $date): bool
+    {
+        if (empty($pushId) || empty($date)) {
+            return false;
+        }
+
+        $cacheKey = Utils::getCacheKey('push.statsPv', [$pushId, $date]);
+        Redis::incrBy($cacheKey, 1);
+        $ttl = Redis::ttl($cacheKey);
+        if ((int)$ttl < 1) {
+            Redis::expire($cacheKey, BaseConst::ONE_DAY_SECONDS * 3);
+        }
+        return true;
+    }
+
+    /**
+     * @param $pushId
+     * @param $date
+     * @param $uid
+     * @return bool
+     */
+    public static function zAddPushUv($pushId, $date, $uid): bool
+    {
+        if (empty($pushId) || empty($date) || empty($uid)) {
+            return false;
+        }
+
+        $cacheKey = Utils::getCacheKey('push.statsUv', [$pushId, $date]);
+        Redis::zAdd($cacheKey, time(), $uid);
+        $ttl = Redis::ttl($cacheKey);
+        if ((int)$ttl < 1) {
+            Redis::expire($cacheKey, BaseConst::ONE_DAY_SECONDS * 3);
+        }
+
+        return true;
+    }
+
+    /**
+     * 获取pv数
+     * @param $pushId
+     * @param $date
+     * @return int
+     */
+    public static function getPushyPv($pushId, $date): int
+    {
+        $cacheKey = Utils::getCacheKey('push.statPv', [$pushId, $date]);
+        $exist    = Redis::exists($cacheKey);
+        if (!$exist) {
+            return 0;
+        }
+
+        return (int)Redis::get($cacheKey);
+    }
+
+    /**
+     * 获取uv数
+     * @param $pushId
+     * @param $date
+     * @return int
+     */
+    public static function getPushUv($pushId, $date): int
+    {
+        $cacheKey = Utils::getCacheKey('push.statUv', [$pushId, $date]);
+        $exist    = Redis::exists($cacheKey);
+        if (!$exist) {
+            return 0;
+        }
+
+        return (int)Redis::zCount($cacheKey, 0, 99999999999999999999999999);
+    }
+}

+ 0 - 34
app/Cache/PushCache.php

@@ -1,34 +0,0 @@
-<?php
-
-
-namespace App\Cache;
-
-
-use App\Libs\Utils;
-use Illuminate\Support\Facades\Redis;
-
-class PushCache
-{
-    /**
-     * 获取用户reg id
-     * @param $uid
-     * @return mixed
-     */
-    public static function getUserPushRegId($uid)
-    {
-        $cacheKey = Utils::getCacheKey('push.user', [$uid]);
-        return Redis::get($cacheKey);
-    }
-
-    /**
-     * 设置用户reg id
-     * @param $uid
-     * @param $regId
-     * @return mixed
-     */
-    public static function setUserPushRegId($uid, $regId)
-    {
-        $cacheKey = Utils::getCacheKey('push.user', [$uid]);
-        return Redis::set($cacheKey, $regId);
-    }
-}

+ 1 - 0
app/Consts/ErrorConst.php

@@ -45,4 +45,5 @@ class ErrorConst
     const ACTIVITY_NOT_START                = '20002:活动还未开始';
     const ACTIVITY_IS_END                   = '20003:活动已经结束';
     const ACTIVITY_INVALID                  = '20004:无效的活动';
+    const ACTIVITY_CHARGE_OUT_OF_LIMIT      = '20005:活动充值已达最大次数限制';
 }

+ 1 - 1
app/Exceptions/Handler.php

@@ -36,7 +36,7 @@ class Handler extends ExceptionHandler
     public function report(Exception $e)
     {
         $appEnv = env('APP_ENV', 'production');
-        if ($this->shouldReport($e) && env('APP_ENV') !== 'local') {
+        if ($this->shouldReport($e) && env('APP_ENV') == 'production') {
             $date        = date('Y-m-d H:i:s');
             $file        = $e->getFile();
             $line        = $e->getLine();

+ 1 - 1
app/Http/Controllers/QuickApp/Activity/ActivityController.php

@@ -208,7 +208,7 @@ class ActivityController extends BaseController
         // 获取用户信息
         $user        = User::getUser($this->uid);
         $sendOrderId = getProp($user, 'send_order_id');
-        
+
         // 用户派单的信息是否跟创建该活动的子账号一致
         $qappAccountId = (int)getProp($activity, 'qapp_account_id');
         if ($qappAccountId && $sendOrderId) {

+ 1 - 1
app/Http/Controllers/QuickApp/Activity/Transformers/ReBuildData.php

@@ -51,7 +51,7 @@ class ReBuildData
 
             // 支付产品信息
             $product = collect($products)->firstWhere('id', $productId);
-            $price   = getProp($product, 'price');
+            $price   = (float)getProp($product, 'price');
             $total   = $price * 100 + (int)getProp($product, 'given');
 
             $result[] = [

+ 28 - 6
app/Http/Controllers/QuickApp/Book/BookController.php

@@ -253,6 +253,12 @@ class BookController extends BaseController
         if ($status != '') {
             $where['status'] = $status;
         }
+
+        // 搜索关键词的情况下,屏蔽书籍完本状态
+        if ($key && isset($where['status'])) {
+            unset($where['status']);
+        }
+
         $page_size = $request->input('page_size', 15);
         $books     = BookConfigService::getBooks($where, $order, $page_size);
         return response()->pagination(new BookTransformer, $books);
@@ -310,14 +316,30 @@ class BookController extends BaseController
 
     public function rank(Request $request)
     {
-        $sex = $request->input('sex');
-        if ($sex == 1) {
-            $books = collectionTransform(new BookTransformer, BookConfigService::getBooksByIds([11601, 11529, 3365, 10377, 11457, 8102, 6464, 7287, 2563, 10419]));
-        } elseif ($sex == 2) {
-            $books = collectionTransform(new BookTransformer, BookConfigService::getBooksByIds([10823, 10479, 10467, 10139, 9990, 9973, 9479, 9423, 1148, 8693, 8497, 8148, 8129, 7857, 7854, 7629, 7362, 5748, 5362, 4811, 4470, 4135, 3759, 3696, 3418, 3401, 3369, 2698, 1634, 1479]));
-        } else {
+        // 1:男频,2:女频
+        $sex = (int)$request->input('sex');
+        if (!in_array($sex, [1, 2], true)) {
             return response()->error('PARAM_ERROR');
         }
+
+        // 默认
+        $bids = [11601, 11529, 3365, 10377, 11457, 8102, 6464, 7287, 2563, 10419];
+        if ($sex === 2) {
+            $bids = [10823, 10479, 10467, 10139, 9990, 9973, 9479, 9423, 1148, 8693, 8497, 8148, 8129, 7857, 7854, 7629, 7362, 5748, 5362, 4811, 4470, 4135, 3759, 3696, 3418, 3401, 3369, 2698, 1634, 1479];
+        }
+
+        // 根据包名、平台、版本号判断是否审核
+        $package     = $request->header('x-package', '');
+        $brand       = $request->header('x-nbrand', '');
+        $codeVersion = $request->header('x-codeversion', '');
+        if (Utils::checkIsAudit($package, $brand, $codeVersion)) {
+            $bids = [2266, 3838, 9700, 10175, 10301, 3422, 1166, 4546, 9163, 2509];
+            if ($sex === 2) {
+                $bids = [159, 2439, 6276, 10074, 5409, 9379, 10323, 9078, 3603, 487];
+            }
+        }
+
+        $books = collectionTransform(new BookTransformer, BookConfigService::getBooksByIds($bids));
         return response()->success($books);
     }
 

+ 72 - 8
app/Http/Controllers/QuickApp/Book/ChapterController.php

@@ -56,6 +56,9 @@ class ChapterController extends BaseController
 
     private function getChapterCatalog(int $bid, $chapters, $book_info)
     {
+        // 查询书籍是否限免
+        $isFree = BookConfigService::judgeBookIsFree($bid);
+
         switch ($book_info->charge_type) {
             case 'BOOK':
                 $price          = $this->getPrice($book_info);
@@ -63,12 +66,24 @@ class ChapterController extends BaseController
                 foreach ($chapters as $v) {
                     $v->is_need_charge = $v->is_vip ? $is_need_charge : false;
                     $v->price          = $price;
+
+                    // 限免判断
+                    if ($isFree) {
+                        $v->is_need_charge = false;
+                        $v->price          = 0;
+                    }
                 }
                 break;
             default:
                 foreach ($chapters as $v) {
-                    $v->price          = $v->is_vip ? $this->getPrice($book_info, $v->size) : 0;
-                    $v->is_need_charge = $v->is_vip ? $this->isChapterNeedCharge($bid, $v->id, $v->price) : false;
+                    // 限免判断
+                    if ($isFree) {
+                        $v->is_need_charge = false;
+                        $v->price          = 0;
+                    } else {
+                        $v->price          = $v->is_vip ? $this->getPrice($book_info, $v->size) : 0;
+                        $v->is_need_charge = $v->is_vip ? $this->isChapterNeedCharge($bid, $v->id, $v->price) : false;
+                    }
                 }
                 break;
         }
@@ -97,18 +112,59 @@ class ChapterController extends BaseController
         }
 
         if ($chapter->is_vip == 0) {
+            ReadRecordService::addReadLog($this->uid, [
+                'distribution_channel_id' => $this->distribution_channel_id,
+                'bid' => $bid,
+                'cid' => $chapter->id,
+                'uid' => $this->uid,
+                'send_order_id' => $this->send_order_id,
+                'sequence' => $chapter->sequence,
+            ]);
+            ReadRecordService::addReadRecord([
+                'uid' => $this->uid, 'bid' => $bid, 'book_name' => $book_info->book_name,
+                'cid' => $cid, 'chapter_name' => $chapter->name, 'sequence' => $chapter->sequence
+            ]);
+            return response()->item(new ChapterTransformer, $this->getChapter($bid, $cid, $chapter));
+        }
+
+        // 书籍是否限免
+        $free = BookConfigService::judgeBookIsFree($bid);
+        if ($free) {
+            ReadRecordService::addReadLog($this->uid, [
+                'distribution_channel_id' => $this->distribution_channel_id,
+                'bid' => $bid,
+                'cid' => $chapter->id,
+                'uid' => $this->uid,
+                'send_order_id' => $this->send_order_id,
+                'sequence' => $chapter->sequence,
+            ]);
             ReadRecordService::addReadRecord([
                 'uid' => $this->uid, 'bid' => $bid, 'book_name' => $book_info->book_name,
-                'cid' => $cid, 'chapter_name' => $chapter->name
+                'cid' => $cid, 'chapter_name' => $chapter->name, 'sequence' => $chapter->sequence
             ]);
+            if ($chapter->is_vip == 1) {
+                $fee  = $this->getPrice($book_info, $chapter->size);
+                $now = date('Y-m-d');
+                Redis::hincrby('qapp:book:free:virtual:' . $free->id, $now, $fee);
+                Redis::sadd('qapp:free:virtual' . $now, $free->id);
+            }
             return response()->item(new ChapterTransformer, $this->getChapter($bid, $cid, $chapter));
         }
 
-        //已经付费 或者 书籍是否限免
-        if ($this->getOrderRecord($bid, $cid) || BookConfigService::judgeBookIsFree($bid)) {
+
+        //已经付费
+        if ($this->getOrderRecord($bid, $cid)) {
+            ReadRecordService::addReadLog($this->uid, [
+                'distribution_channel_id' => $this->distribution_channel_id,
+                'bid' => $bid,
+                'cid' => $chapter->id,
+                'uid' => $this->uid,
+                'send_order_id' => $this->send_order_id,
+                'sequence' => $chapter->sequence,
+            ]);
             ReadRecordService::addReadRecord([
                 'uid' => $this->uid, 'bid' => $bid, 'book_name' => $book_info->book_name,
-                'cid' => $cid, 'chapter_name' => $chapter->name
+                'cid' => $cid, 'chapter_name' => $chapter->name, 'sequence' => $chapter->sequence
             ]);
 
             return response()->item(new ChapterTransformer, $this->getChapter($bid, $cid, $chapter));
@@ -147,9 +203,17 @@ class ChapterController extends BaseController
         //付费 不提醒
         if ($this->balancePay($book_info, $cid, $chapter->size, $chapter->name, 0)) {
             UserTaskService::addUserTaskQueue($this->uid, BaseTask::read, UserTaskService::judge_trigger);
+            ReadRecordService::addReadLog($this->uid, [
+                'distribution_channel_id' => $this->distribution_channel_id,
+                'bid' => $bid,
+                'cid' => $chapter->id,
+                'uid' => $this->uid,
+                'send_order_id' => $this->send_order_id,
+                'sequence' => $chapter->sequence,
+            ]);
             ReadRecordService::addReadRecord([
                 'uid' => $this->uid, 'bid' => $bid, 'book_name' => $book_info->book_name,
-                'cid' => $cid, 'chapter_name' => $chapter->name
+                'cid' => $cid, 'chapter_name' => $chapter->name, 'sequence' => $chapter->sequence
             ]);
 
             return response()->item(new ChapterTransformer, $this->getChapter($bid, $cid, $chapter));
@@ -188,7 +252,7 @@ class ChapterController extends BaseController
         if ($this->balancePay($book_info, $cid, $chapter->size, $chapter->name, $remind)) {
             ReadRecordService::addReadRecord([
                 'uid' => $this->uid, 'bid' => $bid, 'book_name' => $book_info->book_name,
-                'cid' => $cid, 'chapter_name' => $chapter->name
+                'cid' => $cid, 'chapter_name' => $chapter->name, 'sequence' => $chapter->sequence
             ]);
 
             return response()->item(new ChapterTransformer, $this->getChapter($bid, $cid, $chapter));

+ 10 - 10
app/Http/Controllers/QuickApp/Book/Transformers/ChapterListTransformer.php

@@ -10,16 +10,16 @@ class ChapterListTransformer
     public function transform($chapter)
     {
         return [
-            'bid'       =>  Hashids::encode($chapter->bid),
-            'chapter_id'       =>  $chapter->id,
-            'chapter_name'   =>  $chapter->name,
-            'chapter_sequence'   =>  $chapter->sequence,
-            'chapter_is_vip'   =>  $chapter->is_vip,
-            'chapter_size'   =>  $chapter->size,
-            'prev_cid'   =>  $chapter->prev_cid,
-            'next_cid'   =>  $chapter->next_cid,
-            'recent_update_at'   =>  $chapter->recent_update_at,
-            'is_need_charge' => $chapter->is_need_charge ? 1 : 0,
+            'bid'              => Hashids::encode($chapter->bid),
+            'chapter_id'       => $chapter->id,
+            'chapter_name'     => $chapter->name,
+            'chapter_sequence' => $chapter->sequence,
+            'chapter_is_vip'   => $chapter->is_vip,
+            'chapter_size'     => $chapter->size,
+            'prev_cid'         => $chapter->prev_cid,
+            'next_cid'         => $chapter->next_cid,
+            'recent_update_at' => $chapter->recent_update_at,
+            'is_need_charge'   => $chapter->is_need_charge ? 1 : 0,
         ];
     }
 }

+ 52 - 1
app/Http/Controllers/QuickApp/Order/OrdersController.php

@@ -2,9 +2,12 @@
 
 namespace App\Http\Controllers\QuickApp\Order;
 
+use App\Consts\ErrorConst;
+use App\Libs\Utils;
 use App\Modules\Activity\Models\Activity;
 use App\Modules\Statistic\Services\AdVisitStatService;
 use App\Http\Controllers\QuickApp\BaseController;
+use App\Modules\User\Models\QappPackage;
 use Illuminate\Http\Request;
 
 use App\Modules\Subscribe\Services\BookOrderService;
@@ -20,6 +23,7 @@ use App\Modules\Book\Services\BookConfigService;
 use App\Modules\Book\Services\BookService;
 use App\Modules\Channel\Services\PayTemplateService;
 use App\Modules\Subscribe\Models\Order;
+use App\Modules\Trade\Models\Order as TradeOrder;
 use App\Modules\Trade\Pay\OrderArousePayFactory;
 use App\Modules\Trade\Pay\OrderPaySuccess;
 use App\Modules\Trade\Services\PayMerchantService;
@@ -377,7 +381,7 @@ class OrdersController extends BaseController
     public function chargeRecordLists(Request $request)
     {
         $page_size = $request->input('page_size', 15);
-        $res       = OrderService::getOrderList($this->uid, $page_size);
+        $res       = OrderService::getSuccessOrderList($this->uid, $page_size);
         return response()->pagination(new ChargeListTransformer(), $res);
     }
 
@@ -426,6 +430,32 @@ class OrdersController extends BaseController
         if ($activity_token) {
             $activity    = Activity::getActivityBuToken($activity_token);
             $activity_id = (int)getProp($activity, 'id');
+
+            // 校验活动次数
+            $settingJson = getProp($activity, 'setting');
+            if ($settingJson) {
+                $setting      = json_decode($settingJson, true);
+                $productInfos = getProp($setting, 'product_info', []);
+                $productInfo  = collect($productInfos)->firstWhere('product_id', $product_id);
+                $limit        = (int)getProp($productInfo, 'limit');
+                if ($limit > 0) {
+                    // 查询用户通过该活动已经充值的次数
+                    $paidNum = TradeOrder::getActivityOrderNum([
+                        'uid'         => $uid,
+                        'begin_time'  => getProp($activity, 'start_time'),
+                        'end_time'    => getProp($activity, 'end_time'),
+                        'status'      => 'PAID',
+                        'product_id'  => $product_id,
+                        'activity_id' => $activity_id
+                    ]);
+                    myLog('charge')->info('', compact('uid', 'product_id', 'activity', 'paidNum'));
+
+                    // 活动充值次数限制
+                    if ($paidNum >= $limit) {
+                        Utils::throwError(ErrorConst::ACTIVITY_CHARGE_OUT_OF_LIMIT);
+                    }
+                }
+            }
         }
 
         return compact(
@@ -476,6 +506,17 @@ class OrdersController extends BaseController
     {
         if ($params = $this->getPayParams($request)) {
             $params['pay_merchant_id'] = $this->app_pay_merchat_id;
+
+            // 针对聚裕的包无法支付的问题(注册时传入了仙女阅读的包名,导致支付时取的支付信息不一致)
+            $package = $request->header('x-package', '');
+            if ($package === 'com.juyu.kuaiying.rmyq') {
+                $packageInfo   = QappPackage::getPackageByPackage($package);
+                $payMerchantId = getProp($packageInfo, 'app_pay_merchat_id');
+                if ($payMerchantId) {
+                    $params['pay_merchant_id'] = $payMerchantId;
+                }
+            }
+
         } else {
             return response()->error('QAPP_PARAM_ERROR');
         }
@@ -525,6 +566,16 @@ class OrdersController extends BaseController
     {
         if ($params = $this->getPayParams($request)) {
             $params['pay_merchant_id'] = $this->h5_pay_merchat_id;
+
+            // 针对聚裕的包无法支付的问题(注册时传入了仙女阅读的包名,导致支付时取的支付信息不一致)
+            $package = $request->header('x-package', '');
+            if ($package === 'com.juyu.kuaiying.rmyq') {
+                $packageInfo   = QappPackage::getPackageByPackage($package);
+                $payMerchantId = getProp($packageInfo, 'h5_pay_merchat_id');
+                if ($payMerchantId) {
+                    $params['pay_merchant_id'] = $payMerchantId;
+                }
+            }
         } else {
             return response()->error('QAPP_PARAM_ERROR');
         }

+ 9 - 10
app/Http/Controllers/QuickApp/User/ReadRecordController.php

@@ -21,12 +21,11 @@ class ReadRecordController extends BaseController
      */
 
 
-
     /**
      * @apiVersion 1.0.0
      * @apiDescription 获取阅读记录
      * @api {get} readrecord 获取阅读记录
-     * @apiHeader {String} [Authorization]  token 
+     * @apiHeader {String} [Authorization]  token
      * @apiGroup ReadRecord
      * @apiName index
      * @apiSuccess {int}         code 状态码
@@ -65,21 +64,21 @@ class ReadRecordController extends BaseController
     public function index(Request $request)
     {
         $user = $this->user_info;
-        $res = ReadRecordService::getReadRecord($this->uid);
+        $res  = ReadRecordService::getReadRecord($this->uid);
         if ($res) {
             $id_arr = [];
             foreach ($res as $key => $value) {
                 $id_arr[] = $value['bid'];
             }
 
-            $book = BookConfigService::getBooksByIds($id_arr);
+            $book = BookConfigService::getBooksByIds($id_arr, [], false);//下架图书最近阅读可看到
             foreach ($res as $key => &$value) {
-                $value['cover'] = '';
+                $value['cover']        = '';
                 $value['last_chapter'] = 0;
-                foreach ($book as  $val) {
+                foreach ($book as $val) {
                     if ($value['bid'] == $val->bid) {
-                        $value['book_name'] = $val->book_name;
-                        $value['cover'] = $val->cover;
+                        $value['book_name']    = $val->book_name;
+                        $value['cover']        = $val->cover;
                         $value['last_chapter'] = $val->last_chapter;
                         break;
                     }
@@ -90,7 +89,7 @@ class ReadRecordController extends BaseController
             if ($a['time'] >= $b['time']) return -1;
             return 1;
         });
-        return response()->collection(new ReadRecordTransformer(),  array_to_object($res));
+        return response()->collection(new ReadRecordTransformer(), array_to_object($res));
     }
 
 
@@ -136,7 +135,7 @@ class ReadRecordController extends BaseController
      * @apiDescription 删除阅读记录
      * @api {get} readrecord/delete 删除阅读记录
      * @apiGroup ReadRecord
-     * @apiHeader {String} [Authorization]  token 
+     * @apiHeader {String} [Authorization]  token
      * @apiName delReadRecord
      * @apiParam   {String}         bid     多个bid以,分隔
      * @apiSuccess {int}         code 状态码

+ 6 - 5
app/Http/Controllers/QuickApp/User/Transformers/ReadRecordTransformer.php

@@ -9,12 +9,13 @@ class ReadRecordTransformer
     public function transform($res)
     {
         return [
-            'book_id' => Hashids::encode($res->bid),
-            'cid' => $res->cid,
-            'book_name' => $res->book_name,
+            'book_id'      => Hashids::encode($res->bid),
+            'cid'          => $res->cid,
+            'book_name'    => $res->book_name,
             'chapter_name' => $res->chapter_name,
-            'time' => $res->time,
-            'cover' => $res->cover,
+            'time'         => $res->time,
+            'cover_url'    => $res->cover,
+            'cover'        => $res->cover,
             'last_chapter' => $res->last_chapter
         ];
     }

+ 25 - 13
app/Http/Controllers/QuickApp/User/UserShelfBooksController.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Controllers\QuickApp\User;
 
+use App\Libs\Utils;
 use Illuminate\Http\Request;
 use App\Http\Controllers\QuickApp\BaseController;
 use Redis;
@@ -36,6 +37,12 @@ class UserShelfBooksController extends BaseController
                     break;
                 }
             }
+
+            //补充逻辑 书架有、阅读记录没有场景
+            if(!isset($v['recent_cid']))
+            {
+                $v['recent_cid']             = $v['first_cid'];
+            }
         }
         return response()->collection(new UserShelfBooksTransformer(), $res);
     }
@@ -65,12 +72,12 @@ class UserShelfBooksController extends BaseController
         if (checkParam($param, ['bid'])) {
             return response()->error('LACK_PARAM');
         }
-
-        $param['uid']                     = $this->uid;
-        $param['bid']                     = Hashids::decode($param['bid'])[0];
-        $param['distribution_channel_id'] = $this->distribution_channel_id;
-        $res                              = UserShelfBooksService::create($param);
+        $res = true;
         try {
+            $param['uid']                     = $this->uid;
+            $param['bid']                     = Hashids::decode($param['bid'])[0];
+            $param['distribution_channel_id'] = $this->distribution_channel_id;
+            $res                              = UserShelfBooksService::create($param);
         } catch (\Exception $e) {
             return response()->error('QAPP_PARAM_ERROR');
         }
@@ -103,15 +110,20 @@ class UserShelfBooksController extends BaseController
      */
     public function delShelf(Request $request)
     {
-        $bid = $request->input('bid');
-        if (empty($bid)) return response()->error('LACK_PARAM');
-        $param['uid'] = $this->uid;
-        $param['bid'] = Hashids::decode($bid)[0];
-        $res          = UserShelfBooksService::del($this->uid, $param['bid']);
-        if ($res) {
-            return response()->success();
+        $uid       = $this->uid;
+        $bid       = $request->input('bid');
+        $decodeBid = Utils::getDecodeId($bid);
+        if (empty($bid) || empty($decodeBid)) {
+            return response()->error('LACK_PARAM');
         }
-        return response()->error('QAPP_SYS_ERROR');
+
+        // 删除书架中的书籍
+        UserShelfBooksService::del($uid, $decodeBid);
+
+        // 删除最近阅读记录
+        ReadRecordService::delReadRecordStatic($uid, [$decodeBid]);
+
+        return response()->success();
     }
 
 

+ 16 - 5
app/Http/Controllers/QuickApp/WelcomeController.php

@@ -27,13 +27,20 @@ class WelcomeController extends BaseController
             $send_order              = SendOrderService::getSendOrderStatic($this->send_order_id);
             $distribution_channel_id = $send_order->distribution_channel_id;
             $qappPackage             = QappPackageService::getPackage($distribution_channel_id);
+
+            $showGzh     = 0;
+            $sendOrderId = $this->send_order_id;
+            if ($sendOrderId && in_array($sendOrderId, explode(',', env('SHOW_GZH_SEND_ORDER_IDS')))) {
+                $showGzh = 1;
+            }
             if ($send_order && $qappPackage) {
                 $this->sendOrderStatistic($send_order);//统计
-                return view('qapp.welcome')->with([
+                return view('qapp.start')->with([
                     'package'       => $qappPackage->package,
                     'hash_bid'      => Hashids::encode($send_order->book_id),
                     'cid'           => $send_order->chapter_id,
-                    'send_order_id' => $this->send_order_id
+                    'send_order_id' => $this->send_order_id,
+                    'show_gzh'      => $showGzh
                 ]);
             }
         }
@@ -137,12 +144,16 @@ class WelcomeController extends BaseController
 
         // 配置
         $data = [
-            'support'     => $support,
-            'task_center' => [
+            'support'        => $support,
+            'task_center'    => [
                 'home_show'           => 1,
                 'pay_back_alert_show' => 1,
             ],
-            'position'    => [
+            'add_desk_alert' => [
+                'sign_out_app_show'    => $sendOrderId ? 1 : 0,
+                'sign_out_reader_show' => $sendOrderId ? 1 : 0,
+            ],
+            'position'       => [
                 'home_alert'    => getProp($adPositions, 'home_alert', []),
                 'reader_banner' => getProp($adPositions, 'reader_banner', [])
             ]

+ 3 - 3
app/Http/Kernel.php

@@ -23,7 +23,7 @@ class Kernel extends HttpKernel
      * @var array
      */
     protected $middlewareGroups = [
-        'web' => [
+        'web'      => [
             \App\Http\Middleware\EncryptCookies::class,
             \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
             \Illuminate\Session\Middleware\StartSession::class,
@@ -33,7 +33,7 @@ class Kernel extends HttpKernel
             \App\Http\Middleware\QuickAppGetUserFromToken::class,
             \App\Http\Middleware\QuickAppRefreshToken::class,
         ],
-        'api' => [
+        'api'      => [
             'throttle:60,1',
         ],
     ];
@@ -46,7 +46,7 @@ class Kernel extends HttpKernel
      * @var array
      */
     protected $routeMiddleware = [
-        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
+        'throttle'  => \Illuminate\Routing\Middleware\ThrottleRequests::class,
         'checkSign' => \App\Http\Middleware\CheckSign::class,
     ];
 }

+ 8 - 0
app/Http/Middleware/QuickAppGetUserFromToken.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Middleware;
 
+use App\Cache\Push\PushCache;
 use App\Modules\Push\Services\PushService;
 use App\Modules\User\Services\QappUserService;
 use App\Modules\User\Services\UserService;
@@ -50,6 +51,13 @@ class QuickAppGetUserFromToken extends BaseMiddleware
         $regId    = $request->header('x-regid', '');
         PushService::setUserRegId($uid, $regId, $provider, $package);
 
+        // 推送pv、uv统计
+        $pushId = (int)$request->get('push_id', 0);
+        if ($pushId) {
+            PushCache::incrPushPv($pushId, date('Ymd'));
+            PushCache::zAddPushUv($pushId, date('Ymd'), $uid);
+        }
+
         return $next($request);
     }
 }

+ 53 - 23
app/Modules/AdPosition/Services/AdPositionService.php

@@ -21,12 +21,13 @@ class AdPositionService
      */
     public function getAdPositions($uid, $accountId): array
     {
+        myLog('getAdPositions')->info('', compact('uid', 'accountId'));
         // 参数判断
         if (empty($uid) || empty($accountId)) {
             return [];
         }
 
-        // 获取广告位
+        // 获取所有有效广告位
         $positions = AdPosition::getAllValidAdPositions();
         if (empty($positions)) {
             return [];
@@ -39,6 +40,10 @@ class AdPositionService
             return [];
         }
 
+        // 获取用户相关数据
+        $userData = $this->getUserFilterData($uid);
+        myLog('getAdPositions')->info('', compact('uid', 'userData'));
+
         // 针对分配数据筛选出优先级最高的分配任务
         $result     = [];
         $dispatches = collect($dispatches)->groupBy('ad_position_id')->all();
@@ -47,17 +52,27 @@ class AdPositionService
             $positionId = getProp($position, 'id');
             $ident      = getProp($position, 'ident');
 
-            // 获取优先级最高的任务
+            // 获取对应广告位所有任务
             $validDispatches = getProp($dispatches, $positionId, []);
-            $validDispatch   = $validDispatches ? $validDispatches[0] : [];
-            if (empty($validDispatch)) {
+            if (empty($validDispatches)) {
                 continue;
             }
 
-            // 过滤条件判断
-            $filterContentJson = getProp($validDispatch, 'filter_condition');
-            $matchFilter       = $this->filterDispatch($uid, $filterContentJson);
-            if (!$matchFilter) {
+            // 根据优先级循环匹配,直到匹配到为止
+            $validDispatches = collect($validDispatches)->sortByDesc('priority')->all();
+            $validDispatch   = [];
+            foreach ($validDispatches as $value) {
+                // 过滤条件判断
+                $filterContentJson = getProp($value, 'filter_condition');
+                $matchFilter       = $this->filterDispatch($filterContentJson, $userData);
+                if ($matchFilter) {
+                    $validDispatch = $value;
+                    break;
+                }
+            }
+
+            // 判断
+            if (empty($validDispatch)) {
                 continue;
             }
 
@@ -69,30 +84,47 @@ class AdPositionService
     }
 
     /**
-     * 过滤条件筛选
+     * 用户的数据
      * @param $uid
+     * @return array
+     */
+    private function getUserFilterData($uid): array
+    {
+        // 获取用户信息
+        $user         = QappUser::getUserByUid($uid);
+        $registerAt   = getProp($user, 'created_at');
+        $registerUnix = strtotime($registerAt);
+
+        // 获取用户付费情况
+        $order  = OrderService::getUserLastestOrder($uid);
+        $isPaid = $order ? 1 : 0;
+
+        return compact('uid', 'registerUnix', 'isPaid');
+    }
+
+    /**
+     * 过滤条件筛选
      * @param $filterContentJson
+     * @param $userData
      * @return bool
      */
-    private function filterDispatch($uid, $filterContentJson): bool
+    private function filterDispatch($filterContentJson, $userData): bool
     {
         // 过滤条件
         $filterContent = json_decode($filterContentJson, true);
-        if (empty($uid) || empty($filterContentJson) || empty($filterContent)) {
+        if (empty($userData) || empty($filterContentJson) || empty($filterContent)) {
             return true;
         }
 
+        myLog('getAdPositions')->info('', compact('filterContent', 'userData'));
+
         // 判断注册时间
         $registerFilter = true;
         $registerAtArr  = getProp($filterContent, 'registerAt');
         if ($registerAtArr) {
             // 默认值
             $registerFilter = false;
-
-            // 获取用户信息
-            $user         = QappUser::getUserByUid($uid);
-            $registerAt   = getProp($user, 'created_at');
-            $registerUnix = strtotime($registerAt);
+            $registerUnix   = $userData['registerUnix'];
 
             // 循环条件,满足一条即可
             foreach ($registerAtArr as $register) {
@@ -111,20 +143,18 @@ class AdPositionService
 
         // 判断付费情况
         $paidFilter = true;
-        if (isset($filterContent['isPaid'])) {
-            // 默认值
-            $paidFilter = false;
-
+        if (getProp($filterContent, 'isPaid') !== '') {
             // 获取用户付费情况
-            $order = OrderService::getUserLastestOrder($uid);
+            $isPaid     = getProp($userData, 'isPaid', 0);
+            $paidFilter = false;
 
             // 有付费
-            if ($order && $filterContent['isPaid']) {
+            if ($isPaid && (int)getProp($filterContent, 'isPaid') === 1) {
                 $paidFilter = true;
             }
 
             // 未付费
-            if (!$order && !$filterContent['isPaid']) {
+            if (!$isPaid && (int)getProp($filterContent, 'isPaid') === 0) {
                 $paidFilter = true;
             }
         }

+ 5 - 3
app/Modules/Book/Models/BookConfig.php

@@ -315,7 +315,7 @@ class BookConfig extends Model
      * @param array $order
      * @return mixed
      */
-    public static function getBooksByIds(array $bid_arr, array $order = [])
+    public static function getBooksByIds(array $bid_arr, array $order = [], $is_external_shelf = true)
     {
         $res = self::join('books', 'book_configs.bid', '=', 'books.id')
             ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
@@ -355,8 +355,10 @@ class BookConfig extends Model
                 'books.name as old_name',
                 'book_configs.recommend_cid'
             )
-            ->whereIn('book_configs.bid', $bid_arr)
-            ->where('is_on_shelf', 2);
+            ->whereIn('book_configs.bid', $bid_arr);
+
+        if($is_external_shelf) $res->where('is_on_shelf',2);// 默认外部上架
+
         if ($order) {
             $res->orderBy($order[0], $order[1]);
         } else {

+ 21 - 4
app/Modules/Book/Services/BookConfigService.php

@@ -42,15 +42,15 @@ class BookConfigService
      * @param null $order
      * @return mixed
      */
-    public static function getBooksByIds(array $where, $order = [])
+    public static function getBooksByIds(array $where, $order = [],$is_external_shelf=true)
     {
         if (empty($where)) {
             return (object)array();
         }
         if ($order)
-            $res = BookConfig::getBooksByIds($where, $order);
+            $res = BookConfig::getBooksByIds($where,$order,$is_external_shelf);
         else
-            $res = BookConfig::getBooksByIds($where);
+            $res = BookConfig::getBooksByIds($where,[],$is_external_shelf);
         return $res;
     }
 
@@ -530,6 +530,23 @@ class BookConfigService
         }
         return FreeBook::where('bid', $bid)
             ->whereIn('config_id', $ids)
-            ->where('is_enabled', 1)->exists();
+            ->where('is_enabled', 1)->select('id')->first();
+    }
+
+
+    public static function getByBidNoFilter($bid){
+        return   FreeBook::join('free_book_config','free_book_config.id','=','free_books.config_id')
+            ->where('bid',$bid)
+            ->select('free_books.id','end_time')
+            ->where('end_time','<',date('Y-m-d H:i:s'))
+            ->orderBy('free_book_config.end_time','desc')
+            ->first();
+    }
+
+    public static function chargeStats($id,$amount){
+        $now = date('Y-m-d');
+        $amount = $amount*100;
+        Redis::hincrby('qapp:book:free:charge:'.$id,$now,$amount);
+        Redis::sadd('qapp:free:charge'.$now,$id);
     }
 }

+ 2 - 1
app/Modules/Push/Services/PushService.php

@@ -6,7 +6,7 @@ namespace App\Modules\Push\Services;
 
 use App\Cache\Lock\LockCache;
 use Exception;
-use App\Cache\PushCache;
+use App\Cache\Push\PushCache;
 use App\Consts\PushConst;
 use App\Libs\Push\OPPOPush\OPPOPushCommon;
 use App\Libs\Push\XMPush\MiPushCommon;
@@ -292,6 +292,7 @@ class PushService
             QappPushTaskLogs::updateSubTaskStatus($subTaskId, PushConst::STATUS_DOING);
 
             // 循环批量
+            $result = [];
             $regIdArr = array_chunk($regIds, 1000);
             try {
                 switch ($provider) {

+ 2 - 0
app/Modules/Trade/Models/Order.php

@@ -215,10 +215,12 @@ class Order extends Model
     static function getActivityOrderNum($params = [])
     {
         $search_obj = self::orderBy('created_at', 'desc');
+        if (isset($params['uid']) && $params['uid']) $search_obj->where('uid', $params['uid']);
         if (isset($params['status']) && $params['status']) $search_obj->where('status', $params['status']);
         if (isset($params['activity_id']) && $params['activity_id']) $search_obj->where('activity_id', $params['activity_id']);
         if (isset($params['begin_time']) && $params['begin_time']) $search_obj->where('created_at', '>=', $params['begin_time']);
         if (isset($params['end_time']) && $params['end_time']) $search_obj->where('created_at', '<=', $params['end_time']);
+        if (isset($params['product_id']) && $params['product_id']) $search_obj->where('product_id', $params['product_id']);
         if (isset($params['distribution_channel_id']) && $params['distribution_channel_id']) $search_obj->where('distribution_channel_id', $params['distribution_channel_id']);
         return $search_obj->count();
     }

+ 2 - 2
app/Modules/Trade/Pay/OrderArousePayFactory.php

@@ -4,8 +4,8 @@ namespace App\Modules\Trade\Pay;
 
 /**
  * 
- * @method static \App\Modules\Trade\Pay\WxOrderArousePay wx(int uid)
- * @method static \App\Modules\Trade\Pay\AliOrderArousePay ali(int uid)
+ * @method static \App\Modules\Trade\Pay\WxOrderArousePay wx(int $uid)
+ * @method static \App\Modules\Trade\Pay\AliOrderArousePay ali(int $uid)
  */
 class OrderArousePayFactory
 {

+ 12 - 0
app/Modules/Trade/Pay/OrderPaySuccess.php

@@ -2,6 +2,7 @@
 
 namespace App\Modules\Trade\Pay;
 
+use App\Modules\Book\Services\BookConfigService;
 use App\Modules\Subscribe\Models\Order;
 use DB;
 
@@ -31,6 +32,8 @@ class OrderPaySuccess
                 $app = new YearOrderPaySuccess($order);
             } elseif ($order->order_type == 'BOOK') {
                 $app = new BookOrderPaySuccess($order);
+            } elseif ($order->order_type == 'QUARTER') {
+                $app = new QuarterOrderPaySuccess($order);
             } elseif ($order->order_type == 'RECHARGE') {
                 $app = new RechargeOrderPaySuccess($order);
             }
@@ -42,6 +45,7 @@ class OrderPaySuccess
                     'created_at' => date('Y-m-d H:i:s')
                 ]);
             }
+            self::freeBookStats($order->from_bid,$order->price);
             return $status;
         } else {
             return false;
@@ -49,6 +53,14 @@ class OrderPaySuccess
     }
 
 
+    private static function freeBookStats($bid,$price){
+        if(!$bid) return ;
+        $free_book = BookConfigService::getByBidNoFilter($bid);
+        if(!$free_book) return ;
+        if(strtotime($free_book->end_time)+14*86400 < time())   return ;
+        BookConfigService::chargeStats($free_book->id,$price);
+    }
+
     private static function orderAcrossDay($order_info)
     {
         if (date('Y-m-d', strtotime($order_info->created_at)) == date('Y-m-d')) return false;

+ 46 - 0
app/Modules/Trade/Pay/QuarterOrderPaySuccess.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace App\Modules\Trade\Pay;
+
+use App\Modules\Subscribe\Models\Order;
+use App\Modules\Subscribe\Models\YearOrder;
+
+
+class QuarterOrderPaySuccess extends PaySuccessAbstract
+{
+    private $year_order;
+
+    public function __construct(Order $order)
+    {
+        parent::__construct($order);
+        $this->year_order = [];
+        $this->year_order['uid'] = $order->uid;
+        $this->year_order['distribution_channel_id'] = $order->distribution_channel_id;
+        $this->year_order['fee'] = $order->price;
+        $this->year_order['send_order_id'] = $order->send_order_id;
+    }
+
+    protected function handlePayProcess()
+    {
+        $this->year_order['begin_time'] = date('Y-m-d H:i:s');
+        $this->year_order['end_time'] = date('Y-m-d H:i:s', strtotime('+92 day'));
+        $old = YearOrder::where('uid', $this->year_order['uid'])->select('id', 'uid', 'u', 'begin_time', 'end_time', 'fee')->first();
+        if ($old) {
+            //如果包过年
+            if (strtotime($old->end_time) > time()) {
+                //旧的包年没过期
+                $old->end_time = date('Y-m-d H:i:s', strtotime($old->end_time) + 86400 * 92);
+                $old->fee = $old->fee + $this->year_order['fee'];
+                $old->save();
+            } else {
+                //旧的包年过期了
+                $old->end_time = date('Y-m-d H:i:s', strtotime('+92 day'));
+                $old->fee = $old->fee + $this->year_order['fee'];
+                $old->save();
+            }
+            return $old;
+        } else {
+            return YearOrder::firstOrCreate($this->year_order);
+        }
+    }
+}

+ 10 - 10
app/Modules/Trade/Pay/WxOrderArousePay.php

@@ -11,19 +11,19 @@ class WxOrderArousePay extends OrderArousePayAbstract
 {
     public function arouse(array $data)
     {
-        $pay_merchant_id = (int) $data['pay_merchant_id'];
-        $config = PayMerchantService::findPayConfig($pay_merchant_id);
-        $pay = PayFactory::official($config);
+        $pay_merchant_id = (int)$data['pay_merchant_id'];
+        $config          = PayMerchantService::findPayConfig($pay_merchant_id);
+        $pay             = PayFactory::official($config);
         try {
             $payOrder = [
-                'trade_type'     => $data['trade_type'], // 交易类型
-                'trade_no'     => $data['trade_no'], // 订单号
-                'price'        => $data['price'], // 订单金额,单位:分
-                'body'             => $this->getSubjectName($data['distribution_channel_id']), // 订单描述
-                'create_ip' => _getIp(), // 支付人的 IP
-                'remark'            =>  $pay_merchant_id
+                'trade_type' => $data['trade_type'], // 交易类型
+                'trade_no'   => $data['trade_no'], // 订单号
+                'price'      => $data['price'], // 订单金额,单位:分
+                'body'       => $this->getSubjectName($data['distribution_channel_id']), // 订单描述
+                'create_ip'  => _getIp(), // 支付人的 IP
+                'remark'     => $pay_merchant_id
             ];
-            $result = $pay->send($payOrder);
+            $result   = $pay->send($payOrder);
             if ($result) {
                 return $result;
             } else {

+ 30 - 0
app/Modules/User/Models/ReadLog.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Modules\User\Models;
+
+use App\Modules\TableSuffix;
+use Illuminate\Database\Eloquent\Model;
+
+class ReadLog extends Model
+{
+    use TableSuffix;
+
+    protected $table = 'record_logs';
+    protected $fillable = [
+        'distribution_channel_id',
+        'bid',
+        'cid',
+        'uid',
+        'send_order_id',
+        'from',
+        'attach',
+        'sequence',
+    ];
+    protected $connection = 'qapp_log_mysql';
+
+    public static function model(int $uid)
+    {
+        self::suffix($uid % 1024);
+        return new static;
+    }
+}

+ 103 - 83
app/Modules/User/Services/ReadRecordService.php

@@ -14,6 +14,7 @@ use Redis;
 use Hashids;
 use App\Modules\Book\Services\BookConfigService;
 use App\Modules\Book\Models\Chapter;
+use App\Modules\User\Models\ReadLog;
 use DB;
 
 class ReadRecordService
@@ -22,7 +23,7 @@ class ReadRecordService
     {
         $record = Redis::hGet('book_read:' . $uid, $bid);
         if ($record) {
-            $cid = explode('_', $record)[0];
+            $cid  = explode('_', $record)[0];
             $name = self::cid2ChapterName($cid);
             return ['record_chapter_id' => $cid, 'record_chapter_name' => $name];
         }
@@ -31,15 +32,15 @@ class ReadRecordService
 
     /**
      * 删除最近阅读记录
-     * @param int $uid
+     * @param int   $uid
      * @param array $bids
      */
     public static function delReadRecordStatic(int $uid, array $bids)
     {
-        $key = 'book_read:' . $uid;
-        $last_record = explode('_', Redis::hGet($key, 'last_read'));
+        $key             = 'book_read:' . $uid;
+        $last_record     = explode('_', Redis::hGet($key, 'last_read'));
         $last_record_bid = $last_record[0];
-        $is_del_last = false;
+        $is_del_last     = false;
         foreach ($bids as $bid) {
             if ($bid == $last_record_bid) {
                 $is_del_last = true;
@@ -57,18 +58,18 @@ class ReadRecordService
      */
     public static function reSetLastRecord($uid)
     {
-        $key = 'book_read:' . $uid;
-        $alls = Redis::hGetAll($key);
-        $has_record = false;
+        $key            = 'book_read:' . $uid;
+        $alls           = Redis::hGetAll($key);
+        $has_record     = false;
         $last_timestamp = 0;
-        $last_record = '';
+        $last_record    = '';
         foreach ($alls as $k => $v) {
             if (is_numeric($k)) {
                 $has_record = true;
-                $record = explode('_', $v);
-                $timestamp = $record[1];
+                $record     = explode('_', $v);
+                $timestamp  = $record[1];
                 if ($last_timestamp < $timestamp) {
-                    $last_record = $k . '_' . $v;
+                    $last_record    = $k . '_' . $v;
                     $last_timestamp = $timestamp;
                 }
             }
@@ -94,15 +95,15 @@ class ReadRecordService
     public static function getReadRecord_($uid)
     {
         $read_bids = Redis::hgetall('book_read:' . $uid);
-        $res = [];
-        $i = 0;
+        $res       = [];
+        $i         = 0;
         foreach ($read_bids as $key => $v) {
-            $record = explode('_', $v);
-            $latest_read_cid = $record[0];
-            $book_name = $record[1];
-            $chapter_name = $record[2];
+            $record           = explode('_', $v);
+            $latest_read_cid  = $record[0];
+            $book_name        = $record[1];
+            $chapter_name     = $record[2];
             $latest_read_time = $record[count($record) - 1];
-            $res[$i] = ['book_name' => $book_name, 'bid' => $key, 'cid' => (int) $latest_read_cid, 'time' => (int) $latest_read_time, 'chapter_name' => $chapter_name];
+            $res[$i]          = ['book_name' => $book_name, 'bid' => $key, 'cid' => (int)$latest_read_cid, 'time' => (int)$latest_read_time, 'chapter_name' => $chapter_name];
             $i++;
         }
         usort($res, function ($a, $b) {
@@ -125,18 +126,18 @@ class ReadRecordService
         }
         self::delTheLastRecord($uid);
         $read_bids = Redis::hgetall('book_read:' . $uid);
-        $res = [];
-        $i = 0;
+        $res       = [];
+        $i         = 0;
         foreach ($read_bids as $key => $v) {
             if (in_array($key, self::$not_uid_key)) {
                 continue;
             }
-            $record = explode('_', $v);
-            $latest_read_cid = $record[0];
+            $record           = explode('_', $v);
+            $latest_read_cid  = $record[0];
             $latest_read_time = $record[count($record) - 1];
-            $book_name = self::bid2BookName($key);
-            $chapter_name = self::cid2ChapterName($latest_read_cid);
-            $res[$i] = ['book_name' => $book_name, 'bid' => $key, 'cid' => (int) $latest_read_cid, 'time' => (int) $latest_read_time, 'chapter_name' => $chapter_name];
+            $book_name        = self::bid2BookName($key);
+            $chapter_name     = self::cid2ChapterName($latest_read_cid);
+            $res[$i]          = ['book_name' => $book_name, 'bid' => $key, 'cid' => (int)$latest_read_cid, 'time' => (int)$latest_read_time, 'chapter_name' => $chapter_name];
             $i++;
         }
         usort($res, function ($a, $b) {
@@ -156,10 +157,10 @@ class ReadRecordService
      */
     public static function addReadRecord_($param)
     {
-        $uid = $param['uid'];
-        $bid = $param['bid'];
-        $cid = $param['cid'];
-        $book_name = $param['book_name'];
+        $uid          = $param['uid'];
+        $bid          = $param['bid'];
+        $cid          = $param['cid'];
+        $book_name    = $param['book_name'];
         $chapter_name = $param['chapter_name'];
         Redis::hset('book_base:' . $uid, 'last_read', "{$bid}_{$cid}_{$book_name}_{$chapter_name}_" . time());
         //Redis::hset('book_read:'.$uid, $bid, $cid."_".time());
@@ -168,18 +169,25 @@ class ReadRecordService
 
     /**
      * 添加阅读记录升级版
-     * @param array $param
+     * @param $param
+     * @return bool
+     * @throws \Exception
      */
     public static function addReadRecord($param)
     {
-        $uid = $param['uid'];
-        $bid = $param['bid'];
-        $cid = $param['cid'];
-
-        $book_name = isset($param['book_name']) ? $param['book_name'] : '';
-        $chapter_name = isset($param['chapter_name']) ? $param['chapter_name'] : '';
-        $book_key = 'wap:string:book:' . $bid;
-        $chapter_key = 'wap:string:chapter:' . $cid;
+        // 第一章不计入阅读记录
+        $sequence = (int)getProp($param, 'sequence');
+//        if ($sequence <= 1) {
+//            return false;
+//        }
+
+        $uid          = $param['uid'];
+        $bid          = $param['bid'];
+        $cid          = $param['cid'];
+        $book_name    = getProp($param, 'book_name');
+        $chapter_name = getProp($param, 'chapter_name');
+        $book_key     = 'wap:string:book:' . $bid;
+        $chapter_key  = 'wap:string:chapter:' . $cid;
         if ($book_name) {
             Redis::setex($book_key, 3600, $book_name);
         }
@@ -191,6 +199,8 @@ class ReadRecordService
         if ($num <= 3) {
             self::delTheLastRecord($uid);
         }
+
+        return true;
     }
 
     /**
@@ -203,17 +213,17 @@ class ReadRecordService
         if (empty($all)) return [];
         $first = $all[0];
         if (!$first) return [];
-        if (!isset($first['bid']))  return [];
+        if (!isset($first['bid'])) return [];
         try {
             //$bid = Hashids::encode($first['bid']);
-            $bid = $first['bid'];
+            $bid       = $first['bid'];
             $book_info = BookConfigService::getBookById($bid);
-            $cid = $first['cid'];
+            $cid       = $first['cid'];
             $book_name = $first['book_name'];
-            $res = [
-                'url' => '/reader?bid=' . $bid . '&cid=' . $cid,
-                'book_name' => $book_name,
-                'cover' => $book_info->cover,
+            $res       = [
+                'url'          => '/reader?bid=' . $bid . '&cid=' . $cid,
+                'book_name'    => $book_name,
+                'cover'        => $book_info->cover,
                 'channel_name' => $book_info->channel_name,
             ];
         } catch (\Exception $e) {
@@ -233,21 +243,21 @@ class ReadRecordService
         self::delBookBase($uid);
         $record = Redis::hget('book_read:' . $uid, 'last_read');
         if ($record) {
-            $record_arr = explode('_', $record);
-            $bid = $record_arr[0];
-            $bid = Hashids::encode($bid);
-            $cid = $record_arr[1];
-            $time = $record_arr[2];
-            $book_info = BookConfigService::getBookById($bid);
-            $book_name = isset($book_info->book_name) ? $book_info->book_name : '';
-            $cover = isset($book_info->cover) ? $book_info->cover : '';
+            $record_arr   = explode('_', $record);
+            $bid          = $record_arr[0];
+            $bid          = Hashids::encode($bid);
+            $cid          = $record_arr[1];
+            $time         = $record_arr[2];
+            $book_info    = BookConfigService::getBookById($bid);
+            $book_name    = isset($book_info->book_name) ? $book_info->book_name : '';
+            $cover        = isset($book_info->cover) ? $book_info->cover : '';
             $channel_name = isset($book_info->channel_name) ? $book_info->channel_name : '';
-            $res = [
-                'url' => '/reader?bid=' . $bid . '&cid=' . $cid,
-                'book_name' => $book_name,
-                'cover' => $cover,
+            $res          = [
+                'url'          => '/reader?bid=' . $bid . '&cid=' . $cid,
+                'book_name'    => $book_name,
+                'cover'        => $cover,
                 'channel_name' => $channel_name,
-                'time' => $time
+                'time'         => $time
             ];
             return $res;
         }
@@ -265,8 +275,8 @@ class ReadRecordService
             $record = Redis::hget('book_read:' . $uid, 'last_read');
             if ($record) {
                 $record_arr = explode('_', $record);
-                $bid = $record_arr[0];
-                return (int) $bid;
+                $bid        = $record_arr[0];
+                return (int)$bid;
             }
         } catch (\Exception $e) {
         }
@@ -298,7 +308,7 @@ class ReadRecordService
      */
     public static function bid2BookName($bid)
     {
-        $book_key = 'wap:string:book:' . $bid;
+        $book_key  = 'wap:string:book:' . $bid;
         $book_name = Redis::get($book_key);
         Redis::EXPIRE($book_key, 3600);
         if (!$book_name) {
@@ -317,7 +327,7 @@ class ReadRecordService
      */
     public static function cid2ChapterName($cid)
     {
-        $chapter_key = 'wap:string:chapter:' . $cid;
+        $chapter_key  = 'wap:string:chapter:' . $cid;
         $chapter_name = Redis::get($chapter_key);
         Redis::EXPIRE($chapter_key, 3600);
         if (!$chapter_name) {
@@ -340,10 +350,10 @@ class ReadRecordService
         $base_record = Redis::hget('book_base:' . $uid, 'last_read');
         if ($base_record) {
             $record_arr = explode('_', $base_record);
-            $c = count($record_arr);
+            $c          = count($record_arr);
             if ($c > 3) {
-                $bid = $record_arr[0];
-                $cid = $record_arr[1];
+                $bid  = $record_arr[0];
+                $cid  = $record_arr[1];
                 $time = $record_arr[$c - 1];
                 Redis::hset('book_base:' . $uid, 'last_read', "{$bid}_{$cid}_" . $time);
             }
@@ -351,15 +361,15 @@ class ReadRecordService
         $records = Redis::hgetall('book_read:' . $uid);
         foreach ($records as $key => $v) {
             $record = explode('_', $v);
-            $count = count($record);
+            $count  = count($record);
             if ($count > 3) {
-                $latest_read_cid = $record[0];
-                $book_name = $record[1];
-                $chapter_name = $record[2];
+                $latest_read_cid  = $record[0];
+                $book_name        = $record[1];
+                $chapter_name     = $record[2];
                 $latest_read_time = $record[$count - 1];
                 Redis::hset('book_read:' . $uid, $key, "{$latest_read_cid}_" . $latest_read_time);
 
-                $book_key = 'wap:string:book:' . $key;
+                $book_key    = 'wap:string:book:' . $key;
                 $chapter_key = 'wap:string:chapter:' . $latest_read_cid;
                 Redis::set($book_key, $book_name);
                 Redis::set($chapter_key, $chapter_name);
@@ -384,7 +394,7 @@ class ReadRecordService
     public static function getSimpleReadRecord(int $uid): array
     {
         $read_bids = Redis::hgetall('book_read:' . $uid);
-        $res = [];
+        $res       = [];
         if (!$read_bids) {
             return $res;
         }
@@ -402,11 +412,11 @@ class ReadRecordService
     {
         try {
             DB::table('temp_read_active')->insert([
-                'uid' => $uid,
+                'uid'                     => $uid,
                 'distribution_channel_id' => $distribution_channel_id,
-                'from' => $from,
-                'created_at' => date('Y-m-d H:i:s'),
-                'updated_at' => date('Y-m-d H:i:s'),
+                'from'                    => $from,
+                'created_at'              => date('Y-m-d H:i:s'),
+                'updated_at'              => date('Y-m-d H:i:s'),
             ]);
         } catch (\Exception $e) {
         }
@@ -422,7 +432,7 @@ class ReadRecordService
         try {
             $send_order_id = Redis::hget('book_read:' . $uid, 'send_order_id');
             if ($send_order_id)
-                return (int) $send_order_id;
+                return (int)$send_order_id;
         } catch (\Exception $e) {
         }
         return 0;
@@ -458,6 +468,7 @@ class ReadRecordService
         }
         return '';
     }
+
     /**
      * 签到日期
      * @param int $uid
@@ -522,7 +533,7 @@ class ReadRecordService
         try {
             $count = Redis::hget('book_read:' . $uid, 'sign_counts');
             if ($count) {
-                return (int) $count;
+                return (int)$count;
             }
             return 0;
         } catch (\Exception $e) {
@@ -555,7 +566,7 @@ class ReadRecordService
 
     public static function getSmartPush(int $uid): array
     {
-        $res =  Redis::hget('book_read:' . $uid, 'smart_push');
+        $res = Redis::hget('book_read:' . $uid, 'smart_push');
         if ($res) {
             return explode(',', $res);
         }
@@ -631,15 +642,15 @@ class ReadRecordService
             return;
         }
         $read_bids = Redis::hgetall('book_read:' . $uid);
-        $i = 0;
+        $i         = 0;
         foreach ($read_bids as $key => $v) {
             if (in_array($key, self::$not_uid_key)) {
                 continue;
             }
-            $record = explode('_', $v);
-            $latest_read_cid = $record[0];
+            $record           = explode('_', $v);
+            $latest_read_cid  = $record[0];
             $latest_read_time = $record[count($record) - 1];
-            $res[$i++] = ['bid' => $key, 'cid' => (int) $latest_read_cid, 'time' => (int) $latest_read_time];
+            $res[$i++]        = ['bid' => $key, 'cid' => (int)$latest_read_cid, 'time' => (int)$latest_read_time];
         }
         usort($res, function ($a, $b) {
             if ($a['time'] >= $b['time']) return -1;
@@ -653,4 +664,13 @@ class ReadRecordService
             }
         }
     }
+
+    /**
+     * 添加用户的阅读记录
+     */
+    public static function addReadLog(int $uid, array $data)
+    {
+        $log = ReadLog::model($uid);
+        $log->create($data);
+    }
 }

+ 32 - 32
config/app.php

@@ -176,39 +176,39 @@ return [
 
     'aliases' => [
 
-        'App' => Illuminate\Support\Facades\App::class,
-        'Artisan' => Illuminate\Support\Facades\Artisan::class,
-        'Auth' => Illuminate\Support\Facades\Auth::class,
-        'Blade' => Illuminate\Support\Facades\Blade::class,
-        'Cache' => Illuminate\Support\Facades\Cache::class,
-        'Config' => Illuminate\Support\Facades\Config::class,
-        'Cookie' => Illuminate\Support\Facades\Cookie::class,
-        'Crypt' => Illuminate\Support\Facades\Crypt::class,
-        'DB' => Illuminate\Support\Facades\DB::class,
-        'Eloquent' => Illuminate\Database\Eloquent\Model::class,
-        'Event' => Illuminate\Support\Facades\Event::class,
-        'File' => Illuminate\Support\Facades\File::class,
-        'Gate' => Illuminate\Support\Facades\Gate::class,
-        'Hash' => Illuminate\Support\Facades\Hash::class,
-        'Lang' => Illuminate\Support\Facades\Lang::class,
-        'Log' => Illuminate\Support\Facades\Log::class,
-        'Mail' => Illuminate\Support\Facades\Mail::class,
-        'Password' => Illuminate\Support\Facades\Password::class,
-        'Queue' => Illuminate\Support\Facades\Queue::class,
-        'Redirect' => Illuminate\Support\Facades\Redirect::class,
-        'Redis' => Illuminate\Support\Facades\Redis::class,
-        'Request' => Illuminate\Support\Facades\Request::class,
-        'Response' => Illuminate\Support\Facades\Response::class,
-        'Route' => Illuminate\Support\Facades\Route::class,
-        'Schema' => Illuminate\Support\Facades\Schema::class,
-        'Session' => Illuminate\Support\Facades\Session::class,
-        'Storage' => Illuminate\Support\Facades\Storage::class,
-        'URL' => Illuminate\Support\Facades\URL::class,
+        'App'       => Illuminate\Support\Facades\App::class,
+        'Artisan'   => Illuminate\Support\Facades\Artisan::class,
+        'Auth'      => Illuminate\Support\Facades\Auth::class,
+        'Blade'     => Illuminate\Support\Facades\Blade::class,
+        'Cache'     => Illuminate\Support\Facades\Cache::class,
+        'Config'    => Illuminate\Support\Facades\Config::class,
+        'Cookie'    => Illuminate\Support\Facades\Cookie::class,
+        'Crypt'     => Illuminate\Support\Facades\Crypt::class,
+        'DB'        => Illuminate\Support\Facades\DB::class,
+        'Eloquent'  => Illuminate\Database\Eloquent\Model::class,
+        'Event'     => Illuminate\Support\Facades\Event::class,
+        'File'      => Illuminate\Support\Facades\File::class,
+        'Gate'      => Illuminate\Support\Facades\Gate::class,
+        'Hash'      => Illuminate\Support\Facades\Hash::class,
+        'Lang'      => Illuminate\Support\Facades\Lang::class,
+        'Log'       => Illuminate\Support\Facades\Log::class,
+        'Mail'      => Illuminate\Support\Facades\Mail::class,
+        'Password'  => Illuminate\Support\Facades\Password::class,
+        'Queue'     => Illuminate\Support\Facades\Queue::class,
+        'Redirect'  => Illuminate\Support\Facades\Redirect::class,
+        'Redis'     => Illuminate\Support\Facades\Redis::class,
+        'Request'   => Illuminate\Support\Facades\Request::class,
+        'Response'  => Illuminate\Support\Facades\Response::class,
+        'Route'     => Illuminate\Support\Facades\Route::class,
+        'Schema'    => Illuminate\Support\Facades\Schema::class,
+        'Session'   => Illuminate\Support\Facades\Session::class,
+        'Storage'   => Illuminate\Support\Facades\Storage::class,
+        'URL'       => Illuminate\Support\Facades\URL::class,
         'Validator' => Illuminate\Support\Facades\Validator::class,
-        'View' => Illuminate\Support\Facades\View::class,
-         'Hashids' => Vinkla\Hashids\Facades\Hashids::class,
-        'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class ,
-        'Captcha' => Mews\Captcha\Facades\Captcha::class,
+        'View'      => Illuminate\Support\Facades\View::class,
+        'Hashids'   => Vinkla\Hashids\Facades\Hashids::class,
+        'JWTAuth'   => Tymon\JWTAuth\Facades\JWTAuth::class,
+        'Captcha'   => Mews\Captcha\Facades\Captcha::class,
     ],
 
 ];

+ 5 - 1
config/audit.php

@@ -1,6 +1,10 @@
 <?php
 return [
-    'com.app.kyy.xjxs' => [
+    'com.app.kyy.xjxs'       => [
+        'brand'       => 'huawei',
+        'codeVersion' => '0.0.2'
+    ],
+    'com.juyu.kuaiying.rmyq' => [
         'brand'       => 'huawei',
         'codeVersion' => '0.0.2'
     ],

+ 13 - 0
config/database.php

@@ -97,6 +97,19 @@ return [
             'strict' => false,
             'engine' => null,
         ],
+        'qapp_log_mysql' => [
+            'driver' => 'mysql',
+            'host' => env('QAPP_LOG_DB_HOST', 'localhost'),
+            'port' => env('QAPP_LOG_DB_PORT', '3306'),
+            'database' => env('QAPP_LOG_DB_DATABASE', 'forge'),
+            'username' => env('QAPP_LOG_DB_USERNAME', 'forge'),
+            'password' => env('QAPP_LOG_DB_PASSWORD', ''),
+            'charset' => 'utf8',
+            'collation' => 'utf8_unicode_ci',
+            'prefix' => '',
+            'strict' => false,
+            'engine' => null,
+        ],
         'new_yunqi' => [
             'driver' => 'mysql',
             'host' => env('NEW_YUNQI_DB_HOST', 'localhost'),

+ 4 - 0
config/option.php

@@ -10,5 +10,9 @@ return [
             'customerAccount' => 'youyou1552',
             'customerImage'   => 'http://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/service/customimage_868_1552544217.%E5%AE%A2%E6%9C%8D.jpg'
         ],
+        'com.juyu.kuaiying.rmyq'        => [
+            'customerAccount' => 'youyou1552',
+            'customerImage'   => 'http://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/service/customimage_868_1552544217.%E5%AE%A2%E6%9C%8D.jpg'
+        ],
     ]
 ];

File diff suppressed because it is too large
+ 403 - 0
resources/views/qapp/start.blade.php


File diff suppressed because it is too large
+ 352 - 303
resources/views/qapp/welcome.blade.php