Kaynağa Gözat

Merge branch 'kuaiyingyong' into kuaiyingyong_push

Wang Chen 4 yıl önce
ebeveyn
işleme
c2eefbb641
37 değiştirilmiş dosya ile 1072 ekleme ve 72 silme
  1. 7 4
      app/Console/Commands/Push/PushTest.php
  2. 0 1
      app/Http/Controllers/QuickApp/BaseController.php
  3. 22 1
      app/Http/Controllers/QuickApp/Book/BookController.php
  4. 21 10
      app/Http/Controllers/QuickApp/Book/ChapterController.php
  5. 2 2
      app/Http/Controllers/QuickApp/Book/Transformers/ChapterTransformer.php
  6. 55 2
      app/Http/Controllers/QuickApp/User/UserController.php
  7. 31 9
      app/Http/Controllers/QuickApp/WelcomeController.php
  8. 8 1
      app/Http/Routes/QuickApp/QuickAppRoutes.php
  9. 42 0
      app/Jobs/UserTaskJob.php
  10. 7 6
      app/Libs/Push/HuaWei/HwPushCommon.php
  11. 12 8
      app/Libs/Push/OPPOPush/OPPOPushCommon.php
  12. 1 0
      app/Libs/Push/XMPush/MiPushCommon.php
  13. 0 6
      app/Modules/Book/Services/RecoBannerService.php
  14. 23 3
      app/Modules/Push/Services/PushService.php
  15. 19 0
      app/Modules/TableSuffix.php
  16. 1 1
      app/Modules/Trade/Pay/AliOrderArousePay.php
  17. 8 0
      app/Modules/Trade/Pay/OrderArousePayAbstract.php
  18. 3 0
      app/Modules/Trade/Pay/PaySuccessAbstract.php
  19. 1 1
      app/Modules/Trade/Pay/WxOrderArousePay.php
  20. 0 1
      app/Modules/Trade/Services/PayMerchantService.php
  21. 2 1
      app/Modules/User/Models/QappPackage.php
  22. 14 7
      app/Modules/User/Services/QappUserService.php
  23. 140 0
      app/Modules/User/Services/SignService.php
  24. 3 0
      app/Modules/User/Services/UserService.php
  25. 35 0
      app/Modules/UserTask/Models/ChapterOrder.php
  26. 34 0
      app/Modules/UserTask/Models/Task.php
  27. 28 0
      app/Modules/UserTask/Models/UserRepeatTask.php
  28. 17 0
      app/Modules/UserTask/Models/UserTask.php
  29. 165 0
      app/Modules/UserTask/Services/BaseTask.php
  30. 23 0
      app/Modules/UserTask/Services/ChargeTask.php
  31. 28 0
      app/Modules/UserTask/Services/ReadTask.php
  32. 87 0
      app/Modules/UserTask/Services/RepeatTask.php
  33. 35 0
      app/Modules/UserTask/Services/SingleTask.php
  34. 166 0
      app/Modules/UserTask/Services/UserTaskService.php
  35. 20 7
      config/database.php
  36. 2 1
      config/error.php
  37. 10 0
      config/option.php

+ 7 - 4
app/Console/Commands/Push/PushTest.php

@@ -20,7 +20,7 @@ class PushTest extends Command
      *
      * @var string
      */
-    protected $signature = 'push:test {uid}';
+    protected $signature = 'push:test {uid} {url}';
 
     /**
      * The console command description.
@@ -36,6 +36,7 @@ class PushTest extends Command
     {
         // 用户Uid
         $uid = $this->argument('uid');
+        $url = $this->argument('url');
 
         // 获取用户push信息
         $pushUser  = QappPushUser::getPushUserByUid($uid);
@@ -64,11 +65,13 @@ class PushTest extends Command
 
         $title   = '这是' . $name . '标题';
         $content = '这是' . $name . '内容,创建于' . date('Y-m-d H:i:s');
-        $url     = 'hap://app/com.app.kyy.xnyd/views/Reader?send_order_id=1643289&bid=vdqY7p15xnZQzK4VzzgmMD6wG2yr8BNX&chapter_id=4774851';
+        $url     = $url ?: '/views/Reader';
+        $params  = ['send_order_id' => 1643289, 'bid' => 'vdqY7p15xnZQzK4VzzgmMD6wG2yr8BNX', 'chapter_id' => 4774851];
         var_dump('uid:' . $uid);
         var_dump('title:' . $title);
         var_dump('content:' . $content);
         var_dump('url:' . $url);
+        var_dump('params:' . json_encode($params));
         var_dump('reg id:' . $regId);
 
         $result = [];
@@ -81,7 +84,7 @@ class PushTest extends Command
 
                     // 循环推送
                     $client->setToken($regIdList);
-                    $result = $client->sendPushMessage($title, $content, $url);
+                    $result = $client->sendPushMessage($title, $content, $url, $params);
                     break;
                 // 小米
                 case PushConst::PROVIDER_MI:
@@ -96,7 +99,7 @@ class PushTest extends Command
                 case PushConst::PROVIDER_OPPO:
                     // 初始化oppo推送
                     $client    = new OPPOPushCommon($appKey, $masterSecret);
-                    $messageId = $client->getMessageId($title, $content, $url);
+                    $messageId = $client->getMessageId($title, $content, $url, $params);
 
                     // 循环推送
                     $client->setRegArr($regIdList);

+ 0 - 1
app/Http/Controllers/QuickApp/BaseController.php

@@ -27,7 +27,6 @@ class BaseController extends Controller
             $qapp_user = (new QappUserService)->getGolableUser();
             if ($name == 'user_info') {
                 $user = User::find($qapp_user->uid);
-                //$this->field[$name] = $qapp_user->user;
                 $this->field[$name] = $user;
             }
             if ($name == 'uid') {

+ 22 - 1
app/Http/Controllers/QuickApp/Book/BookController.php

@@ -271,7 +271,7 @@ class BookController extends BaseController
             $reco_banner_type = ['FEMALE', 'PUBLIC'];
             $channel = 2;
         }
-        $books = RecoBannerService::getByTypeStatic($reco_banner_type, 2);
+        $books = (new RecoBannerService)->getByType($reco_banner_type, 2);
         $books->transform(function ($item) {
             $result = $this->getBidCidFromUrl($item->redirect_url);
             $item->bid = $result['bid'];
@@ -780,4 +780,25 @@ class BookController extends BaseController
         $data = ['male' => $male, 'female' => $female];
         return response()->success($data);
     }
+
+    /**
+     * 推荐书
+     */
+    public function recommen()
+    {
+        $reco_banner_type = ['FEMALE', 'PUBLIC'];
+        $books = (new RecoBannerService)->getByType($reco_banner_type, 2);
+        $books->transform(function ($item) {
+            $result = $this->getBidCidFromUrl($item->redirect_url);
+            $item->bid = $result['bid'];
+            $item->cid = $result['cid'];
+            if ($result['cid']) {
+                $item->redirect_url = "views/Reader";
+            } else {
+                $item->redirect_url = "views/Detail";
+            }
+            return $item;
+        });
+        return response()->success($books);
+    }
 }

+ 21 - 10
app/Http/Controllers/QuickApp/Book/ChapterController.php

@@ -20,10 +20,14 @@ use App\Modules\Subscribe\Services\YearOrderService;
 use App\Modules\OfficialAccount\Services\ForceSubscribeService;
 use App\Modules\Subscribe\Services\ChapterReminderService;
 use App\Modules\User\Services\UserDeepReadTagService;
+use App\Modules\UserTask\Services\BaseTask;
+use App\Modules\UserTask\Services\UserTaskService;
 
 class ChapterController extends BaseController
 {
 
+    private $book_info;
+
     /**
      * @apiDefine Chapter 章节
      */
@@ -258,6 +262,7 @@ class ChapterController extends BaseController
         $book_info  = BookConfigService::getBookById($bid);
         if (empty($book_info))
             return response()->error('QAPP_SYS_ERROR');
+        $this->book_info = $book_info;
         //获取章节信息
         $chapter = ChapterService::getChapterNameById($cid, $bid);
         if (!$chapter) {
@@ -321,7 +326,7 @@ 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::addReadRecord([
                 'uid' => $this->uid, 'bid' => $bid, 'book_name' => $book_info->book_name,
                 'cid' => $cid, 'chapter_name' => $chapter->name
@@ -475,7 +480,7 @@ class ChapterController extends BaseController
         $old = Redis::hget($key, $field);
         if (!$old)  $old = 0;
         Redis::hset($key, $field, $old + 1);
-        $force_add_desk_type = $this->addDesktopType($chapter->sequence);
+        $force_add_desk_type = $this->addDesktopType($bid,$chapter->sequence);
         $chapter->force_add_desk_type = $force_add_desk_type;
         //统计
         $this->stats();
@@ -596,18 +601,18 @@ class ChapterController extends BaseController
         return   ceil($chapter_size / 100);
     }*/
 
-    private function getPrice($book_info, $chapter_size=0)
+    private function getPrice($book_info, $chapter_size = 0)
     {
         if ($book_info->charge_type == 'BOOK') {
-            if(BookOrderService::isHasBookOrder($this->uid)){
+            if (BookOrderService::isHasBookOrder($this->uid)) {
                 $this->is_first_book_order = 0;
                 return 1399;
-            }else{
+            } else {
                 $this->is_first_book_order = 1;
                 return  899;
             }
         } else {
-            $fee = BookService::getPrice($book_info,$this->distribution_channel_id,$chapter_size);
+            $fee = BookService::getPrice($book_info, $this->distribution_channel_id, $chapter_size);
             return $fee;
         }
     }
@@ -678,22 +683,28 @@ class ChapterController extends BaseController
     }
 
 
-    private function stats(){
+    private function stats()
+    {
         //阅读器统计
         WapVisitStatService::recordReaderUvAndPv($this->uid, $this->distribution_channel_id);
     }
 
     //加桌类型
-    private function addDesktopType($sequence){
+    private function addDesktopType($bid,$sequence){
         $force_add_desk_type = 0;
         $send_order_id = ReadRecordService::getSendOrderId($this->uid);
         if(!$send_order_id) return $force_add_desk_type;
         $send_order_info = SendOrderService::getById($send_order_id);
         if(!$send_order_info)  return $force_add_desk_type;
-        if($send_order_info->force_add_desk_type && $send_order_info->force_add_desk_seq){
-            if($sequence >= $send_order_info->force_add_desk_seq){
+        if($send_order_info->book_id == $bid){
+            if($send_order_info->force_add_desk_type == 1 && $send_order_info->force_add_desk_type){
                 $force_add_desk_type = $send_order_info->force_add_desk_type;
             }
+            if($send_order_info->force_add_desk_type == 2){
+                if($sequence >= $this->book_info->force_subscribe_chapter_seq && $sequence<= $this->book_info->force_subscribe_chapter_seq+3){
+                    $force_add_desk_type = $send_order_info->force_add_desk_type;
+                }
+            }
         }
         return $force_add_desk_type;
     }

+ 2 - 2
app/Http/Controllers/QuickApp/Book/Transformers/ChapterTransformer.php

@@ -18,7 +18,7 @@ class ChapterTransformer
             'recent_update_at'   =>  $chapter->recent_update_at,
             'chapter_content'   =>  $chapter->content,
             'sign_status'   =>  $chapter->sign_status,
-            'force_add_desk_type'   =>  $chapter->force_add_desk_type,
+            'force_add_desk_type'   =>  $chapter->force_add_desk_type
         ];
     }
-}
+}

+ 55 - 2
app/Http/Controllers/QuickApp/User/UserController.php

@@ -11,8 +11,10 @@ use App\Modules\Book\Services\BookUrgeUpdateService;
 use App\Modules\Subscribe\Services\YearOrderService;
 use App\Modules\User\Services\QappUserService;
 use App\Modules\User\Services\ReadRecordService;
+use App\Modules\User\Services\SignService;
 use App\Modules\User\Services\UserService;
 use App\Modules\User\Services\UserSignService;
+use App\Modules\UserTask\Services\UserTaskService;
 use Illuminate\Http\Request;
 use Redis;
 
@@ -88,6 +90,7 @@ class UserController extends BaseController
                 $data['vip_days'] = $time . '秒';
             }
         }
+        $data['pay_mode_default'] = 'weixin';
         $data['is_check'] = false;
         // $data['is_check'] = !$this->phone;
         return response()->success($data);
@@ -174,11 +177,12 @@ class UserController extends BaseController
     {
         $code = $request->post('code');
         $phone = $request->post('phone');
+        $version = $request->post('version', '1.0');
         $old = Redis::get('quser_code:' . $phone);
         if ($old && $old == $code) {
             Redis::del('quser_code:' . $phone);
             if (!$this->phone) {
-                $result = (new QappUserService)->bindPhone($this->uid, $phone);
+                $result = (new QappUserService)->bindPhone($this->uid, $phone, $version);
                 if ($result) {
                     return response()->success();
                 } else {
@@ -316,11 +320,60 @@ class UserController extends BaseController
         return response()->success();
     }
 
+    /**
+     * 加桌
+     */
     public function addDesktop(Request $request)
     {
         $status = $request->get('status');
         if (is_numeric($status)) {
-            UserService::qappAddDesktop($this->uid,$status);
+            UserService::qappAddDesktop($this->uid, $status);
+        }
+    }
+
+    /**
+     * 获取任务奖励
+     */
+    public function getUserTaskReward(int $id)
+    {
+        $service = new UserTaskService($this->uid);
+        $result  = $service->getTaskReward($id);
+        if ($result == 1) {
+            return response()->success(['is_sign' => true]);
+        } else if ($result == -1) {
+            return response()->error('REWARD_GOTTEN_ERROR');
+        } else if ($result == 0) {
+            return response()->error('NO_REWARD');
         }
     }
+
+    /**
+     * 任务中心
+     */
+    public function taskList()
+    {
+        $service        = new UserTaskService($this->uid);
+        $new_user_tasks = $service->findNewUserTaskList();
+        $date_tasks     = $service->findDateUserTaskList();
+        return response()->success(compact('new_user_tasks', 'date_tasks'));
+    }
+
+    /**
+     * 新版签到信息
+     */
+    public function findSignInfo()
+    {
+        $service = new SignService($this->uid);
+        return response()->success($service->getSignInfo());
+    }
+
+    /**
+     * 新版签到
+     */
+    public function newSign()
+    {
+        $service = new SignService($this->uid);
+        $service->sign();
+        return response()->success();
+    }
 }

+ 31 - 9
app/Http/Controllers/QuickApp/WelcomeController.php

@@ -19,16 +19,16 @@ class WelcomeController extends BaseController
     {
         $decode_id = Hashids::decode($send_order_id_encode);
         if ($decode_id) {
-            $this->send_order_id = $decode_id[0];
-            $send_order = SendOrderService::getSendOrderStatic($this->send_order_id);
+            $this->send_order_id     = $decode_id[0];
+            $send_order              = SendOrderService::getSendOrderStatic($this->send_order_id);
             $distribution_channel_id = $send_order->distribution_channel_id;
-            $qappPackage = QappPackageService::getPackage($distribution_channel_id);
+            $qappPackage             = QappPackageService::getPackage($distribution_channel_id);
             if ($send_order && $qappPackage) {
                 $this->sendOrderStatistic($send_order);//统计
                 return view('qapp.welcome')->with([
-                    'package' =>$qappPackage->package,
-                    'hash_bid' => Hashids::encode($send_order->book_id),
-                    'cid' => $send_order->chapter_id,
+                    'package'       => $qappPackage->package,
+                    'hash_bid'      => Hashids::encode($send_order->book_id),
+                    'cid'           => $send_order->chapter_id,
                     'send_order_id' => $this->send_order_id
                 ]);
             }
@@ -37,9 +37,9 @@ class WelcomeController extends BaseController
 
     private function sendOrderStatistic($send_order)
     {
-        $key = date('Y-m-d');
+        $key             = date('Y-m-d');
         $send_order_flag = Cookie::get('send_order_flag');
-        $send_orders = explode(',', $send_order_flag);
+        $send_orders     = explode(',', $send_order_flag);
         //uv
         if (!Cookie::get('send_order_flag_' . $this->send_order_id) && !in_array($this->send_order_id, $send_orders)) {
             Redis::hincrby('send_order_uv_' . $this->send_order_id, $key, 1);
@@ -59,7 +59,8 @@ class WelcomeController extends BaseController
         Redis::hincrby('send_order_pv_' . $this->send_order_id, $key, 1); //每天
         Redis::hincrby('send_order_pv_' . $this->send_order_id, 'total', 1); //汇总
         Redis::sadd('send_order' . $key, $this->send_order_id);
-        if (isset($send_order->send_time) && $send_order->send_time) { } else {
+        if (isset($send_order->send_time) && $send_order->send_time) {
+        } else {
             $uv = Redis::hget('send_order_uv_' . $this->send_order_id, $key);
             if ($uv && $uv > 20) {
                 SendOrderService::updateSendOrderTime($this->send_order_id);
@@ -94,4 +95,25 @@ class WelcomeController extends BaseController
         }
         return response()->success(compact('url', 'name'));
     }
+
+    /**
+     * 系统设置
+     * @return mixed
+     */
+    public function getOptions(Request $request)
+    {
+        // 获取包名
+        $package = $request->header('x-package', '');
+
+        // 获取客服信息
+        $supports = config('option.supports');
+        $support  = getProp($supports, $package, (object)[]);
+
+        // 配置
+        $data = [
+            'support' => $support
+        ];
+
+        return response()->success($data);
+    }
 }

+ 8 - 1
app/Http/Routes/QuickApp/QuickAppRoutes.php

@@ -15,11 +15,14 @@ Route::group(['domain' => env('QUICKAPP_DOMAIN'), 'namespace' => 'App\Http\Contr
         Route::post('login', 'Oauth\UsersController@index');
     });
 
+    // 全局配置
+    Route::get('api/options', 'WelcomeController@getOptions');
+
     Route::group(['prefix' => 'api', 'middleware' => 'jwttoken'], function () {
-        // Route::group(['prefix' => 'api'], function () {
         //首页
         Route::get('books/{sex}/index', 'Book\BookController@getBookLists');
         //书库
+        Route::get('books/recommen', 'Book\BookController@recommen');
         Route::get('books/library', 'Book\BookController@library');
         //相似推荐
         Route::get('books/similar', 'Book\BookController@similarRecom');
@@ -53,12 +56,16 @@ Route::group(['domain' => env('QUICKAPP_DOMAIN'), 'namespace' => 'App\Http\Contr
         Route::get('userinfo', 'User\UserController@index');
         Route::post('user/sendCode', 'User\UserController@sendCode');
         Route::post('user/bindPhone', 'User\UserController@bindPhone');
+        Route::any('user/task/get/{id}', 'User\UserController@getUserTaskReward')->where('id', '\d+');
+        Route::any('user/task', 'User\UserController@taskList');
         //催更
         Route::post('user/urgeUpdate', 'User\UserController@urgeUpdate');
         //设置派单ID
         Route::post('user/setSendOrder', 'User\UserController@setSendOrder');
         //签到
         Route::get('sign', 'User\UserController@sign');
+        Route::get('sign/new', 'User\UserController@newSign');
+        Route::get('sign/info', 'User\UserController@findSignInfo');
         Route::get('user/sign_record', 'User\UserController@signRecord');
         Route::get('user/addDesktop', 'User\UserController@addDesktop');
         //书架

+ 42 - 0
app/Jobs/UserTaskJob.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Modules\UserTask\Services\UserTaskService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+
+class UserTaskJob implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    private $uid;
+    private $type;
+    private $trigger_type;
+
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct(int $uid, string $type, string $trigger_type)
+    {
+        $this->uid = $uid;
+        $this->type = $type;
+        $this->trigger_type = $trigger_type;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        $service = new UserTaskService($this->uid);
+        $service->trigger($this->type, $this->trigger_type);
+    }
+}

+ 7 - 6
app/Libs/Push/HuaWei/HwPushCommon.php

@@ -71,15 +71,16 @@ class HwPushCommon
 
     /**
      * 发送通知消息
-     * @param $title
-     * @param $desc
-     * @param $pageUrl
-     * @return mixed|null
+     * @param       $title
+     * @param       $desc
+     * @param       $pageUrl
+     * @param array $params
+     * @return bool|mixed|string|null
      */
-    public function sendPushMessage($title, $desc, $pageUrl)
+    public function sendPushMessage($title, $desc, $pageUrl, $params = [])
     {
         // 组装发送数据
-        $data    = $this->createFastAppConfigNotificationData($title, $desc, $pageUrl);
+        $data    = $this->createFastAppConfigNotificationData($title, $desc, $pageUrl, 0, $params);
         $message = $this->createFastAppMsg($data->getFields());
 
         # 创建app

+ 12 - 8
app/Libs/Push/OPPOPush/OPPOPushCommon.php

@@ -46,7 +46,7 @@ class OPPOPushCommon
      */
     public function broadCastAll($messageId)
     {
-        return $this->broadCast('all', $messageId);
+        return $this->broadCast(1, $messageId);
     }
 
     /**
@@ -62,21 +62,25 @@ class OPPOPushCommon
 
     /**
      * 保存通知栏消息内容体
-     * @param $title
-     * @param $content
-     * @param $url
+     * @param       $title
+     * @param       $content
+     * @param       $url
+     * @param array $params
      * @return mixed|string
      * @throws GuzzleException
      */
-    public function getMessageId($title, $content, $url)
+    public function getMessageId($title, $content, $url, $params = [])
     {
         // 组装数据
         $pushMessage = new PushMessage();
-        $pushMessage->style(1);
+        $pushMessage->style(1); // 通知栏样式,1. 标准样式
         $pushMessage->title($title);
         $pushMessage->content($content);
-        $pushMessage->click_action_type(1);
-        $pushMessage->click_action_activity($url);
+        $pushMessage->click_action_type(1); // 点击动作类型0,启动应用;1,打开应用内页
+        $pushMessage->click_action_activity('com.nearme.instant.action.PUSH');
+        $pushMessage->action_parameters(json_encode([
+            'page' => $url,
+        ]));
         $pushMessage->channel_id('OPPO PUSH');
         $pushMessage->auth_token($this->_authToken);
         $fields = $pushMessage->getData();

+ 1 - 0
app/Libs/Push/XMPush/MiPushCommon.php

@@ -77,6 +77,7 @@ class MiPushCommon
         $message->extra(Builder::intentUri, $url); // 此处设置预定义点击行为,1为打开app
         $message->extra(Builder::notifyEffect, 2); // 此处设置预定义点击行为,1为打开app 2通知栏点击后打开app的任一Activity
         $message->extra(Builder::notifyForeground, 1); // 应用在前台是否展示通知,如果不希望应用在前台时候弹出通知,则设置这个参数为0
+        $message->extra(Builder::flowControl, 3000); // 设置平滑推送, 推送速度3000每秒(qps=3000)
         $message->notifyId(2); // 通知类型。最多支持0-4 5个取值范围,同样的类型的通知会互相覆盖,不同类型可以在通知栏并存
         $message->build();
         return $message;

+ 0 - 6
app/Modules/Book/Services/RecoBannerService.php

@@ -9,16 +9,10 @@
 
 namespace App\Modules\Book\Services;
 
-use App\Modules\BaseService;
 use App\Modules\Book\Models\RecoBanner;
 
-/**
- * @method \Illuminate\Support\Collection getByTypeStatic(array $reco_type, int $type)
- */
 class RecoBannerService
 {
-    use BaseService;
-
     public function getByType(array $reco_type, int $type)
     {
         return RecoBanner::whereIn('reco_type', $reco_type)

+ 23 - 3
app/Modules/Push/Services/PushService.php

@@ -30,14 +30,14 @@ class PushService
      */
     public static function setUserRegId($uid, string $regId, string $provider, string $package): bool
     {
-        myLog('push')->info('setUserRegId', compact('uid', 'regId', 'provider', 'package'));
-
         // push服务商(转小写)
         $provider = strtolower($provider);
-        if (empty($uid) || empty($regId) || empty($package) || empty($provider)) {
+        if (empty($uid) || empty($regId) || empty($package) || empty($provider) || $package !== 'com.app.kyy.xnyd') {
             return false;
         }
 
+        myLog('push')->info('setUserRegId', compact('uid', 'regId', 'provider', 'package'));
+
         // 获取缓存
         $userCacheRegId = PushCache::getUserPushRegId($uid);
         if ($regId === $userCacheRegId) {
@@ -288,9 +288,16 @@ class PushService
                         $client = new HwPushCommon($appId, $appSecret);
 
                         // 循环推送
+                        $i = 0;
                         foreach ($regIdArr as $regIdList) {
                             $client->setToken($regIdList);
                             $result = $client->sendPushMessage($title, $content, $url);
+
+                            // 一般的应用默认消息流控是针对单个应用3000QPS(每秒不能超过3000个token数)
+                            $i++;
+                            if ($i % 3 === 0) {
+                                sleep(1);
+                            }
                         }
                         break;
                     // 小米
@@ -299,9 +306,16 @@ class PushService
                         $client = new MiPushCommon($package, $appSecret);
 
                         // 循环推送
+                        $i = 0;
                         foreach ($regIdArr as $regIdList) {
                             $client->setRegArr($regIdList);
                             $result = $client->sendMessage($title, $content, $url);
+
+                            // 一般的应用默认消息流控是针对单个应用3000QPS(每秒不能超过3000个token数)
+                            $i++;
+                            if ($i % 3 === 0) {
+                                sleep(1);
+                            }
                         }
                         break;
                     // OPPO
@@ -311,9 +325,15 @@ class PushService
                         $messageId = $client->getMessageId($title, $content, $url);
 
                         // 循环推送
+                        $i = 0;
                         foreach ($regIdArr as $regIdList) {
                             $client->setRegArr($regIdList);
                             $result = $client->broadCastRegIds($messageId);
+                            // 一般的应用默认消息流控是针对单个应用3000QPS(每秒不能超过3000个token数)
+                            $i++;
+                            if ($i % 3 === 0) {
+                                sleep(1);
+                            }
                         }
                         break;
                 }

+ 19 - 0
app/Modules/TableSuffix.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Modules;
+
+trait TableSuffix
+{
+    private static $suffix;
+
+    public static function suffix($suffix)
+    {
+        static::$suffix = $suffix;
+    }
+
+    public function __construct(array $attributes = [])
+    {
+        $this->table .= static::$suffix;
+        parent::__construct($attributes);
+    }
+}

+ 1 - 1
app/Modules/Trade/Pay/AliOrderArousePay.php

@@ -14,7 +14,7 @@ class AliOrderArousePay extends OrderArousePayAbstract
         $pay_merchant_id = (int) $data['pay_merchant_id'];
         $ali_param = [
             'body' => '小说阅读',
-            'subject' => '追书云',
+            'subject' => $this->getSubjectName($data['distribution_channel_id']),
             'out_trade_no' => $data['trade_no'],
             'timeout_express' => '90m',
             'total_amount' => $data['price'] / 100,

+ 8 - 0
app/Modules/Trade/Pay/OrderArousePayAbstract.php

@@ -3,6 +3,7 @@
 namespace App\Modules\Trade\Pay;
 
 use App\Modules\Subscribe\Models\Order;
+use App\Modules\User\Models\QappPackage;
 
 abstract class OrderArousePayAbstract
 {
@@ -50,4 +51,11 @@ abstract class OrderArousePayAbstract
         ];
         Order::firstOrCreate($params);
     }
+
+    protected function getSubjectName(int $channel_id)
+    {
+        $package = QappPackage::where('channel_id', $channel_id)->select('name')->first();
+        $name = $package ? $package->name : '';
+        return "搜索快应用({$name})继续阅读,投诉电话:0571-56680189";
+    }
 }

+ 3 - 0
app/Modules/Trade/Pay/PaySuccessAbstract.php

@@ -6,6 +6,8 @@ use App\Jobs\QappTikTokUserCharge;
 use App\Modules\Book\Models\BookConfig;
 use App\Modules\Subscribe\Models\Order;
 use App\Modules\User\Services\ReadRecordService;
+use App\Modules\UserTask\Services\BaseTask;
+use App\Modules\UserTask\Services\UserTaskService;
 use Exception;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
@@ -77,6 +79,7 @@ abstract class PaySuccessAbstract
 
    protected function addQueue()
    {
+      UserTaskService::addUserTaskQueue($this->order->uid, BaseTask::charge, UserTaskService::judge_trigger);
       $bid = ReadRecordService::getSimpleFirstReadRecord($this->order->uid);
       $book_id = book_hash_encode($bid);
       $book = BookConfig::where('bid', $bid)->select('book_name')->first();

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

@@ -19,7 +19,7 @@ class WxOrderArousePay extends OrderArousePayAbstract
                 'trade_type'     => $data['trade_type'], // 交易类型
                 'trade_no'     => $data['trade_no'], // 订单号
                 'price'        => $data['price'], // 订单金额,单位:分
-                'body'             => '快应用 小说', // 订单描述
+                'body'             => $this->getSubjectName($data['distribution_channel_id']), // 订单描述
                 'create_ip' => _getIp(), // 支付人的 IP
                 'remark'            =>  $pay_merchant_id
             ];

+ 0 - 1
app/Modules/Trade/Services/PayMerchantService.php

@@ -9,7 +9,6 @@
 
 namespace App\Modules\Trade\Services;
 
-use App\Modules\BaseService;
 use App\Modules\Trade\Models\PayMerchant;
 
 class PayMerchantService

+ 2 - 1
app/Modules/User/Models/QappPackage.php

@@ -10,6 +10,7 @@ class QappPackage extends Model
 
     protected $fillable =
     [
+        'name',
         'package',
         'channel_id',
         'company',
@@ -21,7 +22,7 @@ class QappPackage extends Model
 
     static function getPackage($channel_id)
     {
-        return self::where('channel_id',$channel_id)->first();
+        return self::where('channel_id', $channel_id)->first();
     }
 
     public static function getPackageByPackage($package)

+ 14 - 7
app/Modules/User/Services/QappUserService.php

@@ -8,6 +8,8 @@ use App\Jobs\QappTikTokUser;
 use App\Modules\User\Models\QappPackage;
 use App\Modules\User\Models\QappUser;
 use App\Modules\User\Models\User;
+use App\Modules\UserTask\Services\BaseTask;
+use App\Modules\UserTask\Services\UserTaskService;
 use Exception;
 use Illuminate\Support\Facades\DB;
 use Tymon\JWTAuth\Facades\JWTAuth;
@@ -54,7 +56,7 @@ class QappUserService
      * 绑定手机号
      * 多个账号可以绑定一个手机号
      */
-    public function bindPhone(int $uid, string $phone)
+    public function bindPhone(int $uid, string $phone, string $version = "1.0")
     {
         $qapp_user = QappUser::where('uid', $uid)->first();
         if ($qapp_user->phone && $qapp_user->phone != $phone) {
@@ -64,12 +66,16 @@ class QappUserService
                 DB::beginTransaction();
                 if (!$qapp_user->phone) {
                     $reward = 100;
-                    User::where('id', $uid)->update(
-                        [
-                            'balance' => DB::raw('balance+' . $reward),
-                            'reward_balance' => DB::raw('reward_balance+' . $reward)
-                        ]
-                    );
+                    if ($version == "1.0") {
+                        User::where('id', $uid)->update(
+                            [
+                                'balance' => DB::raw('balance+' . $reward),
+                                'reward_balance' => DB::raw('reward_balance+' . $reward)
+                            ]
+                        );
+                    } else {
+                        UserTaskService::addUserTaskQueue($uid, BaseTask::bind_phone, UserTaskService::add_trigger);
+                    }
                 }
                 $qapp_user->phone = $phone;
                 $qapp_user->save();
@@ -152,6 +158,7 @@ class QappUserService
             DB::commit();
             $job = new QappTikTokUser($user->register_ip, $data['device_no'], $data['mac'], $channel_id, $user->id, $user->created_at, true);
             dispatch($job->onConnection('rabbitmq')->onQueue('qapp_tiktok_user_register_queue'));
+            UserTaskService::addUserTaskQueue($user->id, BaseTask::register, UserTaskService::add_trigger);
             return $qapp_user;
         } catch (Exception $e) {
             myLog('create_user')->error($e->getMessage());

+ 140 - 0
app/Modules/User/Services/SignService.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace App\Modules\User\Services;
+
+use App\Modules\User\Models\User;
+use Illuminate\Support\Facades\DB;
+use Redis;
+
+/**
+ * @property int $this->uid;
+ * @property int $reward_list;
+ */
+class SignService
+{
+    protected $uid;
+
+    protected $reward_list = [30, 35, 40, 45, 50, 55, 60];
+
+    public function __construct(int $uid)
+    {
+        $this->uid = $uid;
+    }
+
+    protected function setRewardList(array $data)
+    {
+        $this->reward_list = $data;
+    }
+
+    /**
+     * 用户签到
+     */
+    public function sign()
+    {
+        $date = $this->getSignDate();
+        $sign_day = $this->getSignDay();
+        if (!$date || $date != date('Y-m-d')) {
+            $reward = $this->getRewardCoin($sign_day);
+            $this->saveReward($reward);
+            $this->saveRewardInfoInRedis($reward, $sign_day);
+            $this->addSignDay();
+        }
+    }
+
+    /**
+     * 获取用户签到信息
+     */
+    public function getSignInfo()
+    {
+        $date = $this->getSignDate();
+        $is_sign = $date == date('Y-m-d');
+        $sign_day = $this->getSignDay();
+        $reward_list = $this->reward_list;
+        return compact('is_sign', 'sign_day', 'reward_list');
+    }
+
+    /**
+     * 保存奖励金额
+     * @param int $reward 签到奖励书币
+     */
+    private function saveReward(int $reward)
+    {
+        User::where('id', $this->uid)->update([
+            'balance' => DB::raw('balance+' . $reward),
+            'reward_balance' => DB::raw('reward_balance+' . $reward)
+        ]);
+    }
+
+    /**
+     * 保存签到信息到redis
+     * @param int $reward 签到奖励书币
+     * @param int $sign_day 签到天数
+     */
+    private function saveRewardInfoInRedis(int $reward, int $sign_day)
+    {
+        $sign_data = [
+            'uid' => $this->uid,
+            'price' => $reward,
+            'day' => $sign_day,
+            'sign_time' => time(),
+            'created_at' => date('Y-m-d H:i:s'),
+            'updated_at' => date('Y-m-d H:i:s')
+        ];
+        Redis::sadd('user_sign:uid', $this->uid);
+        Redis::hset('user_sign:uid:info', $this->uid, json_encode($sign_data));
+        Redis::hset('book_read:' . $this->uid, 'sign_info', json_encode($sign_data));
+    }
+
+    /**
+     * 获取用户签到日期
+     * @return string|bool
+     */
+    private function getSignDate()
+    {
+        $sign_date = Redis::hget('book_read:' . $this->uid, 'sign_day');
+        if ($sign_date && ($sign_date == date('Y-m-d', time() - 86400) || $sign_date == date('Y-m-d'))) {
+            return $sign_date;
+        } else {
+            $this->delSignDay();
+            return false;
+        }
+    }
+
+    /**
+     * 获取用户签到天数
+     * @return int|bool
+     */
+    private function getSignDay()
+    {
+        $sign_day =  Redis::hget('book_read:' . $this->uid, 'sign_counts');
+        return $sign_day ? (int)$sign_day : 0;
+    }
+
+    /**
+     * 增加签到
+     * @return int
+     */
+    private function addSignDay()
+    {
+        Redis::hset('book_read:' . $this->uid, 'sign_day', date('Y-m-d'));
+        return Redis::hincrby('book_read:' . $this->uid, 'sign_counts', 1);
+    }
+
+    /**
+     * 重置签到天数
+     */
+    private function delSignDay()
+    {
+        return Redis::hDel('book_read:' . $this->uid, 'sign_counts');
+    }
+
+    /**
+     * 获取签到奖励金额
+     * @param int $sign_day 签到天数
+     * @return int 
+     */
+    private function getRewardCoin(int $sign_day)
+    {
+        return $this->reward_list[$sign_day % 7];
+    }
+}

+ 3 - 0
app/Modules/User/Services/UserService.php

@@ -24,6 +24,8 @@ use App\Modules\OfficialAccount\Models\DistributionSelfDefineConfig;
 use App\Modules\Channel\Models\Channel;
 use App\Modules\Trade\Models\Order;
 use App\Modules\User\Models\QappUserAddDestop;
+use App\Modules\UserTask\Services\BaseTask;
+use App\Modules\UserTask\Services\UserTaskService;
 use Redis;
 
 class UserService
@@ -59,6 +61,7 @@ class UserService
         // 加桌统计
         if (!$log && $status === 1) {
             QappAddDeskTopService::incrAddDeskTop($uid, QuickConst::FIELD_ADD_DESKTOP);
+            UserTaskService::addUserTaskQueue($uid, BaseTask::add_desk, UserTaskService::add_trigger);
         }
     }
 

+ 35 - 0
app/Modules/UserTask/Models/ChapterOrder.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Modules\UserTask\Models;
+
+use App\Modules\TableSuffix;
+use Illuminate\Database\Eloquent\Model;
+
+class ChapterOrder extends Model
+{
+    use TableSuffix;
+
+    protected $connection = 'chapter_order_mysql';
+
+    protected $fillable = [
+        'distribution_channel_id',
+        'bid',
+        'cid',
+        'chapter_name',
+        'book_name',
+        'uid',
+        'u',
+        'fee',
+        'book_name',
+        'send_order_id',
+        'charge_balance',
+        'reward_balance'
+    ];
+    protected $table = 'chapter_orders';
+
+    public static function model(int $uid)
+    {
+        self::suffix($uid % 512);
+        return new static;
+    }
+}

+ 34 - 0
app/Modules/UserTask/Models/Task.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace App\Modules\UserTask\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * @property string $code
+ * @property string $name
+ * @property string $desc
+ * @property bool $is_repeat
+ * @property int $repeat_cycles
+ * @property int $reward_type
+ * @property int $value
+ * @property string $type
+ * @property bool $is_enabled
+ */
+class Task extends Model
+{
+    protected $table = 'qapp_tasks';
+    protected $fillable = [
+        'code',
+        'name',
+        'desc',
+        'is_repeat',
+        'repeat_cycles',
+        'reward_type',
+        'value',
+        'type',
+        'path',
+        'icon',
+        'is_enabled',
+    ];
+}

+ 28 - 0
app/Modules/UserTask/Models/UserRepeatTask.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Modules\UserTask\Models;
+
+use App\Modules\TableSuffix;
+use Illuminate\Database\Eloquent\Model;
+
+class UserRepeatTask extends Model
+{
+    use TableSuffix;
+
+    protected $table = 'qapp_user_repeat_task';
+    protected $connection = 'qapp_order_mysql';
+    protected $fillable = [
+        'uid',
+        'task_id',
+        'status',
+        'type',
+        'value',
+        'date',
+    ];
+
+    public static function model(int $uid)
+    {
+        self::suffix($uid % 32);
+        return new static;
+    }
+}

+ 17 - 0
app/Modules/UserTask/Models/UserTask.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Modules\UserTask\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class UserTask extends Model
+{
+    protected $table = 'qapp_user_task';
+    protected $fillable = [
+        'uid',
+        'task_id',
+        'status',
+        'type',
+        'value',
+    ];
+}

+ 165 - 0
app/Modules/UserTask/Services/BaseTask.php

@@ -0,0 +1,165 @@
+<?php
+
+namespace App\Modules\UserTask\Services;
+
+use App\Modules\User\Models\User;
+use App\Modules\UserTask\Models\Task;
+use Exception;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * @property Task $task
+ * @property int $uid
+ */
+abstract class BaseTask
+{
+    /**
+     * 未符合条件
+     */
+    const under_status = 0;
+    /**
+     * 符合条件
+     */
+    const up_status = 1;
+    /**
+     * 已领取
+     */
+    const get_status = 2;
+    /**
+     * 用户书币奖励
+     */
+    const coin_reward = 1;
+    /**
+     * 阅读卡奖励
+     */
+    const read_card_reward = 2;
+    /**
+     * 注册 
+     */
+    const register = 'register';
+    /**
+     * 加桌
+     */
+    const add_desk = 'add_desk';
+    /**
+     * 绑定手机号
+     */
+    const bind_phone = 'bind_phone';
+    /**
+     * 充值
+     */
+    const charge = 'charge';
+    /**
+     * 阅读
+     */
+    const read = 'read';
+
+    /**
+     * 新用户任务code组
+     */
+    const new_user_codes = [
+        'user_register',
+        'add_desk',
+        'bind_phone',
+    ];
+    /**
+     * 用户每日任务code组
+     */
+    const date_codes = [
+        'date_charge_reward',
+        'date_read_reward',
+        'date_subscribe_reward',
+    ];
+
+    protected $task;
+    protected $uid;
+
+    /**
+     * 检查任务
+     */
+    public abstract function checkUserTask();
+    /**
+     * 添加用户任务
+     */
+    public abstract function addUserTask();
+    /**
+     * 查找用户任务
+     * @param int $status 任务状态
+     */
+    public abstract function findUserTask(int $status);
+
+    public function __construct(int $uid, ?Task $task)
+    {
+        $this->task = $task ?? new Task;
+        $this->uid = $uid;
+    }
+
+    /**
+     * 设置任务
+     */
+    public function setTask(Task $task)
+    {
+        $this->task = $task;
+    }
+
+    /**
+     * 处理添加用户任务
+     */
+    public function handleAddUserTask()
+    {
+        if (!$this->checkUserTask()) {
+            $this->addUserTask();
+        }
+    }
+
+    /**
+     * 处理用户任务奖励
+     * @return int
+     */
+    public function handleUserTaskReward()
+    {
+        $user_task = $this->findUserTask(self::up_status);
+        if ($user_task) {
+            try {
+                DB::beginTransaction();
+                $user_task->status = self::get_status;
+                $user_task->save();
+                switch ($this->task->reward_type) {
+                    case self::coin_reward:
+                        $this->coinReward();
+                        break;
+                    case self::read_card_reward:
+                        $this->readCardReward();
+                        break;
+                }
+                DB::commit();
+                return 1;
+            } catch (Exception $e) {
+                DB::rollback();
+                return -1;
+            }
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * 书币奖励
+     */
+    protected function coinReward()
+    {
+        User::where('id', $this->uid)->update(
+            [
+                'balance' => DB::raw('balance+' . $this->task->value),
+                'reward_balance' => DB::raw('reward_balance+' . $this->task->value)
+            ]
+        );
+    }
+
+    /**
+     * 阅读卡奖励
+     */
+    protected function readCardReward()
+    {
+    }
+}

+ 23 - 0
app/Modules/UserTask/Services/ChargeTask.php

@@ -0,0 +1,23 @@
+<?php
+namespace App\Modules\UserTask\Services;
+
+use App\Modules\Subscribe\Models\Order;
+
+/**
+ * 充值任务
+ */
+class ChargeTask extends RepeatTask
+{
+    public function judgeUpTo()
+    {
+        switch ($this->task->code) {
+            case 'date_charge_reward':
+                return Order::where('uid', $this->uid)
+                    ->where('status', 'PAID')
+                    ->where('created_at', '>=', date('Y-m-d'))
+                    ->exists();
+            default:
+                return false;
+        }
+    }
+}

+ 28 - 0
app/Modules/UserTask/Services/ReadTask.php

@@ -0,0 +1,28 @@
+<?php
+namespace App\Modules\UserTask\Services;
+
+use App\Modules\UserTask\Models\ChapterOrder;
+
+/**
+ * 阅读任务
+ */
+class ReadTask extends RepeatTask
+{
+    public function judgeUpTo()
+    {
+        switch ($this->task->code) {
+            case 'date_subscribe_reward':
+                return ChapterOrder::model($this->uid)
+                    ->where('uid', $this->uid)
+                    ->where('created_at', '>=', date('Y-m-d'))
+                    ->select('cid')
+                    ->distinct()
+                    ->count() >= 10;
+            case 'date_subscribe_reward':
+                return true;
+                break;
+            default:
+                return false;
+        }
+    }
+}

+ 87 - 0
app/Modules/UserTask/Services/RepeatTask.php

@@ -0,0 +1,87 @@
+<?php
+
+namespace App\Modules\UserTask\Services;
+
+use App\Modules\UserTask\Models\Task;
+use App\Modules\UserTask\Models\UserRepeatTask;
+
+/**
+ * 重复任务
+ * @property UserRepeatTask $model
+ */
+class RepeatTask extends BaseTask
+{
+    private $model;
+
+    public function __construct(int $uid, ?Task $task)
+    {
+        $this->model = UserRepeatTask::model($uid);
+        parent::__construct($uid, $task);
+    }
+
+    public function checkUserTask()
+    {
+        $date = $this->getDate();
+        return $this->model::where('task_id', $this->task->id)
+            ->where('uid', $this->uid)
+            ->where('date', '>=', $date)
+            ->exists();
+    }
+
+    public function addUserTask()
+    {
+        $this->model->create([
+            'date' => date('Y-m-d'),
+            'uid' => $this->uid,
+            'task_id' => $this->task->id,
+            'status' => self::under_status,
+            'type' => $this->task->reward_type,
+            'value' => $this->task->value,
+        ]);
+    }
+
+    public function findUserTask(int $status)
+    {
+        $date = $this->getDate();
+        return $this->model::where('task_id', $this->task->id)
+            ->where('uid', $this->uid)
+            ->where('date', '>=', $date)
+            ->where('status', $status)
+            ->first();
+    }
+
+    /**
+     * 判断条件是否符合
+     * @return bool
+     */
+    public function judgeUpTo()
+    {
+        return true;
+    }
+
+    /**
+     * 处理用户符合任务流程
+     */
+    public function handleUpToUserTask()
+    {
+        $user_task = $this->findUserTask(self::under_status);
+        if ($user_task && $this->judgeUpTo()) {
+            $user_task->status = self::up_status;
+            $user_task->save();
+        }
+    }
+
+    /**
+     * 获取日期
+     */
+    private function getDate()
+    {
+        $diff_day = $this->task->repeat_cycles - 1;
+        if ($diff_day > 0) {
+            $date = date('Y-m-d', strtotime("-{$diff_day} days"));
+        } else {
+            $date = date('Y-m-d');
+        }
+        return $date;
+    }
+}

+ 35 - 0
app/Modules/UserTask/Services/SingleTask.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Modules\UserTask\Services;
+
+use App\Modules\UserTask\Models\UserTask;
+
+/**
+ * 单次任务
+ */
+class SingleTask extends BaseTask
+{
+    public function checkUserTask()
+    {
+        return UserTask::where('task_id', $this->task->id)->where('uid', $this->uid)->exists();
+    }
+
+    public function addUserTask()
+    {
+        UserTask::create([
+            'uid' => $this->uid,
+            'task_id' => $this->task->id,
+            'status' => self::up_status,
+            'type' => $this->task->reward_type,
+            'value' => $this->task->value,
+        ]);
+    }
+
+    public function findUserTask(int $status)
+    {
+        return UserTask::where('task_id', $this->task->id)
+            ->where('uid', $this->uid)
+            ->where('status', $status)
+            ->first();
+    }
+}

+ 166 - 0
app/Modules/UserTask/Services/UserTaskService.php

@@ -0,0 +1,166 @@
+<?php
+
+namespace App\Modules\UserTask\Services;
+
+use App\Jobs\UserTaskJob;
+use App\Modules\UserTask\Models\Task;
+use App\Modules\UserTask\Models\UserRepeatTask;
+use App\Modules\UserTask\Models\UserTask;
+use Illuminate\Database\Eloquent\Collection;
+
+class UserTaskService
+{
+    const add_trigger = 'add';
+    const judge_trigger = 'judge';
+
+    private $uid;
+
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct(int $uid)
+    {
+        $this->uid = $uid;
+    }
+
+    /**
+     * 触发任务
+     * @param string $type 任务类型
+     * @param string $trigger_type 触发类型
+     */
+    public function trigger(string $type, string $trigger_type)
+    {
+        $model = $this->model($type);
+        $tasks = Task::where('type', $type)->get();
+        foreach ($tasks as $task) {
+            $model->setTask($task);
+            switch ($trigger_type) {
+                case self::add_trigger:
+                    $model->handleAddUserTask();
+                    break;
+                case self::judge_trigger:
+                    $model->handleAddUserTask();
+                    $model->handleUpToUserTask();
+                    break;
+            }
+        }
+    }
+
+    /**
+     * 领取任务奖励
+     * @return int
+     */
+    public function getTaskReward(int $task_id)
+    {
+        $task = Task::find($task_id);
+        $model = $this->model($task->type, $task);
+        return $model->handleUserTaskReward();
+    }
+
+    /**
+     * 获取任务model
+     * @return SingleTask|ChargeTask|ReadTask
+     */
+    public function model(string $type, Task $task = null)
+    {
+        switch ($type) {
+            case SingleTask::register:
+            case SingleTask::bind_phone:
+            case SingleTask::add_desk:
+                return new SingleTask($this->uid, $task);
+                break;
+            case RepeatTask::charge:
+                return new ChargeTask($this->uid, $task);
+                break;
+            case RepeatTask::read:
+                return new ReadTask($this->uid, $task);
+                break;
+        }
+    }
+
+    /**
+     * 添加用户任务队列
+     * @param int $uid 
+     * @param string $type 任务类型
+     * @param string $trigger_type 触发类型
+     */
+    public static function addUserTaskQueue(int $uid, string $type, string $trigger_type)
+    {
+        $job = new UserTaskJob($uid, $type, $trigger_type);
+        dispatch($job)->onConnection('rabbitmq')->onQueue('qapp_user_task_queue');
+    }
+
+    /**
+     * 新手任务
+     */
+    public function findNewUserTaskList()
+    {
+        $tasks = $this->findTaskList(BaseTask::new_user_codes);
+        $this->setUserTaskStatus($tasks, 'new');
+        return $tasks;
+    }
+
+    /**
+     * 用户每日任务
+     */
+    public function findDateUserTaskList()
+    {
+        $tasks = $this->findTaskList(BaseTask::date_codes);
+        $this->setUserTaskStatus($tasks, 'date');
+        return $tasks;
+    }
+
+    /**
+     * 查找任务列表
+     * @return Collection
+     */
+    private function findTaskList(array $codes)
+    {
+        return Task::whereIn('code', $codes)->where('is_enabled', 1)->get();
+    }
+
+    /**
+     * 查找用户单次任务
+     * @return Collection
+     */
+    private function findUserTasks(array $task_ids)
+    {
+        return UserTask::whereIn('task_id', $task_ids)->where('uid', $this->uid)->get();
+    }
+
+    /**
+     * 查找用户每日任务
+     * @return Collection
+     */
+    private function findUserDateTasks(array $task_ids)
+    {
+        $model = UserRepeatTask::model($this->uid);
+        $date = date('Y-m-d');
+        return  $model::whereIn('task_id', $task_ids)
+            ->where('date', '>=', $date)
+            ->where('uid', $this->uid)
+            ->get();
+    }
+
+    /**
+     * 设置用户任务状态标记
+     */
+    private function setUserTaskStatus(Collection $tasks, string $code_type)
+    {
+        $task_ids = $tasks->pluck('id')->all();
+        if ($code_type == 'new') {
+            $user_tasks = $this->findUserTasks($task_ids);
+        } else if ($code_type == 'date') {
+            $user_tasks = $this->findUserDateTasks($task_ids);
+        } else {
+            $user_tasks = collect();
+        }
+        $tasks->transform(function (Task $task) use ($user_tasks) {
+            $user_task = $user_tasks->where('task_id', $task->id)->first();
+            $task->status = $user_task ?  $user_task->status : 0;
+            return $task;
+        });
+    }
+}

+ 20 - 7
config/database.php

@@ -56,10 +56,10 @@ return [
             'driver' => 'mysql',
             //'host' => env('DB_HOST', 'localhost'),
             'read' => [
-                'host' => env('DB_READ_HOST','localhost'),
+                'host' => env('DB_READ_HOST', 'localhost'),
             ],
             'write' => [
-                'host' => env('DB_WRITE_HOST','localhost'),
+                'host' => env('DB_WRITE_HOST', 'localhost'),
             ],
             'port' => env('DB_PORT', '3306'),
             'database' => env('DB_DATABASE', 'forge'),
@@ -71,7 +71,7 @@ return [
             'strict' => false,
             'engine' => null,
         ],
-        'chapter_order_mysql'=>[
+        'chapter_order_mysql' => [
             'driver' => 'mysql',
             'host' => env('CHAPTER_DB_HOST', 'localhost'),
             'port' => env('CHAPTER_DB_PORT', '3306'),
@@ -84,7 +84,20 @@ return [
             'strict' => false,
             'engine' => null,
         ],
-        'new_yunqi'=>[
+        'qapp_order_mysql' => [
+            'driver' => 'mysql',
+            'host' => env('QAPP_DB_HOST', 'localhost'),
+            'port' => env('QAPP_DB_PORT', '3306'),
+            'database' => env('QAPP_DB_DATABASE', 'forge'),
+            'username' => env('QAPP_DB_USERNAME', 'forge'),
+            'password' => env('QAPP_DB_PASSWORD', ''),
+            'charset' => 'utf8',
+            'collation' => 'utf8_unicode_ci',
+            'prefix' => '',
+            'strict' => false,
+            'engine' => null,
+        ],
+        'new_yunqi' => [
             'driver' => 'mysql',
             'host' => env('NEW_YUNQI_DB_HOST', 'localhost'),
             'port' => env('NEW_YUNQI_DB_PORT', '3306'),
@@ -146,14 +159,14 @@ return [
             'database' => 0,
         ],
 
-        'order'=> [
+        'order' => [
             'host' => env('REDIS_HOST_ORDER', 'localhost'),
             'password' => env('REDIS_PASSWORD_ORDER', null),
             'port' => env('REDIS_PORT_ORDER', 6379),
             'database' => env('REDIS_DATABASE_ORDER', 0),
         ],
-        'chapter'=>[
-            'host'=>env('REDIS_HOST_CHAPTER','localhost'),
+        'chapter' => [
+            'host' => env('REDIS_HOST_CHAPTER', 'localhost'),
             'password' => env('REDIS_PASSWORD_CHAPTER', null),
             'port' => env('REDIS_PORT_CHAPTER', 6379),
             'database' => env('REDIS_DATABASE_CHAPTER', 0),

+ 2 - 1
config/error.php

@@ -214,5 +214,6 @@ return [
         'QAPP_CHAPTER_SECOND_BALANCE_PAY' => ['code' => 10021, 'msg' => '第二次章节订购余额不足'],
         'QAPP_DOMAIN_NOT_MATCH' => ['code' => 10022, 'msg' => '域名不匹配'],
         'APP_CREATE_WECHAT_ORDER_FAIL' => ['code' => 10025, 'msg' => '微信订单创建失败'],
-
+        'NO_REWARD' => ['code' => 10026, 'msg' => '不符合领取条件!'],
+        'REWARD_GOTTEN_ERROR' => ['code' => 10027, 'msg' => '获取奖励失败!'],
 ];

+ 10 - 0
config/option.php

@@ -0,0 +1,10 @@
+<?php
+
+return [
+    'supports' => [
+        'com.beidao.kuaiying.zsy' => [
+            'customerAccount' => 'zhenzhenyd',
+            'customerImage'   => 'https://cdn-novel.iycdm.com/static/img/kefu20190331.png'
+        ]
+    ]
+];