// +---------------------------------------------------------------------- declare (strict_types = 1); namespace addon\wxchat\controller\api; use addon\wxchat\model\WxchatTaskRecord; use think\facade\Db; use think\facade\Request; use ywxapp\controller\FrontendBase; use ywxapp\service\WalletService; /** * Task 类 * * @author ywxapp */ class Task extends FrontendBase { protected $noNeedLogin = []; protected $noNeedVerify = ['*']; protected function initialize() { if ($this->auth->isLogin) { $this->uid = $this->auth->model->uid; } } private $uid = 0; /** * 每日任务定义(硬编码;进度基于真实统计,领取记录防重复) * status: 0 进行中 / 1 可领取 / 2 今日已领取 */ private function definitions() : array { return [ ['id' => 1, 'key' => 'login', 'title' => '每日登录', 'desc' => '每天登录 App 领取奖励', 'reward' => 5, 'target' => 1, 'icon' => 'calendar'], ['id' => 2, 'key' => 'publish', 'title' => '发布动态', 'desc' => '今日发布 1 条动态', 'reward' => 10, 'target' => 1, 'icon' => 'camera'], ['id' => 3, 'key' => 'like', 'title' => '点赞互动', 'desc' => '今日点赞 3 条动态', 'reward' => 8, 'target' => 3, 'icon' => 'heart'], ['id' => 4, 'key' => 'share', 'title' => '分享动态', 'desc' => '今日分享 1 条动态', 'reward' => 6, 'target' => 1, 'icon' => 'share'], ['id' => 5, 'key' => 'profile', 'title' => '完善资料', 'desc' => '完善个人交友资料', 'reward' => 20, 'target' => 1, 'icon' => 'person'], ]; } /** * 任务列表(含真实进度 + 领取状态) */ public function index() { $uid = $this->uid; $today = strtotime('today'); $tasks = $this->definitions(); $result = []; foreach ($tasks as $t) { $current = $this->calcProgress($t['key'], $uid); $done = $current >= $t['target']; $received = WxchatTaskRecord::where('uid', $uid) ->where('task_id', $t['id']) ->where('status', 2) ->where('update_at', '>=', $today) ->count(); $status = $received > 0 ? 2 : ($done ? 1 : 0); $result[] = [ 'id' => $t['id'], 'title' => $t['title'], 'desc' => $t['desc'], 'icon' => $t['icon'], 'reward' => $t['reward'], 'target' => $t['target'], 'current' => min($current, $t['target']), 'status' => $status, ]; } $this->success([ 'list' => $result, 'coins' => WalletService::getCoins($uid), ]); } /** * 领取任务奖励(金币发放,每日每任务一次) */ public function receive() { $uid = $this->uid; $taskId = (int) Request::post('task_id'); $task = null; foreach ($this->definitions() as $t) { if ($t['id'] == $taskId) { $task = $t; break; } } if (! $task) { $this->error('任务不存在'); } // 进度校验 $current = $this->calcProgress($task['key'], $uid); if ($current < $task['target']) { $this->error('任务未完成'); } // 今日是否已领取 $today = strtotime('today'); $got = WxchatTaskRecord::where('uid', $uid) ->where('task_id', $taskId) ->where('status', 2) ->where('update_at', '>=', $today) ->count(); if ($got > 0) { $this->error('今日已领取'); } // 发放金币 WalletService::incCoins($uid, (int) $task['reward'], "任务奖励:{$task['title']}"); // 写领取记录;利用 UNIQUE(uid,task_id) 实现每日重置(次日触发冲突后更新) try { (new WxchatTaskRecord())->save([ 'uid' => $uid, 'task_id' => $taskId, 'progress' => $task['target'], 'status' => 2, 'reward_coins' => $task['reward'], 'create_at' => time(), 'update_at' => time(), ]); } catch (\Throwable $e) { WxchatTaskRecord::where('uid', $uid) ->where('task_id', $taskId) ->update([ 'progress' => $task['target'], 'status' => 2, 'reward_coins' => $task['reward'], 'update_at' => time(), ]); } $this->success([ 'coins_left' => WalletService::getCoins($uid), 'reward' => $task['reward'], ], '领取成功'); } /** * 计算任务当前进度(基于真实业务统计) */ private function calcProgress(string $key, int $uid) : int { $today = strtotime('today'); try { switch ($key) { case 'login': return 1; case 'publish': return (int) Db::name('wxchat_moments') ->where('user_id', $uid) ->where('create_at', '>=', $today) ->count(); case 'like': return (int) Db::name('wxchat_moment_likes') ->where('user_id', $uid) ->where('create_at', '>=', $today) ->count(); case 'share': return (int) Db::name('wxchat_moment_shares') ->where('user_id', $uid) ->where('create_at', '>=', $today) ->count(); case 'profile': $user = Db::name('member')->where('uid', $uid)->field('nickname,avatar')->find(); $profile = Db::name('member_profile')->where('uid', $uid) ->field('bio,birthday,gender')->find(); $score = 0; if (! empty($user['nickname'])) { $score++; } if (! empty($user['avatar'])) { $score++; } if (! empty($profile['bio'])) { $score++; } if (! empty($profile['birthday'])) { $score++; } if (! empty($profile['gender'])) { $score++; } return $score >= 4 ? 1 : 0; } } catch (\Throwable $e) { return 0; } return 0; } }