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:
kate522 committed 2026-07-17 02:05:10 +08:00
1 parent a7489798fe
commit 5949c7a503
9 files changed
+243 -8

No files matched your search

+61 -6
View File
@@ -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');
}