Prechádzať zdrojové kódy

Merge branch 'quickapp_fly' into kuaiyingyong

onlinetest 4 rokov pred
rodič
commit
ec9916318d

+ 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);
+    }
 }

+ 9 - 6
app/Http/Controllers/QuickApp/Book/ChapterController.php

@@ -20,6 +20,8 @@ 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
 {
@@ -321,7 +323,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
@@ -596,18 +598,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,7 +680,8 @@ class ChapterController extends BaseController
     }
 
 
-    private function stats(){
+    private function stats()
+    {
         //阅读器统计
         WapVisitStatService::recordReaderUvAndPv($this->uid, $this->distribution_channel_id);
     }

+ 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'   =>  1,
         ];
     }
-}
+}

+ 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();
+        } 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();
+    }
 }

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

@@ -19,10 +19,10 @@ Route::group(['domain' => env('QUICKAPP_DOMAIN'), 'namespace' => 'App\Http\Contr
     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');
@@ -56,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);
+    }
+}

+ 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)

+ 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);
+    }
+}

+ 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();

+ 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' => '获取奖励失败!'],
 ];