Files

208 lines
7.3 KiB
PHP

<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
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 <admin@ywxapp.cn>
*/
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;
}
}