feat(identity): close free-task progress, level card, hot threshold
Finish remaining 1:1 parity gaps: free-task done/progress DTO with daily marks, user-center level/integral card UI, configurable forum hot recommend threshold, and task progress bars.
This commit is contained in:
@@ -24,6 +24,7 @@ class AKSRT_Admin_Schema_Forum_Credits {
|
||||
['key' => 'bbs_credits_score_extra', 'label' => '被加分', 'type' => 'number', 'default' => 3, 'min' => 0],
|
||||
['key' => 'bbs_credits_essence', 'label' => '被设精华', 'type' => 'number', 'default' => 10, 'min' => 0],
|
||||
['key' => 'bbs_credits_posts_hot', 'label' => '成为热帖', 'type' => 'number', 'default' => 5, 'min' => 0],
|
||||
['key' => 'bbs_hot_recommend_threshold', 'label' => '热帖推荐分阈值', 'type' => 'number', 'default' => 500, 'min' => 1, 'help' => '推荐分达到该值触发热帖奖励与勋章累计'],
|
||||
['key' => 'bbs_credits_adopted', 'label' => '被采纳', 'type' => 'number', 'default' => 20, 'min' => 0],
|
||||
['key' => 'bbs_credits_daily_max', 'label' => '每日积分上限', 'type' => 'number', 'default' => 50, 'min' => 0, 'help' => '0 = 不限'],
|
||||
]],
|
||||
|
||||
@@ -13,6 +13,8 @@ class AKSRT_Points_Free {
|
||||
|
||||
public const META_DETAIL = 'aksrt_free_points_detail';
|
||||
public const META_LOGIN = 'aksrt_free_points_login_date';
|
||||
public const META_SIGNIN = 'aksrt_free_points_signin_date';
|
||||
public const META_TASKS = 'aksrt_free_points_task_dates';
|
||||
|
||||
/**
|
||||
* Task catalog: key => [label, short_desc, default_points]
|
||||
@@ -162,6 +164,7 @@ class AKSRT_Points_Free {
|
||||
}
|
||||
|
||||
self::bump_detail($user_id, $points);
|
||||
self::mark_task_done_today($user_id, $task_key);
|
||||
return $points;
|
||||
}
|
||||
|
||||
@@ -182,13 +185,22 @@ class AKSRT_Points_Free {
|
||||
public static function task_list_for_user(int $user_id = 0): array {
|
||||
$cfg = self::settings();
|
||||
$list = [];
|
||||
$today = self::today_key();
|
||||
$login_done = false;
|
||||
$signin_done = false;
|
||||
$task_dates = [];
|
||||
if ($user_id > 0) {
|
||||
$login_done = (string) get_user_meta($user_id, self::META_LOGIN, true) === self::today_key();
|
||||
$login_done = (string) get_user_meta($user_id, self::META_LOGIN, true) === $today;
|
||||
$signin_done = (string) get_user_meta($user_id, self::META_SIGNIN, true) === $today;
|
||||
$raw = get_user_meta($user_id, self::META_TASKS, true);
|
||||
$task_dates = is_array($raw) ? $raw : [];
|
||||
}
|
||||
|
||||
$passive = ['post_like', 'post_favorite', 'followed', 'comment_like', 'bbs_essence', 'bbs_adopt', 'bbs_posts_hot', 'bbs_comment_hot', 'bbs_score_extra'];
|
||||
$active_once = ['post_new', 'comment_new', 'bbs_posts_new', 'bbs_reply'];
|
||||
|
||||
foreach (self::catalog() as $key => $meta) {
|
||||
$pts = (int) ($cfg['tasks'][$key] ?? 0);
|
||||
// Hide sign_up from daily task list (one-time); still grant on register.
|
||||
if ($key === 'sign_up') {
|
||||
continue;
|
||||
}
|
||||
@@ -196,10 +208,27 @@ class AKSRT_Points_Free {
|
||||
continue;
|
||||
}
|
||||
$status = 'todo';
|
||||
if (in_array($key, ['login', 'sign_in'], true) && $login_done) {
|
||||
$progress = null;
|
||||
$target = null;
|
||||
if ($key === 'login' && $login_done) {
|
||||
$status = 'done_today';
|
||||
} elseif (in_array($key, ['post_like', 'post_favorite', 'followed', 'comment_like', 'bbs_essence', 'bbs_adopt', 'bbs_posts_hot', 'bbs_comment_hot', 'bbs_score_extra'], true)) {
|
||||
$progress = 1;
|
||||
$target = 1;
|
||||
} elseif ($key === 'sign_in' && $signin_done) {
|
||||
$status = 'done_today';
|
||||
$progress = 1;
|
||||
$target = 1;
|
||||
} elseif (in_array($key, $passive, true)) {
|
||||
$status = 'passive';
|
||||
} elseif (in_array($key, $active_once, true)) {
|
||||
$target = 1;
|
||||
$done_day = is_array($task_dates[$key] ?? null) ? (string) ($task_dates[$key]['day'] ?? '') : (string) ($task_dates[$key] ?? '');
|
||||
if ($done_day === $today) {
|
||||
$status = 'done_today';
|
||||
$progress = 1;
|
||||
} else {
|
||||
$progress = 0;
|
||||
}
|
||||
}
|
||||
$list[] = [
|
||||
'key' => $key,
|
||||
@@ -208,13 +237,39 @@ class AKSRT_Points_Free {
|
||||
'points' => $pts,
|
||||
'enabled' => true,
|
||||
'status' => $status,
|
||||
'progress' => null,
|
||||
'target' => null,
|
||||
'progress' => $progress,
|
||||
'target' => $target,
|
||||
];
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a free-task as completed today (for progress DTO).
|
||||
*/
|
||||
public static function mark_task_done_today(int $user_id, string $task_key): void {
|
||||
if ($user_id <= 0) {
|
||||
return;
|
||||
}
|
||||
$task_key = sanitize_key($task_key);
|
||||
$today = self::today_key();
|
||||
if ($task_key === 'login') {
|
||||
update_user_meta($user_id, self::META_LOGIN, $today);
|
||||
return;
|
||||
}
|
||||
if ($task_key === 'sign_in') {
|
||||
update_user_meta($user_id, self::META_SIGNIN, $today);
|
||||
return;
|
||||
}
|
||||
$raw = get_user_meta($user_id, self::META_TASKS, true);
|
||||
$map = is_array($raw) ? $raw : [];
|
||||
$map[$task_key] = ['day' => $today, 'ts' => time()];
|
||||
if (count($map) > 40) {
|
||||
$map = array_slice($map, -40, null, true);
|
||||
}
|
||||
update_user_meta($user_id, self::META_TASKS, $map);
|
||||
}
|
||||
|
||||
private static function today_key(): string {
|
||||
return (new DateTimeImmutable('today', wp_timezone()))->format('Y-m-d');
|
||||
}
|
||||
|
||||
@@ -222,7 +222,14 @@ class AKSRT_Forum_Score_Service {
|
||||
}
|
||||
|
||||
private function maybe_reward_hot_topic(int $topic_id, float $score): void {
|
||||
$hot_threshold = 500.0;
|
||||
$config = $this->forum->get_config();
|
||||
$hot_threshold = (float) ($config['post_page']['hot_recommend_threshold']
|
||||
?? $config['credits']['hot_recommend_threshold']
|
||||
?? $config['other']['hot_topic_threshold']
|
||||
?? 500);
|
||||
if ($hot_threshold <= 0) {
|
||||
$hot_threshold = 500.0;
|
||||
}
|
||||
if ($score < $hot_threshold) {
|
||||
return;
|
||||
}
|
||||
@@ -239,7 +246,6 @@ class AKSRT_Forum_Score_Service {
|
||||
}
|
||||
do_action('aksrt_forum_topic_hot', $topic_id, (int) $author_id);
|
||||
update_post_meta($topic_id, '_aksrt_hot_rewarded', '1');
|
||||
$config = $this->forum->get_config();
|
||||
$amount = (int) ($config['credits']['posts_hot'] ?? 5);
|
||||
if ($amount > 0) {
|
||||
if (class_exists('AKSRT_Points_Free')) {
|
||||
|
||||
@@ -263,6 +263,7 @@ class AKSRT_Settings_Forum_Shop {
|
||||
'breadcrumbs_bbs_home_name' => $str('bbs_breadcrumbs_bbs_home_name', '论坛'),
|
||||
'breadcrumbs_plate_cat' => $bool('bbs_breadcrumbs_plate_cat', true),
|
||||
'score_extra_max' => $int('bbs_score_extra_max', 5),
|
||||
'hot_recommend_threshold' => $int('bbs_hot_recommend_threshold', 500),
|
||||
'score_deduct_max' => $int('bbs_score_deduct_max', 3),
|
||||
'maxheight_enabled' => $bool('bbs_posts_maxheight_s'),
|
||||
'maxheight' => $int('bbs_posts_maxheight', 800),
|
||||
@@ -337,6 +338,7 @@ class AKSRT_Settings_Forum_Shop {
|
||||
'score_extra' => $int('bbs_credits_score_extra', 3),
|
||||
'essence' => $int('bbs_credits_essence', 10),
|
||||
'posts_hot' => $int('bbs_credits_posts_hot', 5),
|
||||
'hot_recommend_threshold' => $int('bbs_hot_recommend_threshold', 500),
|
||||
'adopted' => $int('bbs_credits_adopted', 20),
|
||||
'daily_max' => $int('bbs_credits_daily_max', 50),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user