feat(identity): author card, per-user tip, comment caps, task status

Author card uses configurable limit/orderby/style and self CTAs.
Tip is per-user weixin/alipay QR modal (no site-global image).
Comment action permissions honor user_caps matrix.
Free points tasks expose done_today/passive status + better comment deep link.
audit-admin-contracts errors=0.
This commit is contained in:
2026-07-17 01:21:35 +08:00
parent b4d04ae346
commit 8d4e94a02c
10 changed files with 374 additions and 148 deletions
@@ -75,6 +75,17 @@ class AKSRT_Admin_Schema_Post_List {
['key' => 'breadcrumbs_single_text', 'label' => '末项显示「正文」', 'type' => 'switch', 'default' => true, 'depends_on' => 'breadcrumbs_single_s', 'description' => '关闭后末项显示文章标题'],
['key' => 'post_prevnext_s', 'label' => '上一篇/下一篇', 'type' => 'switch', 'default' => true],
['key' => 'post_authordesc_s', 'label' => '作者简介', 'type' => 'switch', 'default' => true],
['key' => 'post_author_card_limit', 'label' => '作者卡文章数', 'type' => 'number', 'default' => 6, 'min' => 0, 'max' => 12],
['key' => 'post_author_card_orderby', 'label' => '作者卡文章排序', 'type' => 'select', 'default' => 'views', 'options' => [
['label' => '浏览量', 'value' => 'views'],
['label' => '发布时间', 'value' => 'date'],
['label' => '更新时间', 'value' => 'modified'],
['label' => '评论数', 'value' => 'comment_count'],
]],
['key' => 'post_author_card_style', 'label' => '作者卡文章样式', 'type' => 'radio', 'default' => 'card', 'options' => [
['label' => '卡片', 'value' => 'card'],
['label' => '列表', 'value' => 'list'],
]],
['key' => 'post_single_hide_time_s', 'label' => '隐藏文章时间', 'type' => 'switch', 'default' => false],
]],
['key' => 'cover', 'title' => '封面展示', 'fields' => [
@@ -127,8 +138,8 @@ class AKSRT_Admin_Schema_Post_List {
['key' => 'post_copyright_enabled', 'label' => '版权信息', 'type' => 'switch', 'default' => true],
['key' => 'post_copyright_text', 'label' => '版权默认文案', 'type' => 'textarea', 'default' => '', 'description' => '留空则自动生成"本文由 XX 原创发布"'],
['key' => 'post_wechat_share', 'label' => '微信分享', 'type' => 'switch', 'default' => false],
['key' => 'post_rewards_enabled', 'label' => '打赏功能', 'type' => 'switch', 'default' => false],
['key' => 'post_rewards_text', 'label' => '打赏文案', 'type' => 'input', 'default' => ''],
['key' => 'post_rewards_s', 'label' => '用户打赏', 'type' => 'switch', 'default' => false],
['key' => 'post_rewards_text', 'label' => '打赏按钮文案', 'type' => 'input', 'default' => '赞赏'],
['key' => 'post_button_toptext', 'label' => '按钮上方文案', 'type' => 'input', 'default' => '喜欢就支持一下吧'],
]],
['key' => 'content', 'title' => '内容处理', 'fields' => [
+18 -6
View File
@@ -180,9 +180,12 @@ class AKSRT_Points_Free {
* @return list<array{key:string,title:string,desc:string,points:int,enabled:bool}>
*/
public static function task_list_for_user(int $user_id = 0): array {
unset($user_id); // reserved for per-user progress later
$cfg = self::settings();
$list = [];
$login_done = false;
if ($user_id > 0) {
$login_done = (string) get_user_meta($user_id, self::META_LOGIN, true) === self::today_key();
}
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.
@@ -192,12 +195,21 @@ class AKSRT_Points_Free {
if ($pts <= 0) {
continue;
}
$status = 'todo';
if (in_array($key, ['login', 'sign_in'], true) && $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)) {
$status = 'passive';
}
$list[] = [
'key' => $key,
'title' => $meta[0],
'desc' => $meta[1],
'points' => $pts,
'enabled' => true,
'key' => $key,
'title' => $meta[0],
'desc' => $meta[1],
'points' => $pts,
'enabled' => true,
'status' => $status,
'progress' => null,
'target' => null,
];
}
return $list;
@@ -237,10 +237,20 @@ class AKSRT_Settings_Post_Display {
$authordesc = !isset($settings['post_authordesc_s']) || !empty($settings['post_authordesc_s']);
$hide_time = !empty($settings['post_single_hide_time_s']);
$share_enabled = !isset($settings['share_s']) || !empty($settings['share_s']);
$rewards_enabled = !empty($settings['post_rewards_enabled']) || !empty($settings['post_rewards_s']);
$rewards_image = (string) ($settings['post_rewards_image'] ?? $settings['post_rewards_qrcode'] ?? $settings['post_rewards_img'] ?? '');
$rewards_enabled = !empty($settings['post_rewards_s']) || !empty($settings['post_rewards_enabled']);
$rewards_text = sanitize_text_field((string) ($settings['post_rewards_text'] ?? ''));
$rewards_btn_text = sanitize_text_field((string) ($settings['post_rewards_btn_text'] ?? '赞赏'));
if ($rewards_text === '') {
$rewards_text = '赞赏';
}
$author_card_limit = max(0, min(12, (int) ($settings['post_author_card_limit'] ?? 6)));
$author_card_orderby = sanitize_key((string) ($settings['post_author_card_orderby'] ?? 'views'));
if (!in_array($author_card_orderby, ['views', 'date', 'modified', 'comment_count'], true)) {
$author_card_orderby = 'views';
}
$author_card_style = sanitize_key((string) ($settings['post_author_card_style'] ?? 'card'));
if (!in_array($author_card_style, ['card', 'list'], true)) {
$author_card_style = 'card';
}
$maxheight_enabled = !empty($settings['article_maxheight_kg'])
|| !empty($settings['post_article_maxheight_kg'])
|| !empty($settings['post_maxheight_kg']);
@@ -318,11 +328,15 @@ class AKSRT_Settings_Post_Display {
// Canonical + legacy share.
'share_enabled' => $share_enabled,
'share_s' => $share_enabled,
// Rewards (Zibll post_rewards_s).
// Author card posts (Zibll user_card_box defaults).
'author_card_limit' => $author_card_limit,
'author_card_orderby' => $author_card_orderby,
'author_card_style' => $author_card_style,
// Rewards (Zibll post_rewards_s) — per-user QR only.
'rewards_enabled' => $rewards_enabled,
'rewards_image' => $rewards_image,
'post_rewards_s' => $rewards_enabled,
'rewards_text' => $rewards_text,
'rewards_btn_text' => $rewards_btn_text !== '' ? $rewards_btn_text : '赞赏',
'rewards_btn_text' => $rewards_text,
// Content max height (Zibll article_maxheight_kg / article_maxheight).
'maxheight_enabled' => $maxheight_enabled,
'maxheight' => $maxheight,