导入 AKSRT 主题开发源码
This commit is contained in:
1 parent
9681dd3d48
commit
1268a55dd0
595 files changed
+127705
No files matched your search
@@ -0,0 +1,297 @@
|
||||
<?php
|
||||
/**
|
||||
* Forum board template.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
$current_user_id = get_current_user_id();
|
||||
$board = get_queried_object();
|
||||
$board_id = $board ? (int) $board->term_id : 0;
|
||||
$paged = max(1, (int) get_query_var('paged', 1));
|
||||
$view = $forum ? $forum->get_board_view($board_id, [
|
||||
'user_id' => $current_user_id,
|
||||
'paged' => $paged,
|
||||
]) : [
|
||||
'board' => null,
|
||||
'topics' => [],
|
||||
'sticky_topics' => [],
|
||||
'moderators' => [],
|
||||
'pagination' => ['page' => 1, 'max_pages' => 1, 'total' => 0],
|
||||
'permissions' => [],
|
||||
'application' => null,
|
||||
'board_options' => [],
|
||||
];
|
||||
|
||||
$board_data = $view['board'] ?? null;
|
||||
$topics = $view['topics'] ?? [];
|
||||
$sticky_topics = $view['sticky_topics'] ?? [];
|
||||
$moderators = $view['moderators'] ?? [];
|
||||
$permissions = $view['permissions'] ?? [];
|
||||
$application = $view['application'] ?? null;
|
||||
$board_options = $view['board_options'] ?? [];
|
||||
$compose_url = add_query_arg('board', $board_id, home_url('/compose/'));
|
||||
$admin_forum_url = admin_url('admin.php?page=aksrt-theme-admin#/forum/topics');
|
||||
|
||||
// Forum settings — names
|
||||
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
|
||||
$forum_names = $forum_settings['names'] ?? [];
|
||||
$name_topic = $forum_names['posts'] ?? __('主题', 'aksrt');
|
||||
$name_reply = $forum_names['comment'] ?? __('回复', 'aksrt');
|
||||
$name_sticky = __('置顶', 'aksrt');
|
||||
$name_featured = __('精华', 'aksrt');
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main container" tabindex="-1">
|
||||
|
||||
<div class="aksrt-forum-board container">
|
||||
<div class="aksrt-forum-board__header">
|
||||
<div class="aksrt-forum-board__info">
|
||||
<h1 class="aksrt-forum-board__title"><?php echo esc_html((string) ($board_data['name'] ?? '')); ?></h1>
|
||||
<?php if (!empty($board_data['description'])) : ?>
|
||||
<p class="aksrt-forum-board__desc"><?php echo esc_html((string) $board_data['description']); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-forum-board__meta">
|
||||
<span><i class="fas fa-list-alt"></i> <?php printf(esc_html__('%1$d 个%2$s', 'aksrt'), (int) ($board_data['topic_count'] ?? 0), esc_html($name_topic)); ?></span>
|
||||
<span><i class="fas fa-shield-alt"></i> <?php printf(esc_html__('%d 位版主', 'aksrt'), count($moderators)); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-board__actions">
|
||||
<?php if (!empty($permissions['can_compose'])) : ?>
|
||||
<a href="<?php echo esc_url($compose_url); ?>" class="aksrt-forum-board__compose-btn">
|
||||
<i class="fas fa-pen"></i>
|
||||
<?php esc_html_e('发布新主题', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url(wp_login_url(get_term_link($board))); ?>" class="aksrt-forum-board__compose-btn">
|
||||
<i class="fas fa-sign-in-alt"></i>
|
||||
<?php esc_html_e('登录后发帖', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($permissions['can_moderate'])) : ?>
|
||||
<a href="<?php echo esc_url($admin_forum_url); ?>" class="aksrt-forum-board__manage-btn">
|
||||
<i class="fas fa-tools"></i>
|
||||
<?php esc_html_e('进入治理后台', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="aksrt-forum-board__governance">
|
||||
<div class="aksrt-forum-board__governance-card">
|
||||
<h2 class="aksrt-forum-board__section-title"><?php esc_html_e('权限反馈', 'aksrt'); ?></h2>
|
||||
<?php if (!is_user_logged_in()) : ?>
|
||||
<p><?php esc_html_e('登录后可以发帖、申请版主,并在有权限时执行治理动作。', 'aksrt'); ?></p>
|
||||
<?php elseif (!empty($permissions['can_moderate'])) : ?>
|
||||
<p><?php esc_html_e('你当前拥有本版块治理权限,可在主题页执行审核、移动版块、可见性调整等操作。', 'aksrt'); ?></p>
|
||||
<?php elseif ($application) : ?>
|
||||
<p>
|
||||
<?php esc_html_e('你的版主申请状态:', 'aksrt'); ?>
|
||||
<strong><?php echo esc_html((string) ($application['status_label'] ?? '')); ?></strong>
|
||||
</p>
|
||||
<?php else : ?>
|
||||
<p><?php esc_html_e('当前可浏览并发帖,若你熟悉本版块内容,可提交版主申请参与治理。', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-board__governance-card">
|
||||
<h2 class="aksrt-forum-board__section-title"><?php esc_html_e('版主团队', 'aksrt'); ?></h2>
|
||||
<?php if (!empty($moderators)) : ?>
|
||||
<div class="aksrt-forum-board__moderators">
|
||||
<?php foreach ($moderators as $moderator) : ?>
|
||||
<div class="aksrt-forum-board__moderator">
|
||||
<?php if (!empty($moderator['avatar_url'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $moderator['avatar_url']); ?>" alt="" width="36" height="36">
|
||||
<?php endif; ?>
|
||||
<span><?php echo esc_html((string) ($moderator['display_name'] ?? '')); ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p><?php esc_html_e('当前还没有设置版主。', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (is_user_logged_in() && empty($permissions['can_moderate'])) : ?>
|
||||
<div class="aksrt-forum-board__governance-card">
|
||||
<h2 class="aksrt-forum-board__section-title"><?php esc_html_e('申请版主', 'aksrt'); ?></h2>
|
||||
<?php if ($application) : ?>
|
||||
<p><?php echo esc_html((string) ($application['status_label'] ?? '')); ?></p>
|
||||
<?php if (!empty($application['review_note'])) : ?>
|
||||
<p class="aksrt-forum-board__application-note"><?php echo esc_html((string) $application['review_note']); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<form class="aksrt-forum-board__application-form js-aksrt-moderator-apply-form" data-board-id="<?php echo esc_attr((string) $board_id); ?>">
|
||||
<label for="aksrt-board-apply-reason"><?php esc_html_e('申请理由', 'aksrt'); ?></label>
|
||||
<textarea id="aksrt-board-apply-reason" name="reason" rows="3" placeholder="<?php esc_attr_e('说明你熟悉该版块内容、希望承担的治理职责等。', 'aksrt'); ?>" required></textarea>
|
||||
<div class="aksrt-forum-board__application-actions">
|
||||
<button type="submit" class="aksrt-forum-board__apply-btn"><?php esc_html_e('提交申请', 'aksrt'); ?></button>
|
||||
<span class="aksrt-forum-board__application-feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<?php if (!empty($sticky_topics)) : ?>
|
||||
<div class="aksrt-forum-board__sticky">
|
||||
<h3><i class="fas fa-thumbtack"></i> <?php esc_html_e('置顶主题', 'aksrt'); ?></h3>
|
||||
<?php foreach ($sticky_topics as $topic) : ?>
|
||||
<a href="<?php echo esc_url((string) ($topic['permalink'] ?? '#')); ?>" class="aksrt-forum-board__sticky-item">
|
||||
<?php
|
||||
$sticky_label = (string) ($topic['sticky_label'] ?? '');
|
||||
if ($sticky_label === '') {
|
||||
$sticky_label = __('置顶', 'aksrt');
|
||||
}
|
||||
?>
|
||||
<span class="aksrt-forum-board__sticky-badge"><?php echo esc_html($sticky_label); ?></span>
|
||||
<span class="aksrt-forum-board__sticky-title"><?php echo esc_html((string) ($topic['title'] ?? '')); ?></span>
|
||||
<span class="aksrt-forum-board__sticky-meta">
|
||||
<?php echo esc_html((string) ($topic['author']['display_name'] ?? '')); ?>
|
||||
· <?php echo esc_html((string) ($topic['date'] ?? '')); ?>
|
||||
</span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-forum-board__topics">
|
||||
<?php if (!empty($topics)) : ?>
|
||||
<?php foreach ($topics as $topic) :
|
||||
$topic_id = (int) ($topic['id'] ?? 0);
|
||||
?>
|
||||
<?php
|
||||
$item_sticky_level_class = (int) ($topic['sticky_level'] ?? 0) > 0
|
||||
? ' is-sticky is-sticky-' . (int) ($topic['sticky_level'] ?? 0)
|
||||
: '';
|
||||
?>
|
||||
<article class="aksrt-forum-topic-item<?php echo esc_attr($item_sticky_level_class); ?><?php echo !empty($topic['featured']) ? ' is-featured' : ''; ?>">
|
||||
<div class="aksrt-forum-topic-item__avatar">
|
||||
<?php if (!empty($topic['author']['avatar_url'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $topic['author']['avatar_url']); ?>" alt="" width="40" height="40">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($topic['cover'])) : ?>
|
||||
<div class="aksrt-forum-topic-item__cover">
|
||||
<?php if ($topic['cover']['type'] === 'video') : ?>
|
||||
<div class="aksrt-forum-topic-item__cover-video">
|
||||
<img src="<?php echo esc_url((string) ($topic['cover']['poster'] ?: $topic['cover']['url'])); ?>" alt="" loading="lazy">
|
||||
<span class="aksrt-forum-topic-item__cover-play"><i class="fas fa-play-circle"></i></span>
|
||||
</div>
|
||||
<?php elseif ($topic['cover']['type'] === 'slide') : ?>
|
||||
<div class="aksrt-forum-topic-item__cover-slide">
|
||||
<img src="<?php echo esc_url((string) ($topic['cover']['images'][0] ?? '')); ?>" alt="" loading="lazy">
|
||||
<span class="aksrt-forum-topic-item__cover-count"><i class="fas fa-images"></i> <?php echo count($topic['cover']['images']); ?></span>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<img src="<?php echo esc_url((string) ($topic['cover']['url'] ?? '')); ?>" alt="" loading="lazy">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-forum-topic-item__body">
|
||||
<div class="aksrt-forum-topic-item__title">
|
||||
<?php
|
||||
$item_sticky_level = (int) ($topic['sticky_level'] ?? 0);
|
||||
$item_sticky_label = (string) ($topic['sticky_label'] ?? '');
|
||||
if ($item_sticky_level > 0 && $item_sticky_label !== '') :
|
||||
$item_sticky_mod = $item_sticky_level >= 3 ? 'global' : ($item_sticky_level === 2 ? 'super' : 'plate');
|
||||
?>
|
||||
<span class="aksrt-forum-topic-item__badge aksrt-forum-topic-item__badge--sticky aksrt-forum-topic-item__badge--sticky-<?php echo esc_attr($item_sticky_mod); ?>"><?php echo esc_html($item_sticky_label); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($topic['featured'])) : ?><span class="aksrt-forum-topic-item__badge aksrt-forum-topic-item__badge--featured"><?php esc_html_e('精华', 'aksrt'); ?></span><?php endif; ?>
|
||||
<?php if (($topic['bbs_type'] ?? 'standard') === 'question') : ?>
|
||||
<?php $q_status = (int) ($topic['question_status'] ?? 0); ?>
|
||||
<span class="aksrt-forum-topic-item__badge aksrt-forum-topic-item__badge--question<?php echo $q_status === 1 ? ' aksrt-forum-topic-item__badge--solved' : ''; ?>">
|
||||
<?php echo $q_status === 1 ? esc_html__('已解决', 'aksrt') : esc_html__('提问', 'aksrt'); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($topic['locked'])) : ?><i class="fas fa-lock aksrt-forum-topic-item__lock"></i><?php endif; ?>
|
||||
<?php if (!empty($topic['visibility']['key']) && $topic['visibility']['key'] !== 'public') : ?>
|
||||
<span class="aksrt-forum-topic-item__badge aksrt-forum-topic-item__badge--muted"><?php echo esc_html((string) ($topic['visibility']['label'] ?? '')); ?></span>
|
||||
<?php endif; ?>
|
||||
<a href="<?php echo esc_url((string) ($topic['permalink'] ?? '#')); ?>"><?php echo esc_html((string) ($topic['title'] ?? '')); ?></a>
|
||||
</div>
|
||||
<div class="aksrt-forum-topic-item__meta">
|
||||
<span><?php echo esc_html((string) ($topic['author']['display_name'] ?? '')); ?></span>
|
||||
<span><?php echo esc_html((string) ($topic['date'] ?? '')); ?></span>
|
||||
<?php if (!empty($topic['special_topic'])) : ?>
|
||||
<span><?php echo esc_html((string) $topic['special_topic']); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic-item__stats">
|
||||
<span title="<?php echo esc_attr($name_reply); ?>"><i class="fas fa-comment"></i> <?php echo esc_html(number_format_i18n((int) ($topic['comment_count'] ?? 0))); ?></span>
|
||||
<span title="<?php esc_attr_e('浏览', 'aksrt'); ?>"><i class="fas fa-eye"></i> <?php echo esc_html(number_format_i18n((int) ($topic['views'] ?? 0))); ?></span>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($permissions['can_moderate'])) : ?>
|
||||
<div class="aksrt-forum-topic-item__actions">
|
||||
<?php
|
||||
$sticky_level = (int) ($topic['sticky_level'] ?? 0);
|
||||
// 快捷按钮:无置顶↔版块置顶 切换;超级/全局置顶需进入治理表单调整。
|
||||
$sticky_next = $sticky_level > 0 ? 0 : 1;
|
||||
?>
|
||||
<button
|
||||
type="button"
|
||||
class="aksrt-forum-topic-item__action js-aksrt-topic-action"
|
||||
data-topic-id="<?php echo esc_attr((string) $topic_id); ?>"
|
||||
data-action="sticky"
|
||||
data-value="<?php echo esc_attr((string) $sticky_next); ?>"
|
||||
data-value-type="int"
|
||||
>
|
||||
<?php echo $sticky_level > 0 ? esc_html__('取消置顶', 'aksrt') : esc_html__('置顶', 'aksrt'); ?>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="aksrt-forum-topic-item__action js-aksrt-topic-action"
|
||||
data-topic-id="<?php echo esc_attr((string) $topic_id); ?>"
|
||||
data-action="locked"
|
||||
data-value="<?php echo !empty($topic['locked']) ? '0' : '1'; ?>"
|
||||
>
|
||||
<?php echo !empty($topic['locked']) ? esc_html__('解锁', 'aksrt') : esc_html__('锁定', 'aksrt'); ?>
|
||||
</button>
|
||||
<a href="<?php echo esc_url((string) ($topic['permalink'] ?? '#') . '#aksrt-topic-moderation'); ?>" class="aksrt-forum-topic-item__action aksrt-forum-topic-item__action--link">
|
||||
<?php esc_html_e('更多治理', 'aksrt'); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (($view['pagination']['max_pages'] ?? 1) > 1) : ?>
|
||||
<div class="aksrt-forum-board__pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'total' => (int) ($view['pagination']['max_pages'] ?? 1),
|
||||
'current' => $paged,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum-board__empty">
|
||||
<i class="fas fa-comments"></i>
|
||||
<p><?php esc_html_e('当前版块还没有公开主题。', 'aksrt'); ?></p>
|
||||
<?php if (!empty($permissions['can_compose'])) : ?>
|
||||
<a href="<?php echo esc_url($compose_url); ?>"><?php esc_html_e('发布第一个主题', 'aksrt'); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,409 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: 论坛发帖
|
||||
* Template Post Type: page
|
||||
*
|
||||
* §7.4 — wp_editor rich editor + sidebar panels + server-side draft + capability gates.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
|
||||
wp_safe_redirect($login_url);
|
||||
exit;
|
||||
}
|
||||
|
||||
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
$current_user_id = get_current_user_id();
|
||||
$board_id = isset($_GET['board']) ? (int) $_GET['board'] : 0;
|
||||
$draft_id = isset($_GET['draft']) ? (int) $_GET['draft'] : 0;
|
||||
|
||||
$view = $forum ? $forum->get_compose_view($current_user_id, ['board_id' => $board_id]) : [
|
||||
'boards' => [],
|
||||
'selected_board_id' => 0,
|
||||
'visibility_options' => [],
|
||||
'publish_mode' => 'pending',
|
||||
'draft_count' => 0,
|
||||
'drafts' => [],
|
||||
'capabilities' => [],
|
||||
];
|
||||
|
||||
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
|
||||
$title_placeholder = $forum_settings['other']['t_placeholder'] ?? __('请输入标题', 'aksrt');
|
||||
$content_placeholder = $forum_settings['other']['c_placeholder'] ?? __('请输入内容', 'aksrt');
|
||||
$title_maxlen = max(5, min(100, (int) ($forum_settings['other']['title_strlen_limit'] ?? 30)));
|
||||
$vote_max = (int) ($forum_settings['other']['vote_max'] ?? 8);
|
||||
$forum_name = $forum_settings['names']['forum'] ?? __('论坛', 'aksrt');
|
||||
|
||||
$boards = $view['boards'] ?? [];
|
||||
$visibility_options = $view['visibility_options'] ?? [];
|
||||
$publish_mode = (string) ($view['publish_mode'] ?? 'pending');
|
||||
$draft_count = (int) ($view['draft_count'] ?? 0);
|
||||
$drafts = $view['drafts'] ?? [];
|
||||
$caps = $view['capabilities'] ?? [];
|
||||
$nonce = wp_create_nonce('aksrt_forum_compose');
|
||||
|
||||
// Load draft data if resuming
|
||||
$draft_data = null;
|
||||
if ($draft_id > 0 && $forum) {
|
||||
$draft_data = $forum->load_draft_data($current_user_id, $draft_id);
|
||||
if ($draft_data) {
|
||||
$board_id = (int) ($draft_data['board_id'] ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
$initial_content = $draft_data ? $draft_data['content'] : '';
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main container" tabindex="-1">
|
||||
|
||||
<div class="aksrt-forum-compose container">
|
||||
<div class="aksrt-forum-compose__header">
|
||||
<div>
|
||||
<h1><i class="fas fa-pen-fancy"></i> <?php esc_html_e('发布新主题', 'aksrt'); ?></h1>
|
||||
<p class="aksrt-forum-compose__notice">
|
||||
<?php
|
||||
echo $publish_mode === 'publish'
|
||||
? esc_html__('你在当前版块具备直接发布权限。', 'aksrt')
|
||||
: esc_html__('普通用户发帖将进入审核流程,审核通过后才会公开展示。', 'aksrt');
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<a href="<?php echo esc_url(home_url('/forums/')); ?>" class="aksrt-forum-compose__back">
|
||||
<i class="fas fa-arrow-left"></i> <?php printf(esc_html__('返回%s', 'aksrt'), esc_html($forum_name)); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<?php if ($draft_count > 0) : ?>
|
||||
<div class="aksrt-forum-compose__draft-notice">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<?php printf(
|
||||
esc_html__('您有 %d 篇草稿。', 'aksrt'),
|
||||
$draft_count
|
||||
); ?>
|
||||
<button type="button" class="aksrt-forum-compose__draft-toggle js-aksrt-draft-toggle">
|
||||
<?php esc_html_e('查看草稿', 'aksrt'); ?>
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</button>
|
||||
<div class="aksrt-forum-compose__draft-list" id="compose-draft-list" hidden>
|
||||
<?php foreach ($drafts as $d) : ?>
|
||||
<div class="aksrt-forum-compose__draft-item" data-draft-id="<?php echo esc_attr((string) $d['id']); ?>">
|
||||
<a href="<?php echo esc_url(add_query_arg('draft', $d['id'], get_permalink())); ?>" class="aksrt-forum-compose__draft-title">
|
||||
<?php echo esc_html($d['title']); ?>
|
||||
</a>
|
||||
<span class="aksrt-forum-compose__draft-meta">
|
||||
<?php echo esc_html($d['board_name'] ?: __('未选版块', 'aksrt')); ?> ·
|
||||
<?php echo esc_html(human_time_diff(strtotime($d['date']), current_time('timestamp'))); ?><?php esc_html_e('前', 'aksrt'); ?>
|
||||
</span>
|
||||
<button type="button" class="aksrt-forum-compose__draft-delete js-aksrt-delete-draft" data-draft-id="<?php echo esc_attr((string) $d['id']); ?>" title="<?php esc_attr_e('删除草稿', 'aksrt'); ?>">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form
|
||||
id="aksrt-forum-compose-form"
|
||||
class="aksrt-forum-compose__form aksrt-forum-compose__layout js-aksrt-forum-compose-form"
|
||||
data-ajax="<?php echo esc_url(admin_url('admin-ajax.php')); ?>"
|
||||
data-nonce="<?php echo esc_attr($nonce); ?>"
|
||||
data-publish-mode="<?php echo esc_attr($publish_mode); ?>"
|
||||
data-vote-max="<?php echo esc_attr((string) $vote_max); ?>"
|
||||
data-draft-id="<?php echo esc_attr((string) ($draft_data['draft_id'] ?? 0)); ?>"
|
||||
>
|
||||
<!-- ═══ Main content area ═══ -->
|
||||
<div class="aksrt-forum-compose__main">
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-title"><?php esc_html_e('主题标题', 'aksrt'); ?> <span class="required">*</span></label>
|
||||
<input type="text" id="compose-title" name="title" required
|
||||
maxlength="<?php echo esc_attr((string) $title_maxlen); ?>"
|
||||
placeholder="<?php echo esc_attr($title_placeholder); ?>"
|
||||
value="<?php echo esc_attr($draft_data['title'] ?? ''); ?>"
|
||||
data-aksrt-maxlength="<?php echo esc_attr((string) $title_maxlen); ?>">
|
||||
<span class="aksrt-forum-compose__char-counter" id="compose-title-counter">
|
||||
<span class="js-aksrt-counter-current"><?php echo esc_html((string) mb_strlen($draft_data['title'] ?? '')); ?></span> / <?php echo esc_html((string) $title_maxlen); ?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field aksrt-forum-compose__editor-wrap">
|
||||
<label><?php esc_html_e('主题内容', 'aksrt'); ?> <span class="required">*</span></label>
|
||||
<?php
|
||||
$editor_settings = [
|
||||
'textarea_name' => 'content',
|
||||
'textarea_rows' => 18,
|
||||
'media_buttons' => !empty($caps['can_upload_image']) || !empty($caps['can_upload_video']) || !empty($caps['can_upload_file']),
|
||||
'teeny' => false,
|
||||
'quicktags' => true,
|
||||
'tinymce' => [
|
||||
'toolbar1' => 'formatselect,bold,italic,underline,strikethrough,blockquote,bullist,numlist,alignleft,aligncenter,alignright,link,unlink,wp_more,fullscreen',
|
||||
'toolbar2' => 'pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',
|
||||
'plugins' => 'paste,link,lists,fullscreen,wordpress,wplink,charmap',
|
||||
],
|
||||
];
|
||||
|
||||
if (empty($caps['can_upload_image']) && empty($caps['can_upload_video']) && empty($caps['can_upload_file'])) {
|
||||
$editor_settings['tinymce']['toolbar1'] = str_replace(',wp_more', '', $editor_settings['tinymce']['toolbar1']);
|
||||
}
|
||||
|
||||
wp_editor($initial_content, 'compose-content', $editor_settings);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══ Sidebar panels ═══ -->
|
||||
<div class="aksrt-forum-compose__sidebar">
|
||||
|
||||
<!-- Panel: Submit / Status -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-paper-plane"></i> <?php esc_html_e('发布', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<p class="aksrt-forum-compose__status-line">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<span id="compose-status-text">
|
||||
<?php echo $publish_mode === 'publish'
|
||||
? esc_html__('状态:直接发布', 'aksrt')
|
||||
: esc_html__('状态:待审核', 'aksrt'); ?>
|
||||
</span>
|
||||
</p>
|
||||
<div class="aksrt-forum-compose__actions">
|
||||
<button type="submit" class="aksrt-forum-compose__submit" id="compose-submit">
|
||||
<i class="fas fa-paper-plane"></i> <?php esc_html_e('提交主题', 'aksrt'); ?>
|
||||
</button>
|
||||
<button type="button" class="aksrt-forum-compose__draft" id="compose-draft">
|
||||
<i class="fas fa-save"></i> <?php esc_html_e('保存草稿', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
<span class="aksrt-forum-compose__feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Board selector -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-th-large"></i> <?php esc_html_e('版块', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field aksrt-remote-select" data-search-action="aksrt_forum_search_boards">
|
||||
<input type="hidden" id="compose-board" name="board_id" value="<?php echo esc_attr((string) $board_id); ?>">
|
||||
<input type="text" class="aksrt-remote-select__input js-aksrt-remote-input"
|
||||
placeholder="<?php esc_attr_e('搜索版块…', 'aksrt'); ?>"
|
||||
autocomplete="off"
|
||||
value="<?php
|
||||
if ($board_id > 0) {
|
||||
foreach ($boards as $b) {
|
||||
if (((int) ($b['id'] ?? 0)) === $board_id) {
|
||||
echo esc_attr((string) ($b['name'] ?? ''));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>">
|
||||
<div class="aksrt-remote-select__dropdown" hidden></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Post type -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-tag"></i> <?php esc_html_e('类型 & 分类', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-bbs-type"><?php esc_html_e('帖子类型', 'aksrt'); ?></label>
|
||||
<select id="compose-bbs-type" name="bbs_type">
|
||||
<option value="standard" <?php selected($draft_data['bbs_type'] ?? '', 'standard'); ?>><?php esc_html_e('标准帖子', 'aksrt'); ?></option>
|
||||
<option value="question" <?php selected($draft_data['bbs_type'] ?? '', 'question'); ?>><?php esc_html_e('提问', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-special"><?php esc_html_e('专题/系列', 'aksrt'); ?></label>
|
||||
<input type="text" id="compose-special" name="special_topic" maxlength="80"
|
||||
placeholder="<?php esc_attr_e('例如:站点重构周报', 'aksrt'); ?>"
|
||||
value="<?php echo esc_attr($draft_data['special_topic'] ?? ''); ?>">
|
||||
</div>
|
||||
|
||||
<?php if (taxonomy_exists('aksrt_forum_topic_cat')) : ?>
|
||||
<div class="aksrt-forum-compose__field aksrt-remote-select" data-search-action="aksrt_forum_search_topics">
|
||||
<label><?php esc_html_e('话题', 'aksrt'); ?></label>
|
||||
<input type="hidden" name="topic_cat" value="<?php echo esc_attr($draft_data['topic_cat'] ?? ''); ?>">
|
||||
<input type="text" class="aksrt-remote-select__input js-aksrt-remote-input"
|
||||
placeholder="<?php esc_attr_e('搜索话题…', 'aksrt'); ?>"
|
||||
autocomplete="off"
|
||||
value="<?php echo esc_attr($draft_data['topic_cat'] ?? ''); ?>">
|
||||
<div class="aksrt-remote-select__dropdown" hidden></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Tags -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-tags"></i> <?php esc_html_e('标签', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field aksrt-tag-input" data-search-action="aksrt_forum_search_tags" data-max="5">
|
||||
<input type="hidden" id="compose-tags" name="tags" value="<?php echo esc_attr($draft_data['tags'] ?? ''); ?>">
|
||||
<div class="aksrt-tag-input__tokens" id="compose-tag-tokens"></div>
|
||||
<input type="text" class="aksrt-tag-input__input js-aksrt-tag-search"
|
||||
placeholder="<?php esc_attr_e('输入标签名,回车添加', 'aksrt'); ?>"
|
||||
autocomplete="off" maxlength="30">
|
||||
<div class="aksrt-tag-input__dropdown" hidden></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Visibility -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-eye"></i> <?php esc_html_e('可见性', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<select id="compose-visibility" name="visibility">
|
||||
<?php foreach ($visibility_options as $option) : ?>
|
||||
<option value="<?php echo esc_attr((string) ($option['value'] ?? '')); ?>"
|
||||
<?php selected($draft_data['visibility'] ?? 'public', $option['value'] ?? ''); ?>>
|
||||
<?php echo esc_html((string) ($option['label'] ?? '')); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__visibility-extra" id="compose-credits-cost-field" style="display:none;">
|
||||
<label for="compose-credits-cost"><?php esc_html_e('积分价格', 'aksrt'); ?></label>
|
||||
<input type="number" id="compose-credits-cost" name="credits_cost" min="1" max="99999"
|
||||
value="<?php echo esc_attr((string) ($draft_data['credits_cost'] ?? '')); ?>"
|
||||
placeholder="<?php esc_attr_e('查看需要的积分数', 'aksrt'); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__visibility-extra" id="compose-pay-price-field" style="display:none;">
|
||||
<label for="compose-pay-price"><?php esc_html_e('付费价格(¥)', 'aksrt'); ?></label>
|
||||
<input type="number" id="compose-pay-price" name="pay_price" min="0.01" step="0.01" max="99999"
|
||||
value="<?php echo esc_attr((string) ($draft_data['pay_price'] ?? '')); ?>"
|
||||
placeholder="<?php esc_attr_e('查看需要的金额', 'aksrt'); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__visibility-extra" id="compose-role-field" style="display:none;">
|
||||
<label for="compose-visibility-roles"><?php esc_html_e('允许的角色', 'aksrt'); ?></label>
|
||||
<?php $selected_roles = $draft_data['visibility_roles'] ?? []; ?>
|
||||
<select id="compose-visibility-roles" name="visibility_roles[]" multiple>
|
||||
<?php foreach (wp_roles()->get_names() as $role_slug => $role_name) : ?>
|
||||
<option value="<?php echo esc_attr($role_slug); ?>"
|
||||
<?php echo in_array($role_slug, $selected_roles, true) ? 'selected' : ''; ?>>
|
||||
<?php echo esc_html(translate_user_role($role_name)); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Cover -->
|
||||
<?php if (!empty($caps['can_set_cover'])) : ?>
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-image"></i> <?php esc_html_e('封面', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<select id="compose-cover-type" name="cover_type">
|
||||
<option value="" <?php selected($draft_data['cover_type'] ?? '', ''); ?>><?php esc_html_e('无封面', 'aksrt'); ?></option>
|
||||
<?php if (!empty($caps['can_set_cover_image'])) : ?>
|
||||
<option value="image" <?php selected($draft_data['cover_type'] ?? '', 'image'); ?>><?php esc_html_e('图片封面', 'aksrt'); ?></option>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($caps['can_set_cover_slide'])) : ?>
|
||||
<option value="slide" <?php selected($draft_data['cover_type'] ?? '', 'slide'); ?>><?php esc_html_e('幻灯片封面', 'aksrt'); ?></option>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($caps['can_set_cover_video'])) : ?>
|
||||
<option value="video" <?php selected($draft_data['cover_type'] ?? '', 'video'); ?>><?php esc_html_e('视频封面', 'aksrt'); ?></option>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__cover-upload" id="compose-cover-image-field" style="display:none;">
|
||||
<input type="hidden" name="cover_image" id="compose-cover-image" value="<?php echo esc_attr($draft_data['cover_image'] ?? ''); ?>">
|
||||
<div class="aksrt-forum-compose__cover-preview" id="compose-cover-preview">
|
||||
<?php if (!empty($draft_data['cover_image'])) : ?>
|
||||
<img src="<?php echo esc_url($draft_data['cover_image']); ?>" alt="">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<button type="button" class="aksrt-forum-compose__cover-btn" id="compose-cover-upload-btn"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__cover-upload" id="compose-cover-slide-field" style="display:none;">
|
||||
<input type="hidden" name="featured_slide" id="compose-featured-slide"
|
||||
value="<?php echo esc_attr(!empty($draft_data['featured_slide']) ? wp_json_encode($draft_data['featured_slide']) : ''); ?>">
|
||||
<div class="aksrt-forum-compose__cover-preview" id="compose-slide-preview">
|
||||
<?php if (!empty($draft_data['featured_slide'])) : foreach ($draft_data['featured_slide'] as $su) : ?>
|
||||
<img src="<?php echo esc_url($su); ?>" alt="">
|
||||
<?php endforeach; endif; ?>
|
||||
</div>
|
||||
<button type="button" class="aksrt-forum-compose__cover-btn" id="compose-slide-upload-btn"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__cover-upload" id="compose-cover-video-field" style="display:none;">
|
||||
<input type="url" name="featured_video" id="compose-featured-video"
|
||||
value="<?php echo esc_attr($draft_data['featured_video'] ?? ''); ?>"
|
||||
placeholder="<?php esc_attr_e('https://...mp4', 'aksrt'); ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Panel: Vote -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title">
|
||||
<label class="aksrt-forum-compose__checkbox">
|
||||
<input type="checkbox" id="compose-vote-enabled" name="vote_enabled" value="1"
|
||||
<?php checked(!empty($draft_data['vote_enabled'])); ?>>
|
||||
<span><i class="fas fa-poll"></i> <?php esc_html_e('投票', 'aksrt'); ?></span>
|
||||
</label>
|
||||
</h3>
|
||||
<div class="aksrt-forum-compose__panel-body aksrt-forum-compose__vote-fields" <?php echo empty($draft_data['vote_enabled']) ? 'hidden' : ''; ?>>
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-vote-title"><?php esc_html_e('投票标题', 'aksrt'); ?></label>
|
||||
<input type="text" id="compose-vote-title" name="vote_title" maxlength="120"
|
||||
value="<?php echo esc_attr($draft_data['vote_title'] ?? ''); ?>"
|
||||
placeholder="<?php esc_attr_e('你更希望改造哪个模块?', 'aksrt'); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label class="aksrt-forum-compose__checkbox">
|
||||
<input type="checkbox" id="compose-vote-multiple" name="vote_multiple" value="1"
|
||||
<?php checked(!empty($draft_data['vote_multiple'])); ?>>
|
||||
<span><?php esc_html_e('允许多选', 'aksrt'); ?></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-vote-type"><?php esc_html_e('投票类型', 'aksrt'); ?></label>
|
||||
<select id="compose-vote-type" name="vote_type">
|
||||
<option value="standard" <?php selected($draft_data['vote_type'] ?? '', 'standard'); ?>><?php esc_html_e('标准投票', 'aksrt'); ?></option>
|
||||
<option value="pk" <?php selected($draft_data['vote_type'] ?? '', 'pk'); ?>><?php esc_html_e('PK 双选', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-vote-expiry"><?php esc_html_e('投票有效期', 'aksrt'); ?></label>
|
||||
<select id="compose-vote-expiry" name="vote_expiry_days">
|
||||
<option value="0" <?php selected((int) ($draft_data['vote_expiry_days'] ?? 0), 0); ?>><?php esc_html_e('永久', 'aksrt'); ?></option>
|
||||
<option value="1" <?php selected((int) ($draft_data['vote_expiry_days'] ?? 0), 1); ?>><?php esc_html_e('1 天', 'aksrt'); ?></option>
|
||||
<option value="7" <?php selected((int) ($draft_data['vote_expiry_days'] ?? 0), 7); ?>><?php esc_html_e('7 天', 'aksrt'); ?></option>
|
||||
<option value="30" <?php selected((int) ($draft_data['vote_expiry_days'] ?? 0), 30); ?>><?php esc_html_e('30 天', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-vote-options"><?php printf(esc_html__('选项(最多 %d 项)', 'aksrt'), (int) $vote_max); ?></label>
|
||||
<textarea id="compose-vote-options" name="vote_options" rows="4"
|
||||
placeholder="<?php esc_attr_e("每行一个选项", 'aksrt'); ?>"><?php echo esc_textarea($draft_data['vote_options'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!-- /.aksrt-forum-compose__sidebar -->
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,362 @@
|
||||
<?php
|
||||
/**
|
||||
* 论坛帖子编辑模板
|
||||
*
|
||||
* §7.4 — Full-field AJAX editing with wp_editor, matching compose capabilities.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
wp_safe_redirect(wp_login_url(get_permalink()));
|
||||
exit;
|
||||
}
|
||||
|
||||
$topic_id = get_the_ID();
|
||||
$user_id = get_current_user_id();
|
||||
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
|
||||
if (!$forum || !$forum->can_edit_topic($user_id, $topic_id)) {
|
||||
wp_safe_redirect(get_permalink($topic_id));
|
||||
exit;
|
||||
}
|
||||
|
||||
$topic = get_post($topic_id);
|
||||
|
||||
// Board
|
||||
$board_id = 0;
|
||||
$board_name = '';
|
||||
if ($forum->is_plate_cpt_active()) {
|
||||
$board_id = (int) get_post_meta($topic_id, '_aksrt_plate_id', true);
|
||||
if ($board_id > 0) {
|
||||
$board_name = get_the_title($board_id);
|
||||
}
|
||||
} else {
|
||||
$terms = wp_get_post_terms($topic_id, 'aksrt_forum_board', ['fields' => 'all']);
|
||||
if (!is_wp_error($terms) && !empty($terms)) {
|
||||
$board_id = (int) $terms[0]->term_id;
|
||||
$board_name = (string) $terms[0]->name;
|
||||
}
|
||||
}
|
||||
|
||||
// Tags
|
||||
$tags = wp_get_post_terms($topic_id, 'aksrt_forum_tag', ['fields' => 'names']);
|
||||
$tag_str = !is_wp_error($tags) && !empty($tags) ? implode(', ', $tags) : '';
|
||||
|
||||
// Topic category
|
||||
$topic_cat = '';
|
||||
if (taxonomy_exists('aksrt_forum_topic_cat')) {
|
||||
$cats = wp_get_post_terms($topic_id, 'aksrt_forum_topic_cat', ['fields' => 'names']);
|
||||
if (!is_wp_error($cats) && !empty($cats)) {
|
||||
$topic_cat = $cats[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Post meta
|
||||
$visibility = get_post_meta($topic_id, '_aksrt_visibility', true) ?: 'public';
|
||||
$bbs_type = get_post_meta($topic_id, '_aksrt_bbs_type', true) ?: 'standard';
|
||||
$special_topic = get_post_meta($topic_id, '_aksrt_special_topic', true) ?: '';
|
||||
$cover_type = get_post_meta($topic_id, '_aksrt_cover_type', true) ?: '';
|
||||
$cover_image = get_post_meta($topic_id, '_aksrt_cover_image', true) ?: '';
|
||||
$featured_slide = get_post_meta($topic_id, '_aksrt_featured_slide', true) ?: [];
|
||||
$featured_video = get_post_meta($topic_id, '_aksrt_featured_video', true) ?: '';
|
||||
$credits_cost = (int) get_post_meta($topic_id, '_aksrt_credits_cost', true);
|
||||
$pay_price = get_post_meta($topic_id, '_aksrt_pay_price', true) ?: '';
|
||||
$visibility_roles = get_post_meta($topic_id, '_aksrt_visibility_roles', true) ?: [];
|
||||
$vote_enabled = get_post_meta($topic_id, '_aksrt_vote_enabled', true) === '1';
|
||||
$vote_title = get_post_meta($topic_id, '_aksrt_vote_title', true) ?: '';
|
||||
$vote_multiple = get_post_meta($topic_id, '_aksrt_vote_multiple', true) === '1';
|
||||
$vote_type = get_post_meta($topic_id, '_aksrt_vote_type', true) ?: 'standard';
|
||||
$vote_expiry_days = (int) get_post_meta($topic_id, '_aksrt_vote_expiry_days', true);
|
||||
$vote_options_raw = get_post_meta($topic_id, '_aksrt_vote_options', true) ?: [];
|
||||
$vote_options_text = is_array($vote_options_raw) ? implode("\n", array_column($vote_options_raw, 'label')) : '';
|
||||
|
||||
// Settings & capabilities
|
||||
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
|
||||
$title_maxlen = max(5, min(100, (int) ($forum_settings['other']['title_strlen_limit'] ?? 30)));
|
||||
$vote_max = (int) ($forum_settings['other']['vote_max'] ?? 8);
|
||||
$caps = $forum->get_compose_capabilities($user_id);
|
||||
$visibility_options = $forum->get_visibility_options();
|
||||
$nonce = wp_create_nonce('aksrt_forum_compose');
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main container" tabindex="-1">
|
||||
|
||||
<div class="aksrt-forum-compose container">
|
||||
<div class="aksrt-forum-compose__header">
|
||||
<div>
|
||||
<h1><i class="fas fa-edit"></i> <?php esc_html_e('编辑帖子', 'aksrt'); ?></h1>
|
||||
</div>
|
||||
<a href="<?php echo esc_url(get_permalink($topic_id)); ?>" class="aksrt-forum-compose__back">
|
||||
<i class="fas fa-arrow-left"></i> <?php esc_html_e('返回帖子', 'aksrt'); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form
|
||||
id="aksrt-forum-compose-form"
|
||||
class="aksrt-forum-compose__form aksrt-forum-compose__layout js-aksrt-forum-edit-form"
|
||||
data-ajax="<?php echo esc_url(admin_url('admin-ajax.php')); ?>"
|
||||
data-nonce="<?php echo esc_attr($nonce); ?>"
|
||||
data-topic-id="<?php echo esc_attr((string) $topic_id); ?>"
|
||||
data-vote-max="<?php echo esc_attr((string) $vote_max); ?>"
|
||||
>
|
||||
<!-- ═══ Main content area ═══ -->
|
||||
<div class="aksrt-forum-compose__main">
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-title"><?php esc_html_e('主题标题', 'aksrt'); ?> <span class="required">*</span></label>
|
||||
<input type="text" id="compose-title" name="title" required
|
||||
maxlength="<?php echo esc_attr((string) $title_maxlen); ?>"
|
||||
value="<?php echo esc_attr($topic->post_title); ?>"
|
||||
data-aksrt-maxlength="<?php echo esc_attr((string) $title_maxlen); ?>">
|
||||
<span class="aksrt-forum-compose__char-counter" id="compose-title-counter">
|
||||
<span class="js-aksrt-counter-current"><?php echo esc_html((string) mb_strlen($topic->post_title)); ?></span> / <?php echo esc_html((string) $title_maxlen); ?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field aksrt-forum-compose__editor-wrap">
|
||||
<label><?php esc_html_e('主题内容', 'aksrt'); ?> <span class="required">*</span></label>
|
||||
<?php
|
||||
wp_editor($topic->post_content, 'compose-content', [
|
||||
'textarea_name' => 'content',
|
||||
'textarea_rows' => 18,
|
||||
'media_buttons' => !empty($caps['can_upload_image']) || !empty($caps['can_upload_video']) || !empty($caps['can_upload_file']),
|
||||
'teeny' => false,
|
||||
'quicktags' => true,
|
||||
'tinymce' => [
|
||||
'toolbar1' => 'formatselect,bold,italic,underline,strikethrough,blockquote,bullist,numlist,alignleft,aligncenter,alignright,link,unlink,wp_more,fullscreen',
|
||||
'toolbar2' => 'pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',
|
||||
'plugins' => 'paste,link,lists,fullscreen,wordpress,wplink,charmap',
|
||||
],
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══ Sidebar panels ═══ -->
|
||||
<div class="aksrt-forum-compose__sidebar">
|
||||
|
||||
<!-- Panel: Submit -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-save"></i> <?php esc_html_e('保存', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__actions">
|
||||
<button type="submit" class="aksrt-forum-compose__submit" id="compose-submit">
|
||||
<i class="fas fa-save"></i> <?php esc_html_e('保存修改', 'aksrt'); ?>
|
||||
</button>
|
||||
<a href="<?php echo esc_url(get_permalink($topic_id)); ?>" class="aksrt-forum-compose__draft">
|
||||
<?php esc_html_e('取消', 'aksrt'); ?>
|
||||
</a>
|
||||
</div>
|
||||
<span class="aksrt-forum-compose__feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Board (read-only in edit mode) -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-th-large"></i> <?php esc_html_e('版块', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<p class="aksrt-forum-compose__readonly"><?php echo esc_html($board_name ?: __('未分配', 'aksrt')); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Type & Classification -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-tag"></i> <?php esc_html_e('类型 & 分类', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-bbs-type"><?php esc_html_e('帖子类型', 'aksrt'); ?></label>
|
||||
<select id="compose-bbs-type" name="bbs_type">
|
||||
<option value="standard" <?php selected($bbs_type, 'standard'); ?>><?php esc_html_e('标准帖子', 'aksrt'); ?></option>
|
||||
<option value="question" <?php selected($bbs_type, 'question'); ?>><?php esc_html_e('提问', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-special"><?php esc_html_e('专题/系列', 'aksrt'); ?></label>
|
||||
<input type="text" id="compose-special" name="special_topic" maxlength="80"
|
||||
value="<?php echo esc_attr($special_topic); ?>">
|
||||
</div>
|
||||
|
||||
<?php if (taxonomy_exists('aksrt_forum_topic_cat')) : ?>
|
||||
<div class="aksrt-forum-compose__field aksrt-remote-select" data-search-action="aksrt_forum_search_topics">
|
||||
<label><?php esc_html_e('话题', 'aksrt'); ?></label>
|
||||
<input type="hidden" name="topic_cat" value="<?php echo esc_attr($topic_cat); ?>">
|
||||
<input type="text" class="aksrt-remote-select__input js-aksrt-remote-input"
|
||||
placeholder="<?php esc_attr_e('搜索话题…', 'aksrt'); ?>"
|
||||
autocomplete="off"
|
||||
value="<?php echo esc_attr($topic_cat); ?>">
|
||||
<div class="aksrt-remote-select__dropdown" hidden></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Tags -->
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-tags"></i> <?php esc_html_e('标签', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field aksrt-tag-input" data-search-action="aksrt_forum_search_tags" data-max="5">
|
||||
<input type="hidden" id="compose-tags" name="tags" value="<?php echo esc_attr($tag_str); ?>">
|
||||
<div class="aksrt-tag-input__tokens" id="compose-tag-tokens"></div>
|
||||
<input type="text" class="aksrt-tag-input__input js-aksrt-tag-search"
|
||||
placeholder="<?php esc_attr_e('输入标签名,回车添加', 'aksrt'); ?>"
|
||||
autocomplete="off" maxlength="30">
|
||||
<div class="aksrt-tag-input__dropdown" hidden></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Visibility -->
|
||||
<?php if (!empty($caps['can_set_visibility'])) : ?>
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-eye"></i> <?php esc_html_e('可见性', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<select id="compose-visibility" name="visibility">
|
||||
<?php foreach ($visibility_options as $option) : ?>
|
||||
<option value="<?php echo esc_attr((string) ($option['value'] ?? '')); ?>"
|
||||
<?php selected($visibility, $option['value'] ?? ''); ?>>
|
||||
<?php echo esc_html((string) ($option['label'] ?? '')); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__visibility-extra" id="compose-credits-cost-field" style="display:none;">
|
||||
<label for="compose-credits-cost"><?php esc_html_e('积分价格', 'aksrt'); ?></label>
|
||||
<input type="number" id="compose-credits-cost" name="credits_cost" min="1" max="99999"
|
||||
value="<?php echo esc_attr((string) $credits_cost); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__visibility-extra" id="compose-pay-price-field" style="display:none;">
|
||||
<label for="compose-pay-price"><?php esc_html_e('付费价格(¥)', 'aksrt'); ?></label>
|
||||
<input type="number" id="compose-pay-price" name="pay_price" min="0.01" step="0.01" max="99999"
|
||||
value="<?php echo esc_attr($pay_price); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__visibility-extra" id="compose-role-field" style="display:none;">
|
||||
<label for="compose-visibility-roles"><?php esc_html_e('允许的角色', 'aksrt'); ?></label>
|
||||
<select id="compose-visibility-roles" name="visibility_roles[]" multiple>
|
||||
<?php foreach (wp_roles()->get_names() as $role_slug => $role_name) : ?>
|
||||
<option value="<?php echo esc_attr($role_slug); ?>"
|
||||
<?php echo in_array($role_slug, $visibility_roles, true) ? 'selected' : ''; ?>>
|
||||
<?php echo esc_html(translate_user_role($role_name)); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Panel: Cover -->
|
||||
<?php if (!empty($caps['can_set_cover'])) : ?>
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title"><i class="fas fa-image"></i> <?php esc_html_e('封面', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-forum-compose__panel-body">
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<select id="compose-cover-type" name="cover_type">
|
||||
<option value="" <?php selected($cover_type, ''); ?>><?php esc_html_e('无封面', 'aksrt'); ?></option>
|
||||
<?php if (!empty($caps['can_set_cover_image'])) : ?>
|
||||
<option value="image" <?php selected($cover_type, 'image'); ?>><?php esc_html_e('图片封面', 'aksrt'); ?></option>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($caps['can_set_cover_slide'])) : ?>
|
||||
<option value="slide" <?php selected($cover_type, 'slide'); ?>><?php esc_html_e('幻灯片封面', 'aksrt'); ?></option>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($caps['can_set_cover_video'])) : ?>
|
||||
<option value="video" <?php selected($cover_type, 'video'); ?>><?php esc_html_e('视频封面', 'aksrt'); ?></option>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__cover-upload" id="compose-cover-image-field" style="display:none;">
|
||||
<input type="hidden" name="cover_image" id="compose-cover-image" value="<?php echo esc_attr($cover_image); ?>">
|
||||
<div class="aksrt-forum-compose__cover-preview" id="compose-cover-preview">
|
||||
<?php if ($cover_image) : ?>
|
||||
<img src="<?php echo esc_url($cover_image); ?>" alt="">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<button type="button" class="aksrt-forum-compose__cover-btn" id="compose-cover-upload-btn"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__cover-upload" id="compose-cover-slide-field" style="display:none;">
|
||||
<input type="hidden" name="featured_slide" id="compose-featured-slide"
|
||||
value="<?php echo esc_attr(is_array($featured_slide) && !empty($featured_slide) ? wp_json_encode($featured_slide) : ''); ?>">
|
||||
<div class="aksrt-forum-compose__cover-preview" id="compose-slide-preview">
|
||||
<?php if (is_array($featured_slide)) : foreach ($featured_slide as $su) : ?>
|
||||
<img src="<?php echo esc_url($su); ?>" alt="">
|
||||
<?php endforeach; endif; ?>
|
||||
</div>
|
||||
<button type="button" class="aksrt-forum-compose__cover-btn" id="compose-slide-upload-btn"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__cover-upload" id="compose-cover-video-field" style="display:none;">
|
||||
<input type="url" name="featured_video" id="compose-featured-video"
|
||||
value="<?php echo esc_attr($featured_video); ?>"
|
||||
placeholder="<?php esc_attr_e('https://...mp4', 'aksrt'); ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Panel: Vote -->
|
||||
<?php if (!empty($caps['can_set_vote'])) : ?>
|
||||
<div class="aksrt-forum-compose__panel">
|
||||
<h3 class="aksrt-forum-compose__panel-title">
|
||||
<label class="aksrt-forum-compose__checkbox">
|
||||
<input type="checkbox" id="compose-vote-enabled" name="vote_enabled" value="1"
|
||||
<?php checked($vote_enabled); ?>>
|
||||
<span><i class="fas fa-poll"></i> <?php esc_html_e('投票', 'aksrt'); ?></span>
|
||||
</label>
|
||||
</h3>
|
||||
<div class="aksrt-forum-compose__panel-body aksrt-forum-compose__vote-fields" <?php echo !$vote_enabled ? 'hidden' : ''; ?>>
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-vote-title"><?php esc_html_e('投票标题', 'aksrt'); ?></label>
|
||||
<input type="text" id="compose-vote-title" name="vote_title" maxlength="120"
|
||||
value="<?php echo esc_attr($vote_title); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label class="aksrt-forum-compose__checkbox">
|
||||
<input type="checkbox" id="compose-vote-multiple" name="vote_multiple" value="1"
|
||||
<?php checked($vote_multiple); ?>>
|
||||
<span><?php esc_html_e('允许多选', 'aksrt'); ?></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-vote-type"><?php esc_html_e('投票类型', 'aksrt'); ?></label>
|
||||
<select id="compose-vote-type" name="vote_type">
|
||||
<option value="standard" <?php selected($vote_type, 'standard'); ?>><?php esc_html_e('标准投票', 'aksrt'); ?></option>
|
||||
<option value="pk" <?php selected($vote_type, 'pk'); ?>><?php esc_html_e('PK 双选', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-vote-expiry"><?php esc_html_e('投票有效期', 'aksrt'); ?></label>
|
||||
<select id="compose-vote-expiry" name="vote_expiry_days">
|
||||
<option value="0" <?php selected($vote_expiry_days, 0); ?>><?php esc_html_e('永久', 'aksrt'); ?></option>
|
||||
<option value="1" <?php selected($vote_expiry_days, 1); ?>><?php esc_html_e('1 天', 'aksrt'); ?></option>
|
||||
<option value="7" <?php selected($vote_expiry_days, 7); ?>><?php esc_html_e('7 天', 'aksrt'); ?></option>
|
||||
<option value="30" <?php selected($vote_expiry_days, 30); ?>><?php esc_html_e('30 天', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-compose__field">
|
||||
<label for="compose-vote-options"><?php printf(esc_html__('选项(最多 %d 项)', 'aksrt'), (int) $vote_max); ?></label>
|
||||
<textarea id="compose-vote-options" name="vote_options" rows="4"><?php echo esc_textarea($vote_options_text); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div><!-- /.aksrt-forum-compose__sidebar -->
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/**
|
||||
* Plate category (分区) archive template.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
$term = get_queried_object();
|
||||
$cat_id = $term ? (int) $term->term_id : 0;
|
||||
|
||||
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
|
||||
$forum_names = $forum_settings['names'] ?? [];
|
||||
$forum_name = $forum_names['forum'] ?? __('论坛', 'aksrt');
|
||||
|
||||
$plates = [];
|
||||
if ($forum && $cat_id > 0) {
|
||||
$plates = $forum->get_sorted_plates('menu_order', 'ASC', 100);
|
||||
$plates = array_filter($plates, static function ($plate) use ($cat_id): bool {
|
||||
return isset($plate['plate_cat']['id']) && (int) $plate['plate_cat']['id'] === $cat_id;
|
||||
});
|
||||
$plates = array_values($plates);
|
||||
}
|
||||
|
||||
$cat_moderator_ids = get_term_meta($cat_id, '_aksrt_cat_moderator', true);
|
||||
$cat_moderators = [];
|
||||
if (is_array($cat_moderator_ids)) {
|
||||
foreach ($cat_moderator_ids as $uid) {
|
||||
$user = get_userdata((int) $uid);
|
||||
if ($user) {
|
||||
$cat_moderators[] = [
|
||||
'id' => (int) $user->ID,
|
||||
'name' => $user->display_name,
|
||||
'avatar' => function_exists('aksrt_get_avatar_url') ? aksrt_get_avatar_url($user->ID, 36) : get_avatar_url($user->ID, ['size' => 36]),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
|
||||
|
||||
<div class="aksrt-forum-plate-cat container">
|
||||
<div class="aksrt-forum-plate-cat__header">
|
||||
<h1><?php echo esc_html($term ? $term->name : ''); ?></h1>
|
||||
<?php if ($term && $term->description) : ?>
|
||||
<p><?php echo esc_html($term->description); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($cat_moderators)) : ?>
|
||||
<div class="aksrt-forum-plate-cat__moderators">
|
||||
<span><?php esc_html_e('分区版主:', 'aksrt'); ?></span>
|
||||
<?php foreach ($cat_moderators as $mod) : ?>
|
||||
<span class="aksrt-forum-plate-cat__moderator">
|
||||
<?php if (!empty($mod['avatar'])) : ?>
|
||||
<img src="<?php echo esc_url($mod['avatar']); ?>" alt="" width="24" height="24">
|
||||
<?php endif; ?>
|
||||
<?php echo esc_html($mod['name']); ?>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-plate-cat__plates">
|
||||
<?php if (!empty($plates)) : ?>
|
||||
<?php foreach ($plates as $plate) : ?>
|
||||
<a href="<?php echo esc_url((string) ($plate['url'] ?? '#')); ?>" class="aksrt-forum-plate-cat__plate-card">
|
||||
<?php if (!empty($plate['cover_url'])) : ?>
|
||||
<img class="aksrt-forum-plate-cat__plate-cover" src="<?php echo esc_url($plate['cover_url']); ?>" alt="" loading="lazy">
|
||||
<?php elseif (!empty($plate['icon'])) : ?>
|
||||
<div class="aksrt-forum-plate-cat__plate-icon"><i class="<?php echo esc_attr($plate['icon']); ?>"></i></div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-forum-plate-cat__plate-info">
|
||||
<h3><?php echo esc_html((string) ($plate['name'] ?? '')); ?></h3>
|
||||
<p><?php echo esc_html((string) ($plate['description'] ?? '')); ?></p>
|
||||
<div class="aksrt-forum-plate-cat__plate-meta">
|
||||
<span><?php printf(esc_html__('%d 主题', 'aksrt'), (int) ($plate['post_count'] ?? 0)); ?></span>
|
||||
<span><?php printf(esc_html__('%d 关注', 'aksrt'), (int) ($plate['follow_count'] ?? 0)); ?></span>
|
||||
<?php if (!empty($plate['is_hot'])) : ?>
|
||||
<span class="aksrt-forum-plate-cat__hot-badge"><?php esc_html_e('热门', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum-plate-cat__empty">
|
||||
<p><?php esc_html_e('该分区暂无版块。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-plate-cat__back">
|
||||
<a href="<?php echo esc_url(home_url('/forums/')); ?>">
|
||||
<i class="fas fa-arrow-left"></i> <?php printf(esc_html__('返回%s', 'aksrt'), esc_html($forum_name)); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,312 @@
|
||||
<?php
|
||||
/**
|
||||
* Plate CPT single template (§7.2 板块独立页面).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
$current_user_id = get_current_user_id();
|
||||
$plate_id = get_queried_object_id();
|
||||
$paged = max(1, (int) get_query_var('paged', 1));
|
||||
|
||||
$view = $forum ? $forum->get_board_view($plate_id, [
|
||||
'user_id' => $current_user_id,
|
||||
'paged' => $paged,
|
||||
]) : [
|
||||
'board' => null,
|
||||
'topics' => [],
|
||||
'sticky_topics' => [],
|
||||
'moderators' => [],
|
||||
'pagination' => ['page' => 1, 'max_pages' => 1, 'total' => 0],
|
||||
'permissions' => [],
|
||||
'application' => null,
|
||||
'board_options' => [],
|
||||
];
|
||||
|
||||
$board_data = $view['board'] ?? null;
|
||||
$topics = $view['topics'] ?? [];
|
||||
$sticky_topics = $view['sticky_topics'] ?? [];
|
||||
$moderators = $view['moderators'] ?? [];
|
||||
$permissions = $view['permissions'] ?? [];
|
||||
$application = $view['application'] ?? null;
|
||||
$compose_url = add_query_arg('board', $plate_id, home_url('/compose/'));
|
||||
|
||||
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
|
||||
$forum_names = $forum_settings['names'] ?? [];
|
||||
$name_topic = $forum_names['posts'] ?? __('主题', 'aksrt');
|
||||
$name_reply = $forum_names['comment'] ?? __('回复', 'aksrt');
|
||||
$is_followed = $forum && $current_user_id > 0 ? $forum->is_user_following_plate($current_user_id, $plate_id) : false;
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
|
||||
|
||||
<?php if (!empty($permissions['access_denied'])) : ?>
|
||||
<div class="aksrt-forum-board container">
|
||||
<div class="aksrt-forum-board__access-denied">
|
||||
<i class="fas fa-lock"></i>
|
||||
<h2><?php esc_html_e('访问受限', 'aksrt'); ?></h2>
|
||||
<p><?php
|
||||
$reason = $permissions['access_reason'] ?? 'login';
|
||||
if ($reason === 'login') {
|
||||
esc_html_e('请登录后访问此版块。', 'aksrt');
|
||||
} elseif ($reason === 'follow') {
|
||||
esc_html_e('请先关注此版块后才能浏览内容。', 'aksrt');
|
||||
} elseif ($reason === 'role') {
|
||||
esc_html_e('你当前的角色无权访问此版块。', 'aksrt');
|
||||
}
|
||||
?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
|
||||
<div class="aksrt-forum-board container">
|
||||
<div class="aksrt-forum-board__header">
|
||||
<div class="aksrt-forum-board__info">
|
||||
<?php if (!empty($board_data['cover_url'])) : ?>
|
||||
<img class="aksrt-forum-board__cover" src="<?php echo esc_url((string) $board_data['cover_url']); ?>" alt="" loading="lazy">
|
||||
<?php endif; ?>
|
||||
<h1 class="aksrt-forum-board__title"><?php echo esc_html((string) ($board_data['name'] ?? '')); ?></h1>
|
||||
<?php if (!empty($board_data['description'])) : ?>
|
||||
<p class="aksrt-forum-board__desc"><?php echo esc_html((string) $board_data['description']); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-forum-board__meta">
|
||||
<span><i class="fas fa-list-alt"></i> <?php printf(esc_html__('%1$d 个%2$s', 'aksrt'), (int) ($board_data['post_count'] ?? $board_data['topic_count'] ?? 0), esc_html($name_topic)); ?></span>
|
||||
<span><i class="fas fa-comments"></i> <?php printf(esc_html__('%d 条%s', 'aksrt'), (int) ($board_data['reply_count'] ?? 0), esc_html($name_reply)); ?></span>
|
||||
<span><i class="fas fa-eye"></i> <?php printf(esc_html__('%d 浏览', 'aksrt'), (int) ($board_data['views'] ?? 0)); ?></span>
|
||||
<span><i class="fas fa-heart"></i> <?php printf(esc_html__('%d 关注', 'aksrt'), (int) ($board_data['follow_count'] ?? 0)); ?></span>
|
||||
<span><i class="fas fa-shield-alt"></i> <?php printf(esc_html__('%d 位版主', 'aksrt'), count($moderators)); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-board__actions">
|
||||
<?php if ($current_user_id > 0) : ?>
|
||||
<button type="button"
|
||||
class="aksrt-forum-board__follow-btn js-aksrt-follow-plate"
|
||||
data-plate-id="<?php echo esc_attr((string) $plate_id); ?>"
|
||||
data-followed="<?php echo $is_followed ? '1' : '0'; ?>">
|
||||
<i class="fas <?php echo $is_followed ? 'fa-heart' : 'fa-heart'; ?>"></i>
|
||||
<?php echo $is_followed ? esc_html__('已关注', 'aksrt') : esc_html__('关注', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($permissions['can_compose'])) : ?>
|
||||
<a href="<?php echo esc_url($compose_url); ?>" class="aksrt-forum-board__compose-btn">
|
||||
<i class="fas fa-pen"></i>
|
||||
<?php esc_html_e('发布新主题', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
$is_forum_admin = $forum && $forum->is_forum_admin($current_user_id);
|
||||
$is_plate_author = $board_data && (int) ($board_data['author_id'] ?? 0) === $current_user_id;
|
||||
?>
|
||||
<?php if ($is_forum_admin || $is_plate_author) : ?>
|
||||
<button type="button" class="aksrt-forum-board__manage-btn js-aksrt-edit-plate"
|
||||
data-plate-id="<?php echo esc_attr((string) $plate_id); ?>"
|
||||
data-name="<?php echo esc_attr((string) ($board_data['name'] ?? '')); ?>"
|
||||
data-description="<?php echo esc_attr((string) ($board_data['description'] ?? '')); ?>"
|
||||
data-icon="<?php echo esc_attr((string) ($board_data['icon'] ?? '')); ?>"
|
||||
data-cover="<?php echo esc_attr((string) ($board_data['cover_url'] ?? '')); ?>">
|
||||
<i class="fas fa-cog"></i> <?php esc_html_e('编辑版块', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if ($is_forum_admin) : ?>
|
||||
<button type="button" class="aksrt-forum-board__manage-btn aksrt-forum-board__manage-btn--danger js-aksrt-delete-plate"
|
||||
data-plate-id="<?php echo esc_attr((string) $plate_id); ?>"
|
||||
data-topic-count="<?php echo esc_attr((string) ($board_data['post_count'] ?? $board_data['topic_count'] ?? 0)); ?>">
|
||||
<i class="fas fa-trash-alt"></i> <?php esc_html_e('删除版块', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($board_data['content'])) : ?>
|
||||
<div class="aksrt-forum-board__content entry-content">
|
||||
<?php echo wp_kses_post((string) $board_data['content']); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<section class="aksrt-forum-board__governance">
|
||||
<div class="aksrt-forum-board__governance-card">
|
||||
<h2 class="aksrt-forum-board__section-title"><?php esc_html_e('版主团队', 'aksrt'); ?></h2>
|
||||
<?php if (!empty($moderators)) : ?>
|
||||
<div class="aksrt-forum-board__moderators">
|
||||
<?php foreach ($moderators as $moderator) : ?>
|
||||
<div class="aksrt-forum-board__moderator">
|
||||
<?php if (!empty($moderator['avatar'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $moderator['avatar']); ?>" alt="" width="36" height="36">
|
||||
<?php endif; ?>
|
||||
<span><?php echo esc_html((string) ($moderator['name'] ?? $moderator['display_name'] ?? '')); ?></span>
|
||||
<?php if (!empty($moderator['role'])) : ?>
|
||||
<small class="aksrt-forum-board__moderator-role"><?php echo esc_html((string) $moderator['role']); ?></small>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p><?php esc_html_e('当前还没有设置版主。', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-board__governance-card">
|
||||
<h2 class="aksrt-forum-board__section-title"><?php esc_html_e('版主申请', 'aksrt'); ?></h2>
|
||||
<?php if (!is_user_logged_in()) : ?>
|
||||
<p class="aksrt-forum-board__application-note"><?php esc_html_e('登录后可申请协助管理本版块。', 'aksrt'); ?></p>
|
||||
<a href="<?php echo esc_url(wp_login_url(get_permalink())); ?>" class="aksrt-forum-board__apply-btn"><?php esc_html_e('登录后申请', 'aksrt'); ?></a>
|
||||
<?php elseif (!empty($application)) : ?>
|
||||
<p class="aksrt-forum-board__application-note">
|
||||
<?php printf(
|
||||
esc_html__('你最近一次申请状态:%s', 'aksrt'),
|
||||
esc_html((string) ($application['status_label'] ?? __('待处理', 'aksrt')))
|
||||
); ?>
|
||||
</p>
|
||||
<?php if (!empty($application['reason'])) : ?>
|
||||
<blockquote class="aksrt-forum-board__application-reason"><?php echo esc_html((string) $application['reason']); ?></blockquote>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($application['review_note'])) : ?>
|
||||
<p class="aksrt-forum-board__application-note"><?php printf(esc_html__('审核备注:%s', 'aksrt'), esc_html((string) $application['review_note'])); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if (($application['status'] ?? '') !== 'pending' && !empty($permissions['can_apply_moderator'])) : ?>
|
||||
<form class="aksrt-forum-board__application-form js-aksrt-moderator-apply-form" data-board-id="<?php echo esc_attr((string) $plate_id); ?>">
|
||||
<label for="aksrt-plate-apply-reason"><?php esc_html_e('重新申请理由', 'aksrt'); ?></label>
|
||||
<textarea id="aksrt-plate-apply-reason" name="reason" rows="4" placeholder="<?php esc_attr_e('请简要说明你的社区经验、擅长领域或管理计划。', 'aksrt'); ?>"></textarea>
|
||||
<div class="aksrt-forum-board__application-actions">
|
||||
<button type="submit" class="aksrt-forum-board__apply-btn"><?php esc_html_e('重新提交申请', 'aksrt'); ?></button>
|
||||
<span class="aksrt-forum-board__application-feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php elseif (!empty($permissions['can_apply_moderator'])) : ?>
|
||||
<p class="aksrt-forum-board__application-note"><?php esc_html_e('如果你熟悉本版块内容并愿意协助维护秩序,可以提交版主申请。', 'aksrt'); ?></p>
|
||||
<form class="aksrt-forum-board__application-form js-aksrt-moderator-apply-form" data-board-id="<?php echo esc_attr((string) $plate_id); ?>">
|
||||
<label for="aksrt-plate-apply-reason"><?php esc_html_e('申请理由', 'aksrt'); ?></label>
|
||||
<textarea id="aksrt-plate-apply-reason" name="reason" rows="4" placeholder="<?php esc_attr_e('请简要说明你的社区经验、擅长领域或管理计划。', 'aksrt'); ?>"></textarea>
|
||||
<div class="aksrt-forum-board__application-actions">
|
||||
<button type="submit" class="aksrt-forum-board__apply-btn"><?php esc_html_e('提交版主申请', 'aksrt'); ?></button>
|
||||
<span class="aksrt-forum-board__application-feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
</div>
|
||||
</form>
|
||||
<?php else : ?>
|
||||
<p class="aksrt-forum-board__application-note"><?php esc_html_e('你当前已是本版块管理成员,或暂不满足申请条件。', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php if (!empty($sticky_topics)) : ?>
|
||||
<div class="aksrt-forum-board__sticky">
|
||||
<h3><i class="fas fa-thumbtack"></i> <?php esc_html_e('置顶主题', 'aksrt'); ?></h3>
|
||||
<?php foreach ($sticky_topics as $topic) : ?>
|
||||
<a href="<?php echo esc_url((string) ($topic['permalink'] ?? '#')); ?>" class="aksrt-forum-board__sticky-item">
|
||||
<?php
|
||||
$sticky_label = (string) ($topic['sticky_label'] ?? __('置顶', 'aksrt'));
|
||||
?>
|
||||
<span class="aksrt-forum-board__sticky-badge"><?php echo esc_html($sticky_label); ?></span>
|
||||
<span class="aksrt-forum-board__sticky-title"><?php echo esc_html((string) ($topic['title'] ?? '')); ?></span>
|
||||
<span class="aksrt-forum-board__sticky-meta">
|
||||
<?php echo esc_html((string) ($topic['author']['display_name'] ?? '')); ?>
|
||||
· <?php echo esc_html((string) ($topic['date'] ?? '')); ?>
|
||||
</span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-forum-board__topics">
|
||||
<?php if (!empty($topics)) : ?>
|
||||
<?php foreach ($topics as $topic) : ?>
|
||||
<?php
|
||||
$topic_id = (int) ($topic['id'] ?? 0);
|
||||
$item_sticky_level = (int) ($topic['sticky_level'] ?? 0);
|
||||
$item_sticky_class = $item_sticky_level > 0
|
||||
? ' is-sticky is-sticky-' . $item_sticky_level
|
||||
: '';
|
||||
?>
|
||||
<article class="aksrt-forum-topic-item<?php echo esc_attr($item_sticky_class); ?><?php echo !empty($topic['featured']) ? ' is-featured' : ''; ?>">
|
||||
<div class="aksrt-forum-topic-item__avatar">
|
||||
<?php if (!empty($topic['author']['avatar_url'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $topic['author']['avatar_url']); ?>" alt="" width="40" height="40">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic-item__body">
|
||||
<div class="aksrt-forum-topic-item__title">
|
||||
<?php if (!empty($topic['featured'])) : ?>
|
||||
<span class="aksrt-forum-topic-item__badge aksrt-forum-topic-item__badge--featured"><?php esc_html_e('精华', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if (($topic['bbs_type'] ?? 'standard') === 'question') : ?>
|
||||
<?php $q_status = (int) ($topic['question_status'] ?? 0); ?>
|
||||
<span class="aksrt-forum-topic-item__badge aksrt-forum-topic-item__badge--question<?php echo $q_status === 1 ? ' aksrt-forum-topic-item__badge--solved' : ''; ?>">
|
||||
<?php echo $q_status === 1 ? esc_html__('已解决', 'aksrt') : esc_html__('提问', 'aksrt'); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<a href="<?php echo esc_url((string) ($topic['permalink'] ?? '#')); ?>"><?php echo esc_html((string) ($topic['title'] ?? '')); ?></a>
|
||||
</div>
|
||||
<div class="aksrt-forum-topic-item__meta">
|
||||
<span><?php echo esc_html((string) ($topic['author']['display_name'] ?? '')); ?></span>
|
||||
<span><?php echo esc_html((string) ($topic['date'] ?? '')); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($topic['cover'])) : ?>
|
||||
<div class="aksrt-forum-topic-item__cover">
|
||||
<?php if ($topic['cover']['type'] === 'video') : ?>
|
||||
<div class="aksrt-forum-topic-item__cover-video">
|
||||
<?php if (!empty($topic['cover']['poster'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $topic['cover']['poster']); ?>" alt="" loading="lazy">
|
||||
<?php endif; ?>
|
||||
<i class="fas fa-play-circle"></i>
|
||||
</div>
|
||||
<?php elseif ($topic['cover']['type'] === 'slide') : ?>
|
||||
<div class="aksrt-forum-topic-item__cover-slide">
|
||||
<?php if (!empty($topic['cover']['images'][0])) : ?>
|
||||
<img src="<?php echo esc_url((string) $topic['cover']['images'][0]); ?>" alt="" loading="lazy">
|
||||
<?php endif; ?>
|
||||
<span class="aksrt-forum-topic-item__cover-count"><i class="fas fa-images"></i> <?php echo count($topic['cover']['images']); ?></span>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<img src="<?php echo esc_url((string) ($topic['cover']['url'] ?? '')); ?>" alt="" loading="lazy">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-forum-topic-item__stats">
|
||||
<span title="<?php echo esc_attr($name_reply); ?>"><i class="fas fa-comment"></i> <?php echo esc_html(number_format_i18n((int) ($topic['comment_count'] ?? 0))); ?></span>
|
||||
<span title="<?php esc_attr_e('浏览', 'aksrt'); ?>"><i class="fas fa-eye"></i> <?php echo esc_html(number_format_i18n((int) ($topic['views'] ?? 0))); ?></span>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (($view['pagination']['max_pages'] ?? 1) > 1) : ?>
|
||||
<div class="aksrt-forum-board__pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'total' => (int) ($view['pagination']['max_pages'] ?? 1),
|
||||
'current' => $paged,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum-board__empty">
|
||||
<i class="fas fa-comments"></i>
|
||||
<p><?php esc_html_e('当前版块还没有公开主题。', 'aksrt'); ?></p>
|
||||
<?php if (!empty($permissions['can_compose'])) : ?>
|
||||
<a href="<?php echo esc_url($compose_url); ?>"><?php esc_html_e('发布第一个主题', 'aksrt'); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* 论坛标签归档模板
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$term = get_queried_object();
|
||||
$paged = max(1, (int) get_query_var('paged'));
|
||||
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
$view = $forum ? $forum->get_tag_archive_view([
|
||||
'term_id' => $term->term_id,
|
||||
'paged' => $paged,
|
||||
]) : ['topics' => [], 'term' => null, 'total' => 0, 'max_pages' => 0];
|
||||
|
||||
$topics = $view['topics'];
|
||||
$total = $view['total'];
|
||||
$max_pages = $view['max_pages'];
|
||||
$term_name = $term->name ?? '';
|
||||
$term_desc = $term->description ?? '';
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main container" tabindex="-1">
|
||||
|
||||
<div class="aksrt-forum-tag container">
|
||||
<header class="aksrt-forum-tag__header">
|
||||
<h1 class="aksrt-forum-tag__title">
|
||||
<i class="fas fa-tag"></i>
|
||||
<?php echo esc_html($term_name); ?>
|
||||
</h1>
|
||||
<?php if ($term_desc) : ?>
|
||||
<p class="aksrt-forum-tag__desc"><?php echo esc_html($term_desc); ?></p>
|
||||
<?php endif; ?>
|
||||
<p class="aksrt-forum-tag__count"><?php printf(esc_html__('共 %d 个话题', 'aksrt'), $total); ?></p>
|
||||
</header>
|
||||
|
||||
<?php if (!empty($topics)) : ?>
|
||||
<div class="aksrt-forum-tag__list">
|
||||
<?php foreach ($topics as $topic) : ?>
|
||||
<article class="aksrt-forum-topic-card">
|
||||
<div class="aksrt-forum-topic-card__body">
|
||||
<h3 class="aksrt-forum-topic-card__title">
|
||||
<a href="<?php echo esc_url($topic['permalink']); ?>"><?php echo esc_html($topic['title']); ?></a>
|
||||
</h3>
|
||||
<?php if ($topic['excerpt']) : ?>
|
||||
<p class="aksrt-forum-topic-card__excerpt"><?php echo esc_html(wp_trim_words($topic['excerpt'], 30)); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-forum-topic-card__meta">
|
||||
<span class="aksrt-forum-topic-card__author">
|
||||
<i class="fas fa-user"></i> <?php echo esc_html($topic['author']); ?>
|
||||
</span>
|
||||
<span class="aksrt-forum-topic-card__date">
|
||||
<i class="fas fa-clock"></i> <?php echo esc_html($topic['date']); ?>
|
||||
</span>
|
||||
<span class="aksrt-forum-topic-card__comments">
|
||||
<i class="fas fa-comment"></i> <?php echo (int) $topic['comment_count']; ?>
|
||||
</span>
|
||||
<span class="aksrt-forum-topic-card__views">
|
||||
<i class="fas fa-eye"></i> <?php echo (int) $topic['views']; ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($max_pages > 1) : ?>
|
||||
<nav class="aksrt-forum-tag__pagination" aria-label="<?php esc_attr_e('话题分页', 'aksrt'); ?>">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'total' => $max_pages,
|
||||
'current' => $paged,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum-tag__empty">
|
||||
<i class="fas fa-comments"></i>
|
||||
<p><?php esc_html_e('该标签下暂无话题', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,635 @@
|
||||
<?php
|
||||
/**
|
||||
* Forum topic template.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
if (!have_posts()) {
|
||||
get_template_part('templates/parts/content', 'none');
|
||||
get_footer();
|
||||
return;
|
||||
}
|
||||
|
||||
the_post();
|
||||
|
||||
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
$current_user_id = get_current_user_id();
|
||||
$topic_id = get_the_ID();
|
||||
$view = $forum ? $forum->get_topic_view($topic_id, $current_user_id) : [
|
||||
'topic' => null,
|
||||
'board' => null,
|
||||
'permissions' => [],
|
||||
'board_options' => [],
|
||||
'visibility_options' => [],
|
||||
'review_options' => [],
|
||||
];
|
||||
|
||||
$topic = $view['topic'] ?? null;
|
||||
$board = $view['board'] ?? null;
|
||||
$permissions = $view['permissions'] ?? [];
|
||||
$board_options = $view['board_options'] ?? [];
|
||||
$visibility_options = $view['visibility_options'] ?? [];
|
||||
$review_options = $view['review_options'] ?? [];
|
||||
|
||||
// Forum settings for names, breadcrumbs, reply
|
||||
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
|
||||
$forum_names = $forum_settings['names'] ?? [];
|
||||
$forum_bc = $forum_settings['post_page'] ?? [];
|
||||
$reply_settings = $forum_settings['reply'] ?? [];
|
||||
$show_breadcrumbs = $forum_bc['breadcrumbs'] ?? true;
|
||||
$bc_show_home = $forum_bc['breadcrumbs_bbs_home'] ?? true;
|
||||
$bc_forum_name = $forum_bc['breadcrumbs_bbs_home_name'] ?: ($forum_names['forum'] ?? __('论坛', 'aksrt'));
|
||||
$reply_placeholder = $reply_settings['placeholder'] ?? __('写下你的回复…', 'aksrt');
|
||||
$name_sticky = $forum_names['posts'] ?? __('置顶', 'aksrt');
|
||||
$name_featured = $forum_names['topic'] ?? __('精华', 'aksrt');
|
||||
$name_reply = $forum_names['comment'] ?? __('回复', 'aksrt');
|
||||
|
||||
if (!$topic) {
|
||||
get_template_part('templates/parts/content', 'none');
|
||||
get_footer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($topic['can_view'])) :
|
||||
$deny_vis = $topic['visibility']['key'] ?? '';
|
||||
$credits_cost = (int) get_post_meta($topic_id, '_aksrt_credits_cost', true);
|
||||
$pay_price = get_post_meta($topic_id, '_aksrt_pay_price', true);
|
||||
?>
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<div class="aksrt-forum-topic container">
|
||||
<div class="aksrt-forum-topic__denied">
|
||||
<i class="fas fa-eye-slash"></i>
|
||||
<h1><?php esc_html_e('当前主题暂不可访问', 'aksrt'); ?></h1>
|
||||
<?php if ($deny_vis === 'login') : ?>
|
||||
<p><?php esc_html_e('该主题仅限登录用户查看,请先登录后重试。', 'aksrt'); ?></p>
|
||||
<a href="<?php echo esc_url(wp_login_url(get_permalink($topic_id))); ?>" class="aksrt-forum-topic__primary-btn"><?php esc_html_e('登录查看', 'aksrt'); ?></a>
|
||||
<?php elseif ($deny_vis === 'comment') : ?>
|
||||
<p><?php esc_html_e('评论后即可查看该主题的完整内容。', 'aksrt'); ?></p>
|
||||
<?php elseif ($deny_vis === 'role') : ?>
|
||||
<p><?php esc_html_e('你当前的角色无权查看此主题。', 'aksrt'); ?></p>
|
||||
<?php elseif ($deny_vis === 'credits' && $credits_cost > 0) : ?>
|
||||
<p><?php printf(esc_html__('查看该主题需要 %d 积分。', 'aksrt'), $credits_cost); ?></p>
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<button type="button" class="aksrt-forum-topic__primary-btn js-aksrt-unlock-topic"
|
||||
data-topic-id="<?php echo esc_attr((string) $topic_id); ?>"
|
||||
data-cost="<?php echo esc_attr((string) $credits_cost); ?>">
|
||||
<i class="fas fa-unlock"></i> <?php printf(esc_html__('使用 %d 积分解锁', 'aksrt'), $credits_cost); ?>
|
||||
</button>
|
||||
<span class="aksrt-forum-topic__unlock-feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url(wp_login_url(get_permalink($topic_id))); ?>" class="aksrt-forum-topic__primary-btn"><?php esc_html_e('登录后解锁', 'aksrt'); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php elseif ($deny_vis === 'pay') : ?>
|
||||
<p><?php esc_html_e('该主题为付费内容,请购买后查看。', 'aksrt'); ?></p>
|
||||
<?php if (!empty($pay_price)) : ?>
|
||||
<span class="aksrt-forum-topic__pay-price"><?php printf(esc_html__('价格:¥%s', 'aksrt'), esc_html((string) $pay_price)); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<p><?php esc_html_e('该主题当前处于受限可见或审核状态。', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<?php
|
||||
get_footer();
|
||||
return;
|
||||
endif;
|
||||
|
||||
if ($forum) {
|
||||
$forum->increment_view_count($topic_id);
|
||||
$topic['views'] = (int) ($topic['views'] ?? 0) + 1;
|
||||
}
|
||||
|
||||
$is_locked = !empty($topic['locked']);
|
||||
$comments_enabled = !empty($permissions['can_reply']);
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main container" tabindex="-1">
|
||||
|
||||
<div class="aksrt-forum-topic container">
|
||||
<?php if ($show_breadcrumbs) : ?>
|
||||
<div class="aksrt-forum-topic__breadcrumb">
|
||||
<?php if ($bc_show_home) : ?>
|
||||
<a href="<?php echo esc_url(home_url('/forums/')); ?>"><?php echo esc_html($bc_forum_name); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php if ($board) : ?>
|
||||
<?php if ($bc_show_home) : ?><span class="aksrt-forum-topic__sep">/</span><?php endif; ?>
|
||||
<a href="<?php echo esc_url((string) ($board['url'] ?? '#')); ?>"><?php echo esc_html((string) ($board['name'] ?? '')); ?></a>
|
||||
<?php endif; ?>
|
||||
<span class="aksrt-forum-topic__sep">/</span>
|
||||
<span><?php echo esc_html((string) ($topic['title'] ?? '')); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<header class="aksrt-forum-topic__header">
|
||||
<div class="aksrt-forum-topic__header-top">
|
||||
<h1 class="aksrt-forum-topic__title">
|
||||
<?php
|
||||
$sticky_level = (int) ($topic['sticky_level'] ?? 0);
|
||||
$sticky_label = (string) ($topic['sticky_label'] ?? '');
|
||||
if ($sticky_level > 0 && $sticky_label !== '') :
|
||||
$sticky_mod = $sticky_level >= 3 ? 'global' : ($sticky_level === 2 ? 'super' : 'plate');
|
||||
?>
|
||||
<span class="aksrt-forum-topic__badge aksrt-forum-topic__badge--sticky aksrt-forum-topic__badge--sticky-<?php echo esc_attr($sticky_mod); ?>">
|
||||
<?php echo esc_html($sticky_label); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($topic['featured'])) : ?><span class="aksrt-forum-topic__badge aksrt-forum-topic__badge--featured"><?php esc_html_e('精华', 'aksrt'); ?></span><?php endif; ?>
|
||||
<?php if ($is_locked) : ?><span class="aksrt-forum-topic__badge aksrt-forum-topic__badge--locked"><?php esc_html_e('已锁定', 'aksrt'); ?></span><?php endif; ?>
|
||||
<?php if (($topic['visibility']['key'] ?? 'public') !== 'public') : ?><span class="aksrt-forum-topic__badge aksrt-forum-topic__badge--visibility"><?php echo esc_html((string) ($topic['visibility']['label'] ?? '')); ?></span><?php endif; ?>
|
||||
<?php if (($topic['bbs_type'] ?? 'standard') === 'question') : ?>
|
||||
<?php $q_status = (int) ($topic['question_status'] ?? 0); ?>
|
||||
<span class="aksrt-forum-topic__badge aksrt-forum-topic__badge--question<?php echo $q_status === 1 ? ' aksrt-forum-topic__badge--solved' : ''; ?>">
|
||||
<?php echo $q_status === 1 ? esc_html($forum_names['question_ok_badge'] ?? __('已解决', 'aksrt')) : esc_html($forum_names['question_badge'] ?? __('提问', 'aksrt')); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php echo esc_html((string) ($topic['title'] ?? '')); ?>
|
||||
</h1>
|
||||
|
||||
<div class="aksrt-forum-topic__meta">
|
||||
<span class="aksrt-forum-topic__author">
|
||||
<?php if (!empty($topic['author']['avatar_url'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $topic['author']['avatar_url']); ?>" alt="" width="24" height="24">
|
||||
<?php endif; ?>
|
||||
<?php echo esc_html((string) ($topic['author']['display_name'] ?? '')); ?>
|
||||
</span>
|
||||
<span><i class="fas fa-clock"></i> <?php echo esc_html((string) ($topic['date'] ?? '')); ?></span>
|
||||
<span><i class="fas fa-eye"></i> <?php echo esc_html(number_format_i18n((int) ($topic['views'] ?? 0))); ?></span>
|
||||
<span><i class="fas fa-comment"></i> <?php echo esc_html(number_format_i18n((int) ($topic['comment_count'] ?? 0))); ?></span>
|
||||
<?php if (!empty($topic['review_status']['label'])) : ?>
|
||||
<span><i class="fas fa-shield-check"></i> <?php echo esc_html((string) $topic['review_status']['label']); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if (($topic['score'] ?? 0) !== 0) : ?>
|
||||
<span class="aksrt-forum-topic__score-badge"><i class="fas fa-star"></i> <?php echo esc_html(number_format_i18n((int) $topic['score'])); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if (($topic['favorite_count'] ?? 0) > 0) : ?>
|
||||
<span><i class="fas fa-bookmark"></i> <?php echo esc_html(number_format_i18n((int) $topic['favorite_count'])); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__quick-actions">
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<button type="button" class="aksrt-forum-topic__quick-action js-aksrt-report-trigger"
|
||||
data-target-type="post"
|
||||
data-target-id="<?php echo esc_attr((string) $topic_id); ?>"
|
||||
data-target-title="<?php echo esc_attr((string) ($topic['title'] ?? '')); ?>">
|
||||
<i class="far fa-flag"></i>
|
||||
<?php esc_html_e('举报', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<?php $is_fav = !empty($topic['is_favorited']); ?>
|
||||
<button type="button"
|
||||
class="aksrt-forum-topic__quick-action js-aksrt-topic-favorite"
|
||||
data-topic-id="<?php echo esc_attr((string) $topic_id); ?>"
|
||||
data-favorited="<?php echo $is_fav ? '1' : '0'; ?>">
|
||||
<i class="<?php echo $is_fav ? 'fas' : 'far'; ?> fa-bookmark"></i>
|
||||
<span class="js-aksrt-favorite-label"><?php echo $is_fav ? esc_html__('已收藏', 'aksrt') : esc_html__('收藏', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($permissions['can_edit'])) : ?>
|
||||
<a href="<?php echo esc_url(add_query_arg('edit', '1', get_permalink($topic_id))); ?>" class="aksrt-forum-topic__quick-action">
|
||||
<i class="fas fa-edit"></i>
|
||||
<?php esc_html_e('编辑主题', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($permissions['can_moderate'])) : ?>
|
||||
<a href="#aksrt-topic-moderation" class="aksrt-forum-topic__quick-action">
|
||||
<i class="fas fa-tools"></i>
|
||||
<?php esc_html_e('治理动作', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="aksrt-forum-report-modal" id="aksrt-report-modal" hidden>
|
||||
<div class="aksrt-forum-report-modal__backdrop js-aksrt-report-close"></div>
|
||||
<div class="aksrt-forum-report-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="aksrt-report-title">
|
||||
<div class="aksrt-forum-report-modal__head">
|
||||
<h2 id="aksrt-report-title"><?php esc_html_e('提交举报', 'aksrt'); ?></h2>
|
||||
<button type="button" class="aksrt-forum-report-modal__close js-aksrt-report-close" aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>">×</button>
|
||||
</div>
|
||||
<p class="aksrt-forum-report-modal__target js-aksrt-report-target"></p>
|
||||
<form class="aksrt-forum-report-modal__form js-aksrt-report-form">
|
||||
<input type="hidden" name="target_type" value="post">
|
||||
<input type="hidden" name="target_id" value="<?php echo esc_attr((string) $topic_id); ?>">
|
||||
<div class="aksrt-forum-topic__field">
|
||||
<label for="aksrt-report-category"><?php esc_html_e('举报分类', 'aksrt'); ?></label>
|
||||
<select id="aksrt-report-category" name="category">
|
||||
<option value="spam"><?php esc_html_e('垃圾信息', 'aksrt'); ?></option>
|
||||
<option value="abuse"><?php esc_html_e('人身攻击', 'aksrt'); ?></option>
|
||||
<option value="copyright"><?php esc_html_e('版权投诉', 'aksrt'); ?></option>
|
||||
<option value="other"><?php esc_html_e('其他问题', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="aksrt-forum-topic__field">
|
||||
<label for="aksrt-report-reason"><?php esc_html_e('举报说明', 'aksrt'); ?></label>
|
||||
<textarea id="aksrt-report-reason" name="reason" rows="4" required placeholder="<?php esc_attr_e('请尽量描述清楚问题,以便管理员处理。', 'aksrt'); ?>"></textarea>
|
||||
</div>
|
||||
<div class="aksrt-forum-report-modal__actions">
|
||||
<button type="submit" class="aksrt-forum-topic__primary-btn"><?php esc_html_e('提交举报', 'aksrt'); ?></button>
|
||||
<span class="aksrt-forum-report-modal__feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($topic['cover'])) : ?>
|
||||
<div class="aksrt-forum-topic__cover aksrt-forum-topic__cover--<?php echo esc_attr($topic['cover']['type']); ?>">
|
||||
<?php if ($topic['cover']['type'] === 'video') : ?>
|
||||
<div class="aksrt-forum-topic__cover-player" data-src="<?php echo esc_url((string) $topic['cover']['url']); ?>" data-poster="<?php echo esc_url((string) ($topic['cover']['poster'] ?? '')); ?>">
|
||||
<?php if (!empty($topic['cover']['poster'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $topic['cover']['poster']); ?>" alt="" class="aksrt-forum-topic__cover-poster">
|
||||
<?php endif; ?>
|
||||
<button type="button" class="aksrt-forum-topic__cover-play-btn"><i class="fas fa-play-circle"></i></button>
|
||||
</div>
|
||||
<?php elseif ($topic['cover']['type'] === 'slide') : ?>
|
||||
<div class="aksrt-forum-topic__cover-slides">
|
||||
<?php foreach (($topic['cover']['images'] ?? []) as $slide_url) : ?>
|
||||
<img src="<?php echo esc_url((string) $slide_url); ?>" alt="" loading="lazy">
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<img src="<?php echo esc_url((string) ($topic['cover']['url'] ?? '')); ?>" alt="" class="aksrt-forum-topic__cover-img">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($topic['special_topic']) || !empty($topic['tags']) || !empty($topic['topic_cat'])) : ?>
|
||||
<div class="aksrt-forum-topic__taxonomy">
|
||||
<?php if (!empty($topic['topic_cat'])) : ?>
|
||||
<a class="aksrt-forum-topic__chip aksrt-forum-topic__chip--topic-cat" href="<?php echo esc_url((string) ($topic['topic_cat']['url'] ?? '#')); ?>">
|
||||
<?php echo esc_html((string) ($topic['topic_cat']['name'] ?? '')); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($topic['special_topic'])) : ?>
|
||||
<span class="aksrt-forum-topic__chip aksrt-forum-topic__chip--special"><?php echo esc_html((string) $topic['special_topic']); ?></span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach (($topic['tags'] ?? []) as $tag) : ?>
|
||||
<a class="aksrt-forum-topic__chip" href="<?php echo esc_url((string) ($tag['url'] ?? '#')); ?>">
|
||||
#<?php echo esc_html((string) ($tag['name'] ?? '')); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<article class="aksrt-forum-topic__content">
|
||||
<?php the_content(); ?>
|
||||
</article>
|
||||
|
||||
<?php
|
||||
$score_extra_max = (int) ($forum_settings['post_page']['score_extra_max'] ?? 5);
|
||||
$score_deduct_max = (int) ($forum_settings['post_page']['score_deduct_max'] ?? 3);
|
||||
$current_score = (int) ($topic['score'] ?? 0);
|
||||
?>
|
||||
<?php if (is_user_logged_in() && (int) ($topic['author_id'] ?? 0) !== get_current_user_id()) : ?>
|
||||
<div class="aksrt-forum-topic__score-actions" data-topic-id="<?php echo esc_attr((string) $topic_id); ?>">
|
||||
<span class="aksrt-forum-topic__score-total">
|
||||
<i class="fas fa-star"></i>
|
||||
<span class="js-aksrt-score-value"><?php echo esc_html(number_format_i18n($current_score)); ?></span>
|
||||
<?php esc_html_e('分', 'aksrt'); ?>
|
||||
</span>
|
||||
<?php if ($score_extra_max > 0) : ?>
|
||||
<button type="button" class="aksrt-forum-topic__score-btn aksrt-forum-topic__score-btn--up js-aksrt-topic-score" data-amount="1" title="<?php esc_attr_e('加分', 'aksrt'); ?>">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if ($score_deduct_max > 0) : ?>
|
||||
<button type="button" class="aksrt-forum-topic__score-btn aksrt-forum-topic__score-btn--down js-aksrt-topic-score" data-amount="-1" title="<?php esc_attr_e('减分', 'aksrt'); ?>">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<span class="aksrt-forum-topic__score-feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($topic['vote']['enabled'])) : ?>
|
||||
<?php
|
||||
$vote_type = $topic['vote']['vote_type'] ?? 'standard';
|
||||
$vote_expired = !empty($topic['vote']['expired']);
|
||||
$vote_display = $topic['vote']['display_mode'] ?? 'percent';
|
||||
$vote_expiry = (int) ($topic['vote']['expiry_days'] ?? 0);
|
||||
$vote_disabled = $vote_expired || !empty($topic['vote']['has_voted']);
|
||||
?>
|
||||
<section class="aksrt-forum-topic__vote<?php echo $vote_type === 'pk' ? ' aksrt-forum-topic__vote--pk' : ''; ?><?php echo $vote_expired ? ' aksrt-forum-topic__vote--expired' : ''; ?>">
|
||||
<div class="aksrt-forum-topic__vote-head">
|
||||
<h2><?php echo esc_html((string) ($topic['vote']['title'] ?: __('参与投票', 'aksrt'))); ?></h2>
|
||||
<span>
|
||||
<?php printf(esc_html__('%d 人已投票', 'aksrt'), (int) ($topic['vote']['total_votes'] ?? 0)); ?>
|
||||
<?php if ($vote_type === 'pk') : ?>
|
||||
<span class="aksrt-forum-topic__vote-type-badge"><?php esc_html_e('PK', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if ($vote_expired) : ?>
|
||||
<span class="aksrt-forum-topic__vote-expired-badge"><?php esc_html_e('已结束', 'aksrt'); ?></span>
|
||||
<?php elseif ($vote_expiry > 0) : ?>
|
||||
<span class="aksrt-forum-topic__vote-expiry-info"><?php printf(esc_html__('%d 天有效期', 'aksrt'), $vote_expiry); ?></span>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<form class="aksrt-forum-topic__vote-form js-aksrt-topic-vote-form" data-topic-id="<?php echo esc_attr((string) $topic_id); ?>" data-multiple="<?php echo !empty($topic['vote']['multiple']) ? '1' : '0'; ?>">
|
||||
<div class="aksrt-forum-topic__vote-options">
|
||||
<?php foreach (($topic['vote']['options'] ?? []) as $option) :
|
||||
$selected = !empty($option['selected']);
|
||||
$count = (int) ($option['count'] ?? 0);
|
||||
$total_votes = max(1, (int) ($topic['vote']['total_votes'] ?? 0));
|
||||
$ratio = (int) round(($count / $total_votes) * 100);
|
||||
?>
|
||||
<label class="aksrt-forum-topic__vote-option<?php echo $selected ? ' is-selected' : ''; ?>">
|
||||
<input
|
||||
type="<?php echo !empty($topic['vote']['multiple']) ? 'checkbox' : 'radio'; ?>"
|
||||
name="option_ids[]"
|
||||
value="<?php echo esc_attr((string) ($option['id'] ?? '')); ?>"
|
||||
<?php checked($selected); ?>
|
||||
<?php disabled($vote_disabled); ?>
|
||||
>
|
||||
<span class="aksrt-forum-topic__vote-label"><?php echo esc_html((string) ($option['label'] ?? '')); ?></span>
|
||||
<span class="aksrt-forum-topic__vote-count">
|
||||
<?php if ($vote_display === 'number') : ?>
|
||||
<?php echo esc_html(number_format_i18n($count)); ?>
|
||||
<?php else : ?>
|
||||
<?php echo esc_html(number_format_i18n($count)); ?> / <?php echo esc_html((string) $ratio); ?>%
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__vote-actions">
|
||||
<?php if ($vote_expired) : ?>
|
||||
<span class="aksrt-forum-topic__vote-feedback is-error"><?php esc_html_e('投票已结束。', 'aksrt'); ?></span>
|
||||
<?php elseif (!empty($topic['vote']['has_voted'])) : ?>
|
||||
<span class="aksrt-forum-topic__vote-feedback is-success"><?php esc_html_e('你已经参与过本次投票。', 'aksrt'); ?></span>
|
||||
<?php else : ?>
|
||||
<button type="submit" class="aksrt-forum-topic__primary-btn"><?php esc_html_e('提交投票', 'aksrt'); ?></button>
|
||||
<span class="aksrt-forum-topic__vote-feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($permissions['can_moderate'])) : ?>
|
||||
<section id="aksrt-topic-moderation" class="aksrt-forum-topic__moderation">
|
||||
<div class="aksrt-forum-topic__moderation-head">
|
||||
<h2><?php esc_html_e('主题治理', 'aksrt'); ?></h2>
|
||||
<p><?php esc_html_e('支持审核、移动版块、可见性调整以及置顶/精华/锁定等治理动作。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($topic['moderation_note'])) : ?>
|
||||
<div class="aksrt-forum-topic__moderation-note">
|
||||
<strong><?php esc_html_e('最近治理备注:', 'aksrt'); ?></strong>
|
||||
<span><?php echo esc_html((string) $topic['moderation_note']); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form class="aksrt-forum-topic__moderation-form js-aksrt-topic-moderation-form" data-topic-id="<?php echo esc_attr((string) $topic_id); ?>">
|
||||
<div class="aksrt-forum-topic__moderation-grid">
|
||||
<div class="aksrt-forum-topic__field">
|
||||
<label for="aksrt-topic-moderation-action"><?php esc_html_e('治理动作', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-moderation-action" name="action" class="js-aksrt-moderation-action" required>
|
||||
<option value="review"><?php esc_html_e('审核状态', 'aksrt'); ?></option>
|
||||
<option value="move_board"><?php esc_html_e('移动版块', 'aksrt'); ?></option>
|
||||
<option value="visibility"><?php esc_html_e('修改可见性', 'aksrt'); ?></option>
|
||||
<option value="sticky"><?php esc_html_e('置顶切换', 'aksrt'); ?></option>
|
||||
<option value="featured"><?php esc_html_e('精华切换', 'aksrt'); ?></option>
|
||||
<option value="locked"><?php esc_html_e('锁定切换', 'aksrt'); ?></option>
|
||||
<option value="close"><?php esc_html_e('关闭帖子', 'aksrt'); ?></option>
|
||||
<option value="hide"><?php esc_html_e('隐藏帖子', 'aksrt'); ?></option>
|
||||
<option value="delete"><?php esc_html_e('删除到回收站', 'aksrt'); ?></option>
|
||||
<?php if (get_post_status($topic_id) === 'trash') : ?>
|
||||
<option value="undelete"><?php esc_html_e('撤销删除', 'aksrt'); ?></option>
|
||||
<?php endif; ?>
|
||||
<?php if (($topic['bbs_type'] ?? 'standard') === 'question') : ?>
|
||||
<option value="question_status"><?php esc_html_e('提问状态', 'aksrt'); ?></option>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="review">
|
||||
<label for="aksrt-topic-review-status"><?php esc_html_e('审核结果', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-review-status" name="review_status">
|
||||
<?php foreach ($review_options as $option) : ?>
|
||||
<option value="<?php echo esc_attr((string) ($option['value'] ?? '')); ?>" <?php selected((string) (($topic['review_status']['key'] ?? '')) === (string) ($option['value'] ?? '')); ?>>
|
||||
<?php echo esc_html((string) ($option['label'] ?? '')); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="move_board" hidden>
|
||||
<label for="aksrt-topic-target-board"><?php esc_html_e('目标版块', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-target-board" name="target_board_id">
|
||||
<?php foreach ($board_options as $option) : ?>
|
||||
<option value="<?php echo esc_attr((string) ($option['id'] ?? '')); ?>" <?php selected((int) ($board['id'] ?? 0), (int) ($option['id'] ?? 0)); ?>>
|
||||
<?php echo esc_html((string) ($option['name'] ?? '')); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="visibility" hidden>
|
||||
<label for="aksrt-topic-visibility"><?php esc_html_e('可见性', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-visibility" name="visibility">
|
||||
<?php foreach ($visibility_options as $option) : ?>
|
||||
<option value="<?php echo esc_attr((string) ($option['value'] ?? '')); ?>" <?php selected((string) (($topic['visibility']['key'] ?? '')) === (string) ($option['value'] ?? '')); ?>>
|
||||
<?php echo esc_html((string) ($option['label'] ?? '')); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field js-aksrt-visibility-extra" data-field="visibility" data-visibility-field="credits" hidden>
|
||||
<label for="aksrt-topic-credits-cost"><?php esc_html_e('积分价格', 'aksrt'); ?></label>
|
||||
<input id="aksrt-topic-credits-cost" name="credits_cost" type="number" min="1" max="99999" value="<?php echo esc_attr((string) ((int) get_post_meta($topic_id, '_aksrt_credits_cost', true))); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field js-aksrt-visibility-extra" data-field="visibility" data-visibility-field="pay" hidden>
|
||||
<label for="aksrt-topic-pay-price"><?php esc_html_e('付费价格(¥)', 'aksrt'); ?></label>
|
||||
<input id="aksrt-topic-pay-price" name="pay_price" type="number" min="0.01" step="0.01" max="99999" value="<?php echo esc_attr((string) get_post_meta($topic_id, '_aksrt_pay_price', true)); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field js-aksrt-visibility-extra" data-field="visibility" data-visibility-field="role" hidden>
|
||||
<label for="aksrt-topic-visibility-roles"><?php esc_html_e('允许角色', 'aksrt'); ?></label>
|
||||
<?php $current_visibility_roles = (array) get_post_meta($topic_id, '_aksrt_visibility_roles', true); ?>
|
||||
<select id="aksrt-topic-visibility-roles" name="visibility_roles[]" multiple>
|
||||
<?php foreach (wp_roles()->get_names() as $role_slug => $role_name) : ?>
|
||||
<option value="<?php echo esc_attr($role_slug); ?>" <?php selected(in_array($role_slug, $current_visibility_roles, true)); ?>>
|
||||
<?php echo esc_html(translate_user_role($role_name)); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="sticky" hidden>
|
||||
<label for="aksrt-topic-sticky"><?php esc_html_e('置顶级别', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-sticky" name="sticky_value">
|
||||
<?php
|
||||
$current_sticky = (int) ($topic['sticky_level'] ?? 0);
|
||||
$sticky_levels = [
|
||||
0 => __('不置顶', 'aksrt'),
|
||||
1 => __('版块置顶', 'aksrt'),
|
||||
2 => __('超级置顶', 'aksrt'),
|
||||
3 => __('全局置顶', 'aksrt'),
|
||||
];
|
||||
foreach ($sticky_levels as $level => $label) :
|
||||
?>
|
||||
<option value="<?php echo esc_attr((string) $level); ?>" <?php selected($current_sticky, $level); ?>>
|
||||
<?php echo esc_html($label); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="featured" hidden>
|
||||
<label for="aksrt-topic-featured"><?php esc_html_e('精华状态', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-featured" name="featured_value">
|
||||
<option value="1" <?php selected(!empty($topic['featured'])); ?>><?php esc_html_e('设为精华', 'aksrt'); ?></option>
|
||||
<option value="0" <?php selected(empty($topic['featured'])); ?>><?php esc_html_e('取消精华', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="locked" hidden>
|
||||
<label for="aksrt-topic-locked"><?php esc_html_e('锁定状态', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-locked" name="locked_value">
|
||||
<option value="1" <?php selected(!empty($topic['locked'])); ?>><?php esc_html_e('锁定主题', 'aksrt'); ?></option>
|
||||
<option value="0" <?php selected(empty($topic['locked'])); ?>><?php esc_html_e('解除锁定', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="close" hidden>
|
||||
<label for="aksrt-topic-close"><?php esc_html_e('关闭状态', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-close" name="close_value">
|
||||
<option value="1"><?php esc_html_e('关闭帖子', 'aksrt'); ?></option>
|
||||
<option value="0"><?php esc_html_e('重新开放', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="hide" hidden>
|
||||
<label for="aksrt-topic-hide"><?php esc_html_e('隐藏状态', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-hide" name="hide_value">
|
||||
<option value="1"><?php esc_html_e('隐藏帖子', 'aksrt'); ?></option>
|
||||
<option value="0"><?php esc_html_e('恢复显示', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="delete" hidden>
|
||||
<label for="aksrt-topic-delete-confirm"><?php esc_html_e('删除确认', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-delete-confirm" name="delete_value">
|
||||
<option value="1"><?php esc_html_e('确认删除到回收站', 'aksrt'); ?></option>
|
||||
</select>
|
||||
<small><?php esc_html_e('删除后作者会收到通知,主题可在回收站中恢复。', 'aksrt'); ?></small>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="undelete" hidden>
|
||||
<label for="aksrt-topic-undelete-confirm"><?php esc_html_e('恢复确认', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-undelete-confirm" name="undelete_value">
|
||||
<option value="1"><?php esc_html_e('确认恢复主题', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<?php if (($topic['bbs_type'] ?? 'standard') === 'question') : ?>
|
||||
<div class="aksrt-forum-topic__field js-aksrt-moderation-field" data-field="question_status" hidden>
|
||||
<label for="aksrt-topic-question-status"><?php esc_html_e('提问状态', 'aksrt'); ?></label>
|
||||
<select id="aksrt-topic-question-status" name="question_status_value">
|
||||
<option value="0" <?php selected((int) ($topic['question_status'] ?? 0), 0); ?>><?php esc_html_e('未解决', 'aksrt'); ?></option>
|
||||
<option value="1" <?php selected((int) ($topic['question_status'] ?? 0), 1); ?>><?php esc_html_e('已解决', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__field">
|
||||
<label for="aksrt-topic-moderation-note"><?php esc_html_e('治理备注', 'aksrt'); ?></label>
|
||||
<textarea id="aksrt-topic-moderation-note" name="note" rows="3" placeholder="<?php esc_attr_e('记录处理原因,便于后续审计和沟通。', 'aksrt'); ?>"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-topic__moderation-actions">
|
||||
<button type="submit" class="aksrt-forum-topic__primary-btn"><?php esc_html_e('执行治理动作', 'aksrt'); ?></button>
|
||||
<span class="aksrt-forum-topic__moderation-feedback js-aksrt-action-feedback" aria-live="polite"></span>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<section class="aksrt-forum-topic__replies" id="aksrt-forum-replies"
|
||||
data-topic-id="<?php echo esc_attr((string) $topic_id); ?>"
|
||||
data-nonce="<?php echo esc_attr(wp_create_nonce('aksrt_public_nonce')); ?>">
|
||||
|
||||
<div class="aksrt-forum-replies__header">
|
||||
<h2 class="aksrt-forum-topic__replies-title">
|
||||
<i class="fas fa-comments"></i>
|
||||
<?php
|
||||
printf(esc_html__('%1$d 条%2$s', 'aksrt'), (int) get_comments_number(), esc_html($name_reply));
|
||||
?>
|
||||
</h2>
|
||||
<div class="aksrt-forum-replies__tabs">
|
||||
<button type="button" class="aksrt-forum-replies__tab is-active" data-sort="newest"><?php esc_html_e('最新', 'aksrt'); ?></button>
|
||||
<button type="button" class="aksrt-forum-replies__tab" data-sort="oldest"><?php esc_html_e('最早', 'aksrt'); ?></button>
|
||||
<button type="button" class="aksrt-forum-replies__tab" data-sort="hottest"><?php esc_html_e('最热', 'aksrt'); ?></button>
|
||||
<label class="aksrt-forum-replies__filter">
|
||||
<input type="checkbox" class="aksrt-forum-replies__author-toggle" value="1">
|
||||
<?php esc_html_e('只看楼主', 'aksrt'); ?>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-replies__list js-aksrt-forum-replies-list">
|
||||
<?php
|
||||
if ($forum) {
|
||||
$reply_data = $forum->get_forum_comments($topic_id, 'newest', false, 1, 30);
|
||||
$forum->render_forum_comments($reply_data['comments'], $topic_id, $reply_data['adopted_id']);
|
||||
$reply_max_pages = $reply_data['max_pages'];
|
||||
$reply_total = $reply_data['total'];
|
||||
} else {
|
||||
$reply_max_pages = 1;
|
||||
$reply_total = 0;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php if ($reply_max_pages > 1) : ?>
|
||||
<div class="aksrt-forum-replies__load-more">
|
||||
<button type="button" class="aksrt-forum-replies__more-btn js-aksrt-forum-load-more"
|
||||
data-page="1" data-max="<?php echo esc_attr((string) $reply_max_pages); ?>">
|
||||
<i class="fas fa-chevron-down"></i> <?php esc_html_e('加载更多回复', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<?php if ($comments_enabled) : ?>
|
||||
<section class="aksrt-forum-topic__reply-form">
|
||||
<h2><i class="fas fa-reply"></i> <?php esc_html_e('发表评论', 'aksrt'); ?></h2>
|
||||
<?php
|
||||
comment_form([
|
||||
'title_reply' => '',
|
||||
'comment_notes_before' => '',
|
||||
'comment_field' => '<div class="aksrt-forum-topic__reply-field"><textarea name="comment" rows="5" required placeholder="' . esc_attr($reply_placeholder) . '"></textarea></div>',
|
||||
'submit_button' => '<button type="submit" class="aksrt-forum-topic__reply-btn"><i class="fas fa-paper-plane"></i> %s</button>',
|
||||
'submit_field' => '<div class="aksrt-forum-topic__reply-actions">%1$s %2$s</div>',
|
||||
]);
|
||||
?>
|
||||
</section>
|
||||
<?php elseif ($is_locked) : ?>
|
||||
<div class="aksrt-forum-topic__locked-notice">
|
||||
<i class="fas fa-lock"></i>
|
||||
<?php esc_html_e('当前主题已锁定,暂不接受新的回复。', 'aksrt'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum-topic__login-notice">
|
||||
<a href="<?php echo esc_url(wp_login_url(get_permalink())); ?>"><?php esc_html_e('登录后参与回复', 'aksrt'); ?></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Archives
|
||||
* Template Post Type: page
|
||||
*
|
||||
* 文章归档页:按年月分组展示全站文章。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
global $wpdb;
|
||||
?>
|
||||
|
||||
<main id="main-content" class="container page-content-default" tabindex="-1">
|
||||
<header class="page-header">
|
||||
<h1 class="entry-title"><?php esc_html_e('文章归档', 'aksrt'); ?></h1>
|
||||
</header>
|
||||
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout content-layout--no-sidebar">
|
||||
<div class="content-layout__primary">
|
||||
<div class="aksrt-archives container">
|
||||
<?php
|
||||
$years = $wpdb->get_results(
|
||||
"SELECT DISTINCT YEAR(post_date) AS year, MONTH(post_date) AS month, COUNT(*) AS count
|
||||
FROM {$wpdb->posts}
|
||||
WHERE post_type = 'post' AND post_status = 'publish'
|
||||
GROUP BY YEAR(post_date), MONTH(post_date)
|
||||
ORDER BY year DESC, month DESC"
|
||||
); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
|
||||
|
||||
$current_year = 0;
|
||||
foreach ($years as $row) :
|
||||
if ((int) $row->year !== $current_year) :
|
||||
$current_year = (int) $row->year;
|
||||
?>
|
||||
<h2 class="aksrt-archives__year"><?php echo esc_html($current_year); ?></h2>
|
||||
<?php endif; ?>
|
||||
<h3 class="aksrt-archives__month">
|
||||
<?php echo esc_html(sprintf('%d 月 (%d 篇)', (int) $row->month, (int) $row->count)); ?>
|
||||
</h3>
|
||||
<ul class="aksrt-archives__list">
|
||||
<?php
|
||||
$month_posts = get_posts([
|
||||
'year' => (int) $row->year,
|
||||
'monthnum' => (int) $row->month,
|
||||
'posts_per_page' => -1,
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
foreach ($month_posts as $mp) :
|
||||
?>
|
||||
<li class="aksrt-archives__item">
|
||||
<span class="aksrt-archives__date"><?php echo esc_html(get_the_date('m-d', $mp)); ?></span>
|
||||
<a href="<?php echo esc_url(get_permalink($mp->ID)); ?>" class="aksrt-archives__link"><?php echo esc_html($mp->post_title); ?></a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Bind Account
|
||||
* Template Post Type: page
|
||||
*
|
||||
* Theme auth route template: /bind-account/
|
||||
*
|
||||
* 第三方登录未匹配账号时的绑定页面
|
||||
* 用户输入已有账号密码完成OAuth绑定
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
// ============================================
|
||||
// 处理绑定请求(POST)
|
||||
// ============================================
|
||||
$bind_error = '';
|
||||
$bind_verify_url = '';
|
||||
$oauth_data = null;
|
||||
$provider_name = '';
|
||||
$obk = '';
|
||||
|
||||
if (isset($_GET['obk'])) {
|
||||
$obk = sanitize_text_field($_GET['obk']);
|
||||
$oauth_data = AKSRT_Auth_Service::get_oauth_bind_context($obk);
|
||||
}
|
||||
|
||||
if (! $oauth_data || ! is_array($oauth_data)) {
|
||||
// 无效或已过期的OAuth数据
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$bind_error = __('绑定会话已过期,请重新使用第三方登录', 'aksrt');
|
||||
}
|
||||
} else {
|
||||
$provider_name = AKSRT_Auth_Service::get_oauth_provider_name($oauth_data['provider'] ?? '');
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['log'], $_POST['pwd']) && empty($bind_error)) {
|
||||
if ($obk === '' && !empty($_POST['obk'])) {
|
||||
$obk = sanitize_text_field($_POST['obk']);
|
||||
}
|
||||
|
||||
if ($oauth_data === null && $obk !== '') {
|
||||
$oauth_data = AKSRT_Auth_Service::get_oauth_bind_context($obk);
|
||||
}
|
||||
|
||||
$result = AKSRT_Auth_Service::bind_oauth_account($_POST, $oauth_data);
|
||||
if (empty($result['success'])) {
|
||||
$bind_error = $result['error'] ?? __('绑定失败,请稍后重试', 'aksrt');
|
||||
$bind_verify_url = $result['verify_url'] ?? '';
|
||||
} else {
|
||||
$user = $result['user'];
|
||||
$provider = $result['provider'];
|
||||
wp_safe_redirect(add_query_arg(['tab' => 'settings', 'oauth_bound' => $provider], aksrt_get_user_center_url()));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main" tabindex="-1">
|
||||
<div class="auth-shell">
|
||||
<div class="auth-card">
|
||||
|
||||
<?php if (! $oauth_data || ! is_array($oauth_data)) : ?>
|
||||
<!-- 会话过期状态 -->
|
||||
<div class="auth-card__expired">
|
||||
<div class="auth-card__logo" aria-hidden="true">AK</div>
|
||||
<h1 class="auth-card__title"><?php bloginfo('name'); ?></h1>
|
||||
<p><?php echo esc_html(__('绑定会话已过期或无效', 'aksrt')); ?></p>
|
||||
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>" class="btn-primary btn-lg auth-card__expired-action">
|
||||
<?php esc_html_e('返回登录', 'aksrt'); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<?php else : ?>
|
||||
<!-- 正常绑定表单 -->
|
||||
|
||||
<div class="auth-card__logo" aria-hidden="true">AK</div>
|
||||
<h1 class="auth-card__title"><?php bloginfo('name'); ?></h1>
|
||||
<p class="auth-card__subtitle">
|
||||
<?php printf(esc_html__('通过 %s 登录,请绑定你的已有账号', 'aksrt'), '<strong>' . esc_html($provider_name) . '</strong>'); ?>
|
||||
</p>
|
||||
|
||||
<?php if (!empty($bind_error)) : ?>
|
||||
<div class="alert alert--error" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
|
||||
<span>
|
||||
<?php echo esc_html($bind_error); ?>
|
||||
<?php if (!empty($bind_verify_url)) : ?>
|
||||
<a href="<?php echo esc_url($bind_verify_url); ?>"><?php esc_html_e('前往验证邮箱', 'aksrt'); ?></a>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form class="auth-form" id="aksrt-bind-form" method="post" action="">
|
||||
<?php wp_nonce_field('aksrt_bind', '_bind_nonce'); ?>
|
||||
<input type="hidden" name="obk" value="<?php echo esc_attr($obk); ?>">
|
||||
<div class="form-field">
|
||||
<label for="bind_user_login"><?php esc_html_e('邮箱 / 用户名', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span>
|
||||
<input type="text" name="log" id="bind_user_login" autocomplete="username" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-field form-field--pwd">
|
||||
<label for="bind_user_pass"><?php esc_html_e('密码', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></span>
|
||||
<input type="password" name="pwd" id="bind_user_pass" autocomplete="current-password" required>
|
||||
<button type="button" class="toggle-pwd" data-target="bind_user_pass" aria-label="<?php esc_attr_e('显示或隐藏密码', 'aksrt'); ?>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10 7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
<?php if (function_exists('aksrt_render_captcha')) : ?>
|
||||
<?php aksrt_render_captcha('bind'); ?>
|
||||
<?php endif; ?>
|
||||
<button type="submit" name="wp-submit" class="btn-primary btn-lg" style="width:100%;margin-top:8px;">
|
||||
<?php esc_html_e('绑定并登录', 'aksrt'); ?>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<?php if (get_option('users_can_register')) :
|
||||
$register_url = aksrt_get_register_url();
|
||||
$register_url = add_query_arg('obk', sanitize_text_field($_GET['obk']), $register_url);
|
||||
?>
|
||||
<p class="auth-footer-link">
|
||||
<?php esc_html_e('还没有账号?', 'aksrt'); ?>
|
||||
<a href="<?php echo esc_url($register_url); ?>"><?php esc_html_e('注册并绑定账号', 'aksrt'); ?></a>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php endif; ?><!-- end 正常绑定表单 -->
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Cart
|
||||
* Template Post Type: page
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
|
||||
wp_safe_redirect($login_url);
|
||||
exit;
|
||||
}
|
||||
|
||||
$cart_view = function_exists('aksrt_get_cart_page_view')
|
||||
? aksrt_get_cart_page_view(get_current_user_id())
|
||||
: [
|
||||
'payment_methods' => [],
|
||||
'shipping_methods' => [],
|
||||
'address_book' => [],
|
||||
'coupon_enabled' => false,
|
||||
'currency_symbol' => '¥',
|
||||
'pending_orders' => [],
|
||||
];
|
||||
|
||||
$pending_orders = is_array($cart_view['pending_orders'] ?? null) ? $cart_view['pending_orders'] : [];
|
||||
$shipping_methods = is_array($cart_view['shipping_methods'] ?? null) ? array_values($cart_view['shipping_methods']) : [];
|
||||
$payment_methods = is_array($cart_view['payment_methods'] ?? null) ? array_values($cart_view['payment_methods']) : [];
|
||||
$address_book = is_array($cart_view['address_book'] ?? null) ? $cart_view['address_book'] : [];
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
|
||||
|
||||
<div
|
||||
class="aksrt-cart-page container"
|
||||
data-aksrt-cart-page
|
||||
data-currency-symbol="<?php echo esc_attr((string) ($cart_view['currency_symbol'] ?? '¥')); ?>"
|
||||
data-coupon-enabled="<?php echo !empty($cart_view['coupon_enabled']) ? '1' : '0'; ?>"
|
||||
>
|
||||
<div class="aksrt-cart-page__header">
|
||||
<div>
|
||||
<h1 class="aksrt-cart-page__title"><?php esc_html_e('购物车', 'aksrt'); ?></h1>
|
||||
<p class="aksrt-cart-page__subtitle"><?php esc_html_e('在下单前确认地址、运费、优惠券和支付方式。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php if (!empty($pending_orders)) : ?>
|
||||
<div class="aksrt-cart-page__pending">
|
||||
<span class="aksrt-cart-page__pending-label"><?php esc_html_e('待支付订单', 'aksrt'); ?></span>
|
||||
<div class="aksrt-cart-page__pending-list">
|
||||
<?php foreach ($pending_orders as $pending_order) : ?>
|
||||
<button
|
||||
type="button"
|
||||
class="aksrt-cart-page__pending-chip"
|
||||
data-aksrt-resume-order="<?php echo esc_attr((string) ($pending_order['order_number'] ?? '')); ?>"
|
||||
>
|
||||
<?php echo esc_html((string) ($pending_order['order_number'] ?? '')); ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-cart-page__layout">
|
||||
<section class="aksrt-cart-page__main">
|
||||
<div class="aksrt-cart-page__panel">
|
||||
<div class="aksrt-cart-page__panel-head">
|
||||
<h2><?php esc_html_e('商品清单', 'aksrt'); ?></h2>
|
||||
<button type="button" class="btn-ghost btn-sm" data-aksrt-clear-cart><?php esc_html_e('清空购物车', 'aksrt'); ?></button>
|
||||
</div>
|
||||
<div class="aksrt-cart-page__items" data-aksrt-cart-items>
|
||||
<div class="aksrt-cart-page__empty">
|
||||
<i class="fas fa-shopping-cart" aria-hidden="true"></i>
|
||||
<p><?php esc_html_e('购物车为空,去商品页添加想购买的内容。', 'aksrt'); ?></p>
|
||||
<a href="<?php echo esc_url(home_url('/')); ?>" class="btn-outline btn-sm"><?php esc_html_e('继续浏览', 'aksrt'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-cart-page__grid">
|
||||
<section class="aksrt-cart-page__panel">
|
||||
<div class="aksrt-cart-page__panel-head">
|
||||
<h2><?php esc_html_e('收货地址', 'aksrt'); ?></h2>
|
||||
<button type="button" class="btn-ghost btn-sm" data-aksrt-address-add>
|
||||
<i class="fas fa-plus" aria-hidden="true"></i> <?php esc_html_e('新增地址', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
<div class="aksrt-cart-page__option-list" data-aksrt-address-list>
|
||||
<?php if (empty($address_book)) : ?>
|
||||
<div class="aksrt-cart-page__address-empty" data-aksrt-address-empty>
|
||||
<i class="fas fa-map-marker-alt" aria-hidden="true"></i>
|
||||
<p><?php esc_html_e('暂无收货地址,请先新增。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($address_book as $index => $address) : ?>
|
||||
<div class="aksrt-cart-page__option-card aksrt-cart-page__address-card" data-aksrt-address-card="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>">
|
||||
<label class="aksrt-cart-page__address-label">
|
||||
<input
|
||||
type="radio"
|
||||
name="aksrt_cart_address"
|
||||
value="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>"
|
||||
<?php checked($index === 0 || !empty($address['is_default'])); ?>
|
||||
>
|
||||
<span class="aksrt-cart-page__option-body">
|
||||
<strong>
|
||||
<?php echo esc_html((string) ($address['name'] ?? '')); ?>
|
||||
<?php if (!empty($address['is_default'])) : ?>
|
||||
<span class="aksrt-cart-page__default-tag"><?php esc_html_e('默认', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
</strong>
|
||||
<span><?php echo esc_html((string) ($address['phone'] ?? '')); ?></span>
|
||||
<span><?php echo esc_html((string) ($address['full_text'] ?? '')); ?></span>
|
||||
</span>
|
||||
</label>
|
||||
<div class="aksrt-cart-page__address-actions">
|
||||
<button type="button" class="btn-ghost btn-xs" data-aksrt-address-edit="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>"><?php esc_html_e('编辑', 'aksrt'); ?></button>
|
||||
<button type="button" class="btn-ghost btn-xs" data-aksrt-address-delete="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>"><?php esc_html_e('删除', 'aksrt'); ?></button>
|
||||
<?php if (empty($address['is_default'])) : ?>
|
||||
<button type="button" class="btn-ghost btn-xs" data-aksrt-address-set-default="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>"><?php esc_html_e('设为默认', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Address Editor Modal -->
|
||||
<div class="aksrt-modal" data-aksrt-address-modal hidden>
|
||||
<div class="aksrt-modal__overlay"></div>
|
||||
<div class="aksrt-modal__dialog">
|
||||
<div class="aksrt-modal__header">
|
||||
<h3 data-aksrt-address-modal-title><?php esc_html_e('新增地址', 'aksrt'); ?></h3>
|
||||
<button type="button" class="aksrt-modal__close" data-aksrt-address-modal-close>×</button>
|
||||
</div>
|
||||
<form class="aksrt-modal__body" data-aksrt-address-form>
|
||||
<input type="hidden" name="address_id" value="">
|
||||
<div class="aksrt-cart-page__field">
|
||||
<label><?php esc_html_e('收货人', 'aksrt'); ?> *</label>
|
||||
<input type="text" name="name" class="aksrt-cart-page__input" required maxlength="50">
|
||||
</div>
|
||||
<div class="aksrt-cart-page__field">
|
||||
<label><?php esc_html_e('手机号', 'aksrt'); ?> *</label>
|
||||
<input type="tel" name="phone" class="aksrt-cart-page__input" required maxlength="20">
|
||||
</div>
|
||||
<div class="aksrt-cart-page__field-row">
|
||||
<div class="aksrt-cart-page__field">
|
||||
<label><?php esc_html_e('省份', 'aksrt'); ?></label>
|
||||
<input type="text" name="province" class="aksrt-cart-page__input" maxlength="50">
|
||||
</div>
|
||||
<div class="aksrt-cart-page__field">
|
||||
<label><?php esc_html_e('城市', 'aksrt'); ?></label>
|
||||
<input type="text" name="city" class="aksrt-cart-page__input" maxlength="50">
|
||||
</div>
|
||||
<div class="aksrt-cart-page__field">
|
||||
<label><?php esc_html_e('区/县', 'aksrt'); ?></label>
|
||||
<input type="text" name="district" class="aksrt-cart-page__input" maxlength="50">
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-cart-page__field">
|
||||
<label><?php esc_html_e('详细地址', 'aksrt'); ?> *</label>
|
||||
<input type="text" name="address" class="aksrt-cart-page__input" required maxlength="200">
|
||||
</div>
|
||||
<label class="aksrt-cart-page__checkbox">
|
||||
<input type="checkbox" name="is_default" value="1">
|
||||
<span><?php esc_html_e('设为默认地址', 'aksrt'); ?></span>
|
||||
</label>
|
||||
<div class="aksrt-modal__footer">
|
||||
<button type="button" class="btn-ghost" data-aksrt-address-modal-close><?php esc_html_e('取消', 'aksrt'); ?></button>
|
||||
<button type="submit" class="btn-primary"><?php esc_html_e('保存地址', 'aksrt'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="aksrt-cart-page__panel">
|
||||
<div class="aksrt-cart-page__panel-head">
|
||||
<h2><?php esc_html_e('配送与支付', 'aksrt'); ?></h2>
|
||||
</div>
|
||||
<div class="aksrt-cart-page__option-columns">
|
||||
<div>
|
||||
<h3 class="aksrt-cart-page__mini-title"><?php esc_html_e('配送方式', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-cart-page__option-list" data-aksrt-shipping-list>
|
||||
<?php foreach ($shipping_methods as $index => $method) : ?>
|
||||
<label class="aksrt-cart-page__option-card">
|
||||
<input
|
||||
type="radio"
|
||||
name="aksrt_cart_shipping"
|
||||
value="<?php echo esc_attr((string) ($method['value'] ?? '')); ?>"
|
||||
<?php checked($index === 0); ?>
|
||||
>
|
||||
<span class="aksrt-cart-page__option-body">
|
||||
<strong><?php echo esc_html((string) ($method['label'] ?? '')); ?></strong>
|
||||
<span><?php echo esc_html((string) ($method['description'] ?? '')); ?></span>
|
||||
</span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="aksrt-cart-page__mini-title"><?php esc_html_e('支付方式', 'aksrt'); ?></h3>
|
||||
<div class="aksrt-cart-page__option-list" data-aksrt-payment-list>
|
||||
<?php foreach ($payment_methods as $index => $method) : ?>
|
||||
<label class="aksrt-cart-page__option-card">
|
||||
<input
|
||||
type="radio"
|
||||
name="aksrt_cart_payment"
|
||||
value="<?php echo esc_attr((string) ($method['value'] ?? '')); ?>"
|
||||
<?php checked($index === 0); ?>
|
||||
>
|
||||
<span class="aksrt-cart-page__option-body">
|
||||
<strong><?php echo esc_html((string) ($method['label'] ?? '')); ?></strong>
|
||||
<span><?php echo esc_html((string) ($method['description'] ?? '')); ?></span>
|
||||
</span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="aksrt-cart-page__panel">
|
||||
<div class="aksrt-cart-page__panel-head">
|
||||
<h2><?php esc_html_e('优惠与备注', 'aksrt'); ?></h2>
|
||||
</div>
|
||||
<div class="aksrt-cart-page__coupon-box">
|
||||
<label class="aksrt-cart-page__field">
|
||||
<span><?php esc_html_e('优惠券', 'aksrt'); ?></span>
|
||||
<div class="aksrt-cart-page__coupon-row">
|
||||
<input type="text" class="aksrt-cart-page__input" data-aksrt-coupon-code placeholder="<?php esc_attr_e('输入优惠码后试算', 'aksrt'); ?>">
|
||||
<button type="button" class="btn-outline btn-sm" data-aksrt-preview-checkout><?php esc_html_e('应用并试算', 'aksrt'); ?></button>
|
||||
</div>
|
||||
</label>
|
||||
<p class="aksrt-cart-page__hint" data-aksrt-preview-message><?php esc_html_e('试算后会展示优惠抵扣、运费和最终应付金额。', 'aksrt'); ?></p>
|
||||
|
||||
<label class="aksrt-cart-page__field">
|
||||
<span><?php esc_html_e('订单备注', 'aksrt'); ?></span>
|
||||
<textarea class="aksrt-cart-page__textarea" data-aksrt-customer-note rows="4" placeholder="<?php esc_attr_e('例如发票要求、发货备注等。', 'aksrt'); ?>"></textarea>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<aside class="aksrt-cart-page__sidebar">
|
||||
<section class="aksrt-cart-page__panel aksrt-cart-page__summary">
|
||||
<div class="aksrt-cart-page__panel-head">
|
||||
<h2><?php esc_html_e('订单摘要', 'aksrt'); ?></h2>
|
||||
</div>
|
||||
<dl class="aksrt-cart-page__summary-list">
|
||||
<div>
|
||||
<dt><?php esc_html_e('商品小计', 'aksrt'); ?></dt>
|
||||
<dd data-aksrt-summary-subtotal>¥0.00</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt><?php esc_html_e('运费', 'aksrt'); ?></dt>
|
||||
<dd data-aksrt-summary-shipping>¥0.00</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt><?php esc_html_e('优惠抵扣', 'aksrt'); ?></dt>
|
||||
<dd data-aksrt-summary-discount>-¥0.00</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="aksrt-cart-page__summary-total">
|
||||
<span><?php esc_html_e('应付总额', 'aksrt'); ?></span>
|
||||
<strong data-aksrt-summary-total>¥0.00</strong>
|
||||
</div>
|
||||
<button type="button" class="btn-primary btn-lg aksrt-cart-page__submit" data-aksrt-create-order disabled>
|
||||
<?php esc_html_e('创建订单', 'aksrt'); ?>
|
||||
</button>
|
||||
</section>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Categories
|
||||
* Template Post Type: page
|
||||
*
|
||||
* 分类汇总页面:列出全站所有分类。
|
||||
*
|
||||
* 用法:在后台新建一个 Page,标题任意(默认显示页面标题,否则用"分类目录"),
|
||||
* 模板选择 "AKSRT - Categories";或将 slug 设为 "categories" 自动匹配。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
// ─── 数据准备 ─────────────────────────────────────────────
|
||||
$all_terms = get_terms([
|
||||
'taxonomy' => 'category',
|
||||
'hide_empty' => false, // 全部展示,含 0 篇文章的分类
|
||||
'orderby' => 'menu_order name',
|
||||
'order' => 'ASC',
|
||||
]);
|
||||
if (is_wp_error($all_terms)) {
|
||||
$all_terms = [];
|
||||
}
|
||||
|
||||
$top_level = [];
|
||||
$children_by_parent = [];
|
||||
foreach ($all_terms as $term) {
|
||||
if ((int) $term->parent === 0) {
|
||||
$top_level[] = $term;
|
||||
} else {
|
||||
$children_by_parent[(int) $term->parent][] = $term;
|
||||
}
|
||||
}
|
||||
|
||||
$total_cats = count($all_terms);
|
||||
$total_counts = wp_count_posts();
|
||||
$total_posts = $total_counts && isset($total_counts->publish) ? (int) $total_counts->publish : 0;
|
||||
|
||||
$page_title = trim((string) get_the_title());
|
||||
if ($page_title === '') {
|
||||
$page_title = __('分类目录', 'aksrt');
|
||||
}
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) {
|
||||
aksrt_breadcrumbs();
|
||||
} ?>
|
||||
|
||||
<header class="page-header aksrt-cats-header">
|
||||
<h1 class="entry-title"><?php echo esc_html($page_title); ?></h1>
|
||||
<p class="aksrt-cats-header__meta">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1: total category count, 2: total published post count */
|
||||
esc_html__('共 %1$d 个分类 · 共 %2$d 篇文章', 'aksrt'),
|
||||
$total_cats,
|
||||
$total_posts
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<?php if (!empty($top_level)) : ?>
|
||||
<section class="aksrt-cats-grid" aria-label="<?php esc_attr_e('分类列表', 'aksrt'); ?>">
|
||||
<?php foreach ($top_level as $cat) :
|
||||
$cat_id = (int) $cat->term_id;
|
||||
$cat_link = get_category_link($cat_id);
|
||||
$cover_url = class_exists('AKSRT_Settings')
|
||||
? AKSRT_Settings::get_category_cover_url($cat_id)
|
||||
: (get_template_directory_uri() . '/assets/img/placeholder.svg');
|
||||
$desc = class_exists('AKSRT_Settings')
|
||||
? AKSRT_Settings::get_category_recommend_desc($cat_id)
|
||||
: (string) $cat->description;
|
||||
$children = $children_by_parent[$cat_id] ?? [];
|
||||
?>
|
||||
<article class="aksrt-cat-card">
|
||||
<a class="aksrt-cat-card__cover"
|
||||
href="<?php echo esc_url($cat_link); ?>"
|
||||
style="background-image: url('<?php echo esc_url($cover_url); ?>');"
|
||||
aria-label="<?php echo esc_attr($cat->name); ?>">
|
||||
<span class="aksrt-cat-card__count-badge">
|
||||
<?php printf(esc_html__('%d 篇', 'aksrt'), (int) $cat->count); ?>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<div class="aksrt-cat-card__body">
|
||||
<h2 class="aksrt-cat-card__title">
|
||||
<a href="<?php echo esc_url($cat_link); ?>"><?php echo esc_html($cat->name); ?></a>
|
||||
</h2>
|
||||
|
||||
<?php if ($desc !== '') : ?>
|
||||
<p class="aksrt-cat-card__desc"><?php echo esc_html(wp_trim_words(wp_strip_all_tags($desc), 40, '…')); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($children)) : ?>
|
||||
<ul class="aksrt-cat-card__children" aria-label="<?php esc_attr_e('子分类', 'aksrt'); ?>">
|
||||
<?php foreach ($children as $child) : ?>
|
||||
<li>
|
||||
<a href="<?php echo esc_url(get_category_link((int) $child->term_id)); ?>">
|
||||
<span class="aksrt-cat-card__child-name"><?php echo esc_html($child->name); ?></span>
|
||||
<span class="aksrt-cat-card__child-count"><?php echo (int) $child->count; ?></span>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</section>
|
||||
<?php else : ?>
|
||||
<div class="no-results aksrt-cats-empty">
|
||||
<p><?php esc_html_e('暂无分类。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<p class="aksrt-cats-footer">
|
||||
<a class="btn-outline" href="<?php echo esc_url(home_url('/')); ?>">
|
||||
<?php esc_html_e('返回首页', 'aksrt'); ?>
|
||||
</a>
|
||||
</p>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Document Navigation
|
||||
* Template Post Type: page
|
||||
*
|
||||
* 文档导航页:文档站式导航。
|
||||
* 支持侧边章节树、当前章节高亮、索引卡片、最近更新列表、基础搜索。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
// Read doc mode settings
|
||||
$doc_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_docs_mode_settings() : [];
|
||||
$default_order = $doc_settings['default_order'] ?? 'menu_order';
|
||||
|
||||
$presenter = class_exists('AKSRT_Docs_Presenter') ? AKSRT_Docs_Presenter::get_instance() : null;
|
||||
|
||||
// Get root-level pages
|
||||
$pages = $presenter
|
||||
? $presenter->get_root_pages($default_order)
|
||||
: get_pages([
|
||||
'sort_column' => $default_order === 'title' ? 'post_title' : ($default_order === 'date' ? 'post_date' : 'menu_order, post_title'),
|
||||
'sort_order' => 'ASC',
|
||||
'parent' => 0,
|
||||
'hierarchical' => 0,
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
|
||||
// Recent updates
|
||||
$recent_pages = $presenter
|
||||
? $presenter->get_recent_pages(8)
|
||||
: get_pages([
|
||||
'sort_column' => 'post_modified',
|
||||
'sort_order' => 'DESC',
|
||||
'number' => 8,
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
|
||||
$show_sidebar = !empty($doc_settings['toc_enabled']) || !empty($recent_pages);
|
||||
?>
|
||||
|
||||
<main id="main-content" class="container page-content-default" tabindex="-1">
|
||||
|
||||
<header class="aksrt-doc-nav-header">
|
||||
<h1 class="aksrt-doc-nav-header__title"><?php echo esc_html(get_the_title() ?: __('文档导航', 'aksrt')); ?></h1>
|
||||
<?php $desc = get_the_excerpt(); if ($desc) : ?>
|
||||
<p class="aksrt-doc-nav-header__desc"><?php echo esc_html($desc); ?></p>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
|
||||
<div class="aksrt-doc-nav container" data-aksrt-doc-page-id="<?php echo (int) get_the_ID(); ?>">
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout<?php echo $show_sidebar && !empty($recent_pages) ? '' : ' content-layout--no-sidebar'; ?>">
|
||||
<div class="content-layout__primary">
|
||||
<!-- Quick search -->
|
||||
<div class="aksrt-doc-nav__search">
|
||||
<input type="text" class="aksrt-doc-nav__search-input" placeholder="<?php esc_attr_e('搜索文档...', 'aksrt'); ?>" id="aksrt-doc-search">
|
||||
<i class="fas fa-search aksrt-doc-nav__search-icon"></i>
|
||||
</div>
|
||||
<div class="aksrt-doc-search__results" data-aksrt-doc-search-results hidden></div>
|
||||
|
||||
<?php if (!empty($pages)) : ?>
|
||||
<!-- Toolbar: category chips -->
|
||||
<div class="aksrt-doc-toolbar">
|
||||
<div class="aksrt-doc-toolbar__chips">
|
||||
<button type="button" class="aksrt-doc-toolbar__chip is-active" data-cat-id="0"><?php esc_html_e('全部', 'aksrt'); ?></button>
|
||||
<?php foreach ($pages as $p) : ?>
|
||||
<button type="button" class="aksrt-doc-toolbar__chip" data-cat-id="<?php echo (int) $p->ID; ?>"><?php echo esc_html($p->post_title); ?></button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<span class="aksrt-doc-toolbar__meta"><?php printf(esc_html__('%d 篇文档', 'aksrt'), count($pages)); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-doc-nav__layout">
|
||||
<!-- Document index cards -->
|
||||
<div class="aksrt-doc-nav__main">
|
||||
<?php if (!empty($pages)) : ?>
|
||||
<div class="aksrt-doc-nav__grid">
|
||||
<?php foreach ($pages as $p) :
|
||||
$children = $presenter
|
||||
? $presenter->get_flat_tree($p->ID, 1)
|
||||
: get_pages([
|
||||
'child_of' => $p->ID,
|
||||
'sort_column' => 'menu_order',
|
||||
'sort_order' => 'ASC',
|
||||
'parent' => $p->ID,
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
$child_count = count($children);
|
||||
$thumb = get_the_post_thumbnail_url($p->ID, 'medium');
|
||||
$excerpt = wp_trim_words($p->post_excerpt, 30, '...');
|
||||
?>
|
||||
<a href="<?php echo esc_url(get_permalink($p->ID)); ?>" class="aksrt-doc-index-card" data-cat-id="<?php echo (int) $p->ID; ?>">
|
||||
<?php if ($thumb) : ?>
|
||||
<div class="aksrt-doc-index-card__thumb">
|
||||
<img src="<?php echo esc_url($thumb); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-doc-index-card__icon">
|
||||
<i class="fas fa-book-open"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-doc-index-card__body">
|
||||
<h3 class="aksrt-doc-index-card__title"><?php echo esc_html($p->post_title); ?></h3>
|
||||
<?php if ($excerpt) : ?>
|
||||
<p class="aksrt-doc-index-card__desc"><?php echo esc_html($excerpt); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-doc-index-card__meta">
|
||||
<?php if ($child_count > 0) : ?>
|
||||
<span class="aksrt-doc-index-card__count">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<?php printf(esc_html__('%d 篇文章', 'aksrt'), $child_count); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<span class="aksrt-doc-index-card__date">
|
||||
<i class="fas fa-clock"></i>
|
||||
<?php echo esc_html(get_the_date('', $p->ID)); ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<i class="fas fa-chevron-right aksrt-doc-index-card__arrow"></i>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-doc-nav__empty">
|
||||
<i class="fas fa-book-open"></i>
|
||||
<p><?php esc_html_e('暂无文档页面。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar: Recent updates -->
|
||||
<?php if ($show_sidebar && !empty($recent_pages)) : ?>
|
||||
<aside class="aksrt-doc-nav__sidebar sidebar">
|
||||
<div class="aksrt-doc-nav__recent">
|
||||
<h3 class="aksrt-doc-nav__recent-title">
|
||||
<i class="fas fa-clock"></i>
|
||||
<?php esc_html_e('最近更新', 'aksrt'); ?>
|
||||
</h3>
|
||||
<ul class="aksrt-doc-nav__recent-list">
|
||||
<?php foreach ($recent_pages as $rp) : ?>
|
||||
<li class="aksrt-doc-nav__recent-item">
|
||||
<a href="<?php echo esc_url(get_permalink($rp->ID)); ?>">
|
||||
<span class="aksrt-doc-nav__recent-name"><?php echo esc_html($rp->post_title); ?></span>
|
||||
<time class="aksrt-doc-nav__recent-date"><?php echo esc_html(get_the_date('', $rp->ID)); ?></time>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Download Center
|
||||
* Template Post Type: page
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$paged = max(1, (int) get_query_var('paged'));
|
||||
$per_page = 12;
|
||||
|
||||
$type_filter = isset($_GET['resource_type']) ? sanitize_key((string) $_GET['resource_type']) : '';
|
||||
$resource_type_labels = function_exists('aksrt_get_pay_types') ? aksrt_get_pay_types() : [];
|
||||
unset($resource_type_labels[AKSRT_Domain_Model::PAY_TYPE_READING]);
|
||||
|
||||
if ($type_filter !== '' && !isset($resource_type_labels[$type_filter])) {
|
||||
$type_filter = '';
|
||||
}
|
||||
|
||||
$query_args = [
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $paged,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
'ignore_sticky_posts' => true,
|
||||
'meta_query' => [
|
||||
[
|
||||
'key' => AKSRT_Domain_Model::RESOURCE_MARKER_KEY,
|
||||
'value' => '1',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if ($type_filter !== '') {
|
||||
$query_args['meta_query'][] = [
|
||||
'key' => AKSRT_Domain_Model::PAY_TYPE_KEY,
|
||||
'value' => $type_filter,
|
||||
];
|
||||
}
|
||||
|
||||
$resource_query = new WP_Query($query_args);
|
||||
|
||||
$is_logged_in = is_user_logged_in();
|
||||
$user_credits = 0;
|
||||
$user_download_count = 0;
|
||||
if ($is_logged_in) {
|
||||
$uid = get_current_user_id();
|
||||
if (class_exists('AKSRT_Credits')) {
|
||||
$user_credits = AKSRT_Credits::balance($uid);
|
||||
}
|
||||
$dl_meta = get_user_meta($uid, '_aksrt_downloaded_resources', true);
|
||||
$user_download_count = is_array($dl_meta) ? count($dl_meta) : 0;
|
||||
}
|
||||
|
||||
$currency_name = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
|
||||
$dl_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_cms_features() : [];
|
||||
$dl_requires_login = !empty($dl_settings['download_requires_login']);
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main container" tabindex="-1">
|
||||
|
||||
<?php get_template_part('templates/parts/download/download-hero'); ?>
|
||||
|
||||
<div class="aksrt-download-center container">
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout">
|
||||
<div class="content-layout__primary">
|
||||
<div class="aksrt-dl-status-bar">
|
||||
<?php if ($is_logged_in) : ?>
|
||||
<div class="aksrt-dl-status-bar__item">
|
||||
<i class="fas fa-coins" aria-hidden="true"></i>
|
||||
<span class="aksrt-dl-status-bar__label"><?php echo esc_html($currency_name); ?></span>
|
||||
<span class="aksrt-dl-status-bar__value"><?php echo esc_html(number_format_i18n($user_credits)); ?></span>
|
||||
</div>
|
||||
<div class="aksrt-dl-status-bar__item">
|
||||
<i class="fas fa-download" aria-hidden="true"></i>
|
||||
<span class="aksrt-dl-status-bar__label"><?php esc_html_e('已下载', 'aksrt'); ?></span>
|
||||
<span class="aksrt-dl-status-bar__value"><?php echo esc_html(number_format_i18n($user_download_count)); ?></span>
|
||||
</div>
|
||||
<div class="aksrt-dl-status-bar__item aksrt-dl-status-bar__item--hint">
|
||||
<i class="fas fa-info-circle" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('点击资源卡片查看详情和下载状态', 'aksrt'); ?></span>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-dl-status-bar__item aksrt-dl-status-bar__item--hint">
|
||||
<i class="fas fa-lock" aria-hidden="true"></i>
|
||||
<span>
|
||||
<?php if ($dl_requires_login) : ?>
|
||||
<?php esc_html_e('登录后可查看下载状态和积分余额', 'aksrt'); ?>
|
||||
<?php else : ?>
|
||||
<?php esc_html_e('登录后可管理下载记录和积分余额', 'aksrt'); ?>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="aksrt-dl-status-bar__actions">
|
||||
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>" class="btn-outline btn-sm"><?php esc_html_e('登录', 'aksrt'); ?></a>
|
||||
<?php if (get_option('users_can_register')) : ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_register_url()); ?>" class="btn-primary btn-sm"><?php esc_html_e('注册', 'aksrt'); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-download-center__layout">
|
||||
<div class="aksrt-download-center__main">
|
||||
<?php if ($resource_query->have_posts()) : ?>
|
||||
<div class="aksrt-download-center__grid">
|
||||
<?php while ($resource_query->have_posts()) : $resource_query->the_post(); ?>
|
||||
<article class="aksrt-download-card">
|
||||
<?php if (has_post_thumbnail()) : ?>
|
||||
<div class="aksrt-download-card__thumb">
|
||||
<a href="<?php the_permalink(); ?>">
|
||||
<?php the_post_thumbnail('medium'); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-download-card__body">
|
||||
<h3 class="aksrt-download-card__title">
|
||||
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
|
||||
</h3>
|
||||
<p class="aksrt-download-card__excerpt"><?php echo esc_html(wp_trim_words(get_the_excerpt(), 20)); ?></p>
|
||||
<div class="aksrt-download-card__meta">
|
||||
<span class="aksrt-download-card__date">
|
||||
<i class="fas fa-clock"></i>
|
||||
<?php echo esc_html(get_the_date()); ?>
|
||||
</span>
|
||||
<?php
|
||||
$dl_count = (int) get_post_meta(get_the_ID(), AKSRT_Domain_Model::RESOURCE_DOWNLOAD_COUNT_KEY, true);
|
||||
if ($dl_count > 0) :
|
||||
?>
|
||||
<span class="aksrt-download-card__downloads">
|
||||
<i class="fas fa-download"></i>
|
||||
<?php echo esc_html(number_format_i18n($dl_count)); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
$card_meta = function_exists('aksrt_get_resource_meta') ? aksrt_get_resource_meta(get_the_ID()) : [];
|
||||
$card_price = (float) ($card_meta['price'] ?? 0);
|
||||
$price_label = function_exists('aksrt_resource_price_label')
|
||||
? aksrt_resource_price_label($card_price)
|
||||
: ['text' => __('免费', 'aksrt'), 'free' => true];
|
||||
?>
|
||||
<div class="aksrt-download-card__footer">
|
||||
<span class="aksrt-download-card__price<?php echo $price_label['free'] ? ' is-free' : ' is-paid'; ?>">
|
||||
<?php echo esc_html($price_label['text']); ?>
|
||||
</span>
|
||||
<a href="<?php the_permalink(); ?>" class="aksrt-download-card__action">
|
||||
<?php esc_html_e('查看详情', 'aksrt'); ?>
|
||||
<i class="fas fa-arrow-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<?php endwhile; ?>
|
||||
</div>
|
||||
<?php
|
||||
if (function_exists('aksrt_render_pagination')) {
|
||||
aksrt_render_pagination($resource_query);
|
||||
}
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-download-center__empty">
|
||||
<i class="fas fa-folder-open"></i>
|
||||
<p><?php esc_html_e('暂无可下载资源。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<aside class="aksrt-download-center__sidebar sidebar">
|
||||
<?php get_template_part('templates/parts/download/download-permission-card'); ?>
|
||||
|
||||
<div class="aksrt-dl-sidebar-card">
|
||||
<h3 class="aksrt-dl-sidebar-card__title">
|
||||
<i class="fas fa-folder"></i>
|
||||
<?php esc_html_e('资源类型', 'aksrt'); ?>
|
||||
</h3>
|
||||
<?php if (!empty($resource_type_labels)) : ?>
|
||||
<ul class="aksrt-dl-sidebar-card__list">
|
||||
<li class="<?php echo $type_filter === '' ? 'is-active' : ''; ?>">
|
||||
<a href="<?php echo esc_url(get_permalink()); ?>">
|
||||
<?php esc_html_e('全部资源', 'aksrt'); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php foreach ($resource_type_labels as $type_key => $type_label) : ?>
|
||||
<li class="<?php echo $type_filter === $type_key ? 'is-active' : ''; ?>">
|
||||
<a href="<?php echo esc_url(add_query_arg('resource_type', $type_key, get_permalink())); ?>">
|
||||
<?php echo esc_html($type_label); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-dl-sidebar-card">
|
||||
<h3 class="aksrt-dl-sidebar-card__title">
|
||||
<i class="fas fa-lightbulb"></i>
|
||||
<?php esc_html_e('下载须知', 'aksrt'); ?>
|
||||
</h3>
|
||||
<div class="aksrt-dl-sidebar-card__tips">
|
||||
<p><i class="fas fa-shield-alt" aria-hidden="true"></i> <?php esc_html_e('所有资源均经过安全检测', 'aksrt'); ?></p>
|
||||
<p><i class="fas fa-clock" aria-hidden="true"></i> <?php esc_html_e('下载链接 10 分钟内有效', 'aksrt'); ?></p>
|
||||
<p><i class="fas fa-sync-alt" aria-hidden="true"></i> <?php esc_html_e('已下载资源可再次下载', 'aksrt'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Forums
|
||||
* Template Post Type: page
|
||||
*
|
||||
* §7.10 — Tab engine + quick post + plate grid + follow/synthesis/pending streams.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
$current_user_id = get_current_user_id();
|
||||
$view = $forum ? $forum->get_home_view($current_user_id) : [
|
||||
'boards' => [],
|
||||
'recent_topics' => [],
|
||||
'hot_topics' => [],
|
||||
'stats' => [],
|
||||
'permissions' => ['can_compose' => false, 'can_manage' => false],
|
||||
'applications' => [],
|
||||
'home_tabs' => [],
|
||||
'active_index' => 1,
|
||||
'quick_posts' => true,
|
||||
];
|
||||
|
||||
$boards = $view['boards'] ?? [];
|
||||
$recent_topics = $view['recent_topics'] ?? [];
|
||||
$hot_topics = $view['hot_topics'] ?? [];
|
||||
$stats = $view['stats'] ?? [];
|
||||
$permissions = $view['permissions'] ?? [];
|
||||
$applications = $view['applications'] ?? [];
|
||||
$compose_url = home_url('/compose/');
|
||||
|
||||
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
|
||||
$forum_names = $forum_settings['names'] ?? [];
|
||||
$name_forum = $forum_names['forum'] ?? __('论坛', 'aksrt');
|
||||
$name_plate = $forum_names['plate'] ?? __('版块', 'aksrt');
|
||||
$name_topic = $forum_names['posts'] ?? __('主题', 'aksrt');
|
||||
$name_reply = $forum_names['comment'] ?? __('回复', 'aksrt');
|
||||
$admin_forum_url = admin_url('admin.php?page=aksrt-theme-admin#/forum');
|
||||
|
||||
$home_tabs = $view['home_tabs'] ?? [];
|
||||
$active_index = max(0, min(count($home_tabs) - 1, (int) ($view['active_index'] ?? 1)));
|
||||
$quick_posts = !empty($view['quick_posts']);
|
||||
$nonce = wp_create_nonce('aksrt_public_nonce');
|
||||
|
||||
// Resolve active tab from query param or default
|
||||
$active_tab_type = isset($_GET['forum_tab']) ? sanitize_key(wp_unslash($_GET['forum_tab'])) : '';
|
||||
if ($active_tab_type === '' && isset($home_tabs[$active_index])) {
|
||||
$active_tab_type = $home_tabs[$active_index]['type'] ?? 'synthesis';
|
||||
}
|
||||
if ($active_tab_type === '') {
|
||||
$active_tab_type = 'synthesis';
|
||||
}
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main container" tabindex="-1">
|
||||
|
||||
<header class="aksrt-forum-header">
|
||||
<div class="aksrt-forum-header__content">
|
||||
<h1 class="aksrt-forum-header__title"><?php echo esc_html(get_the_title() ?: __('社区论坛', 'aksrt')); ?></h1>
|
||||
<?php if (get_the_excerpt()) : ?>
|
||||
<p class="aksrt-forum-header__desc"><?php echo esc_html(get_the_excerpt()); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-forum-header__actions">
|
||||
<?php if (!empty($permissions['can_compose'])) : ?>
|
||||
<a class="aksrt-forum-header__action aksrt-forum-header__action--primary" href="<?php echo esc_url($compose_url); ?>">
|
||||
<i class="fas fa-pen"></i> <?php esc_html_e('发布主题', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<a class="aksrt-forum-header__action aksrt-forum-header__action--primary" href="<?php echo esc_url(wp_login_url(get_permalink())); ?>">
|
||||
<i class="fas fa-sign-in-alt"></i> <?php esc_html_e('登录后发帖', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($permissions['can_manage'])) : ?>
|
||||
<a class="aksrt-forum-header__action" href="<?php echo esc_url($admin_forum_url); ?>">
|
||||
<i class="fas fa-tools"></i> <?php esc_html_e('进入治理后台', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-forum-header__stats">
|
||||
<div class="aksrt-forum-header__stat">
|
||||
<span class="aksrt-forum-header__stat-num"><?php echo esc_html(number_format_i18n((int) ($stats['board_count'] ?? 0))); ?></span>
|
||||
<span class="aksrt-forum-header__stat-label"><?php echo esc_html($name_plate); ?></span>
|
||||
</div>
|
||||
<div class="aksrt-forum-header__stat">
|
||||
<span class="aksrt-forum-header__stat-num"><?php echo esc_html(number_format_i18n((int) ($stats['topic_count'] ?? 0))); ?></span>
|
||||
<span class="aksrt-forum-header__stat-label"><?php echo esc_html($name_topic); ?></span>
|
||||
</div>
|
||||
<div class="aksrt-forum-header__stat">
|
||||
<span class="aksrt-forum-header__stat-num"><?php echo esc_html(number_format_i18n((int) ($stats['post_count'] ?? 0))); ?></span>
|
||||
<span class="aksrt-forum-header__stat-label"><?php echo esc_html($name_reply); ?></span>
|
||||
</div>
|
||||
<div class="aksrt-forum-header__stat">
|
||||
<span class="aksrt-forum-header__stat-num"><?php echo esc_html(number_format_i18n((int) ($stats['moderator_count'] ?? 0))); ?></span>
|
||||
<span class="aksrt-forum-header__stat-label"><?php esc_html_e('版主', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<?php if (isset($_GET['compose_status']) && $_GET['compose_status'] === 'pending') : ?>
|
||||
<div class="aksrt-alert aksrt-alert--info" data-aksrt-flash-query="compose_status">
|
||||
<?php esc_html_e('你的主题已提交审核,审核通过后会在版块中展示。', 'aksrt'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-forum container">
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout content-layout--no-sidebar">
|
||||
<div class="content-layout__primary">
|
||||
<div class="aksrt-forum__layout">
|
||||
<div class="aksrt-forum__main">
|
||||
|
||||
<?php if ($quick_posts && !empty($permissions['can_compose'])) : ?>
|
||||
<div class="aksrt-forum-quick-post">
|
||||
<a class="aksrt-forum-quick-post__input" href="<?php echo esc_url($compose_url); ?>">
|
||||
<?php echo get_avatar($current_user_id, 32); ?>
|
||||
<span><?php esc_html_e('分享你的想法…', 'aksrt'); ?></span>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($home_tabs)) : ?>
|
||||
<nav class="aksrt-forum-home-tabs" id="aksrt-forum-home-tabs"
|
||||
data-nonce="<?php echo esc_attr($nonce); ?>"
|
||||
data-ajax-url="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>">
|
||||
<?php foreach ($home_tabs as $i => $tab) :
|
||||
$tab_type = sanitize_key($tab['type'] ?? 'synthesis');
|
||||
$tab_label = esc_html($tab['label'] ?? $tab_type);
|
||||
$is_active = $tab_type === $active_tab_type;
|
||||
if ($tab_type === 'pending' && empty($permissions['can_manage'])) continue;
|
||||
?>
|
||||
<button type="button"
|
||||
class="aksrt-forum-home-tabs__btn<?php echo $is_active ? ' is-active' : ''; ?>"
|
||||
data-tab-type="<?php echo esc_attr($tab_type); ?>">
|
||||
<?php echo $tab_label; ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
<?php if (!empty($permissions['can_manage'])) : ?>
|
||||
<button type="button"
|
||||
class="aksrt-forum-home-tabs__btn<?php echo $active_tab_type === 'pending' ? ' is-active' : ''; ?>"
|
||||
data-tab-type="pending">
|
||||
<?php esc_html_e('待审核', 'aksrt'); ?>
|
||||
<?php if ((int) ($stats['pending_topic_count'] ?? 0) > 0) : ?>
|
||||
<span class="aksrt-forum-home-tabs__badge"><?php echo esc_html((string) ($stats['pending_topic_count'] ?? 0)); ?></span>
|
||||
<?php endif; ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-forum-home-content" id="aksrt-forum-home-content">
|
||||
<?php if ($active_tab_type === 'plate') : ?>
|
||||
<?php if (!empty($boards)) : ?>
|
||||
<div class="aksrt-forum-boards__grid">
|
||||
<?php foreach ($boards as $board) :
|
||||
$board_id = (int) ($board['id'] ?? 0);
|
||||
?>
|
||||
<article class="aksrt-forum-board-card">
|
||||
<a class="aksrt-forum-board-card__link" href="<?php echo esc_url((string) ($board['url'] ?? '#')); ?>">
|
||||
<div class="aksrt-forum-board-card__icon">
|
||||
<?php if (!empty($board['thumbnail_url'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $board['thumbnail_url']); ?>" alt="" width="48" height="48">
|
||||
<?php else : ?>
|
||||
<i class="<?php echo esc_attr((string) ($board['icon'] ?: 'fas fa-comments')); ?>"></i>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="aksrt-forum-board-card__body">
|
||||
<div class="aksrt-forum-board-card__head">
|
||||
<h3 class="aksrt-forum-board-card__title"><?php echo esc_html((string) ($board['name'] ?? '')); ?></h3>
|
||||
</div>
|
||||
<?php if (!empty($board['description'])) : ?>
|
||||
<p class="aksrt-forum-board-card__desc"><?php echo esc_html((string) $board['description']); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-forum-board-card__meta">
|
||||
<span><i class="fas fa-file-alt"></i> <?php echo esc_html(number_format_i18n((int) ($board['topic_count'] ?? $board['post_count'] ?? 0))); ?></span>
|
||||
<span><i class="fas fa-comment"></i> <?php echo esc_html(number_format_i18n((int) ($board['reply_count'] ?? 0))); ?></span>
|
||||
<span><i class="fas fa-heart"></i> <?php echo esc_html(number_format_i18n((int) ($board['follow_count'] ?? 0))); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum__empty">
|
||||
<i class="fas fa-comments"></i>
|
||||
<p><?php esc_html_e('当前还没有论坛版块。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php elseif ($active_tab_type === 'follow') : ?>
|
||||
<?php
|
||||
$follow_data = $forum ? $forum->get_follow_stream($current_user_id) : ['items' => []];
|
||||
if (!empty($follow_data['items'])) : ?>
|
||||
<div class="aksrt-forum-topics__list js-aksrt-home-topic-list">
|
||||
<?php foreach ($follow_data['items'] as $topic) { $forum->render_topic_row($topic); } ?>
|
||||
</div>
|
||||
<?php if ($follow_data['max_pages'] > 1) : ?>
|
||||
<div class="aksrt-forum-home__load-more">
|
||||
<button type="button" class="aksrt-forum-replies__more-btn js-aksrt-home-load-more"
|
||||
data-page="1" data-max="<?php echo esc_attr((string) $follow_data['max_pages']); ?>"
|
||||
data-tab="follow">
|
||||
<i class="fas fa-chevron-down"></i> <?php esc_html_e('加载更多', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php elseif ($current_user_id > 0) : ?>
|
||||
<div class="aksrt-forum__empty">
|
||||
<i class="far fa-heart"></i>
|
||||
<p><?php esc_html_e('你还没有关注任何版块,去看看有哪些版块吧!', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum__empty">
|
||||
<i class="fas fa-sign-in-alt"></i>
|
||||
<p><?php esc_html_e('登录后即可看到你关注的版块内容。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php elseif ($active_tab_type === 'pending') : ?>
|
||||
<?php
|
||||
$pending_data = $forum ? $forum->get_pending_stream($current_user_id) : ['items' => []];
|
||||
if (!empty($pending_data['items'])) : ?>
|
||||
<div class="aksrt-forum-topics__list js-aksrt-home-topic-list">
|
||||
<?php foreach ($pending_data['items'] as $topic) { $forum->render_topic_row($topic); } ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum__empty">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<p><?php esc_html_e('没有待审核的主题。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php else : /* synthesis (default) */ ?>
|
||||
<?php if (!empty($recent_topics)) : ?>
|
||||
<div class="aksrt-forum-topics__list js-aksrt-home-topic-list">
|
||||
<?php foreach ($recent_topics as $topic) {
|
||||
if ($forum) { $forum->render_topic_row($topic); }
|
||||
} ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-forum__empty">
|
||||
<i class="fas fa-feather-alt"></i>
|
||||
<p><?php esc_html_e('还没有公开主题,欢迎创建第一个讨论。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="aksrt-forum__sidebar">
|
||||
<div class="aksrt-forum-sidebar-card">
|
||||
<h3 class="aksrt-forum-sidebar-card__title">
|
||||
<i class="fas fa-fire"></i>
|
||||
<?php printf(esc_html__('热门%s', 'aksrt'), esc_html($name_topic)); ?>
|
||||
</h3>
|
||||
<?php if (!empty($hot_topics)) : ?>
|
||||
<ul class="aksrt-forum-sidebar-card__list">
|
||||
<?php foreach ($hot_topics as $index => $topic) : ?>
|
||||
<li class="aksrt-forum-sidebar-card__item">
|
||||
<span class="aksrt-forum-sidebar-card__rank"><?php echo esc_html((string) ($index + 1)); ?></span>
|
||||
<a href="<?php echo esc_url((string) ($topic['permalink'] ?? '#')); ?>" class="aksrt-forum-sidebar-card__link">
|
||||
<?php echo esc_html((string) ($topic['title'] ?? '')); ?>
|
||||
</a>
|
||||
<span class="aksrt-forum-sidebar-card__views"><?php echo esc_html(number_format_i18n((int) ($topic['views'] ?? 0))); ?></span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php else : ?>
|
||||
<p class="aksrt-forum-sidebar-card__empty"><?php esc_html_e('暂无热门主题', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($boards)) : ?>
|
||||
<div class="aksrt-forum-sidebar-card">
|
||||
<h3 class="aksrt-forum-sidebar-card__title">
|
||||
<i class="fas fa-th-list"></i>
|
||||
<?php echo esc_html($name_plate); ?>
|
||||
</h3>
|
||||
<ul class="aksrt-forum-sidebar-card__list">
|
||||
<?php foreach (array_slice($boards, 0, 8) as $board) : ?>
|
||||
<li class="aksrt-forum-sidebar-card__item">
|
||||
<a href="<?php echo esc_url((string) ($board['url'] ?? '#')); ?>" class="aksrt-forum-sidebar-card__link">
|
||||
<?php echo esc_html((string) ($board['name'] ?? '')); ?>
|
||||
</a>
|
||||
<span class="aksrt-forum-sidebar-card__views"><?php echo esc_html(number_format_i18n((int) ($board['topic_count'] ?? $board['post_count'] ?? 0))); ?></span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($applications)) : ?>
|
||||
<div class="aksrt-forum-sidebar-card">
|
||||
<h3 class="aksrt-forum-sidebar-card__title">
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
<?php esc_html_e('版主申请状态', 'aksrt'); ?>
|
||||
</h3>
|
||||
<ul class="aksrt-forum-sidebar-card__list aksrt-forum-sidebar-card__list--applications">
|
||||
<?php foreach ($applications as $board_id => $application) :
|
||||
if (!$application) continue;
|
||||
$board_name = '';
|
||||
foreach ($boards as $board) {
|
||||
if ((int) ($board['id'] ?? 0) === (int) $board_id) {
|
||||
$board_name = (string) ($board['name'] ?? '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<li class="aksrt-forum-sidebar-card__item aksrt-forum-sidebar-card__item--stack">
|
||||
<strong><?php echo esc_html($board_name); ?></strong>
|
||||
<span><?php echo esc_html((string) ($application['status_label'] ?? '')); ?></span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: 友情链接
|
||||
* Template Post Type: page
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$links = function_exists('aksrt_get_friend_links') ? aksrt_get_friend_links() : [];
|
||||
?>
|
||||
|
||||
<main id="main-content" class="container page-content-default" tabindex="-1">
|
||||
<header class="page-header">
|
||||
<h1 class="entry-title"><?php esc_html_e('友情链接', 'aksrt'); ?></h1>
|
||||
<p><?php esc_html_e('与这些优秀的站点交换友链', 'aksrt'); ?></p>
|
||||
</header>
|
||||
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout content-layout--no-sidebar">
|
||||
<div class="content-layout__primary">
|
||||
|
||||
<?php if (! empty($links)) : ?>
|
||||
<div class="friends-grid">
|
||||
<?php foreach ($links as $link) : ?>
|
||||
<a class="friend-card" href="<?php echo esc_url($link['url'] ?? '#'); ?>" target="_blank" rel="noopener noreferrer">
|
||||
<?php
|
||||
$logo = $link['logo'] ?? '';
|
||||
if ($logo) {
|
||||
echo '<img class="friend-card__avatar" src="' . esc_url($logo) . '" alt="">';
|
||||
} else {
|
||||
$initial = function_exists('mb_substr') ? mb_substr((string) ($link['name'] ?? 'A'), 0, 1, 'UTF-8') : substr((string) ($link['name'] ?? 'A'), 0, 1);
|
||||
echo '<div class="friend-card__avatar" style="display:flex;align-items:center;justify-content:center;font-weight:800;color:var(--color-primary);font-family:var(--font-heading);">' . esc_html($initial) . '</div>';
|
||||
}
|
||||
?>
|
||||
<div class="friend-card__info">
|
||||
<h3 class="friend-card__name"><?php echo esc_html($link['name'] ?? ''); ?></h3>
|
||||
<p class="friend-card__desc"><?php echo esc_html($link['description'] ?? ''); ?></p>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="no-results">
|
||||
<p><?php esc_html_e('暂无友链,请在主题后台添加。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<p style="text-align:center;margin-top:32px;">
|
||||
<a class="btn-outline" href="<?php echo esc_url(home_url('/')); ?>"><?php esc_html_e('返回首页', 'aksrt'); ?></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Login
|
||||
* Template Post Type: page
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
require AKSRT_DIR . '/templates/pages/page-sign.php';
|
||||
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: 消息中心
|
||||
* Template Post Type: page
|
||||
*
|
||||
* 独立消息中心页面 — 两栏布局(左侧导航 + 右侧消息列表)
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
if ( ! is_user_logged_in() ) {
|
||||
$login_url = function_exists( 'aksrt_get_login_url' ) ? aksrt_get_login_url() : wp_login_url( get_permalink() );
|
||||
wp_safe_redirect( $login_url );
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// 获取所有通知(持久化 + 即时状态)
|
||||
$all_notifications = function_exists( 'aksrt_get_user_all_notifications' )
|
||||
? aksrt_get_user_all_notifications( $user_id )
|
||||
: [];
|
||||
|
||||
// 筛选类型
|
||||
$current_type = isset( $_GET['msg_type'] ) ? sanitize_key( $_GET['msg_type'] ) : 'all';
|
||||
|
||||
// 按类型过滤
|
||||
$filtered = $all_notifications;
|
||||
if ( $current_type === 'unread' ) {
|
||||
$filtered = array_filter( $filtered, static fn( $n ) => empty( $n['read'] ) );
|
||||
} elseif ( $current_type !== 'all' ) {
|
||||
$filtered = array_filter( $filtered, static fn( $n ) => ( $n['type'] ?? '' ) === $current_type );
|
||||
}
|
||||
$filtered = array_values( $filtered );
|
||||
|
||||
// 分页
|
||||
$per_page = 20;
|
||||
$current_page = max( 1, (int) ( $_GET['msg_page'] ?? 1 ) );
|
||||
$total = count( $filtered );
|
||||
$total_pages = max( 1, (int) ceil( $total / $per_page ) );
|
||||
$offset = ( $current_page - 1 ) * $per_page;
|
||||
$paged_items = array_slice( $filtered, $offset, $per_page );
|
||||
|
||||
// 统计各类型数量
|
||||
$type_counts = [ 'all' => count( $all_notifications ), 'unread' => 0 ];
|
||||
foreach ( $all_notifications as $n ) {
|
||||
$t = $n['type'] ?? 'notice';
|
||||
$type_counts[ $t ] = ( $type_counts[ $t ] ?? 0 ) + 1;
|
||||
if ( empty( $n['read'] ) ) {
|
||||
$type_counts['unread']++;
|
||||
}
|
||||
}
|
||||
|
||||
// 导航定义
|
||||
$nav_items = [
|
||||
'all' => __( '全部消息', 'aksrt' ),
|
||||
'unread' => __( '未读', 'aksrt' ),
|
||||
'conversation' => __( '私信', 'aksrt' ),
|
||||
'comment_reply' => __( '评论回复', 'aksrt' ),
|
||||
'comment_approved' => __( '评论审核', 'aksrt' ),
|
||||
'credits_added' => __( '积分增加', 'aksrt' ),
|
||||
'credits_deducted' => __( '积分扣减', 'aksrt' ),
|
||||
'download_ready' => __( '下载就绪', 'aksrt' ),
|
||||
'upload_moderation'=> __( '图片审核', 'aksrt' ),
|
||||
'notice' => __( '系统通知', 'aksrt' ),
|
||||
];
|
||||
|
||||
// 图标映射
|
||||
$icon_map = [
|
||||
'comment_reply' => 'fas fa-comment-dots',
|
||||
'comment_approved' => 'fas fa-check-circle',
|
||||
'credits_added' => 'fas fa-coins',
|
||||
'credits_deducted' => 'fas fa-coins',
|
||||
'download_ready' => 'fas fa-download',
|
||||
'upload_moderation'=> 'fas fa-image',
|
||||
'verify_email' => 'fas fa-envelope-open-text',
|
||||
'pending_comments' => 'fas fa-clock',
|
||||
'conversation' => 'fas fa-envelope',
|
||||
'notice' => 'fas fa-bell',
|
||||
];
|
||||
?>
|
||||
|
||||
<div class="messages-center container">
|
||||
<aside class="messages-center__nav">
|
||||
<ul class="messages-nav__list">
|
||||
<?php foreach ( $nav_items as $key => $label ) :
|
||||
$count = (int) ( $type_counts[ $key ] ?? 0 );
|
||||
if ( $key !== 'all' && $key !== 'unread' && $count < 1 ) continue;
|
||||
$is_active = $current_type === $key;
|
||||
?>
|
||||
<li>
|
||||
<a href="<?php echo esc_url( add_query_arg( [ 'msg_type' => $key, 'msg_page' => 1 ] ) ); ?>"
|
||||
class="messages-nav__item<?php echo $is_active ? ' is-active' : ''; ?>"
|
||||
data-type="<?php echo esc_attr( $key ); ?>">
|
||||
<span><?php echo esc_html( $label ); ?></span>
|
||||
<?php if ( $count > 0 ) : ?>
|
||||
<span class="messages-nav__badge" data-type="<?php echo esc_attr( $key ); ?>" data-count="<?php echo esc_attr( (string) $count ); ?>"><?php echo esc_html( (string) $count ); ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<div class="messages-nav__actions">
|
||||
<button type="button" class="messages-nav__action-btn js-msg-mark-all-read"><?php esc_html_e( '全部已读', 'aksrt' ); ?></button>
|
||||
<button type="button" class="messages-nav__action-btn js-msg-clear-read"><?php esc_html_e( '清除已读', 'aksrt' ); ?></button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="messages-center__content">
|
||||
<?php if ( $current_type === 'conversation' ) :
|
||||
$pm = class_exists( 'AKSRT_Private_Message' ) ? AKSRT_Private_Message::get_instance() : null;
|
||||
$conversations = $pm ? $pm->get_conversations( $user_id, 30 ) : [];
|
||||
$pm_nonce = wp_create_nonce( 'aksrt_pm' );
|
||||
?>
|
||||
<div class="messages-conversations" id="aksrt-pm-conversations"
|
||||
data-ajax="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>"
|
||||
data-nonce="<?php echo esc_attr( $pm_nonce ); ?>">
|
||||
<?php if ( ! empty( $conversations ) ) : ?>
|
||||
<div class="aksrt-pm__list">
|
||||
<?php foreach ( $conversations as $conv ) : ?>
|
||||
<div class="aksrt-pm__item<?php echo $conv['unread'] > 0 ? ' is-unread' : ''; ?>"
|
||||
data-conv-id="<?php echo esc_attr( (string) $conv['id'] ); ?>"
|
||||
data-other-id="<?php echo esc_attr( (string) $conv['other_user_id'] ); ?>">
|
||||
<img class="aksrt-pm__avatar" src="<?php echo esc_url( $conv['other_avatar'] ); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('avatar') : ' loading="lazy"'; ?> />
|
||||
<div class="aksrt-pm__info">
|
||||
<div class="aksrt-pm__name">
|
||||
<?php echo esc_html( $conv['other_name'] ); ?>
|
||||
<?php if ( $conv['unread'] > 0 ) : ?>
|
||||
<span class="aksrt-pm__badge"><?php echo esc_html( (string) $conv['unread'] ); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="aksrt-pm__preview"><?php echo esc_html( mb_substr( $conv['last_message'], 0, 50 ) ); ?></div>
|
||||
</div>
|
||||
<div class="aksrt-pm__time"><?php echo esc_html( $conv['last_message_at'] ? mysql2date( 'm-d H:i', $conv['last_message_at'] ) : '' ); ?></div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="messages-empty">
|
||||
<span class="messages-empty__icon"><i class="fas fa-envelope"></i></span>
|
||||
<p class="messages-empty__text"><?php esc_html_e( '暂无私信', 'aksrt' ); ?></p>
|
||||
<p class="messages-empty__hint"><?php esc_html_e( '你可以在用户主页发起私信。', 'aksrt' ); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-pm__thread" id="aksrt-pm-thread" style="display:none;">
|
||||
<div class="aksrt-pm__thread-header">
|
||||
<button type="button" class="aksrt-pm__back-btn" id="aksrt-pm-back"><i class="fas fa-arrow-left"></i> <?php esc_html_e( '返回', 'aksrt' ); ?></button>
|
||||
<span class="aksrt-pm__thread-name" id="aksrt-pm-thread-name"></span>
|
||||
</div>
|
||||
<div class="aksrt-pm__messages" id="aksrt-pm-messages"></div>
|
||||
<div class="aksrt-pm__compose">
|
||||
<textarea id="aksrt-pm-input" rows="2" placeholder="<?php esc_attr_e( '输入消息...', 'aksrt' ); ?>"></textarea>
|
||||
<button type="button" id="aksrt-pm-send" class="aksrt-pm__send-btn"><i class="fas fa-paper-plane"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php /* conversation.js is enqueued via AKSRT_Scripts */ ?>
|
||||
<?php elseif ( ! empty( $paged_items ) ) : ?>
|
||||
<div class="messages-list">
|
||||
<?php foreach ( $paged_items as $notice ) :
|
||||
$n_type = (string) ( $notice['type'] ?? 'notice' );
|
||||
$n_title = (string) ( $notice['title'] ?? '' );
|
||||
$n_desc = (string) ( $notice['desc'] ?? '' );
|
||||
$n_url = (string) ( $notice['url'] ?? '' );
|
||||
$n_id = (string) ( $notice['id'] ?? '' );
|
||||
$is_read = ! empty( $notice['read'] );
|
||||
$is_state = ! empty( $notice['stateful'] );
|
||||
$created = (string) ( $notice['created_at'] ?? '' );
|
||||
$time_str = $is_state
|
||||
? __( '状态提醒', 'aksrt' )
|
||||
: ( $created !== '' ? get_date_from_gmt( $created, 'Y-m-d H:i' ) : '' );
|
||||
$icon_cls = $icon_map[ $n_type ] ?? 'fas fa-bell';
|
||||
?>
|
||||
<div class="message-item<?php echo ! $is_read ? ' is-unread' : ''; ?>" data-notification-id="<?php echo esc_attr( $n_id ); ?>">
|
||||
<span class="message-item__icon">
|
||||
<i class="<?php echo esc_attr( $icon_cls ); ?>" aria-hidden="true"></i>
|
||||
</span>
|
||||
<div class="message-item__body">
|
||||
<div class="message-item__title">
|
||||
<?php echo esc_html( $n_title ); ?>
|
||||
<?php if ( ! $is_read && ! $is_state ) : ?>
|
||||
<span class="message-item__new-badge">NEW</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php if ( $n_desc !== '' ) : ?>
|
||||
<div class="message-item__desc"><?php echo esc_html( $n_desc ); ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ( $time_str !== '' ) : ?>
|
||||
<div class="message-item__time"><?php echo esc_html( $time_str ); ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="message-item__actions">
|
||||
<?php if ( $n_url !== '' ) : ?>
|
||||
<a href="<?php echo esc_url( $n_url ); ?>" class="message-item__action-btn"><?php esc_html_e( '查看', 'aksrt' ); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! $is_state && ! $is_read ) : ?>
|
||||
<button type="button" class="message-item__action-btn js-msg-mark-read" data-id="<?php echo esc_attr( $n_id ); ?>"><?php esc_html_e( '已读', 'aksrt' ); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! $is_state ) : ?>
|
||||
<button type="button" class="message-item__action-btn message-item__action-btn--danger js-msg-delete" data-id="<?php echo esc_attr( $n_id ); ?>"><?php esc_html_e( '删除', 'aksrt' ); ?></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ( $total_pages > 1 ) : ?>
|
||||
<div class="messages-pagination">
|
||||
<?php for ( $i = 1; $i <= $total_pages; $i++ ) :
|
||||
$page_url = add_query_arg( [ 'msg_type' => $current_type, 'msg_page' => $i ] );
|
||||
?>
|
||||
<?php if ( $i === $current_page ) : ?>
|
||||
<span class="profile-status-chip is-active"><?php echo esc_html( (string) $i ); ?></span>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url( $page_url ); ?>" class="profile-status-chip"><?php echo esc_html( (string) $i ); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php else : ?>
|
||||
<div class="messages-empty">
|
||||
<span class="messages-empty__icon"><i class="fas fa-bell-slash"></i></span>
|
||||
<p class="messages-empty__text"><?php esc_html_e( '暂无消息', 'aksrt' ); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - New Posts
|
||||
* Template Post Type: page
|
||||
*
|
||||
* 最新文章页:按时间倒序展示最新发布的文章。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$paged = max(1, (int) get_query_var('paged'));
|
||||
$per_page = 20;
|
||||
|
||||
$query = new WP_Query([
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $paged,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
]);
|
||||
?>
|
||||
|
||||
<main id="main-content" class="container page-content-default" tabindex="-1">
|
||||
<header class="page-header">
|
||||
<h1 class="entry-title"><?php echo esc_html(get_the_title() ?: __('最新文章', 'aksrt')); ?></h1>
|
||||
</header>
|
||||
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout content-layout--no-sidebar">
|
||||
<div class="content-layout__primary">
|
||||
<div class="aksrt-newposts container">
|
||||
<?php if ($query->have_posts()) : ?>
|
||||
<div class="aksrt-newposts__list">
|
||||
<?php while ($query->have_posts()) : $query->the_post(); ?>
|
||||
<article class="aksrt-newposts__item">
|
||||
<span class="aksrt-newposts__date"><?php echo esc_html(get_the_date()); ?></span>
|
||||
<h3 class="aksrt-newposts__title">
|
||||
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
|
||||
</h3>
|
||||
<p class="aksrt-newposts__excerpt"><?php echo esc_html(wp_trim_words(get_the_excerpt(), 30)); ?></p>
|
||||
</article>
|
||||
<?php endwhile; ?>
|
||||
</div>
|
||||
<?php
|
||||
if (function_exists('aksrt_render_pagination')) {
|
||||
aksrt_render_pagination($query);
|
||||
} else {
|
||||
echo '<div class="aksrt-pagination">' . paginate_links(['total' => $query->max_num_pages]) . '</div>';
|
||||
}
|
||||
?>
|
||||
<?php wp_reset_postdata(); ?>
|
||||
<?php else : ?>
|
||||
<p class="aksrt-newposts__empty"><?php esc_html_e('暂无文章。', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Orders
|
||||
* Template Post Type: page
|
||||
*
|
||||
* Enhanced: 5 tabs, logistics timeline, receipt confirm,
|
||||
* review button, re-purchase, gift/discount details (§6.10).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
|
||||
wp_safe_redirect($login_url);
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$per_page = 20;
|
||||
$paged = max(1, (int) ($_GET['order_page'] ?? 1));
|
||||
$tab = sanitize_key((string) ($_GET['tab'] ?? ''));
|
||||
$status = sanitize_key((string) ($_GET['order_status'] ?? ''));
|
||||
|
||||
$tab_status_map = [
|
||||
'pending' => AKSRT_Order::STATUS_PENDING,
|
||||
'shipped' => AKSRT_Order::STATUS_DELIVERED,
|
||||
'received' => AKSRT_Order::STATUS_COMPLETED,
|
||||
'review' => AKSRT_Order::STATUS_PENDING_REVIEW,
|
||||
'after' => AKSRT_Order::STATUS_REFUNDING,
|
||||
];
|
||||
if ($tab !== '' && isset($tab_status_map[$tab])) {
|
||||
$status = $tab_status_map[$tab];
|
||||
}
|
||||
|
||||
$orders_view = function_exists('aksrt_get_orders_page_view')
|
||||
? aksrt_get_orders_page_view($user_id, $paged, $per_page, $status)
|
||||
: ['items' => [], 'total' => 0, 'total_pages' => 1, 'page' => 1];
|
||||
|
||||
$orders = (array) ($orders_view['items'] ?? []);
|
||||
$total_pages = max(1, (int) ($orders_view['total_pages'] ?? 1));
|
||||
|
||||
$shop = class_exists('AKSRT_Shop') ? AKSRT_Shop::get_instance() : null;
|
||||
$shipping = class_exists('AKSRT_Shipping') ? AKSRT_Shipping::get_instance() : null;
|
||||
|
||||
$tabs = [
|
||||
'' => __('全部', 'aksrt'),
|
||||
'pending' => __('待支付', 'aksrt'),
|
||||
'shipped' => __('待收货', 'aksrt'),
|
||||
'review' => __('待评价', 'aksrt'),
|
||||
'after' => __('售后', 'aksrt'),
|
||||
];
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<div class="container aksrt-orders-page" data-aksrt-order-center>
|
||||
<div class="aksrt-orders-page__header">
|
||||
<h1><?php esc_html_e('我的订单', 'aksrt'); ?></h1>
|
||||
</div>
|
||||
|
||||
<!-- 5-tab navigation -->
|
||||
<div class="aksrt-orders-page__tabs">
|
||||
<?php foreach ($tabs as $tab_key => $tab_label) :
|
||||
$is_active = $tab === $tab_key;
|
||||
$tab_url = $tab_key !== '' ? add_query_arg(['tab' => $tab_key, 'order_page' => 1]) : remove_query_arg(['tab', 'order_status', 'order_page']);
|
||||
?>
|
||||
<a href="<?php echo esc_url($tab_url); ?>" class="aksrt-orders-page__tab<?php echo $is_active ? ' is-active' : ''; ?>">
|
||||
<?php echo esc_html($tab_label); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($orders)) : ?>
|
||||
<div class="aksrt-orders-page__list">
|
||||
<?php foreach ($orders as $order) :
|
||||
$on = (string) ($order['order_number'] ?? '');
|
||||
$os = (string) ($order['status'] ?? '');
|
||||
$items = $order['items'] ?? [];
|
||||
?>
|
||||
<article class="aksrt-orders-page__card" data-aksrt-order-card="<?php echo esc_attr($on); ?>">
|
||||
<!-- Card header -->
|
||||
<div class="aksrt-orders-page__card-head">
|
||||
<span class="aksrt-orders-page__card-number"><?php echo esc_html($on); ?></span>
|
||||
<time class="aksrt-orders-page__card-time"><?php echo esc_html((string) ($order['created_at'] ?? '')); ?></time>
|
||||
<span class="aksrt-orders-page__card-status"><?php echo esc_html((string) ($order['status_label'] ?? '')); ?></span>
|
||||
</div>
|
||||
|
||||
<!-- Order items -->
|
||||
<div class="aksrt-orders-page__card-items">
|
||||
<?php if (!empty($items)) : ?>
|
||||
<?php foreach ($items as $item) : ?>
|
||||
<div class="aksrt-orders-page__card-item">
|
||||
<?php if (!empty($item['image'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $item['image']); ?>" alt="" class="aksrt-orders-page__card-img">
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-orders-page__card-item-info">
|
||||
<span class="aksrt-orders-page__card-item-title"><?php echo esc_html((string) ($item['product_title'] ?? '')); ?></span>
|
||||
<?php if (!empty($item['options_label'])) : ?>
|
||||
<small class="aksrt-orders-page__card-item-opts"><?php echo esc_html((string) $item['options_label']); ?></small>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="aksrt-orders-page__card-item-price">
|
||||
<strong>¥<?php echo esc_html(number_format((float) ($item['pay_price'] ?? $item['unit_price'] ?? 0), 2)); ?></strong>
|
||||
<span>×<?php echo esc_html((string) ($item['quantity'] ?? 1)); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-orders-page__card-item">
|
||||
<span class="aksrt-orders-page__card-item-title"><?php echo esc_html((string) ($order['product_name'] ?? __('商品订单', 'aksrt'))); ?></span>
|
||||
<strong>¥<?php echo esc_html(number_format((float) ($order['amount'] ?? 0), 2)); ?></strong>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Price summary -->
|
||||
<div class="aksrt-orders-page__card-summary">
|
||||
<span><?php esc_html_e('合计', 'aksrt'); ?></span>
|
||||
<strong>¥<?php echo esc_html(number_format((float) ($order['amount'] ?? 0), 2)); ?></strong>
|
||||
<?php if ((float) ($order['discount'] ?? 0) > 0) : ?>
|
||||
<small>(<?php printf(esc_html__('已优惠 ¥%s', 'aksrt'), number_format((float) $order['discount'], 2)); ?>)</small>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Logistics timeline (collapsed) -->
|
||||
<?php if (!empty($order['shipping_records'])) : ?>
|
||||
<div class="aksrt-orders-page__timeline" data-aksrt-timeline>
|
||||
<h4 class="aksrt-orders-page__timeline-toggle" data-aksrt-toggle-timeline>
|
||||
<i class="fas fa-truck"></i> <?php esc_html_e('物流信息', 'aksrt'); ?> <i class="fas fa-chevron-down"></i>
|
||||
</h4>
|
||||
<div class="aksrt-orders-page__timeline-body" hidden>
|
||||
<?php foreach ((array) ($order['timeline'] ?? []) as $tl) : ?>
|
||||
<div class="aksrt-orders-page__timeline-item">
|
||||
<time><?php echo esc_html((string) ($tl['time'] ?? '')); ?></time>
|
||||
<span><?php echo esc_html((string) ($tl['label'] ?? '')); ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="aksrt-orders-page__card-actions">
|
||||
<?php if (!empty($order['actions']['can_pay'])) : ?>
|
||||
<button type="button" class="btn-primary btn-sm" data-aksrt-order-pay="<?php echo esc_attr($on); ?>"><?php esc_html_e('去支付', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($order['actions']['can_receipt'])) : ?>
|
||||
<button type="button" class="btn-primary btn-sm" data-aksrt-order-receipt="<?php echo esc_attr($on); ?>"><?php esc_html_e('确认收货', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if ($os === AKSRT_Order::STATUS_PENDING_REVIEW) : ?>
|
||||
<button type="button" class="btn-primary btn-sm" data-aksrt-order-review="<?php echo esc_attr($on); ?>"><?php esc_html_e('去评价', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($order['actions']['can_cancel'])) : ?>
|
||||
<button type="button" class="btn-ghost btn-sm" data-aksrt-order-cancel="<?php echo esc_attr($on); ?>"><?php esc_html_e('取消', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if (in_array($os, [AKSRT_Order::STATUS_COMPLETED, AKSRT_Order::STATUS_PENDING_REVIEW], true)) : ?>
|
||||
<button type="button" class="btn-outline btn-sm" data-aksrt-order-rebuy="<?php echo esc_attr($on); ?>"><?php esc_html_e('再次购买', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($order['actions']['can_after_sale'])) : ?>
|
||||
<button type="button" class="btn-outline btn-sm" data-aksrt-order-after-sale="<?php echo esc_attr($on); ?>"><?php esc_html_e('售后', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($order['time_left'])) : ?>
|
||||
<span class="aksrt-orders-page__countdown" data-aksrt-order-countdown="<?php echo esc_attr((string) $order['time_left']); ?>">
|
||||
<?php printf(esc_html__('%d秒后关闭', 'aksrt'), (int) $order['time_left']); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($total_pages > 1) : ?>
|
||||
<div class="aksrt-orders-page__pagination">
|
||||
<?php for ($i = 1; $i <= $total_pages; $i++) :
|
||||
$page_url = add_query_arg(['order_page' => $i]);
|
||||
?>
|
||||
<?php if ($i === $paged) : ?>
|
||||
<span class="aksrt-orders-page__page-chip is-active"><?php echo esc_html((string) $i); ?></span>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url($page_url); ?>" class="aksrt-orders-page__page-chip"><?php echo esc_html((string) $i); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-orders-page__empty">
|
||||
<i class="fas fa-receipt" aria-hidden="true"></i>
|
||||
<p><?php esc_html_e('暂无订单记录。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- After-sale modal -->
|
||||
<div class="aksrt-modal" data-aksrt-aftersale-modal hidden>
|
||||
<div class="aksrt-modal__overlay"></div>
|
||||
<div class="aksrt-modal__dialog">
|
||||
<div class="aksrt-modal__header">
|
||||
<h3><?php esc_html_e('申请售后', 'aksrt'); ?></h3>
|
||||
<button type="button" class="aksrt-modal__close" data-aksrt-aftersale-modal-close>×</button>
|
||||
</div>
|
||||
<form class="aksrt-modal__body" data-aksrt-aftersale-form>
|
||||
<input type="hidden" name="order_number" value="">
|
||||
<div class="aksrt-orders-page__field">
|
||||
<label><?php esc_html_e('售后类型', 'aksrt'); ?></label>
|
||||
<select name="type" class="aksrt-orders-page__select">
|
||||
<?php foreach (AKSRT_After_Sale::get_valid_types() as $type_key => $type_label) : ?>
|
||||
<option value="<?php echo esc_attr($type_key); ?>"><?php echo esc_html($type_label); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="aksrt-orders-page__field">
|
||||
<label><?php esc_html_e('售后原因', 'aksrt'); ?> *</label>
|
||||
<textarea name="reason" class="aksrt-orders-page__textarea" rows="4" required placeholder="<?php esc_attr_e('请描述问题', 'aksrt'); ?>"></textarea>
|
||||
</div>
|
||||
<div class="aksrt-modal__footer">
|
||||
<button type="button" class="btn-ghost" data-aksrt-aftersale-modal-close><?php esc_html_e('取消', 'aksrt'); ?></button>
|
||||
<button type="submit" class="btn-primary"><?php esc_html_e('提交', 'aksrt'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Favorites section -->
|
||||
<?php
|
||||
$fav_tab = sanitize_key((string) ($_GET['section'] ?? ''));
|
||||
if ($fav_tab === 'favorites' && $shop) :
|
||||
$fav_data = $shop->get_user_favorites($user_id);
|
||||
?>
|
||||
<section class="aksrt-orders-page__favorites">
|
||||
<h2><?php esc_html_e('收藏商品', 'aksrt'); ?></h2>
|
||||
<?php if (!empty($fav_data['items'])) : ?>
|
||||
<div class="aksrt-orders-page__fav-grid">
|
||||
<?php foreach ($fav_data['items'] as $fav) : ?>
|
||||
<a href="<?php echo esc_url((string) ($fav['permalink'] ?? '#')); ?>" class="aksrt-orders-page__fav-card">
|
||||
<?php if (!empty($fav['image'])) : ?>
|
||||
<img src="<?php echo esc_url((string) $fav['image']); ?>" alt="" loading="lazy">
|
||||
<?php endif; ?>
|
||||
<h3><?php echo esc_html((string) ($fav['title'] ?? '')); ?></h3>
|
||||
<strong>¥<?php echo esc_html(number_format((float) ($fav['price'] ?? 0), 2)); ?></strong>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p><?php esc_html_e('暂无收藏商品', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Posts Navigation
|
||||
* Template Post Type: page
|
||||
*
|
||||
* 文章导航页:分类+标签的导航聚合页。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$categories = get_categories(['hide_empty' => true, 'orderby' => 'count', 'order' => 'DESC', 'number' => 20]);
|
||||
$tags = get_tags(['hide_empty' => true, 'orderby' => 'count', 'order' => 'DESC', 'number' => 40]);
|
||||
?>
|
||||
|
||||
<main id="main-content" class="container page-content-default" tabindex="-1">
|
||||
<header class="page-header">
|
||||
<h1 class="entry-title"><?php echo esc_html(get_the_title() ?: __('文章导航', 'aksrt')); ?></h1>
|
||||
</header>
|
||||
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout content-layout--no-sidebar">
|
||||
<div class="content-layout__primary">
|
||||
<div class="aksrt-posts-navs container">
|
||||
<?php if (!empty($categories)) : ?>
|
||||
<section class="aksrt-posts-navs__section">
|
||||
<h2 class="aksrt-posts-navs__heading"><?php esc_html_e('热门分类', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-posts-navs__cats">
|
||||
<?php foreach ($categories as $cat) : ?>
|
||||
<a href="<?php echo esc_url(get_category_link($cat->term_id)); ?>" class="aksrt-posts-navs__cat-chip">
|
||||
<span class="aksrt-posts-navs__cat-name"><?php echo esc_html($cat->name); ?></span>
|
||||
<span class="aksrt-posts-navs__cat-count"><?php echo esc_html($cat->count); ?></span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($tags)) : ?>
|
||||
<section class="aksrt-posts-navs__section">
|
||||
<h2 class="aksrt-posts-navs__heading"><?php esc_html_e('热门标签', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-posts-navs__tags">
|
||||
<?php foreach ($tags as $tag) : ?>
|
||||
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" class="aksrt-posts-navs__tag"><?php echo esc_html($tag->name); ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Product Edit
|
||||
* Template Post Type: page
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
|
||||
wp_safe_redirect($login_url);
|
||||
exit;
|
||||
}
|
||||
|
||||
$product_id = (int) ($_GET['product_id'] ?? 0);
|
||||
$edit_view = function_exists('aksrt_get_product_edit_page_view')
|
||||
? aksrt_get_product_edit_page_view(get_current_user_id(), $product_id)
|
||||
: ['allowed' => false, 'is_edit' => false, 'product' => [], 'taxonomy' => ['categories' => [], 'tags' => []], 'shipping_modes' => [], 'status_options' => []];
|
||||
|
||||
$product = (array) ($edit_view['product'] ?? []);
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
|
||||
|
||||
<div
|
||||
class="aksrt-product-editor container"
|
||||
data-aksrt-product-editor
|
||||
data-product-id="<?php echo esc_attr((string) ($product['id'] ?? 0)); ?>"
|
||||
data-is-edit="<?php echo !empty($edit_view['is_edit']) ? '1' : '0'; ?>"
|
||||
>
|
||||
<?php if (empty($edit_view['allowed'])) : ?>
|
||||
<div class="aksrt-product-editor__empty">
|
||||
<i class="fas fa-lock" aria-hidden="true"></i>
|
||||
<p><?php esc_html_e('你没有权限编辑该商品。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-editor__header">
|
||||
<div>
|
||||
<h1 class="aksrt-product-editor__title">
|
||||
<?php echo !empty($edit_view['is_edit']) ? esc_html__('编辑商品', 'aksrt') : esc_html__('发布商品', 'aksrt'); ?>
|
||||
</h1>
|
||||
<p class="aksrt-product-editor__subtitle"><?php esc_html_e('管理主图、图集、分类标签、发货方式、运费和售后说明。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="aksrt-product-editor__layout" data-aksrt-product-form>
|
||||
<section class="aksrt-product-editor__main">
|
||||
<div class="aksrt-product-editor__panel">
|
||||
<h2><?php esc_html_e('基础信息', 'aksrt'); ?></h2>
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('商品名称', 'aksrt'); ?></span>
|
||||
<input type="text" name="title" class="aksrt-product-editor__input" value="<?php echo esc_attr((string) ($product['title'] ?? '')); ?>" required>
|
||||
</label>
|
||||
|
||||
<div class="aksrt-product-editor__columns">
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('价格', 'aksrt'); ?></span>
|
||||
<input type="number" name="price" class="aksrt-product-editor__input" min="0" step="0.01" value="<?php echo esc_attr((string) ($product['price'] ?? 0)); ?>" required>
|
||||
</label>
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('库存', 'aksrt'); ?></span>
|
||||
<input type="number" name="stock" class="aksrt-product-editor__input" min="0" step="1" value="<?php echo esc_attr((string) ($product['stock'] ?? 0)); ?>" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('商品简介', 'aksrt'); ?></span>
|
||||
<textarea name="excerpt" class="aksrt-product-editor__textarea" rows="4"><?php echo esc_textarea((string) ($product['excerpt'] ?? '')); ?></textarea>
|
||||
</label>
|
||||
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('商品详情', 'aksrt'); ?></span>
|
||||
<textarea name="content" class="aksrt-product-editor__textarea" rows="10"><?php echo esc_textarea((string) ($product['content'] ?? '')); ?></textarea>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-product-editor__panel">
|
||||
<h2><?php esc_html_e('商品素材', 'aksrt'); ?></h2>
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('主图 URL', 'aksrt'); ?></span>
|
||||
<input type="url" name="image" class="aksrt-product-editor__input" value="<?php echo esc_attr((string) ($product['image'] ?? '')); ?>" placeholder="https://">
|
||||
</label>
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('图集 URL(每行一个)', 'aksrt'); ?></span>
|
||||
<textarea name="gallery" class="aksrt-product-editor__textarea" rows="5"><?php echo esc_textarea(implode("\n", (array) ($product['gallery'] ?? []))); ?></textarea>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-product-editor__panel">
|
||||
<h2><?php esc_html_e('发货与售后', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-product-editor__columns">
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('发货方式', 'aksrt'); ?></span>
|
||||
<select name="shipping_mode" class="aksrt-product-editor__input">
|
||||
<?php foreach ((array) ($edit_view['shipping_modes'] ?? []) as $mode) : ?>
|
||||
<option value="<?php echo esc_attr((string) ($mode['value'] ?? '')); ?>" <?php selected((string) ($product['shipping_mode'] ?? ''), (string) ($mode['value'] ?? '')); ?>>
|
||||
<?php echo esc_html((string) ($mode['label'] ?? '')); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('额外运费', 'aksrt'); ?></span>
|
||||
<input type="number" name="shipping_fee" class="aksrt-product-editor__input" min="0" step="0.01" value="<?php echo esc_attr((string) ($product['shipping_fee'] ?? 0)); ?>">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('售后说明', 'aksrt'); ?></span>
|
||||
<textarea name="after_sale_policy" class="aksrt-product-editor__textarea" rows="4"><?php echo esc_textarea((string) ($product['after_sale_policy'] ?? '')); ?></textarea>
|
||||
</label>
|
||||
|
||||
<label class="aksrt-product-editor__checkbox">
|
||||
<input type="checkbox" name="support_refund" value="1" <?php checked(!empty($product['support_refund'])); ?>>
|
||||
<span><?php esc_html_e('支持退款/售后入口', 'aksrt'); ?></span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<aside class="aksrt-product-editor__sidebar">
|
||||
<div class="aksrt-product-editor__panel">
|
||||
<h2><?php esc_html_e('发布设置', 'aksrt'); ?></h2>
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('状态', 'aksrt'); ?></span>
|
||||
<select name="status" class="aksrt-product-editor__input">
|
||||
<?php foreach ((array) ($edit_view['status_options'] ?? []) as $status_option) : ?>
|
||||
<option value="<?php echo esc_attr((string) ($status_option['value'] ?? 'draft')); ?>" <?php selected((string) ($product['status'] ?? 'draft'), (string) ($status_option['value'] ?? 'draft')); ?>>
|
||||
<?php echo esc_html((string) ($status_option['label'] ?? '')); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('分类(按住 Ctrl 可多选)', 'aksrt'); ?></span>
|
||||
<select name="categories[]" class="aksrt-product-editor__input" multiple size="6">
|
||||
<?php foreach ((array) (($edit_view['taxonomy']['categories'] ?? [])) as $category) : ?>
|
||||
<option value="<?php echo esc_attr((string) ($category['id'] ?? 0)); ?>" <?php echo in_array((int) ($category['id'] ?? 0), (array) ($product['categories'] ?? []), true) ? 'selected' : ''; ?>>
|
||||
<?php echo esc_html((string) ($category['name'] ?? '')); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label class="aksrt-product-editor__field">
|
||||
<span><?php esc_html_e('标签(英文逗号分隔)', 'aksrt'); ?></span>
|
||||
<input type="text" name="tags" class="aksrt-product-editor__input" value="<?php echo esc_attr(implode(', ', (array) ($product['tags'] ?? []))); ?>">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-product-editor__panel">
|
||||
<h2><?php esc_html_e('动作', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-product-editor__actions">
|
||||
<button type="submit" class="btn-primary btn-lg"><?php echo !empty($edit_view['is_edit']) ? esc_html__('保存修改', 'aksrt') : esc_html__('发布商品', 'aksrt'); ?></button>
|
||||
<a href="<?php echo esc_url(function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url() : home_url('/')); ?>" class="btn-ghost btn-lg"><?php esc_html_e('返回中心', 'aksrt'); ?></a>
|
||||
</div>
|
||||
<p class="aksrt-product-editor__hint" data-aksrt-product-editor-message><?php esc_html_e('保存后会回到用户中心,商品信息供订单页和商品详情页复用。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
</aside>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,413 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Product Detail
|
||||
* Template Post Type: page
|
||||
*
|
||||
* Enhanced: options selector, video gallery, params/services modal,
|
||||
* review tab, favorites, related products, mobile tabbar (§6.10).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$product_id = (int) ($_GET['product_id'] ?? 0);
|
||||
if ($product_id <= 0) {
|
||||
$product_id = (int) get_query_var('product_id', 0);
|
||||
}
|
||||
|
||||
$shop = class_exists('AKSRT_Shop') ? AKSRT_Shop::get_instance() : null;
|
||||
$product = function_exists('aksrt_get_product_page_view')
|
||||
? aksrt_get_product_page_view($product_id)
|
||||
: ($shop ? $shop->get_product_detail_view($product_id) : []);
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$is_fav = $shop && $user_id > 0 ? $shop->is_favorite($user_id, $product_id) : false;
|
||||
$options = $product['options'] ?? [];
|
||||
$has_options = !empty($options);
|
||||
$price_range = $product['price_range'] ?? [];
|
||||
$params = $product['params'] ?? [];
|
||||
$services = $product['services'] ?? [];
|
||||
$pay_modo = $product['pay_modo'] ?? '0';
|
||||
$scores = class_exists('AKSRT_Product_Review') ? AKSRT_Product_Review::get_instance()->get_product_scores($product_id) : [];
|
||||
$reviews = class_exists('AKSRT_Product_Review') ? AKSRT_Product_Review::get_instance()->get_reviews($product_id, ['per_page' => 5]) : ['items' => [], 'total' => 0];
|
||||
$author_id = (int) get_post_field('post_author', $product_id);
|
||||
$author = $author_id > 0 ? get_userdata($author_id) : null;
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
|
||||
|
||||
<?php if (!empty($product)) : ?>
|
||||
<div
|
||||
class="aksrt-product-page container"
|
||||
data-aksrt-product-page
|
||||
data-product-id="<?php echo esc_attr((string) $product_id); ?>"
|
||||
data-options='<?php echo esc_attr(wp_json_encode($options, JSON_UNESCAPED_UNICODE)); ?>'
|
||||
>
|
||||
<div class="aksrt-product-page__layout">
|
||||
<!-- Gallery -->
|
||||
<section class="aksrt-product-page__gallery">
|
||||
<?php if (!empty($product['image'])) : ?>
|
||||
<div class="aksrt-product-page__primary-image" data-aksrt-main-image>
|
||||
<img src="<?php echo esc_url((string) $product['image']); ?>" alt="<?php echo esc_attr((string) ($product['title'] ?? '')); ?>" id="product-main-img">
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-page__placeholder">
|
||||
<i class="fas fa-image" aria-hidden="true"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
$gallery_items = (array) ($product['gallery'] ?? []);
|
||||
$cover_videos = (array) (get_post_meta($product_id, '_aksrt_cover_videos', true) ?: []);
|
||||
?>
|
||||
<?php if (!empty($gallery_items) || !empty($cover_videos)) : ?>
|
||||
<div class="aksrt-product-page__thumbs">
|
||||
<?php foreach ($cover_videos as $video_url) : ?>
|
||||
<button type="button" class="aksrt-product-page__thumb aksrt-product-page__thumb--video" data-aksrt-product-video="<?php echo esc_url($video_url); ?>">
|
||||
<i class="fas fa-play-circle"></i>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
<?php foreach ($gallery_items as $gallery_image) : ?>
|
||||
<button type="button" class="aksrt-product-page__thumb" data-aksrt-product-thumb="<?php echo esc_url($gallery_image); ?>">
|
||||
<img src="<?php echo esc_url($gallery_image); ?>" alt="">
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<!-- Summary -->
|
||||
<section class="aksrt-product-page__summary">
|
||||
<div class="aksrt-product-page__badges">
|
||||
<?php if ($pay_modo === 'points') : ?>
|
||||
<span class="aksrt-product-page__badge aksrt-product-page__badge--points"><?php esc_html_e('积分商品', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($product['marketing']['headline'])) : ?>
|
||||
<span class="aksrt-product-page__badge aksrt-product-page__badge--promo"><?php echo esc_html((string) $product['marketing']['headline']); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($product['after_sale']['support_refund'])) : ?>
|
||||
<span class="aksrt-product-page__badge"><?php esc_html_e('支持售后', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<h1 class="aksrt-product-page__title"><?php echo esc_html((string) ($product['title'] ?? '')); ?></h1>
|
||||
|
||||
<!-- Price row with range support -->
|
||||
<div class="aksrt-product-page__price-row">
|
||||
<?php if ($has_options && !empty($price_range) && $price_range['min'] !== $price_range['max']) : ?>
|
||||
<strong class="aksrt-product-page__price" data-aksrt-dynamic-price>
|
||||
<?php echo $pay_modo === 'points' ? '' : '¥'; ?><?php echo esc_html(number_format($price_range['min'], 2)); ?> - <?php echo $pay_modo === 'points' ? '' : '¥'; ?><?php echo esc_html(number_format($price_range['max'], 2)); ?>
|
||||
<?php if ($pay_modo === 'points') : ?><small><?php esc_html_e('积分', 'aksrt'); ?></small><?php endif; ?>
|
||||
</strong>
|
||||
<?php else : ?>
|
||||
<strong class="aksrt-product-page__price" data-aksrt-dynamic-price>
|
||||
<?php echo $pay_modo === 'points' ? '' : '¥'; ?><?php echo esc_html(number_format((float) ($product['price'] ?? 0), 2)); ?>
|
||||
<?php if ($pay_modo === 'points') : ?><small><?php esc_html_e('积分', 'aksrt'); ?></small><?php endif; ?>
|
||||
</strong>
|
||||
<?php endif; ?>
|
||||
<span class="aksrt-product-page__sales"><?php printf(esc_html__('已售 %d', 'aksrt'), (int) ($product['sales'] ?? 0)); ?></span>
|
||||
<?php if (!empty($scores['average'])) : ?>
|
||||
<span class="aksrt-product-page__rating"><i class="fas fa-star"></i> <?php echo esc_html((string) $scores['average']); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($product['excerpt'])) : ?>
|
||||
<p class="aksrt-product-page__excerpt"><?php echo esc_html((string) $product['excerpt']); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Product options selector -->
|
||||
<?php if ($has_options) : ?>
|
||||
<div class="aksrt-product-page__options" data-aksrt-options-selector>
|
||||
<?php foreach ($options as $group_idx => $group) : ?>
|
||||
<div class="aksrt-product-page__option-group" data-group-index="<?php echo esc_attr((string) $group_idx); ?>">
|
||||
<span class="aksrt-product-page__option-label"><?php echo esc_html((string) ($group['name'] ?? '')); ?></span>
|
||||
<div class="aksrt-product-page__option-values aksrt-product-page__option-values--<?php echo esc_attr($group['view_mode'] ?? 'list'); ?>">
|
||||
<?php foreach ((array) ($group['values'] ?? []) as $val) : ?>
|
||||
<button type="button"
|
||||
class="aksrt-product-page__option-btn"
|
||||
data-option-group="<?php echo esc_attr((string) $group_idx); ?>"
|
||||
data-option-label="<?php echo esc_attr((string) ($val['label'] ?? '')); ?>"
|
||||
data-price-change="<?php echo esc_attr((string) ($val['price_change'] ?? 0)); ?>"
|
||||
<?php if (!empty($val['image'])) : ?>data-option-image="<?php echo esc_url($val['image']); ?>"<?php endif; ?>
|
||||
>
|
||||
<?php if (($group['view_mode'] ?? '') === 'img' && !empty($val['image'])) : ?>
|
||||
<img src="<?php echo esc_url($val['image']); ?>" alt="<?php echo esc_attr($val['label']); ?>">
|
||||
<?php endif; ?>
|
||||
<span><?php echo esc_html((string) ($val['label'] ?? '')); ?></span>
|
||||
<?php if ((float) ($val['price_change'] ?? 0) !== 0.0) : ?>
|
||||
<em><?php echo (float) $val['price_change'] > 0 ? '+' : ''; ?><?php echo esc_html(number_format((float) $val['price_change'], 2)); ?></em>
|
||||
<?php endif; ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<div class="aksrt-product-page__option-result" data-aksrt-option-result hidden>
|
||||
<span data-aksrt-selected-labels></span>
|
||||
<strong data-aksrt-resolved-price></strong>
|
||||
<span data-aksrt-resolved-stock></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Meta info -->
|
||||
<dl class="aksrt-product-page__meta">
|
||||
<div>
|
||||
<dt><?php esc_html_e('库存', 'aksrt'); ?></dt>
|
||||
<dd data-aksrt-stock-display><?php
|
||||
$stock_val = (int) ($product['stock'] ?? 0);
|
||||
echo $stock_val <= -1 ? esc_html__('充足', 'aksrt') : esc_html((string) $stock_val);
|
||||
?></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt><?php esc_html_e('配送', 'aksrt'); ?></dt>
|
||||
<dd><?php echo esc_html((string) (($product['shipping']['delivery_note'] ?? '') ?: __('标准配送', 'aksrt'))); ?></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt><?php esc_html_e('运费', 'aksrt'); ?></dt>
|
||||
<dd><?php
|
||||
$ship_fee = (float) ($product['shipping']['fee'] ?? 0);
|
||||
echo $ship_fee > 0 ? '¥' . esc_html(number_format($ship_fee, 2)) : esc_html__('包邮', 'aksrt');
|
||||
?></dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<!-- Params & Services quick links -->
|
||||
<?php if (!empty($params)) : ?>
|
||||
<button type="button" class="aksrt-product-page__info-trigger" data-aksrt-show-params>
|
||||
<i class="fas fa-list-ul"></i> <?php esc_html_e('商品参数', 'aksrt'); ?> <i class="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($services)) : ?>
|
||||
<button type="button" class="aksrt-product-page__info-trigger" data-aksrt-show-services>
|
||||
<i class="fas fa-shield-alt"></i> <?php esc_html_e('服务保障', 'aksrt'); ?> <i class="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Purchase box -->
|
||||
<div class="aksrt-product-page__purchase-box">
|
||||
<label class="aksrt-product-page__field">
|
||||
<span><?php esc_html_e('购买数量', 'aksrt'); ?></span>
|
||||
<div class="aksrt-product-page__quantity">
|
||||
<button type="button" class="aksrt-product-page__qty-btn" data-aksrt-qty-action="dec">-</button>
|
||||
<input type="number" min="1" max="<?php echo esc_attr((string) max(1, $stock_val > 0 ? $stock_val : 999)); ?>" value="1" class="aksrt-product-page__qty-input" data-aksrt-quantity>
|
||||
<button type="button" class="aksrt-product-page__qty-btn" data-aksrt-qty-action="inc">+</button>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div class="aksrt-product-page__actions">
|
||||
<?php if (is_user_logged_in() && !empty($product['purchase_enabled'])) : ?>
|
||||
<button type="button" class="btn-outline btn-lg" data-aksrt-add-cart><?php esc_html_e('加入购物车', 'aksrt'); ?></button>
|
||||
<button type="button" class="btn-primary btn-lg" data-aksrt-buy-now>
|
||||
<?php echo $pay_modo === 'points' ? esc_html__('积分兑换', 'aksrt') : esc_html__('立即下单', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php elseif (!is_user_logged_in()) : ?>
|
||||
<a href="<?php echo esc_url(function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink())); ?>" class="btn-primary btn-lg">
|
||||
<?php esc_html_e('登录后购买', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<button type="button" class="btn-primary btn-lg" disabled><?php esc_html_e('暂不可购买', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Auxiliary actions -->
|
||||
<div class="aksrt-product-page__aux-actions">
|
||||
<button type="button" class="aksrt-product-page__aux-btn<?php echo $is_fav ? ' is-active' : ''; ?>" data-aksrt-toggle-fav="<?php echo esc_attr((string) $product_id); ?>">
|
||||
<i class="<?php echo $is_fav ? 'fas' : 'far'; ?> fa-heart"></i>
|
||||
<?php esc_html_e('收藏', 'aksrt'); ?>
|
||||
</button>
|
||||
<button type="button" class="aksrt-product-page__aux-btn" data-aksrt-share>
|
||||
<i class="fas fa-share-alt"></i> <?php esc_html_e('分享', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Merchant info -->
|
||||
<?php if ($author) : ?>
|
||||
<div class="aksrt-product-page__merchant">
|
||||
<img src="<?php echo esc_url(function_exists('aksrt_get_avatar_url') ? aksrt_get_avatar_url($author_id) : get_avatar_url($author_id)); ?>" alt="" class="aksrt-product-page__merchant-avatar">
|
||||
<div>
|
||||
<strong><?php echo esc_html($author->display_name); ?></strong>
|
||||
<a href="<?php echo esc_url(get_author_posts_url($author_id)); ?>?tab=products" class="aksrt-product-page__merchant-link"><?php esc_html_e('进入店铺', 'aksrt'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Tabs: detail / reviews / custom -->
|
||||
<div class="aksrt-product-page__tabs">
|
||||
<nav class="aksrt-product-page__tab-nav">
|
||||
<button class="aksrt-product-page__tab-btn is-active" data-aksrt-tab="detail"><?php esc_html_e('商品详情', 'aksrt'); ?></button>
|
||||
<button class="aksrt-product-page__tab-btn" data-aksrt-tab="reviews">
|
||||
<?php esc_html_e('评价', 'aksrt'); ?>
|
||||
<?php if (($scores['total'] ?? 0) > 0) : ?>
|
||||
<em>(<?php echo esc_html((string) $scores['total']); ?>)</em>
|
||||
<?php endif; ?>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="aksrt-product-page__tab-panel is-active" data-aksrt-tab-panel="detail">
|
||||
<div class="aksrt-product-page__content">
|
||||
<?php echo wp_kses_post((string) ($product['content'] ?? '')); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-product-page__tab-panel" data-aksrt-tab-panel="reviews">
|
||||
<?php if (!empty($scores['total'])) : ?>
|
||||
<div class="aksrt-product-page__review-summary">
|
||||
<strong class="aksrt-product-page__review-avg"><?php echo esc_html((string) ($scores['average'] ?? '0')); ?></strong>
|
||||
<span class="aksrt-product-page__review-level"><?php echo esc_html((string) ($scores['level'] ?? '')); ?></span>
|
||||
<div class="aksrt-product-page__review-counts">
|
||||
<span><?php printf(esc_html__('好评 %d', 'aksrt'), (int) ($scores['good'] ?? 0)); ?></span>
|
||||
<span><?php printf(esc_html__('差评 %d', 'aksrt'), (int) ($scores['bad'] ?? 0)); ?></span>
|
||||
<span><?php printf(esc_html__('有图 %d', 'aksrt'), (int) ($scores['has_image'] ?? 0)); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-product-page__review-list" data-aksrt-review-list>
|
||||
<?php foreach (($reviews['items'] ?? []) as $review) : ?>
|
||||
<div class="aksrt-product-page__review-item">
|
||||
<div class="aksrt-product-page__review-header">
|
||||
<img src="<?php echo esc_url((string) ($review['user_avatar'] ?? '')); ?>" alt="" class="aksrt-product-page__review-avatar">
|
||||
<span class="aksrt-product-page__review-name"><?php echo esc_html((string) ($review['user_name'] ?? '')); ?></span>
|
||||
<span class="aksrt-product-page__review-date"><?php echo esc_html((string) ($review['date'] ?? '')); ?></span>
|
||||
<span class="aksrt-product-page__review-stars">
|
||||
<?php for ($s = 0; $s < 5; $s++) : ?>
|
||||
<i class="<?php echo $s < (int) ($review['rating_average'] ?? 0) ? 'fas' : 'far'; ?> fa-star"></i>
|
||||
<?php endfor; ?>
|
||||
</span>
|
||||
</div>
|
||||
<p class="aksrt-product-page__review-text"><?php echo esc_html((string) ($review['content'] ?? '')); ?></p>
|
||||
<?php if (!empty($review['images'])) : ?>
|
||||
<div class="aksrt-product-page__review-images">
|
||||
<?php foreach ((array) $review['images'] as $rimg) : ?>
|
||||
<img src="<?php echo esc_url($rimg); ?>" alt="" class="aksrt-product-page__review-img">
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (empty($reviews['items'])) : ?>
|
||||
<p class="aksrt-product-page__review-empty"><?php esc_html_e('暂无评价', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Related products -->
|
||||
<?php
|
||||
$related_query = new WP_Query([
|
||||
'post_type' => 'aksrt_product',
|
||||
'posts_per_page' => 6,
|
||||
'post_status' => 'publish',
|
||||
'post__not_in' => [$product_id],
|
||||
'tax_query' => !empty($product['categories']) ? [[
|
||||
'taxonomy' => 'aksrt_product_cat',
|
||||
'field' => 'term_id',
|
||||
'terms' => wp_list_pluck($product['categories'], 'term_id'),
|
||||
]] : [],
|
||||
'orderby' => 'rand',
|
||||
]);
|
||||
?>
|
||||
<?php if ($related_query->have_posts()) : ?>
|
||||
<section class="aksrt-product-page__related">
|
||||
<h2><?php esc_html_e('相关推荐', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-product-page__related-grid">
|
||||
<?php while ($related_query->have_posts()) : $related_query->the_post(); ?>
|
||||
<a href="<?php echo esc_url(get_permalink()); ?>" class="aksrt-product-page__related-card">
|
||||
<?php $thumb = $shop ? $shop->resolve_main_image(get_the_ID()) : get_the_post_thumbnail_url(get_the_ID(), 'medium'); ?>
|
||||
<?php if ($thumb) : ?>
|
||||
<img src="<?php echo esc_url($thumb); ?>" alt="<?php the_title_attribute(); ?>" loading="lazy">
|
||||
<?php endif; ?>
|
||||
<h3><?php the_title(); ?></h3>
|
||||
<strong>¥<?php echo esc_html(number_format((float) get_post_meta(get_the_ID(), '_aksrt_price', true), 2)); ?></strong>
|
||||
</a>
|
||||
<?php endwhile; wp_reset_postdata(); ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Params modal -->
|
||||
<?php if (!empty($params)) : ?>
|
||||
<div class="aksrt-modal" data-aksrt-params-modal hidden>
|
||||
<div class="aksrt-modal__overlay"></div>
|
||||
<div class="aksrt-modal__dialog">
|
||||
<div class="aksrt-modal__header">
|
||||
<h3><?php esc_html_e('商品参数', 'aksrt'); ?></h3>
|
||||
<button type="button" class="aksrt-modal__close" data-aksrt-modal-close>×</button>
|
||||
</div>
|
||||
<div class="aksrt-modal__body">
|
||||
<table class="aksrt-product-page__params-table">
|
||||
<?php foreach ($params as $param) : ?>
|
||||
<tr>
|
||||
<th><?php echo esc_html((string) ($param['name'] ?? '')); ?></th>
|
||||
<td><?php echo esc_html((string) ($param['value'] ?? '')); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Services modal -->
|
||||
<?php if (!empty($services)) : ?>
|
||||
<div class="aksrt-modal" data-aksrt-services-modal hidden>
|
||||
<div class="aksrt-modal__overlay"></div>
|
||||
<div class="aksrt-modal__dialog">
|
||||
<div class="aksrt-modal__header">
|
||||
<h3><?php esc_html_e('服务保障', 'aksrt'); ?></h3>
|
||||
<button type="button" class="aksrt-modal__close" data-aksrt-modal-close>×</button>
|
||||
</div>
|
||||
<div class="aksrt-modal__body">
|
||||
<?php foreach ($services as $service) : ?>
|
||||
<div class="aksrt-product-page__service-item">
|
||||
<?php if (!empty($service['icon'])) : ?>
|
||||
<img src="<?php echo esc_url($service['icon']); ?>" alt="" class="aksrt-product-page__service-icon">
|
||||
<?php else : ?>
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<?php endif; ?>
|
||||
<div>
|
||||
<strong><?php echo esc_html((string) ($service['name'] ?? '')); ?></strong>
|
||||
<?php if (!empty($service['desc'])) : ?>
|
||||
<p><?php echo esc_html((string) $service['desc']); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Mobile purchase tabbar -->
|
||||
<div class="aksrt-product-page__mobile-bar" data-aksrt-mobile-purchase>
|
||||
<button type="button" class="aksrt-product-page__mobile-btn" data-aksrt-toggle-fav="<?php echo esc_attr((string) $product_id); ?>">
|
||||
<i class="<?php echo $is_fav ? 'fas' : 'far'; ?> fa-heart"></i>
|
||||
</button>
|
||||
<button type="button" class="aksrt-product-page__mobile-btn" data-aksrt-add-cart>
|
||||
<i class="fas fa-shopping-cart"></i>
|
||||
</button>
|
||||
<button type="button" class="aksrt-product-page__mobile-buy btn-primary" data-aksrt-buy-now>
|
||||
<?php echo $pay_modo === 'points' ? esc_html__('积分兑换', 'aksrt') : esc_html__('立即购买', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-page container">
|
||||
<div class="aksrt-product-page__empty">
|
||||
<i class="fas fa-box-open" aria-hidden="true"></i>
|
||||
<p><?php esc_html_e('商品不存在或已下架。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Register
|
||||
* Template Post Type: page
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
require AKSRT_DIR . '/templates/pages/page-sign.php';
|
||||
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Reset Password
|
||||
* Template Post Type: page
|
||||
*
|
||||
* Theme auth route template: /reset-password/
|
||||
*
|
||||
* 统一处理:
|
||||
* 1. 忘记密码(无 token 参数)— 输入邮箱/用户名请求重置
|
||||
* 2. 设置密码(有 token+uid 参数)— 邮件链接进入后设置新密码
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
// ============================================
|
||||
// 检测当前模式:设置密码 or 请求重置
|
||||
// ============================================
|
||||
$context = AKSRT_Auth_Service::get_reset_context($_GET);
|
||||
$mode = $context['mode'];
|
||||
$errors = [];
|
||||
$success = '';
|
||||
$token = $context['token'];
|
||||
$user_id = $context['user_id'];
|
||||
|
||||
if (!empty($context['error'])) {
|
||||
$errors[] = $context['error'];
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 处理表单提交
|
||||
// ============================================
|
||||
|
||||
// 模式1:请求重置密码(忘记密码表单提交)
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['aksrt_action']) && $_POST['aksrt_action'] === 'request_reset') {
|
||||
$result = AKSRT_Auth_Service::request_password_reset($_POST);
|
||||
if (!empty($result['success'])) {
|
||||
$success = $result['message'] ?? __('如果该账号存在,重置邮件已发送到注册邮箱', 'aksrt');
|
||||
} else {
|
||||
$errors[] = $result['error'] ?? __('重置请求失败,请稍后重试', 'aksrt');
|
||||
}
|
||||
}
|
||||
|
||||
// 模式2:设置新密码(从邮件链接进入)
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['aksrt_action']) && $_POST['aksrt_action'] === 'set_password') {
|
||||
$result = AKSRT_Auth_Service::reset_password_with_token($_POST);
|
||||
if (!empty($result['success'])) {
|
||||
$mode = 'success';
|
||||
$success = $result['message'] ?? __('密码已设置成功!', 'aksrt');
|
||||
} else {
|
||||
$errors[] = $result['error'] ?? __('重置密码失败,请稍后重试', 'aksrt');
|
||||
$mode = $result['mode'] ?? 'invalid';
|
||||
}
|
||||
}
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main" tabindex="-1">
|
||||
<div class="auth-shell">
|
||||
<div class="auth-card">
|
||||
<div class="auth-card__logo" aria-hidden="true">AK</div>
|
||||
<h1 class="auth-card__title"><?php bloginfo('name'); ?></h1>
|
||||
|
||||
<?php if ($mode === 'success') : ?>
|
||||
<!-- 密码设置成功 -->
|
||||
<p class="auth-card__subtitle"><?php esc_html_e('密码设置成功!', 'aksrt'); ?></p>
|
||||
<div class="alert alert--success" role="alert">
|
||||
<span><?php echo esc_html($success); ?></span>
|
||||
</div>
|
||||
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>" class="btn-primary btn-lg" style="width:100%;display:block;text-align:center;text-decoration:none;margin-top:16px;">
|
||||
<?php esc_html_e('立即登录', 'aksrt'); ?>
|
||||
</a>
|
||||
|
||||
<?php elseif ($mode === 'invalid') : ?>
|
||||
<!-- 链接无效或已过期 -->
|
||||
<p class="auth-card__subtitle"><?php esc_html_e('重置链接无效或已过期', 'aksrt'); ?></p>
|
||||
<?php if (!empty($errors)) : ?>
|
||||
<div class="alert alert--error" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
|
||||
<span><?php echo esc_html($errors[0]); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_reset_password_url()); ?>" class="btn-primary btn-lg" style="width:100%;display:block;text-align:center;text-decoration:none;margin-top:16px;">
|
||||
<?php esc_html_e('重新申请重置密码', 'aksrt'); ?>
|
||||
</a>
|
||||
|
||||
<?php elseif ($mode === 'reset') : ?>
|
||||
<!-- 设置新密码表单 -->
|
||||
<p class="auth-card__subtitle"><?php esc_html_e('请设置你的新密码', 'aksrt'); ?></p>
|
||||
|
||||
<?php if (!empty($errors)) : ?>
|
||||
<div class="alert alert--error" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
|
||||
<span><?php echo esc_html($errors[0]); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form class="auth-form" id="aksrt-set-password-form" method="post" action="">
|
||||
<?php wp_nonce_field('aksrt_set_password', '_setpw_nonce'); ?>
|
||||
<input type="hidden" name="aksrt_action" value="set_password">
|
||||
<input type="hidden" name="reset_token" value="<?php echo esc_attr($token); ?>">
|
||||
<input type="hidden" name="reset_uid" value="<?php echo esc_attr((string) $user_id); ?>">
|
||||
|
||||
<div class="form-field form-field--pwd">
|
||||
<label for="pass1"><?php esc_html_e('新密码', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></span>
|
||||
<input type="password" name="pass1" id="pass1" autocomplete="new-password" required minlength="6">
|
||||
<button type="button" class="toggle-pwd" data-target="pass1" aria-label="<?php esc_attr_e('显示或隐藏密码', 'aksrt'); ?>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-field form-field--pwd">
|
||||
<label for="pass2"><?php esc_html_e('确认新密码', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></span>
|
||||
<input type="password" name="pass2" id="pass2" autocomplete="new-password" required minlength="6">
|
||||
<button type="button" class="toggle-pwd" data-target="pass2" aria-label="<?php esc_attr_e('显示或隐藏密码', 'aksrt'); ?>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn-primary btn-lg btn-block"><?php esc_html_e('设置新密码', 'aksrt'); ?></button>
|
||||
</form>
|
||||
|
||||
<?php else : ?>
|
||||
<!-- 请求重置密码表单(忘记密码) -->
|
||||
<p class="auth-card__subtitle"><?php esc_html_e('输入邮箱或用户名,我们将发送重置链接', 'aksrt'); ?></p>
|
||||
|
||||
<?php if (!empty($errors)) : ?>
|
||||
<div class="alert alert--error" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
|
||||
<span><?php echo esc_html($errors[0]); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($success)) : ?>
|
||||
<div class="alert alert--success" role="alert">
|
||||
<span><?php echo esc_html($success); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form class="auth-form" id="aksrt-request-reset-form" method="post" action="">
|
||||
<?php wp_nonce_field('aksrt_reset_password', '_reset_nonce'); ?>
|
||||
<input type="hidden" name="aksrt_action" value="request_reset">
|
||||
|
||||
<div class="form-field">
|
||||
<label for="user_login"><?php esc_html_e('邮箱 / 用户名', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span>
|
||||
<input type="text" name="user_login" id="user_login" autocomplete="username" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php aksrt_render_captcha('lostpassword'); ?>
|
||||
|
||||
<button type="submit" class="btn-primary btn-lg btn-block"><?php esc_html_e('发送重置链接', 'aksrt'); ?></button>
|
||||
</form>
|
||||
|
||||
<p class="auth-footer-link">
|
||||
<?php esc_html_e('想起密码了?', 'aksrt'); ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>"><?php esc_html_e('返回登录', 'aksrt'); ?></a>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Revenue
|
||||
* Template Post Type: page
|
||||
*
|
||||
* 创作者收益中心页面 — 显示收益概览、分成记录和提现入口
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
|
||||
wp_safe_redirect($login_url);
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// 通过 helper 获取收益视图模型
|
||||
$revenue_view = function_exists('aksrt_get_revenue_page_view')
|
||||
? aksrt_get_revenue_page_view($user_id)
|
||||
: ['balance' => 0, 'total_earned' => 0, 'total_withdrawn' => 0, 'records' => []];
|
||||
|
||||
$balance = (float) ($revenue_view['balance'] ?? 0);
|
||||
$total_earned = (float) ($revenue_view['total_earned'] ?? 0);
|
||||
$total_withdrawn = (float) ($revenue_view['total_withdrawn'] ?? 0);
|
||||
$records = $revenue_view['records'] ?? [];
|
||||
|
||||
$per_page = 20;
|
||||
$paged = max(1, (int) ($_GET['rev_page'] ?? 1));
|
||||
$total_records = count($records);
|
||||
$total_pages = max(1, (int) ceil($total_records / $per_page));
|
||||
$paged_records = array_slice($records, ($paged - 1) * $per_page, $per_page);
|
||||
?>
|
||||
|
||||
<div class="container aksrt-revenue-page">
|
||||
<div class="aksrt-revenue-page__header">
|
||||
<h2><?php esc_html_e('创作收益', 'aksrt'); ?></h2>
|
||||
</div>
|
||||
|
||||
<!-- 收益概览 -->
|
||||
<div class="aksrt-revenue-page__stats">
|
||||
<div class="aksrt-revenue-page__stat-card">
|
||||
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-wallet"></i></div>
|
||||
<div class="aksrt-revenue-page__stat-info">
|
||||
<span class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format($balance, 2)); ?></span>
|
||||
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('可提现余额', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-revenue-page__stat-card">
|
||||
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-chart-line"></i></div>
|
||||
<div class="aksrt-revenue-page__stat-info">
|
||||
<span class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format($total_earned, 2)); ?></span>
|
||||
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('累计收益', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-revenue-page__stat-card">
|
||||
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-money-check-alt"></i></div>
|
||||
<div class="aksrt-revenue-page__stat-info">
|
||||
<span class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format($total_withdrawn, 2)); ?></span>
|
||||
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('已提现', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 提现按钮 -->
|
||||
<?php if ($balance > 0) : ?>
|
||||
<div class="aksrt-revenue-page__actions">
|
||||
<a href="<?php echo esc_url(add_query_arg(['action' => 'withdraw'])); ?>" class="aksrt-revenue-page__withdraw-btn">
|
||||
<i class="fas fa-hand-holding-usd"></i> <?php esc_html_e('申请提现', 'aksrt'); ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 分成记录 -->
|
||||
<div class="aksrt-revenue-page__section">
|
||||
<h3><?php esc_html_e('收益明细', 'aksrt'); ?></h3>
|
||||
|
||||
<?php if (!empty($paged_records)) : ?>
|
||||
<div class="aksrt-revenue-page__list">
|
||||
<?php foreach ($paged_records as $record) :
|
||||
$r_type = (string) ($record['type'] ?? 'earning');
|
||||
?>
|
||||
<div class="aksrt-revenue-page__item">
|
||||
<div class="aksrt-revenue-page__item-icon">
|
||||
<i class="<?php echo $r_type === 'withdrawal' ? 'fas fa-arrow-up' : 'fas fa-arrow-down'; ?>"
|
||||
style="color: <?php echo $r_type === 'withdrawal' ? '#f5222d' : '#52c41a'; ?>;"></i>
|
||||
</div>
|
||||
<div class="aksrt-revenue-page__item-info">
|
||||
<span class="aksrt-revenue-page__item-title"><?php echo esc_html($record['title'] ?? ''); ?></span>
|
||||
<span class="aksrt-revenue-page__item-time"><?php echo esc_html($record['created_at'] ?? ''); ?></span>
|
||||
</div>
|
||||
<div class="aksrt-revenue-page__item-amount" style="color: <?php echo $r_type === 'withdrawal' ? '#f5222d' : '#52c41a'; ?>;">
|
||||
<?php echo $r_type === 'withdrawal' ? '-' : '+'; ?>¥<?php echo esc_html(number_format((float) ($record['amount'] ?? 0), 2)); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($total_pages > 1) : ?>
|
||||
<div class="aksrt-revenue-page__pagination">
|
||||
<?php for ($i = 1; $i <= $total_pages; $i++) :
|
||||
$page_url = add_query_arg(['rev_page' => $i]);
|
||||
?>
|
||||
<?php if ($i === $paged) : ?>
|
||||
<span class="aksrt-revenue-page__page-chip is-active"><?php echo esc_html((string) $i); ?></span>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url($page_url); ?>" class="aksrt-revenue-page__page-chip"><?php echo esc_html((string) $i); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php else : ?>
|
||||
<div class="aksrt-revenue-page__empty">
|
||||
<i class="fas fa-chart-pie"></i>
|
||||
<p><?php esc_html_e('暂无收益记录', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - 登录/注册
|
||||
* Template Post Type: page
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
@session_start();
|
||||
|
||||
$route_tab = function_exists('aksrt_get_auth_tab') ? aksrt_get_auth_tab() : 'login';
|
||||
$requested_tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash((string) $_GET['tab'])) : '';
|
||||
$tab_aliases = [
|
||||
'login' => 'signin',
|
||||
'signin' => 'signin',
|
||||
'register' => 'signup',
|
||||
'signup' => 'signup',
|
||||
];
|
||||
$tab_source = $requested_tab !== '' ? $requested_tab : $route_tab;
|
||||
$tab = $tab_aliases[$tab_source] ?? 'signin';
|
||||
$redirect_to = !empty($_GET['redirect_to']) ? esc_url_raw(wp_unslash((string) $_GET['redirect_to'])) : home_url();
|
||||
$registration_open = class_exists('AKSRT_Settings') && AKSRT_Settings::registration_enabled();
|
||||
|
||||
$titles = [
|
||||
'signin' => __('用户登录', 'aksrt'),
|
||||
'signup' => __('用户注册', 'aksrt'),
|
||||
];
|
||||
$page_title = ($titles[$tab] ?? __('登录 / 注册', 'aksrt')) . ' - ' . get_bloginfo('name');
|
||||
|
||||
$interim = isset($_REQUEST['interim-login']);
|
||||
|
||||
// 搂4.1 Defense-in-depth: redirect out when close_sign is active (backup of auth router gate)
|
||||
if (class_exists('AKSRT_Settings') && AKSRT_Settings::close_sign() && !is_user_logged_in() && !$interim) {
|
||||
wp_safe_redirect(home_url('/'), 302);
|
||||
exit;
|
||||
}
|
||||
|
||||
// §4.1 close_signin: password login disabled — force signin tab to show social-only message
|
||||
$close_signin = class_exists('AKSRT_Settings') ? AKSRT_Settings::close_signin() : false;
|
||||
if ($close_signin && $tab === 'signin') {
|
||||
// Don't allow password form submission
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
if ($user_id) {
|
||||
if ($interim && is_super_admin()) {
|
||||
echo '<!DOCTYPE HTML><html><body class="login interim-login-success"><div style="padding:60px 0;text-align:center;color:#1a88fd;">' . esc_html__('登录成功', 'aksrt') . '</div></body></html>';
|
||||
exit;
|
||||
}
|
||||
wp_safe_redirect($redirect_to);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($tab === 'signup' && !$registration_open) {
|
||||
$tab = 'signin';
|
||||
}
|
||||
|
||||
remove_action('wp_footer', 'aksrt_render_footer_tabbar', 20);
|
||||
remove_action('wp_footer', 'aksrt_render_float_buttons', 30);
|
||||
|
||||
$background_html = '';
|
||||
$sign_ui = class_exists('AKSRT_Settings') ? AKSRT_Settings::sign_page_ui() : [];
|
||||
$card_position = $sign_ui['card_position'] ?? 'center';
|
||||
$sign_show_logo = $sign_ui['show_logo'] ?? true;
|
||||
$sign_show_header = $sign_ui['show_header'] ?? true;
|
||||
$sign_theme_mode = $sign_ui['theme_mode'] ?? 'default';
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$bg_ids = $sign_ui['background'] ?? [];
|
||||
if (is_array($bg_ids) && !empty($bg_ids)) {
|
||||
$bg_url = wp_get_attachment_url((int) $bg_ids[array_rand($bg_ids)]);
|
||||
if ($bg_url) {
|
||||
$background_html = '<div class="sign-bg" style="background-image:url(' . esc_url($bg_url) . ');"></div>';
|
||||
}
|
||||
} elseif (is_string($bg_ids) && $bg_ids !== '') {
|
||||
// BC: comma-separated string from old storage
|
||||
$ids = array_filter(array_map('absint', explode(',', $bg_ids)));
|
||||
if (!empty($ids)) {
|
||||
$bg_url = wp_get_attachment_url($ids[array_rand($ids)]);
|
||||
if ($bg_url) {
|
||||
$background_html = '<div class="sign-bg" style="background-image:url(' . esc_url($bg_url) . ');"></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$login_error = '';
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['log'], $_POST['pwd']) && $tab === 'signin') {
|
||||
if (class_exists('AKSRT_Auth_Service')) {
|
||||
$result = AKSRT_Auth_Service::login_user($_POST, false);
|
||||
if (empty($result['success'])) {
|
||||
$login_error = $result['error'] ?? __('登录失败', 'aksrt');
|
||||
} else {
|
||||
wp_safe_redirect($result['redirect'] ?? home_url('/'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$register_error = '';
|
||||
$register_success = '';
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['user_login'], $_POST['user_email']) && $tab === 'signup') {
|
||||
if (class_exists('AKSRT_Auth_Service')) {
|
||||
$result = AKSRT_Auth_Service::register_user($_POST, ['oauth_bind_data' => null, 'obk' => '']);
|
||||
if (!empty($result['success'])) {
|
||||
if (!empty($result['verification_required'])) {
|
||||
$register_success = sprintf(
|
||||
'%s <a href="%s">%s</a>',
|
||||
esc_html($result['message'] ?? __('Registration successful. Please complete email verification.', 'aksrt')),
|
||||
esc_url($result['verify_url'] ?? ''),
|
||||
esc_html__('前往验证', 'aksrt')
|
||||
);
|
||||
} else {
|
||||
$register_success = sprintf(
|
||||
__('Registration successful. Please continue on the <a href="%s">login page</a>.', 'aksrt'),
|
||||
esc_url(aksrt_get_login_url())
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$register_error = $result['error'] ?? __('注册失败', 'aksrt');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$invite_prefill = '';
|
||||
if (!empty($_GET['invite'])) {
|
||||
$invite_prefill = sanitize_key(wp_unslash($_GET['invite']));
|
||||
} elseif (!empty($_COOKIE['aksrt_invite'])) {
|
||||
$invite_prefill = sanitize_key(wp_unslash($_COOKIE['aksrt_invite']));
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?php echo esc_attr(str_replace('_', '-', get_bloginfo('language'))); ?>">
|
||||
<head>
|
||||
<meta charset="<?php bloginfo('charset'); ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<title><?php echo esc_html($page_title); ?></title>
|
||||
<?php wp_head(); ?>
|
||||
<style>
|
||||
.sign-page{min-height:100vh;display:flex;align-items:center;justify-content:center;position:relative;padding:70px 16px 40px}
|
||||
.sign-bg{position:fixed;inset:0;background-repeat:no-repeat;background-size:cover;background-position:center;z-index:0}
|
||||
.sign-card{position:relative;z-index:1;width:100%;max-width:420px;background:var(--main-bg-color,#fff);border-radius:var(--main-radius,8px);box-shadow:0 0 10px var(--main-shadow,rgba(116,116,116,0.08));padding:30px 35px}
|
||||
.sign-card--left{margin-right:auto}
|
||||
.sign-card--right{margin-left:auto}
|
||||
.sign-card--center{margin:0 auto}
|
||||
.sign-logo{text-align:center;margin-bottom:20px}
|
||||
.sign-logo img{height:36px}
|
||||
.sign-logo__text{display:inline-flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:12px;background:var(--focus-color,#f04494);color:#fff;font-size:18px;font-weight:700;text-decoration:none}
|
||||
.sign-tabs{display:flex;border-bottom:2px solid var(--main-border-color,rgba(50,50,50,0.06));margin-bottom:20px}
|
||||
.sign-tab{flex:1;padding:10px 0;border:none;background:none;font-size:15px;cursor:pointer;color:var(--muted-color,#777);border-bottom:2px solid transparent;margin-bottom:-2px;transition:all .2s;text-align:center;font-weight:500}
|
||||
.sign-tab.is-active{color:var(--focus-color,#f04494);border-bottom-color:var(--focus-color,#f04494);font-weight:600}
|
||||
.sign-tab:hover{color:var(--focus-color,#f04494)}
|
||||
.sign-panel{display:none}
|
||||
.sign-panel.is-active{display:block}
|
||||
.sign-error{background:rgba(239,68,68,0.08);border:1px solid rgba(239,68,68,0.2);border-radius:var(--main-radius,8px);padding:10px 14px;font-size:13px;color:#ef4444;margin-bottom:16px}
|
||||
.sign-success{background:rgba(16,185,129,0.08);border:1px solid rgba(16,185,129,0.2);border-radius:var(--main-radius,8px);padding:10px 14px;font-size:13px;color:#10b981;margin-bottom:16px}
|
||||
.sign-form{display:flex;flex-direction:column;gap:16px}
|
||||
.sign-form .form-field{display:flex;flex-direction:column;gap:6px}
|
||||
.sign-form label{font-size:14px;font-weight:500;color:var(--main-color,#4e5358)}
|
||||
.sign-form .input-wrap{position:relative}
|
||||
.sign-form .input-wrap input{width:100%;height:44px;padding:0 14px;border:1px solid transparent;background:var(--body-bg-color,#f5f6f7);border-radius:var(--main-radius,8px);font-size:14px;color:var(--key-color,#333);transition:border-color .15s}
|
||||
.sign-form .input-wrap input:focus{outline:none;border-color:var(--focus-color,#f04494);box-shadow:0 0 2px 3px var(--focus-shadow-color,rgba(253,83,161,0.4))}
|
||||
.sign-form .toggle-pwd{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;color:var(--muted-2-color,#999);padding:4px}
|
||||
.sign-form .form-row-between{display:flex;align-items:center;justify-content:space-between;font-size:13px}
|
||||
.sign-form .form-row-between a{color:var(--focus-color,#f04494)}
|
||||
.sign-form .form-row-between label{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:13px;color:var(--muted-color,#777)}
|
||||
.sign-form .btn-submit{width:100%;height:44px;border:none;border-radius:var(--main-radius,8px);background:var(--focus-color,#f04494);color:#fff;font-size:15px;font-weight:600;cursor:pointer;transition:opacity .15s}
|
||||
.sign-form .btn-submit:hover{opacity:.85}
|
||||
.sign-form .btn-submit:disabled{opacity:.5;cursor:not-allowed}
|
||||
.sign-hint{margin:0;font-size:13px;color:var(--muted-color,#777)}
|
||||
.sign-terms{display:flex;align-items:flex-start;gap:8px;font-size:13px;cursor:pointer;color:var(--muted-color,#777)}
|
||||
.sign-footer{text-align:center;margin-top:20px;font-size:14px;color:var(--muted-color,#777)}
|
||||
.sign-footer a{color:var(--focus-color,#f04494)}
|
||||
.sign-footer-bar{position:fixed;bottom:0;left:0;right:0;text-align:center;padding:10px;font-size:12px;color:var(--muted-2-color,#999);z-index:1}
|
||||
@media(max-width:480px){.sign-card{padding:24px 20px}}
|
||||
</style>
|
||||
</head>
|
||||
<body <?php body_class('page-template-user-sign' . ($sign_theme_mode !== 'default' ? ' sign-theme-' . esc_attr($sign_theme_mode) : '')); ?>>
|
||||
<?php echo $background_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<main class="sign-page">
|
||||
<div class="sign-card sign-card--<?php echo esc_attr($card_position); ?>">
|
||||
<?php if ($sign_show_logo) : ?>
|
||||
<div class="sign-logo">
|
||||
<?php $logo_url = class_exists('AKSRT_Settings') ? AKSRT_Settings::user_logo_url() : ''; ?>
|
||||
<?php if ($logo_url) : ?>
|
||||
<a href="<?php echo esc_url(home_url('/')); ?>"><img src="<?php echo esc_url($logo_url); ?>" alt="<?php echo esc_attr(get_bloginfo('name')); ?>"></a>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url(home_url('/')); ?>" class="sign-logo__text"><?php echo esc_html(mb_substr(get_bloginfo('name'), 0, 2)); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($sign_show_header) : ?>
|
||||
<div class="sign-tabs">
|
||||
<button type="button" class="sign-tab<?php echo $tab === 'signin' ? ' is-active' : ''; ?>" data-sign-tab="signin"><?php esc_html_e('登录', 'aksrt'); ?></button>
|
||||
<?php if ($registration_open) : ?>
|
||||
<button type="button" class="sign-tab<?php echo $tab === 'signup' ? ' is-active' : ''; ?>" data-sign-tab="signup"><?php esc_html_e('注册', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="sign-panel<?php echo $tab === 'signin' ? ' is-active' : ''; ?>" data-sign-panel="signin">
|
||||
<?php if ($login_error) : ?><div class="sign-error"><?php echo esc_html($login_error); ?></div><?php endif; ?>
|
||||
<?php if ($close_signin) : ?>
|
||||
<div class="sign-notice" style="padding:16px;text-align:center;color:var(--muted-2-color,#666);">
|
||||
<?php esc_html_e('This site currently supports third-party account sign-in only. Please use one of the social login buttons below.', 'aksrt'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<form class="sign-form" id="sign-login-form" method="post" action="">
|
||||
<?php wp_nonce_field('aksrt_login', '_login_nonce'); ?>
|
||||
<div class="form-field">
|
||||
<label for="sign-user-login"><?php esc_html_e('Email / Username', 'aksrt'); ?></label>
|
||||
<div class="input-wrap"><input type="text" name="log" id="sign-user-login" autocomplete="username" required placeholder="<?php esc_attr_e('Please enter your email or username', 'aksrt'); ?>"></div>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="sign-user-pass"><?php esc_html_e('密码', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<input type="password" name="pwd" id="sign-user-pass" autocomplete="current-password" required>
|
||||
<button type="button" class="toggle-pwd" data-target="sign-user-pass"><i class="fas fa-eye"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row-between">
|
||||
<label><input type="checkbox" name="rememberme" value="forever"> <?php esc_html_e('Remember me', 'aksrt'); ?></label>
|
||||
<a href="<?php echo esc_url(aksrt_get_reset_password_url()); ?>"><?php esc_html_e('Forgot password?', 'aksrt'); ?></a>
|
||||
</div>
|
||||
<?php if (function_exists('aksrt_render_captcha')) aksrt_render_captcha('login'); ?>
|
||||
<input type="hidden" name="redirect_to" value="<?php echo esc_url($redirect_to); ?>">
|
||||
<button type="submit" class="btn-submit"><?php esc_html_e('登录', 'aksrt'); ?></button>
|
||||
</form>
|
||||
<?php endif; // close_signin gate ?>
|
||||
<?php if (class_exists('AKSRT_OAuth')) : ?>
|
||||
<?php $social = AKSRT_OAuth::get_instance()->render_social_buttons(); ?>
|
||||
<?php if ($social) echo '<div style="margin-top:20px;">' . $social . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($registration_open) : ?>
|
||||
<div class="sign-footer"><?php esc_html_e('Don\'t have an account yet?', 'aksrt'); ?> <a href="#" data-sign-switch="signup"><?php esc_html_e('Register now', 'aksrt'); ?></a></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($registration_open) : ?>
|
||||
<div class="sign-panel<?php echo $tab === 'signup' ? ' is-active' : ''; ?>" data-sign-panel="signup">
|
||||
<?php if ($register_error) : ?><div class="sign-error"><?php echo esc_html($register_error); ?></div><?php endif; ?>
|
||||
<?php if ($register_success) : ?><div class="sign-success"><?php echo wp_kses($register_success, ['a' => ['href' => []]]); ?></div><?php endif; ?>
|
||||
<form class="sign-form" id="sign-register-form" method="post" action="" novalidate>
|
||||
<?php wp_nonce_field('aksrt_register', '_register_nonce'); ?>
|
||||
<div class="form-field">
|
||||
<label for="sign-reg-login"><?php esc_html_e('Username', 'aksrt'); ?></label>
|
||||
<div class="input-wrap"><input type="text" name="user_login" id="sign-reg-login" autocomplete="username" required placeholder="<?php esc_attr_e('请输入用户名', 'aksrt'); ?>"></div>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="sign-reg-email"><?php esc_html_e('Email Address', 'aksrt'); ?></label>
|
||||
<div class="input-wrap"><input type="email" name="user_email" id="sign-reg-email" autocomplete="email" required placeholder="<?php esc_attr_e('Please enter your email', 'aksrt'); ?>"></div>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="sign-reg-pass"><?php esc_html_e('登录密码', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<input type="password" name="user_pass" id="sign-reg-pass" autocomplete="new-password" required minlength="6">
|
||||
<button type="button" class="toggle-pwd" data-target="sign-reg-pass"><i class="fas fa-eye"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="sign-reg-pass2"><?php esc_html_e('确认密码', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<input type="password" name="user_pass_confirm" id="sign-reg-pass2" autocomplete="new-password" required minlength="6">
|
||||
<button type="button" class="toggle-pwd" data-target="sign-reg-pass2"><i class="fas fa-eye"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
$invite_cfg = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_invite_registration_config() : null;
|
||||
if ($invite_cfg && ($invite_cfg['register_field'] ?? 'hidden') !== 'hidden') {
|
||||
$mode = (string) $invite_cfg['register_field'];
|
||||
$invit_hint = $mode === 'required'
|
||||
? (string) ($invite_cfg['must_desc'] ?? '')
|
||||
: (string) ($invite_cfg['open_desc'] ?? '');
|
||||
?>
|
||||
<div class="form-field">
|
||||
<label for="sign-invite"><?php esc_html_e('邀请码', 'aksrt'); ?><?php echo $mode === 'optional' ? ' <small style="color:var(--muted-color);">(' . esc_html__('选填', 'aksrt') . ')</small>' : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></label>
|
||||
<div class="input-wrap"><input type="text" name="invite_code" id="sign-invite" maxlength="32" autocomplete="off" value="<?php echo esc_attr($invite_prefill); ?>" <?php echo $mode === 'required' ? 'required' : ''; ?>></div>
|
||||
<?php if ($invit_hint !== '') : ?>
|
||||
<p class="sign-hint"><?php echo wp_kses_post($invit_hint); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<label class="sign-terms">
|
||||
<input type="checkbox" name="agree_terms" value="1" required>
|
||||
<span><?php esc_html_e('I agree to the Terms of Service', 'aksrt'); ?></span>
|
||||
</label>
|
||||
<?php if (class_exists('AKSRT_Settings') && AKSRT_Settings::registration_requires_email_verification()) : ?>
|
||||
<p class="sign-hint"><?php esc_html_e('Email verification is required after registration.', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if (function_exists('aksrt_render_captcha')) aksrt_render_captcha('register'); ?>
|
||||
<button type="submit" class="btn-submit"><?php esc_html_e('注册', 'aksrt'); ?></button>
|
||||
</form>
|
||||
<div class="sign-footer"><?php esc_html_e('Already have an account?', 'aksrt'); ?> <a href="#" data-sign-switch="signin"><?php esc_html_e('Sign in now', 'aksrt'); ?></a></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
document.querySelectorAll('[data-sign-tab]').forEach(function(tab){
|
||||
tab.addEventListener('click',function(){
|
||||
var target=this.getAttribute('data-sign-tab');
|
||||
this.parentElement.querySelectorAll('.sign-tab').forEach(function(t){t.classList.remove('is-active');});
|
||||
this.classList.add('is-active');
|
||||
var card=this.closest('.sign-card');
|
||||
card.querySelectorAll('.sign-panel[data-sign-panel]').forEach(function(p){p.classList.remove('is-active');});
|
||||
var panel=card.querySelector('[data-sign-panel="'+target+'"]');
|
||||
if(panel)panel.classList.add('is-active');
|
||||
});
|
||||
});
|
||||
document.querySelectorAll('[data-sign-switch]').forEach(function(link){
|
||||
link.addEventListener('click',function(e){
|
||||
e.preventDefault();
|
||||
var target=this.getAttribute('data-sign-switch');
|
||||
var btn=document.querySelector('[data-sign-tab="'+target+'"]');
|
||||
if(btn)btn.click();
|
||||
});
|
||||
});
|
||||
document.querySelectorAll('.toggle-pwd').forEach(function(btn){
|
||||
btn.addEventListener('click',function(){
|
||||
var input=document.getElementById(this.getAttribute('data-target'));
|
||||
if(!input)return;
|
||||
var isPw=input.type==='password';
|
||||
input.type=isPw?'text':'password';
|
||||
this.querySelector('i').className=isPw?'fas fa-eye-slash':'fas fa-eye';
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<?php if (!$interim) : ?>
|
||||
<div class="sign-footer-bar">
|
||||
<?php
|
||||
$footer_text = $sign_ui['footer'] ?? '';
|
||||
echo $footer_text ? wp_kses_post($footer_text) : '© ' . date('Y') . ' ' . esc_html(get_bloginfo('name'));
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php wp_footer(); ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Special Page
|
||||
*
|
||||
* 专题聚合页模板 — 用于内容专题、活动页、产品介绍页等。
|
||||
* 读取 AKSRT_Settings 中的 page_display.special 配置,支持 per-page meta 覆盖。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$post_id = get_the_ID();
|
||||
|
||||
// 从门面 getter 读取专题页设置(validated & sanitized)
|
||||
$special = class_exists('AKSRT_Settings')
|
||||
? AKSRT_Settings::get_special_page_settings()
|
||||
: [];
|
||||
|
||||
$defaults = [
|
||||
'cover_enabled' => true,
|
||||
'summary_enabled' => true,
|
||||
'summary_length' => 200,
|
||||
'default_cover' => '',
|
||||
'layout' => 'grid',
|
||||
'columns' => 2,
|
||||
'source_type' => 'category',
|
||||
'source_ids' => '',
|
||||
'subpage_display' => 'cards',
|
||||
'subpage_count' => 6,
|
||||
'sidebar' => true,
|
||||
'pagination' => 'numeric',
|
||||
'per_page' => 12,
|
||||
'post_count' => false,
|
||||
'orderby' => 'date',
|
||||
];
|
||||
$settings = array_merge($defaults, $special);
|
||||
|
||||
// Per-page meta override
|
||||
$meta_layout = get_post_meta($post_id, '_aksrt_special_layout', true);
|
||||
$meta_columns = get_post_meta($post_id, '_aksrt_special_columns', true);
|
||||
$meta_source = get_post_meta($post_id, '_aksrt_special_source_type', true);
|
||||
$meta_ids = get_post_meta($post_id, '_aksrt_special_source_ids', true);
|
||||
if ($meta_layout) $settings['layout'] = sanitize_key($meta_layout);
|
||||
if ($meta_columns) $settings['columns'] = max(1, min(4, (int) $meta_columns));
|
||||
if ($meta_source) $settings['source_type'] = sanitize_key($meta_source);
|
||||
if ($meta_ids !== '' && $meta_ids !== false) $settings['source_ids'] = $meta_ids;
|
||||
|
||||
$layout = in_array($settings['layout'], ['grid', 'list', 'masonry'], true) ? $settings['layout'] : 'grid';
|
||||
$columns = max(1, min(4, (int) $settings['columns']));
|
||||
$show_cover = !empty($settings['cover_enabled']);
|
||||
$show_summary = !empty($settings['summary_enabled']);
|
||||
$summary_len = max(50, min(500, (int) $settings['summary_length']));
|
||||
$subpage_style = in_array($settings['subpage_display'], ['cards', 'list', 'timeline'], true) ? $settings['subpage_display'] : 'cards';
|
||||
$per_page = max(4, min(48, (int) $settings['per_page']));
|
||||
$orderby = in_array($settings['orderby'], ['date', 'modified', 'views', 'comments'], true) ? $settings['orderby'] : 'date';
|
||||
|
||||
// 聚合内容源
|
||||
$source_type = sanitize_key($settings['source_type']);
|
||||
$source_ids = array_filter(array_map('absint', explode(',', (string) $settings['source_ids'])));
|
||||
$aggregated_posts = [];
|
||||
|
||||
if (!empty($source_ids)) {
|
||||
$args = [
|
||||
'posts_per_page' => $per_page,
|
||||
'post_status' => 'publish',
|
||||
'orderby' => ($orderby === 'modified') ? 'modified' : 'date',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
if ($source_type === 'category') {
|
||||
$args['category__in'] = $source_ids;
|
||||
} elseif ($source_type === 'tag') {
|
||||
$args['tag__in'] = $source_ids;
|
||||
}
|
||||
$aggregated_query = new WP_Query($args);
|
||||
$aggregated_posts = $aggregated_query->posts;
|
||||
}
|
||||
|
||||
// 子页面列表
|
||||
$children_per_page = max(1, min(20, (int) $settings['subpage_count']));
|
||||
$children = get_pages([
|
||||
'child_of' => $post_id,
|
||||
'sort_column' => 'menu_order',
|
||||
'sort_order' => 'ASC',
|
||||
'parent' => $post_id,
|
||||
'number' => $children_per_page,
|
||||
]);
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell content-shell--page aksrt-special--<?php echo esc_attr($layout); ?>" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
|
||||
|
||||
<?php if ($show_cover) :
|
||||
$default_cover = $settings['default_cover'] ?? '';
|
||||
$show_post_count = !empty($settings['post_count']);
|
||||
include get_template_directory() . '/templates/parts/special/special-cover.php';
|
||||
endif; ?>
|
||||
|
||||
<div class="aksrt-special-content container">
|
||||
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
|
||||
<div class="aksrt-special-content__body">
|
||||
<?php the_content(); ?>
|
||||
</div>
|
||||
<?php endwhile; endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($aggregated_posts)) : ?>
|
||||
<section class="aksrt-special-aggregated container">
|
||||
<h2 class="aksrt-special-aggregated__title"><?php esc_html_e('相关内容', 'aksrt'); ?></h2>
|
||||
<?php
|
||||
// Use the special-grid part
|
||||
$grid_posts = $aggregated_posts;
|
||||
$show_dates = true;
|
||||
include get_template_directory() . '/templates/parts/special/special-grid.php';
|
||||
?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($children)) : ?>
|
||||
<section class="aksrt-special-children container">
|
||||
<h2 class="aksrt-special-children__title"><?php esc_html_e('子页面', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-special-children__grid aksrt-special-children__grid--<?php echo esc_attr($subpage_style); ?>" style="--aksrt-cols:<?php echo esc_attr((string) $columns); ?>">
|
||||
<?php foreach ($children as $child) :
|
||||
$child_img = get_the_post_thumbnail_url($child->ID, 'medium');
|
||||
?>
|
||||
<a href="<?php echo esc_url(get_permalink($child->ID)); ?>" class="aksrt-special-child-card">
|
||||
<?php if ($child_img) : ?>
|
||||
<div class="aksrt-special-child-card__image">
|
||||
<img src="<?php echo esc_url($child_img); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-special-child-card__body">
|
||||
<h3 class="aksrt-special-child-card__title"><?php echo esc_html($child->post_title); ?></h3>
|
||||
<?php if ($child->post_excerpt !== '') : ?>
|
||||
<p class="aksrt-special-child-card__desc"><?php echo esc_html(wp_trim_words($child->post_excerpt, 30)); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Submit
|
||||
*
|
||||
* 前台投稿页面模板。
|
||||
* 支持标题、摘要、分类、标签、正文、封面、草稿保存。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
wp_redirect(aksrt_get_login_url(get_permalink()));
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$can_submit = class_exists('AKSRT_Front_Submit') && AKSRT_Front_Submit::get_instance()->can_submit($user_id);
|
||||
|
||||
if (!$can_submit) {
|
||||
wp_redirect(home_url('/'));
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if editing existing draft
|
||||
$edit_id = isset($_GET['edit']) ? absint($_GET['edit']) : 0;
|
||||
$edit_post = null;
|
||||
if ($edit_id > 0) {
|
||||
$edit_post = get_post($edit_id);
|
||||
if (!$edit_post || (int) $edit_post->post_author !== $user_id || $edit_post->post_status !== 'draft') {
|
||||
$edit_post = null;
|
||||
$edit_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
get_header();
|
||||
|
||||
// Submit settings
|
||||
$submit_settings = [];
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$all = AKSRT_Settings::get_all();
|
||||
$submit_settings = [
|
||||
'enabled' => !empty($all['front_submit_enabled']),
|
||||
'review_mode' => $all['front_submit_review_mode'] ?? 'pending',
|
||||
'allow_cover' => !isset($all['front_submit_cover']) || !empty($all['front_submit_cover']),
|
||||
'allow_excerpt' => !isset($all['front_submit_excerpt']) || !empty($all['front_submit_excerpt']),
|
||||
'allow_category' => !isset($all['front_submit_category']) || !empty($all['front_submit_category']),
|
||||
'allow_tags' => !isset($all['front_submit_tags']) || !empty($all['front_submit_tags']),
|
||||
'max_images' => (int) ($all['front_submit_max_images'] ?? 5),
|
||||
'allowed_cat_ids' => is_array($all['post_article_cat'] ?? null) ? array_map('intval', $all['post_article_cat']) : [],
|
||||
'topics_s' => !empty($all['post_article_topics_s']),
|
||||
'custom_filter_s' => !isset($all['post_article_custom_filter_s']) || !empty($all['post_article_custom_filter_s']),
|
||||
];
|
||||
}
|
||||
|
||||
// §3.7 topics: load topics taxonomy terms
|
||||
$topics_terms = [];
|
||||
if (!empty($submit_settings['topics_s']) && taxonomy_exists('topics')) {
|
||||
$topics_terms = get_terms(['taxonomy' => 'topics', 'hide_empty' => false, 'orderby' => 'name', 'order' => 'ASC']);
|
||||
if (is_wp_error($topics_terms)) $topics_terms = [];
|
||||
}
|
||||
$current_topics = [];
|
||||
if ($edit_post && taxonomy_exists('topics')) {
|
||||
$terms = wp_get_object_terms($edit_post->ID, 'topics', ['fields' => 'ids']);
|
||||
if (!is_wp_error($terms)) $current_topics = $terms;
|
||||
}
|
||||
|
||||
// §3.4 custom_filter: load dimension definitions for submit form
|
||||
$custom_dimensions = [];
|
||||
if (!empty($submit_settings['custom_filter_s']) && class_exists('AKSRT_Settings')) {
|
||||
$filter_all = AKSRT_Settings::get_post_filter_settings();
|
||||
$custom_dimensions = $filter_all['custom_filter'];
|
||||
}
|
||||
|
||||
// §3.4 custom_filter: load current values for edit mode
|
||||
$current_cf = [];
|
||||
if ($edit_post && !empty($custom_dimensions)) {
|
||||
foreach ($custom_dimensions as $dim) {
|
||||
$current_cf[$dim['key']] = get_post_meta($edit_post->ID, '_aksrt_cf_' . $dim['key'], true);
|
||||
}
|
||||
}
|
||||
|
||||
// §3.7 post_article_cat: filter categories by allowed list
|
||||
$cat_args = [
|
||||
'taxonomy' => 'category',
|
||||
'hide_empty' => false,
|
||||
'orderby' => 'name',
|
||||
'order' => 'ASC',
|
||||
];
|
||||
if (!empty($submit_settings['allowed_cat_ids'])) {
|
||||
$cat_args['include'] = $submit_settings['allowed_cat_ids'];
|
||||
}
|
||||
$categories = get_categories($cat_args);
|
||||
|
||||
// Current values for edit mode
|
||||
$current_title = $edit_post ? $edit_post->post_title : '';
|
||||
$current_content = $edit_post ? $edit_post->post_content : '';
|
||||
$current_excerpt = $edit_post ? $edit_post->post_excerpt : '';
|
||||
$current_cats = $edit_post ? wp_get_post_categories($edit_post->ID) : [];
|
||||
$current_tags = $edit_post ? implode(', ', wp_get_post_tags($edit_post->ID, ['fields' => 'names'])) : '';
|
||||
$current_thumb = $edit_post ? get_the_post_thumbnail_url($edit_post->ID, 'large') : '';
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell content-shell--page" tabindex="-1">
|
||||
<div class="aksrt-submit-page container">
|
||||
<header class="aksrt-submit-page__header">
|
||||
<h1 class="aksrt-submit-page__title">
|
||||
<?php echo $edit_post ? esc_html__('编辑草稿', 'aksrt') : esc_html__('投稿', 'aksrt'); ?>
|
||||
</h1>
|
||||
<p class="aksrt-submit-page__desc">
|
||||
<?php echo $edit_post
|
||||
? esc_html__('继续编辑你的草稿,完成后提交审核。', 'aksrt')
|
||||
: esc_html__('分享你的内容,提交后将进入审核流程。', 'aksrt'); ?>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<form class="aksrt-submit-form" id="aksrt-submit-form" data-aksrt-submit-form data-dirty="false">
|
||||
<?php if ($edit_id > 0) : ?>
|
||||
<input type="hidden" name="edit_id" value="<?php echo esc_attr((string) $edit_id); ?>">
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-form-group">
|
||||
<label for="submit-title"><?php esc_html_e('标题', 'aksrt'); ?> *</label>
|
||||
<input type="text" id="submit-title" name="title" class="aksrt-form-input" required maxlength="200" placeholder="<?php esc_attr_e('请输入文章标题', 'aksrt'); ?>" value="<?php echo esc_attr($current_title); ?>">
|
||||
</div>
|
||||
|
||||
<?php if (!empty($submit_settings['allow_excerpt'])) : ?>
|
||||
<div class="aksrt-form-group">
|
||||
<label for="submit-excerpt"><?php esc_html_e('摘要', 'aksrt'); ?></label>
|
||||
<textarea id="submit-excerpt" name="excerpt" class="aksrt-form-input" rows="3" maxlength="300" placeholder="<?php esc_attr_e('可选:文章摘要', 'aksrt'); ?>"><?php echo esc_textarea($current_excerpt); ?></textarea>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-submit-form__row">
|
||||
<?php if (!empty($submit_settings['allow_category'])) : ?>
|
||||
<div class="aksrt-form-group aksrt-submit-form__col">
|
||||
<label for="submit-category"><?php esc_html_e('分类', 'aksrt'); ?></label>
|
||||
<select id="submit-category" name="category" class="aksrt-form-input">
|
||||
<option value=""><?php esc_html_e('选择分类', 'aksrt'); ?></option>
|
||||
<?php foreach ($categories as $cat) : ?>
|
||||
<option value="<?php echo esc_attr((string) $cat->term_id); ?>" <?php selected(in_array($cat->term_id, $current_cats)); ?>><?php echo esc_html($cat->name); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($submit_settings['allow_tags'])) : ?>
|
||||
<div class="aksrt-form-group aksrt-submit-form__col">
|
||||
<label for="submit-tags"><?php esc_html_e('标签', 'aksrt'); ?></label>
|
||||
<input type="text" id="submit-tags" name="tags" class="aksrt-form-input" placeholder="<?php esc_attr_e('多个标签用逗号分隔', 'aksrt'); ?>" value="<?php echo esc_attr($current_tags); ?>">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($submit_settings['topics_s']) && !empty($topics_terms)) : ?>
|
||||
<div class="aksrt-form-group">
|
||||
<label for="submit-topics"><?php esc_html_e('专题', 'aksrt'); ?></label>
|
||||
<select id="submit-topics" name="topics[]" class="aksrt-form-input" multiple>
|
||||
<?php foreach ($topics_terms as $topic) : ?>
|
||||
<option value="<?php echo esc_attr((string) $topic->term_id); ?>" <?php selected(in_array($topic->term_id, $current_topics)); ?>><?php echo esc_html($topic->name); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($submit_settings['custom_filter_s']) && !empty($custom_dimensions)) : ?>
|
||||
<?php foreach ($custom_dimensions as $dim) : ?>
|
||||
<div class="aksrt-form-group">
|
||||
<label for="submit-cf-<?php echo esc_attr($dim['key']); ?>"><?php echo esc_html($dim['name']); ?></label>
|
||||
<select id="submit-cf-<?php echo esc_attr($dim['key']); ?>" name="cf_<?php echo esc_attr($dim['key']); ?>" class="aksrt-form-input">
|
||||
<option value=""><?php printf(esc_html__('选择%s', 'aksrt'), esc_html($dim['name'])); ?></option>
|
||||
<?php foreach ($dim['vals'] as $val) : ?>
|
||||
<option value="<?php echo esc_attr($val['key']); ?>" <?php selected(!empty($current_cf[$dim['key']]) && $current_cf[$dim['key']] === $val['key']); ?>><?php echo esc_html($val['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-form-group">
|
||||
<label for="submit-content"><?php esc_html_e('内容', 'aksrt'); ?> *</label>
|
||||
<div class="aksrt-submit-form__editor-toolbar">
|
||||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="bold" title="<?php esc_attr_e('加粗', 'aksrt'); ?>"><i class="fas fa-bold"></i></button>
|
||||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="italic" title="<?php esc_attr_e('斜体', 'aksrt'); ?>"><i class="fas fa-italic"></i></button>
|
||||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="code" title="<?php esc_attr_e('代码', 'aksrt'); ?>"><i class="fas fa-code"></i></button>
|
||||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="link" title="<?php esc_attr_e('链接', 'aksrt'); ?>"><i class="fas fa-link"></i></button>
|
||||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="image" title="<?php esc_attr_e('图片', 'aksrt'); ?>"><i class="fas fa-image"></i></button>
|
||||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="quote" title="<?php esc_attr_e('引用', 'aksrt'); ?>"><i class="fas fa-quote-left"></i></button>
|
||||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="heading" title="<?php esc_attr_e('标题', 'aksrt'); ?>"><i class="fas fa-heading"></i></button>
|
||||
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="list" title="<?php esc_attr_e('列表', 'aksrt'); ?>"><i class="fas fa-list-ul"></i></button>
|
||||
</div>
|
||||
<textarea id="submit-content" name="content" class="aksrt-form-input aksrt-submit-form__textarea" rows="16" required placeholder="<?php esc_attr_e('请输入文章内容(支持 HTML)', 'aksrt'); ?>"><?php echo esc_textarea($current_content); ?></textarea>
|
||||
<div class="aksrt-submit-form__word-count" id="submit-word-count"></div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($submit_settings['allow_cover'])) : ?>
|
||||
<div class="aksrt-form-group">
|
||||
<label for="submit-thumbnail"><?php esc_html_e('封面图', 'aksrt'); ?></label>
|
||||
<div class="aksrt-submit-form__cover-input">
|
||||
<input type="url" id="submit-thumbnail" name="thumbnail" class="aksrt-form-input" placeholder="<?php esc_attr_e('输入封面图地址', 'aksrt'); ?>" value="<?php echo esc_url($current_thumb); ?>">
|
||||
<button type="button" class="aksrt-submit-form__cover-btn" id="aksrt-pick-cover">
|
||||
<i class="fas fa-image"></i>
|
||||
<?php esc_html_e('选择图片', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
<div class="aksrt-submit-form__cover-preview" id="cover-preview" <?php echo $current_thumb ? '' : 'style="display:none"'; ?>>
|
||||
<img id="cover-preview-img" src="<?php echo esc_url($current_thumb); ?>" alt="">
|
||||
<button type="button" class="aksrt-submit-form__cover-remove" id="cover-remove" title="<?php esc_attr_e('移除封面', 'aksrt'); ?>">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-submit-form__actions">
|
||||
<button type="submit" class="aksrt-auth-submit" id="aksrt-submit-btn">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
<?php echo $edit_post ? esc_html__('更新投稿', 'aksrt') : esc_html__('提交投稿', 'aksrt'); ?>
|
||||
</button>
|
||||
<button type="button" class="btn-outline" id="aksrt-save-draft">
|
||||
<i class="fas fa-save"></i>
|
||||
<?php esc_html_e('保存草稿', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="_nonce" value="<?php echo esc_attr(wp_create_nonce('aksrt_submit')); ?>">
|
||||
<input type="hidden" name="status" id="submit-status" value="pending">
|
||||
</form>
|
||||
|
||||
<!-- Draft list -->
|
||||
<?php
|
||||
$user_drafts = get_posts([
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'draft',
|
||||
'author' => $user_id,
|
||||
'numberposts' => 10,
|
||||
'orderby' => 'modified',
|
||||
'order' => 'DESC',
|
||||
]);
|
||||
if (!empty($user_drafts)) :
|
||||
?>
|
||||
<div class="aksrt-submit-drafts">
|
||||
<h3 class="aksrt-submit-drafts__title">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<?php esc_html_e('我的草稿', 'aksrt'); ?>
|
||||
</h3>
|
||||
<div class="aksrt-submit-drafts__list">
|
||||
<?php foreach ($user_drafts as $draft) : ?>
|
||||
<div class="aksrt-submit-drafts__item">
|
||||
<a href="<?php echo esc_url(add_query_arg('edit', $draft->ID, get_permalink())); ?>" class="aksrt-submit-drafts__link">
|
||||
<span class="aksrt-submit-drafts__name"><?php echo esc_html($draft->post_title ?: __('无标题', 'aksrt')); ?></span>
|
||||
<time class="aksrt-submit-drafts__date"><?php echo esc_html(get_the_date('Y-m-d H:i', $draft->ID)); ?></time>
|
||||
</a>
|
||||
<button type="button" class="aksrt-submit-drafts__delete" data-draft-id="<?php echo esc_attr((string) $draft->ID); ?>" title="<?php esc_attr_e('删除草稿', 'aksrt'); ?>">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
// Enqueue the front-submit script
|
||||
$front_submit_path = get_template_directory() . '/assets/js/front-submit.js';
|
||||
if (file_exists($front_submit_path)) {
|
||||
wp_enqueue_script(
|
||||
'aksrt-front-submit',
|
||||
get_template_directory_uri() . '/assets/js/front-submit.js',
|
||||
['aksrt-script'],
|
||||
(string) filemtime($front_submit_path),
|
||||
true
|
||||
);
|
||||
wp_localize_script('aksrt-front-submit', 'aksrtSubmitData', [
|
||||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('aksrt_submit_nonce'),
|
||||
'i18n' => [
|
||||
'confirmLeave' => __('你有未保存的更改,确定要离开吗?', 'aksrt'),
|
||||
'saving' => __('保存中...', 'aksrt'),
|
||||
'saved' => __('草稿已保存', 'aksrt'),
|
||||
'submitting' => __('提交中...', 'aksrt'),
|
||||
'submitted' => __('投稿已提交', 'aksrt'),
|
||||
'error' => __('操作失败,请重试', 'aksrt'),
|
||||
'confirmDelete' => __('确定要删除这个草稿吗?', 'aksrt'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
get_footer();
|
||||
@@ -0,0 +1,556 @@
|
||||
<?php
|
||||
/**
|
||||
* Public user homepage template.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$target_user_nicename = get_query_var('user_nicename');
|
||||
$user = $target_user_nicename ? get_user_by('slug', $target_user_nicename) : null;
|
||||
|
||||
if (!$user) {
|
||||
wp_safe_redirect(home_url('/'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = (int) $user->ID;
|
||||
|
||||
// 数据聚合:复用共享 helper
|
||||
$dashboard = function_exists('aksrt_get_user_dashboard_view')
|
||||
? aksrt_get_user_dashboard_view($user_id, ['viewer_id' => get_current_user_id()])
|
||||
: [];
|
||||
|
||||
$is_own_profile = !empty($dashboard['is_own_profile']);
|
||||
$user_home_settings = class_exists('AKSRT_Settings')
|
||||
? AKSRT_Settings::get_user_home_settings()
|
||||
: [
|
||||
'tabs' => ['posts', 'comments', 'favorites'],
|
||||
'sidebar' => true,
|
||||
'cover' => true,
|
||||
'follow' => true,
|
||||
'posts_per_page' => 10,
|
||||
];
|
||||
|
||||
$post_count = (int) ($dashboard['post_count'] ?? 0);
|
||||
$comment_count = (int) ($dashboard['comment_count'] ?? 0);
|
||||
$favorite_post_ids = $dashboard['favorite_post_ids'] ?? [];
|
||||
$favorite_count = (int) ($dashboard['favorite_count'] ?? 0);
|
||||
$user_contacts = $dashboard['user_contacts'] ?? [];
|
||||
$user_center_settings = class_exists('AKSRT_Settings')
|
||||
? AKSRT_Settings::get_user_center_settings()
|
||||
: ['social_links' => true];
|
||||
$per_page = (int) $user_home_settings['posts_per_page'];
|
||||
$credits_enabled = !empty($dashboard['credits_enabled']);
|
||||
$credit_balance = $dashboard['credit_balance'] ?? 0.0;
|
||||
$currency_name = $dashboard['currency_name'] ?? __('积分', 'aksrt');
|
||||
$user_home_manager = class_exists('AKSRT_User_Home') ? AKSRT_User_Home::get_instance() : null;
|
||||
$visible_tabs = $user_home_manager ? $user_home_manager->get_visible_tabs($is_own_profile) : [];
|
||||
$profile_signals = $dashboard['profile_signals'] ?? [];
|
||||
$profile_notice = $dashboard['profile_notice'] ?? null;
|
||||
$show_report_button = !empty($dashboard['show_report']);
|
||||
|
||||
$enabled_tabs = array_keys($visible_tabs);
|
||||
if (empty($enabled_tabs)) {
|
||||
$enabled_tabs = ['posts', 'comments', 'favorites'];
|
||||
}
|
||||
|
||||
// Apply admin-configured display order
|
||||
$_uh_order = $user_home_settings['tabs_order'] ?? [];
|
||||
$_uh_ordered = [];
|
||||
foreach ($_uh_order as $_t) {
|
||||
if (in_array($_t, $enabled_tabs, true)) {
|
||||
$_uh_ordered[] = $_t;
|
||||
}
|
||||
}
|
||||
foreach ($enabled_tabs as $_t) {
|
||||
if (!in_array($_t, $_uh_ordered, true)) {
|
||||
$_uh_ordered[] = $_t;
|
||||
}
|
||||
}
|
||||
$enabled_tabs = $_uh_ordered;
|
||||
|
||||
// Device visibility: build PC/mobile tab arrays
|
||||
$_uh_pc_hide = $user_home_settings['tabs_pc_hide'] ?? [];
|
||||
$_uh_mobile_hide = $user_home_settings['tabs_mobile_hide'] ?? [];
|
||||
$enabled_tabs_pc = array_values(array_diff($enabled_tabs, $_uh_pc_hide));
|
||||
$enabled_tabs_mobile = array_values(array_diff($enabled_tabs, $_uh_mobile_hide));
|
||||
$_uh_is_mobile = function_exists('wp_is_mobile') && wp_is_mobile();
|
||||
$display_tabs = $_uh_is_mobile ? $enabled_tabs_mobile : $enabled_tabs_pc;
|
||||
$_uh_default_tab = !empty($display_tabs) ? $display_tabs[0] : $enabled_tabs[0];
|
||||
|
||||
$forum_instance = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
|
||||
$forum_stats = $forum_instance ? $forum_instance->get_user_forum_stats($user_id) : [];
|
||||
$forum_topic_count = (int) ($forum_stats['topic_count'] ?? 0);
|
||||
$forum_followed_count = (int) ($forum_stats['followed_plate_count'] ?? 0);
|
||||
|
||||
$tab_counts = [
|
||||
'posts' => $post_count,
|
||||
'comments' => $comment_count,
|
||||
'favorites' => $favorite_count,
|
||||
'credits' => $credits_enabled && $is_own_profile ? (int) round($credit_balance) : 0,
|
||||
'product' => 0,
|
||||
'plate' => 0,
|
||||
'forum' => $forum_topic_count,
|
||||
'follow' => $forum_followed_count,
|
||||
];
|
||||
$tab_labels = [
|
||||
'posts' => __('文章', 'aksrt'),
|
||||
'comments' => __('评论', 'aksrt'),
|
||||
'favorites' => __('收藏', 'aksrt'),
|
||||
'credits' => sprintf(__('我的%s', 'aksrt'), $currency_name),
|
||||
'product' => __('商品', 'aksrt'),
|
||||
'plate' => __('圈子', 'aksrt'),
|
||||
'forum' => __('论坛', 'aksrt'),
|
||||
'follow' => __('关注', 'aksrt'),
|
||||
];
|
||||
foreach ($visible_tabs as $tab_key => $tab_config) {
|
||||
if (!empty($tab_config['label'])) {
|
||||
$tab_labels[$tab_key] = (string) $tab_config['label'];
|
||||
}
|
||||
}
|
||||
|
||||
$active_tab = isset($_GET['tab']) ? sanitize_key(wp_unslash($_GET['tab'])) : $_uh_default_tab;
|
||||
if (!in_array($active_tab, $enabled_tabs, true)) {
|
||||
$active_tab = $_uh_default_tab;
|
||||
}
|
||||
$posts_page = max(1, isset($_GET['posts_page']) ? (int) $_GET['posts_page'] : 1);
|
||||
$comments_page = max(1, isset($_GET['comments_page']) ? (int) $_GET['comments_page'] : 1);
|
||||
$favorites_page = max(1, isset($_GET['favorites_page']) ? (int) $_GET['favorites_page'] : 1);
|
||||
|
||||
require_once AKSRT_DIR . '/templates/parts/user-shared-helpers.php';
|
||||
|
||||
$svg_empty_post = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M9 13h6M9 17h6M9 9h1"/></svg>';
|
||||
$svg_empty_comment = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>';
|
||||
$svg_empty_favorite = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>';
|
||||
$home_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user) : home_url('/');
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<div class="content-layout<?php echo !empty($user_home_settings['sidebar']) ? '' : ' content-layout--no-sidebar'; ?> aksrt-user-home__layout">
|
||||
<div class="content-layout__primary">
|
||||
<?php
|
||||
// 作者 Hero 区:共享 partial
|
||||
set_query_var('user', $user);
|
||||
set_query_var('dashboard', $dashboard);
|
||||
set_query_var('user_home_settings', $user_home_settings);
|
||||
set_query_var('is_author_page', false);
|
||||
get_template_part('templates/parts/user/author-hero');
|
||||
?>
|
||||
|
||||
<div class="dashboard dashboard--public" data-default-tab="<?php echo esc_attr($_uh_default_tab); ?>">
|
||||
<div class="dashboard-tabs" role="tablist">
|
||||
<?php foreach ($enabled_tabs as $tab_key) :
|
||||
$_tab_class = $tab_key === $active_tab ? 'is-active' : '';
|
||||
$_pc_hidden = in_array($tab_key, $_uh_pc_hide, true);
|
||||
$_mobile_hidden = in_array($tab_key, $_uh_mobile_hide, true);
|
||||
if ($_pc_hidden) $_tab_class .= ' tab-hide-pc';
|
||||
if ($_mobile_hidden) $_tab_class .= ' tab-hide-mobile';
|
||||
?>
|
||||
<button type="button" class="<?php echo esc_attr(trim($_tab_class)); ?>" data-tab="<?php echo esc_attr($tab_key); ?>" role="tab">
|
||||
<?php echo esc_html($tab_labels[$tab_key] ?? ucfirst($tab_key)); ?>
|
||||
<span class="dashboard-tabs__count"><?php echo esc_html((string) ($tab_counts[$tab_key] ?? 0)); ?></span>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if (in_array('posts', $enabled_tabs, true)) : ?>
|
||||
<div id="panel-posts" class="dashboard-panel<?php echo $active_tab === 'posts' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'posts' ? ' hidden' : ''; ?>>
|
||||
<?php
|
||||
$author_posts = new WP_Query([
|
||||
'author' => $user_id,
|
||||
'posts_per_page' => $per_page,
|
||||
'post_status' => 'publish',
|
||||
'paged' => $posts_page,
|
||||
'no_found_rows' => false,
|
||||
'update_post_meta_cache' => false,
|
||||
]);
|
||||
if ($author_posts->have_posts()) :
|
||||
?>
|
||||
<div class="profile-list">
|
||||
<?php while ($author_posts->have_posts()) : $author_posts->the_post(); ?>
|
||||
<?php
|
||||
set_query_var('aksrt_profile_item_action', [
|
||||
'type' => 'view',
|
||||
'url' => get_permalink(),
|
||||
'label' => __('阅读', 'aksrt'),
|
||||
]);
|
||||
set_query_var('aksrt_profile_item_status', '');
|
||||
get_template_part('templates/parts/content', 'profile-list-item');
|
||||
?>
|
||||
<?php endwhile; ?>
|
||||
</div>
|
||||
<?php
|
||||
aksrt_render_profile_pagination((int) $author_posts->max_num_pages, $posts_page, 'posts_page');
|
||||
wp_reset_postdata();
|
||||
set_query_var('aksrt_profile_item_action', []);
|
||||
else :
|
||||
aksrt_render_profile_empty($svg_empty_post, __('TA 还没有发布文章', 'aksrt'));
|
||||
endif;
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (in_array('comments', $enabled_tabs, true)) : ?>
|
||||
<div id="panel-comments" class="dashboard-panel<?php echo $active_tab === 'comments' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'comments' ? ' hidden' : ''; ?>>
|
||||
<?php
|
||||
$user_comments = get_comments([
|
||||
'user_id' => $user_id,
|
||||
'status' => 'approve',
|
||||
'number' => $per_page,
|
||||
'offset' => ($comments_page - 1) * $per_page,
|
||||
'type' => 'comment',
|
||||
'update_comment_meta_cache' => false,
|
||||
]);
|
||||
if ($user_comments) :
|
||||
?>
|
||||
<div class="profile-comment-list">
|
||||
<?php foreach ($user_comments as $c) : ?>
|
||||
<?php
|
||||
set_query_var('aksrt_profile_comment', $c);
|
||||
get_template_part('templates/parts/content', 'profile-comment-item');
|
||||
?>
|
||||
<?php endforeach; ?>
|
||||
<?php set_query_var('aksrt_profile_comment', null); ?>
|
||||
</div>
|
||||
<?php
|
||||
$cm_total_pages = (int) ceil($comment_count / $per_page);
|
||||
aksrt_render_profile_pagination($cm_total_pages, $comments_page, 'comments_page');
|
||||
else :
|
||||
aksrt_render_profile_empty($svg_empty_comment, __('TA 还没有发表评论', 'aksrt'));
|
||||
endif;
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (in_array('favorites', $enabled_tabs, true)) : ?>
|
||||
<div id="panel-favorites" class="dashboard-panel<?php echo $active_tab === 'favorites' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'favorites' ? ' hidden' : ''; ?>>
|
||||
<?php if (!empty($favorite_post_ids)) : ?>
|
||||
<?php
|
||||
$favorites_query = new WP_Query([
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'post__in' => $favorite_post_ids,
|
||||
'orderby' => 'post__in',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $favorites_page,
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => false,
|
||||
'update_post_meta_cache' => false,
|
||||
]);
|
||||
if ($favorites_query->have_posts()) :
|
||||
?>
|
||||
<div class="profile-list">
|
||||
<?php while ($favorites_query->have_posts()) : $favorites_query->the_post(); ?>
|
||||
<?php
|
||||
set_query_var('aksrt_profile_item_action', [
|
||||
'type' => 'view',
|
||||
'url' => get_permalink(),
|
||||
'label' => __('阅读', 'aksrt'),
|
||||
]);
|
||||
set_query_var('aksrt_profile_item_status', '');
|
||||
get_template_part('templates/parts/content', 'profile-list-item');
|
||||
?>
|
||||
<?php endwhile; ?>
|
||||
</div>
|
||||
<?php
|
||||
aksrt_render_profile_pagination((int) $favorites_query->max_num_pages, $favorites_page, 'favorites_page');
|
||||
wp_reset_postdata();
|
||||
set_query_var('aksrt_profile_item_action', []);
|
||||
else :
|
||||
aksrt_render_profile_empty($svg_empty_favorite, __('TA 还没有收藏文章', 'aksrt'));
|
||||
endif;
|
||||
?>
|
||||
<?php else : ?>
|
||||
<?php aksrt_render_profile_empty($svg_empty_favorite, __('TA 还没有收藏文章', 'aksrt')); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (in_array('credits', $enabled_tabs, true) && $credits_enabled && $is_own_profile) : ?>
|
||||
<div id="panel-credits" class="dashboard-panel<?php echo $active_tab === 'credits' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'credits' ? ' hidden' : ''; ?>>
|
||||
<div class="user-home-balance-card">
|
||||
<p class="user-home-balance-card__label"><?php echo esc_html(sprintf(__('当前%s余额', 'aksrt'), $currency_name)); ?></p>
|
||||
<div class="user-home-balance-card__value"><?php echo esc_html(aksrt_format_credits($credit_balance)); ?></div>
|
||||
<p class="user-home-balance-card__hint"><?php esc_html_e('完整账单和赚取/消费记录请在个人中心查看。', 'aksrt'); ?></p>
|
||||
<a href="<?php echo esc_url(aksrt_get_user_center_url('credits')); ?>" class="btn-outline btn-sm"><?php esc_html_e('进入个人中心', 'aksrt'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
// Placeholder panels for extended tabs (product, plate)
|
||||
$_uh_extended_tabs = ['product', 'plate'];
|
||||
$_uh_placeholder_msgs = [
|
||||
'product' => __('暂无商品内容', 'aksrt'),
|
||||
'plate' => __('暂无圈子内容', 'aksrt'),
|
||||
];
|
||||
foreach ($_uh_extended_tabs as $_uh_ext) :
|
||||
if (!in_array($_uh_ext, $enabled_tabs, true)) continue;
|
||||
?>
|
||||
<div id="panel-<?php echo esc_attr($_uh_ext); ?>" class="dashboard-panel<?php echo $active_tab === $_uh_ext ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== $_uh_ext ? ' hidden' : ''; ?>>
|
||||
<?php aksrt_render_profile_empty($svg_empty_post, $_uh_placeholder_msgs[$_uh_ext]); ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (in_array('forum', $enabled_tabs, true)) : ?>
|
||||
<div id="panel-forum" class="dashboard-panel<?php echo $active_tab === 'forum' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'forum' ? ' hidden' : ''; ?>>
|
||||
<?php
|
||||
$forum_page = max(1, isset($_GET['forum_page']) ? (int) $_GET['forum_page'] : 1);
|
||||
$forum_sub = isset($_GET['forum_sub']) ? sanitize_key(wp_unslash($_GET['forum_sub'])) : 'topics';
|
||||
$forum_sub = in_array($forum_sub, ['topics', 'favorites', 'plates'], true) ? $forum_sub : 'topics';
|
||||
?>
|
||||
<div class="uh-forum__subtabs">
|
||||
<a class="uh-forum__subtab<?php echo $forum_sub === 'topics' ? ' is-active' : ''; ?>"
|
||||
href="<?php echo esc_url(add_query_arg(['tab' => 'forum', 'forum_sub' => 'topics', 'forum_page' => 1], $home_url)); ?>">
|
||||
<i class="fas fa-file-alt"></i> <?php esc_html_e('帖子', 'aksrt'); ?>
|
||||
<span class="uh-forum__subtab-count"><?php echo esc_html((string) $forum_topic_count); ?></span>
|
||||
</a>
|
||||
<a class="uh-forum__subtab<?php echo $forum_sub === 'favorites' ? ' is-active' : ''; ?>"
|
||||
href="<?php echo esc_url(add_query_arg(['tab' => 'forum', 'forum_sub' => 'favorites', 'forum_page' => 1], $home_url)); ?>">
|
||||
<i class="fas fa-star"></i> <?php esc_html_e('收藏帖子', 'aksrt'); ?>
|
||||
<span class="uh-forum__subtab-count"><?php echo esc_html((string) ($forum_stats['favorite_count'] ?? 0)); ?></span>
|
||||
</a>
|
||||
<a class="uh-forum__subtab<?php echo $forum_sub === 'plates' ? ' is-active' : ''; ?>"
|
||||
href="<?php echo esc_url(add_query_arg(['tab' => 'forum', 'forum_sub' => 'plates', 'forum_page' => 1], $home_url)); ?>">
|
||||
<i class="fas fa-th-large"></i> <?php esc_html_e('版块', 'aksrt'); ?>
|
||||
<span class="uh-forum__subtab-count"><?php echo esc_html((string) ($forum_stats['managed_plate_count'] ?? 0)); ?></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<?php if ($forum_sub === 'topics' && $forum_instance) :
|
||||
$forum_topics = $forum_instance->get_user_forum_topics($user_id, ['page' => $forum_page, 'limit' => $per_page]);
|
||||
if (!empty($forum_topics['items'])) : ?>
|
||||
<div class="uh-forum__list">
|
||||
<?php foreach ($forum_topics['items'] as $ft) : ?>
|
||||
<div class="uh-forum__item">
|
||||
<div class="uh-forum__item-body">
|
||||
<a class="uh-forum__item-title" href="<?php echo esc_url(get_permalink((int) ($ft['id'] ?? 0))); ?>">
|
||||
<?php echo esc_html((string) ($ft['title'] ?? '')); ?>
|
||||
</a>
|
||||
<div class="uh-forum__item-meta">
|
||||
<span><i class="far fa-eye"></i> <?php echo esc_html((string) ($ft['views'] ?? 0)); ?></span>
|
||||
<span><i class="far fa-comment"></i> <?php echo esc_html((string) ($ft['comment_count'] ?? 0)); ?></span>
|
||||
<time><?php echo esc_html((string) ($ft['date'] ?? '')); ?></time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php if ($forum_topics['max_pages'] > 1) : ?>
|
||||
<div class="uh-forum__pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'base' => add_query_arg('forum_page', '%#%', $home_url),
|
||||
'format' => '',
|
||||
'current' => $forum_page,
|
||||
'total' => $forum_topics['max_pages'],
|
||||
'add_args' => ['tab' => 'forum', 'forum_sub' => 'topics'],
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<?php aksrt_render_profile_empty($svg_empty_post, __('暂无论坛帖子', 'aksrt')); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php elseif ($forum_sub === 'favorites' && $forum_instance) :
|
||||
$fav_topics = $forum_instance->get_user_favorite_topics($user_id, $forum_page, $per_page);
|
||||
if (!empty($fav_topics['items'])) : ?>
|
||||
<div class="uh-forum__list">
|
||||
<?php foreach ($fav_topics['items'] as $ft) : ?>
|
||||
<div class="uh-forum__item">
|
||||
<div class="uh-forum__item-body">
|
||||
<a class="uh-forum__item-title" href="<?php echo esc_url(get_permalink((int) ($ft['id'] ?? 0))); ?>">
|
||||
<?php echo esc_html((string) ($ft['title'] ?? '')); ?>
|
||||
</a>
|
||||
<div class="uh-forum__item-meta">
|
||||
<span><i class="far fa-eye"></i> <?php echo esc_html((string) ($ft['views'] ?? 0)); ?></span>
|
||||
<span><i class="far fa-comment"></i> <?php echo esc_html((string) ($ft['comment_count'] ?? 0)); ?></span>
|
||||
<time><?php echo esc_html((string) ($ft['date'] ?? '')); ?></time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php if ($fav_topics['max_pages'] > 1) : ?>
|
||||
<div class="uh-forum__pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'base' => add_query_arg('forum_page', '%#%', $home_url),
|
||||
'format' => '',
|
||||
'current' => $forum_page,
|
||||
'total' => $fav_topics['max_pages'],
|
||||
'add_args' => ['tab' => 'forum', 'forum_sub' => 'favorites'],
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<?php aksrt_render_profile_empty($svg_empty_favorite, __('暂无收藏帖子', 'aksrt')); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php elseif ($forum_sub === 'plates' && $forum_instance) :
|
||||
$managed_plates = $forum_instance->get_user_managed_plates($user_id);
|
||||
$followed_plates = $forum_instance->get_user_followed_plates($user_id);
|
||||
$has_plates = !empty($managed_plates['owned']) || !empty($managed_plates['moderating']) || !empty($followed_plates);
|
||||
if ($has_plates) : ?>
|
||||
<?php if (!empty($managed_plates['owned'])) : ?>
|
||||
<h3 class="uh-forum__section-title"><i class="fas fa-crown"></i> <?php esc_html_e('创建的版块', 'aksrt'); ?></h3>
|
||||
<div class="uh-forum__plate-grid">
|
||||
<?php foreach ($managed_plates['owned'] as $plate) : ?>
|
||||
<a class="uh-forum__plate-card" href="<?php echo esc_url(get_permalink((int) ($plate['id'] ?? 0))); ?>">
|
||||
<div class="uh-forum__plate-name"><?php echo esc_html((string) ($plate['name'] ?? '')); ?></div>
|
||||
<div class="uh-forum__plate-stats">
|
||||
<span><?php printf(esc_html__('%d 帖子', 'aksrt'), (int) ($plate['topic_count'] ?? 0)); ?></span>
|
||||
<span><?php printf(esc_html__('%d 关注', 'aksrt'), (int) ($plate['follow_count'] ?? 0)); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($managed_plates['moderating'])) : ?>
|
||||
<h3 class="uh-forum__section-title"><i class="fas fa-shield-alt"></i> <?php esc_html_e('管理的版块', 'aksrt'); ?></h3>
|
||||
<div class="uh-forum__plate-grid">
|
||||
<?php foreach ($managed_plates['moderating'] as $plate) : ?>
|
||||
<a class="uh-forum__plate-card" href="<?php echo esc_url(get_permalink((int) ($plate['id'] ?? 0))); ?>">
|
||||
<div class="uh-forum__plate-name"><?php echo esc_html((string) ($plate['name'] ?? '')); ?></div>
|
||||
<div class="uh-forum__plate-stats">
|
||||
<span><?php printf(esc_html__('%d 帖子', 'aksrt'), (int) ($plate['topic_count'] ?? 0)); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($followed_plates)) : ?>
|
||||
<h3 class="uh-forum__section-title"><i class="fas fa-heart"></i> <?php esc_html_e('关注的版块', 'aksrt'); ?></h3>
|
||||
<div class="uh-forum__plate-grid">
|
||||
<?php foreach ($followed_plates as $plate) : ?>
|
||||
<a class="uh-forum__plate-card" href="<?php echo esc_url(get_permalink((int) ($plate['id'] ?? 0))); ?>">
|
||||
<div class="uh-forum__plate-name"><?php echo esc_html((string) ($plate['name'] ?? '')); ?></div>
|
||||
<div class="uh-forum__plate-stats">
|
||||
<span><?php printf(esc_html__('%d 帖子', 'aksrt'), (int) ($plate['topic_count'] ?? 0)); ?></span>
|
||||
<span><?php printf(esc_html__('%d 关注', 'aksrt'), (int) ($plate['follow_count'] ?? 0)); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<?php aksrt_render_profile_empty($svg_empty_post, __('暂无版块数据', 'aksrt')); ?>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (in_array('follow', $enabled_tabs, true)) : ?>
|
||||
<div id="panel-follow" class="dashboard-panel<?php echo $active_tab === 'follow' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'follow' ? ' hidden' : ''; ?>>
|
||||
<?php
|
||||
if ($forum_instance) :
|
||||
$followed = $forum_instance->get_user_followed_plates($user_id);
|
||||
if (!empty($followed)) : ?>
|
||||
<div class="uh-forum__plate-grid">
|
||||
<?php foreach ($followed as $plate) : ?>
|
||||
<a class="uh-forum__plate-card" href="<?php echo esc_url(get_permalink((int) ($plate['id'] ?? 0))); ?>">
|
||||
<div class="uh-forum__plate-name"><?php echo esc_html((string) ($plate['name'] ?? '')); ?></div>
|
||||
<div class="uh-forum__plate-stats">
|
||||
<span><?php printf(esc_html__('%d 帖子', 'aksrt'), (int) ($plate['topic_count'] ?? 0)); ?></span>
|
||||
<span><?php printf(esc_html__('%d 关注', 'aksrt'), (int) ($plate['follow_count'] ?? 0)); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<?php aksrt_render_profile_empty($svg_empty_post, __('暂未关注任何版块', 'aksrt')); ?>
|
||||
<?php endif;
|
||||
else :
|
||||
aksrt_render_profile_empty($svg_empty_post, __('暂无关注内容', 'aksrt'));
|
||||
endif;
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($user_home_settings['sidebar'])) : ?>
|
||||
<div class="sidebar uc-sidebar aksrt-user-home__aside" role="complementary" aria-label="<?php esc_attr_e('用户主页侧栏', 'aksrt'); ?>">
|
||||
<div class="uc-sidebar__section">
|
||||
<div class="uc-sidebar__title"><?php esc_html_e('主页概览', 'aksrt'); ?></div>
|
||||
<div class="uc-stats">
|
||||
<?php foreach ($enabled_tabs as $tab_key) : ?>
|
||||
<a class="uc-stats__item" href="<?php echo esc_url(add_query_arg('tab', $tab_key, $home_url)); ?>">
|
||||
<span class="uc-stats__value"><?php echo esc_html((string) ($tab_counts[$tab_key] ?? 0)); ?></span>
|
||||
<span class="uc-stats__label"><?php echo esc_html($tab_labels[$tab_key] ?? ucfirst($tab_key)); ?></span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($user_contacts) && !empty($user_center_settings['social_links'])) : ?>
|
||||
<div class="uc-sidebar__section">
|
||||
<div class="uc-sidebar__title"><?php esc_html_e('公开联系', 'aksrt'); ?></div>
|
||||
<div class="aksrt-user-home__contacts">
|
||||
<?php if (function_exists('aksrt_render_social_links')) : ?>
|
||||
<?php aksrt_render_social_links($user_contacts); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="uc-sidebar__section">
|
||||
<div class="uc-sidebar__title"><?php esc_html_e('快捷入口', 'aksrt'); ?></div>
|
||||
<div class="uc-sidebar__buttons">
|
||||
<a href="<?php echo esc_url($home_url); ?>" class="uc-sidebar__btn">
|
||||
<i class="fas fa-user" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('主页首页', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php if ($is_own_profile) : ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_user_center_url()); ?>" class="uc-sidebar__btn">
|
||||
<i class="fas fa-cog" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('个人中心', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($is_own_profile) : ?>
|
||||
<?php
|
||||
$orders_url = function_exists('aksrt_get_orders_page_url') ? aksrt_get_orders_page_url() : '';
|
||||
$show_vip = class_exists('AKSRT_Settings') && !empty(AKSRT_Settings::get_all()['payment_vip_enabled']);
|
||||
$credits_enabled = class_exists('AKSRT_Settings') && AKSRT_Settings::credits_enabled();
|
||||
?>
|
||||
<?php if ($orders_url || $show_vip || $credits_enabled) : ?>
|
||||
<div class="uc-sidebar__section">
|
||||
<div class="uc-sidebar__title"><?php esc_html_e('交易服务', 'aksrt'); ?></div>
|
||||
<div class="uc-sidebar__buttons">
|
||||
<?php if ($orders_url) : ?>
|
||||
<a href="<?php echo esc_url($orders_url); ?>" class="uc-sidebar__btn">
|
||||
<i class="fas fa-receipt" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('我的订单', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($show_vip) : ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_user_center_url()); ?>" class="uc-sidebar__btn">
|
||||
<i class="fas fa-crown" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('VIP 会员', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($credits_enabled) : ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_user_center_url()); ?>" class="uc-sidebar__btn">
|
||||
<i class="fas fa-coins" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html(AKSRT_Settings::get_currency_name()); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</aside>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - Verify Email
|
||||
* Template Post Type: page
|
||||
*
|
||||
* Theme auth route template: /verify-email/
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
$verify_error = '';
|
||||
$verify_success = '';
|
||||
$redirect_url = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['verify_email_resend'])) {
|
||||
$result = AKSRT_Auth_Service::resend_email_verification($_POST);
|
||||
if (!empty($result['success'])) {
|
||||
$verify_success = $result['message'] ?? __('验证邮件已重新发送,请注意查收。', 'aksrt');
|
||||
} else {
|
||||
$verify_error = $result['error'] ?? __('验证邮件发送失败,请稍后重试。', 'aksrt');
|
||||
}
|
||||
} elseif (isset($_POST['verify_email_submit'])) {
|
||||
$result = AKSRT_Auth_Service::verify_email_code_submission($_POST);
|
||||
if (!empty($result['success'])) {
|
||||
$verify_success = $result['message'] ?? __('邮箱验证成功,即将进入你的账号。', 'aksrt');
|
||||
$redirect_url = $result['redirect'] ?? '';
|
||||
} else {
|
||||
$verify_error = $result['error'] ?? __('邮箱验证码错误或已过期。', 'aksrt');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$verify_context = AKSRT_Auth_Service::get_email_verification_context($_GET);
|
||||
if ($verify_error === '' && !empty($verify_context['error'])) {
|
||||
$verify_error = $verify_context['error'];
|
||||
}
|
||||
if ($verify_success === '' && !empty($verify_context['message'])) {
|
||||
$verify_success = $verify_context['message'];
|
||||
}
|
||||
if ($redirect_url === '' && !empty($verify_context['redirect'])) {
|
||||
$redirect_url = $verify_context['redirect'];
|
||||
}
|
||||
|
||||
$verify_user = $verify_context['user'] ?? null;
|
||||
$verify_uid = (int) ($verify_context['uid'] ?? 0);
|
||||
$verify_email = (string) ($verify_context['email'] ?? '');
|
||||
$verify_mode = (string) ($verify_context['mode'] ?? 'invalid');
|
||||
$verify_method= (string) ($verify_context['method'] ?? '');
|
||||
$verify_vk = (string) ($verify_context['access_key'] ?? '');
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main" tabindex="-1">
|
||||
<div class="auth-shell">
|
||||
<div class="auth-card">
|
||||
<div class="auth-card__logo" aria-hidden="true">AK</div>
|
||||
<h1 class="auth-card__title"><?php bloginfo('name'); ?></h1>
|
||||
|
||||
<?php if ($verify_mode === 'completed' || $verify_mode === 'verified') : ?>
|
||||
<p class="auth-card__subtitle"><?php esc_html_e('邮箱验证成功', 'aksrt'); ?></p>
|
||||
<?php elseif ($verify_mode === 'code') : ?>
|
||||
<p class="auth-card__subtitle"><?php esc_html_e('请输入邮箱验证码完成验证', 'aksrt'); ?></p>
|
||||
<?php elseif ($verify_mode === 'pending') : ?>
|
||||
<p class="auth-card__subtitle"><?php esc_html_e('验证邮件已经发出,请点击邮箱中的链接完成验证', 'aksrt'); ?></p>
|
||||
<?php else : ?>
|
||||
<p class="auth-card__subtitle"><?php esc_html_e('邮箱验证状态异常,请重新检查链接或重新发送验证邮件', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($verify_error !== '') : ?>
|
||||
<div class="alert alert--error" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
|
||||
<span><?php echo esc_html($verify_error); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($verify_success !== '') : ?>
|
||||
<div class="alert alert--success" role="alert">
|
||||
<span><?php echo esc_html($verify_success); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (($verify_mode === 'completed' || $verify_mode === 'verified') && $redirect_url !== '') : ?>
|
||||
<p class="auth-footer-link">
|
||||
<a href="<?php echo esc_url($redirect_url); ?>"><?php esc_html_e('立即进入账号', 'aksrt'); ?></a>
|
||||
</p>
|
||||
<script>
|
||||
setTimeout(function(){ window.location.href = <?php echo wp_json_encode($redirect_url); ?>; }, 1800);
|
||||
</script>
|
||||
<?php elseif ($verify_mode === 'code') : ?>
|
||||
<form class="auth-form" method="post" action="">
|
||||
<?php wp_nonce_field('aksrt_verify_email', '_verify_email_nonce'); ?>
|
||||
<input type="hidden" name="verify_uid" value="<?php echo esc_attr((string) $verify_uid); ?>">
|
||||
<input type="hidden" name="vk" value="<?php echo esc_attr($verify_vk); ?>">
|
||||
<div class="form-field">
|
||||
<label for="verify_email_code"><?php esc_html_e('邮箱验证码', 'aksrt'); ?></label>
|
||||
<div class="input-wrap">
|
||||
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span>
|
||||
<input type="text" name="email_code" id="verify_email_code" inputmode="numeric" maxlength="6" pattern="[0-9]*" autocomplete="one-time-code" required>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($verify_email !== '') : ?>
|
||||
<p class="auth-card__subtitle" style="margin-top:-8px;"><?php echo esc_html(sprintf(__('验证码已发送到 %s', 'aksrt'), $verify_email)); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if (function_exists('aksrt_render_captcha')) : ?>
|
||||
<?php aksrt_render_captcha('verify_email'); ?>
|
||||
<?php endif; ?>
|
||||
<button type="submit" name="verify_email_submit" class="btn-primary btn-lg btn-block"><?php esc_html_e('验证并登录', 'aksrt'); ?></button>
|
||||
</form>
|
||||
<form method="post" action="" style="margin-top:12px;">
|
||||
<?php wp_nonce_field('aksrt_verify_email', '_verify_email_nonce'); ?>
|
||||
<input type="hidden" name="verify_uid" value="<?php echo esc_attr((string) $verify_uid); ?>">
|
||||
<input type="hidden" name="vk" value="<?php echo esc_attr($verify_vk); ?>">
|
||||
<?php if (function_exists('aksrt_render_captcha')) : ?>
|
||||
<?php aksrt_render_captcha('verify_email'); ?>
|
||||
<?php endif; ?>
|
||||
<button type="submit" name="verify_email_resend" class="btn-primary btn-lg" style="width:100%;background:transparent;color:var(--color-primary);border:1px solid var(--color-primary);"><?php esc_html_e('重新发送验证码', 'aksrt'); ?></button>
|
||||
</form>
|
||||
<?php elseif ($verify_mode === 'pending' && $verify_uid > 0 && $verify_vk !== '') : ?>
|
||||
<?php
|
||||
// method 缺失(历史账号 / meta 被外部清理)→ 回退到设置默认值
|
||||
$resend_method = in_array($verify_method, ['link', 'code'], true)
|
||||
? $verify_method
|
||||
: (class_exists('AKSRT_Settings') ? AKSRT_Settings::registration_verification_method() : 'link');
|
||||
?>
|
||||
<?php if ($verify_email !== '') : ?>
|
||||
<p class="auth-card__subtitle"><?php echo esc_html(sprintf(__('当前待验证邮箱:%s', 'aksrt'), $verify_email)); ?></p>
|
||||
<?php endif; ?>
|
||||
<form method="post" action="">
|
||||
<?php wp_nonce_field('aksrt_verify_email', '_verify_email_nonce'); ?>
|
||||
<input type="hidden" name="verify_uid" value="<?php echo esc_attr((string) $verify_uid); ?>">
|
||||
<input type="hidden" name="vk" value="<?php echo esc_attr($verify_vk); ?>">
|
||||
<?php if (function_exists('aksrt_render_captcha')) : ?>
|
||||
<?php aksrt_render_captcha('verify_email'); ?>
|
||||
<?php endif; ?>
|
||||
<button type="submit" name="verify_email_resend" class="btn-primary btn-lg" style="width:100%;"><?php echo esc_html($resend_method === 'code' ? __('重新发送验证码', 'aksrt') : __('重新发送验证邮件', 'aksrt')); ?></button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<p class="auth-footer-link">
|
||||
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>"><?php esc_html_e('返回登录', 'aksrt'); ?></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* 通用空状态模板
|
||||
*
|
||||
* 用于列表页无内容时的统一展示。
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @var string $icon FA icon class (default: far fa-inbox)
|
||||
* @var string $title 主标题
|
||||
* @var string $desc 描述文字
|
||||
* @var string $action_url 操作按钮链接
|
||||
* @var string $action_text 操作按钮文字
|
||||
* @var string $size 尺寸: sm / md (default: md)
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$icon = $args['icon'] ?? 'far fa-inbox';
|
||||
$title = $args['title'] ?? __('暂无内容', 'aksrt');
|
||||
$desc = $args['desc'] ?? '';
|
||||
$action_url = $args['action_url'] ?? '';
|
||||
$action_text = $args['action_text'] ?? '';
|
||||
$size = $args['size'] ?? 'md';
|
||||
?>
|
||||
|
||||
<div class="empty-state <?php echo $size === 'sm' ? 'empty-state--sm' : ''; ?>">
|
||||
<div class="empty-state__icon"><i class="<?php echo esc_attr($icon); ?>"></i></div>
|
||||
<p class="empty-state__title"><?php echo esc_html($title); ?></p>
|
||||
<?php if ($desc) : ?>
|
||||
<p class="empty-state__desc"><?php echo esc_html($desc); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($action_url && $action_text) : ?>
|
||||
<a href="<?php echo esc_url($action_url); ?>" class="btn btn-primary btn-sm empty-state__action">
|
||||
<?php echo esc_html($action_text); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* 图片画廊模板
|
||||
*
|
||||
* 用于文章内嵌画廊块或图片列表展示。
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @var array $images 图片数组 [{src, alt, caption, width, height}]
|
||||
* @var string $layout 布局: grid / masonry / carousel
|
||||
* @var int $columns 列数 (default: 3)
|
||||
* @var bool $lightbox 是否启用灯箱 (default: true)
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$images = $args['images'] ?? [];
|
||||
$layout = $args['layout'] ?? 'grid';
|
||||
$columns = max(1, min(6, (int) ($args['columns'] ?? 3)));
|
||||
$lightbox = $args['lightbox'] ?? true;
|
||||
|
||||
if (empty($images)) return;
|
||||
?>
|
||||
|
||||
<div class="content-gallery content-gallery--<?php echo esc_attr($layout); ?>" style="--gallery-columns: <?php echo $columns; ?>;">
|
||||
<?php foreach ($images as $index => $img) :
|
||||
$src = $img['src'] ?? '';
|
||||
$alt = $img['alt'] ?? '';
|
||||
$caption = $img['caption'] ?? '';
|
||||
if (!$src) continue;
|
||||
?>
|
||||
<figure class="content-gallery__item" data-index="<?php echo $index; ?>">
|
||||
<a href="<?php echo esc_url($src); ?>"
|
||||
class="content-gallery__link"
|
||||
<?php echo $lightbox ? 'data-lightbox="gallery"' : ''; ?>
|
||||
data-caption="<?php echo esc_attr($caption); ?>">
|
||||
<img src="<?php echo esc_url($src); ?>"
|
||||
alt="<?php echo esc_attr($alt); ?>"
|
||||
class="content-gallery__img"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('content') : ' loading="lazy"'; ?>
|
||||
width="<?php echo esc_attr($img['width'] ?? 800); ?>"
|
||||
height="<?php echo esc_attr($img['height'] ?? 600); ?>">
|
||||
</a>
|
||||
<?php if ($caption) : ?>
|
||||
<figcaption class="content-gallery__caption"><?php echo esc_html($caption); ?></figcaption>
|
||||
<?php endif; ?>
|
||||
</figure>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/**
|
||||
* Post Card / List Item Template — Unified Wrapper (v4.0)
|
||||
*
|
||||
* This template delegates to the unified shared renderer (aksrt_render_post).
|
||||
* It preserves backward compatibility for callers using get_template_part().
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
// If the shared renderer is available, delegate entirely
|
||||
if (function_exists('aksrt_render_post')) {
|
||||
$args = isset($args) && is_array($args) ? $args : [];
|
||||
|
||||
// Resolve layout mode from query var or args
|
||||
$forced_layout = (string) get_query_var('aksrt_post_card_layout', '');
|
||||
$mode = 'card';
|
||||
|
||||
if (is_string($forced_layout) && in_array($forced_layout, ['card', 'list', 'grid-cms'], true)) {
|
||||
$mode = $forced_layout;
|
||||
} elseif (!empty($args['mode']) && in_array($args['mode'], ['card', 'list', 'grid-cms', 'mini'], true)) {
|
||||
$mode = $args['mode'];
|
||||
} elseif (function_exists('aksrt_get_post_flow') && aksrt_get_post_flow(get_the_ID()) === 'cms') {
|
||||
$mode = 'grid-cms';
|
||||
} elseif (class_exists('AKSRT_Settings')) {
|
||||
$archive_layout = AKSRT_Settings::get_archive_layout();
|
||||
$mode = in_array($archive_layout, ['card', 'list', 'grid-cms'], true) ? $archive_layout : 'card';
|
||||
}
|
||||
|
||||
// Resolve scene context
|
||||
$scene = (string) get_query_var('aksrt_post_card_scene', '');
|
||||
$context = ($scene === 'home' || is_front_page() || (is_home() && !is_paged())) ? 'home' : 'archive';
|
||||
|
||||
$config = array_merge($args, [
|
||||
'mode' => $mode,
|
||||
'context' => $context,
|
||||
]);
|
||||
|
||||
echo aksrt_render_post($config); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Fallback: self-contained rendering when shared renderer unavailable
|
||||
// ============================================================
|
||||
|
||||
$args = isset($args) && is_array($args) ? $args : [];
|
||||
|
||||
$lazy_cfg = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_lazyload_config() : ['enabled' => false, 'placeholder_url' => ''];
|
||||
$lazy_on = !empty($lazy_cfg['enabled']);
|
||||
$placeholder_url = !empty($lazy_cfg['placeholder_url']) ? (string) $lazy_cfg['placeholder_url'] : (get_template_directory_uri() . '/assets/img/placeholder.svg');
|
||||
|
||||
$forced_layout = (string) get_query_var('aksrt_post_card_layout', '');
|
||||
$layout = 'card';
|
||||
if (is_string($forced_layout) && in_array($forced_layout, ['card', 'list', 'masonry', 'grid-cms'], true)) {
|
||||
$layout = $forced_layout;
|
||||
} elseif (function_exists('aksrt_get_post_flow') && aksrt_get_post_flow(get_the_ID()) === 'cms') {
|
||||
$layout = 'grid-cms';
|
||||
} elseif (class_exists('AKSRT_Settings')) {
|
||||
$layout = AKSRT_Settings::get_archive_layout();
|
||||
}
|
||||
|
||||
$post_id = get_the_ID();
|
||||
$author_id = get_the_author_meta('ID');
|
||||
$author = get_the_author();
|
||||
$avatar_url = get_avatar_url($author_id, ['size' => 40]);
|
||||
$time_ago = human_time_diff(get_the_time('U'), current_time('timestamp')) . __('前', 'aksrt');
|
||||
$excerpt = wp_trim_words(get_the_excerpt(), 'list' === $layout ? 30 : 20, '...');
|
||||
$tags = get_the_tags() ?: [];
|
||||
$categories = get_the_category() ?: [];
|
||||
$comment_count = (int) get_comments_number();
|
||||
$views = function_exists('aksrt_get_post_views') ? aksrt_get_post_views($post_id) : 0;
|
||||
$is_sticky = is_sticky($post_id);
|
||||
$title_html = isset($args['title_html']) ? (string) $args['title_html'] : get_the_title();
|
||||
$resource_badge = function_exists('aksrt_resource_card_badge_text') ? aksrt_resource_card_badge_text($post_id) : '';
|
||||
|
||||
$img_url = '';
|
||||
if (has_post_thumbnail()) {
|
||||
$img_url = get_the_post_thumbnail_url($post_id, 'medium_large');
|
||||
} elseif (function_exists('aksrt_get_first_content_image_url')) {
|
||||
$img_url = (string) aksrt_get_first_content_image_url($post_id);
|
||||
}
|
||||
$has_img = !empty($img_url);
|
||||
|
||||
$scene = (string) get_query_var('aksrt_post_card_scene', '');
|
||||
$is_home_scene = $scene === 'home' || is_front_page() || (is_home() && !is_paged());
|
||||
$category_limit = $is_home_scene ? 1 : 3;
|
||||
$tag_limit = $is_home_scene ? 2 : 3;
|
||||
|
||||
// Badges HTML
|
||||
ob_start();
|
||||
?>
|
||||
<div class="item-tags scroll-x no-scrollbar">
|
||||
<?php if ($resource_badge !== '') : ?>
|
||||
<badge class="meta-pay but jb-yellow"><?php echo esc_html($resource_badge); ?></badge>
|
||||
<?php endif; ?>
|
||||
<?php foreach (array_slice($categories, 0, $category_limit) as $category) : ?>
|
||||
<a href="<?php echo esc_url(get_category_link($category->term_id)); ?>" class="but"><i class="far fa-folder-open" aria-hidden="true"></i> <?php echo esc_html($category->name); ?></a>
|
||||
<?php endforeach; ?>
|
||||
<?php foreach (array_slice($tags, 0, $tag_limit) as $tag) : ?>
|
||||
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" class="but"># <?php echo esc_html($tag->name); ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php
|
||||
$badges_html = trim((string) ob_get_clean());
|
||||
|
||||
// Meta HTML
|
||||
ob_start();
|
||||
?>
|
||||
<div class="item-meta muted-2-color flex jsb ac">
|
||||
<item class="meta-author flex ac">
|
||||
<img src="<?php echo esc_url($avatar_url); ?>" alt="" class="avatar-mini" width="20" height="20" loading="lazy">
|
||||
<name class="meta-name"><?php echo esc_html($author); ?></name>
|
||||
<item class="meta-time"><?php echo esc_html($time_ago); ?></item>
|
||||
</item>
|
||||
<div class="meta-right">
|
||||
<item class="meta-view"><i class="fas fa-eye" aria-hidden="true"></i> <?php echo esc_html(function_exists('aksrt_format_number') ? aksrt_format_number($views) : (string) $views); ?></item>
|
||||
<item class="meta-view"><i class="fas fa-comment" aria-hidden="true"></i> <?php echo esc_html((string) $comment_count); ?></item>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
$meta_html = trim((string) ob_get_clean());
|
||||
|
||||
if ('list' === $layout) : ?>
|
||||
<article <?php post_class('posts-item list ajax-item'); ?>>
|
||||
<div class="item-thumbnail">
|
||||
<a href="<?php the_permalink(); ?>">
|
||||
<?php if ($has_img && $lazy_on) : ?>
|
||||
<span class="aksrt-skeleton"></span>
|
||||
<img class="fit-cover aksrt-lazy" data-src="<?php echo esc_url($img_url); ?>" src="<?php echo esc_url($placeholder_url); ?>" alt="<?php echo esc_attr(get_the_title()); ?>">
|
||||
<?php elseif ($has_img) : ?>
|
||||
<img class="fit-cover" src="<?php echo esc_url($img_url); ?>" alt="<?php echo esc_attr(get_the_title()); ?>">
|
||||
<?php else : ?>
|
||||
<img class="fit-cover" src="<?php echo esc_url($placeholder_url); ?>" alt="">
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<?php if ($is_sticky) : ?>
|
||||
<span class="img-badge left badge-sticky"><?php esc_html_e('置顶', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="item-body">
|
||||
<h2 class="item-heading"><a href="<?php the_permalink(); ?>"><?php echo wp_kses_post($title_html); ?></a></h2>
|
||||
<p class="item-excerpt"><?php echo wp_kses_post(esc_html($excerpt)); ?></p>
|
||||
<?php echo $badges_html; ?>
|
||||
<?php echo $meta_html; ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php else : ?>
|
||||
<article <?php post_class('posts-item card ajax-item' . ($is_home_scene ? ' posts-item--home' : '')); ?>>
|
||||
<div class="item-thumbnail">
|
||||
<a href="<?php the_permalink(); ?>">
|
||||
<?php if ($has_img && $lazy_on) : ?>
|
||||
<span class="aksrt-skeleton"></span>
|
||||
<img class="fit-cover aksrt-lazy" data-src="<?php echo esc_url($img_url); ?>" src="<?php echo esc_url($placeholder_url); ?>" alt="<?php echo esc_attr(get_the_title()); ?>">
|
||||
<?php elseif ($has_img) : ?>
|
||||
<img class="fit-cover" src="<?php echo esc_url($img_url); ?>" alt="<?php echo esc_attr(get_the_title()); ?>">
|
||||
<?php else : ?>
|
||||
<img class="fit-cover" src="<?php echo esc_url($placeholder_url); ?>" alt="">
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<?php if ($is_sticky) : ?>
|
||||
<span class="img-badge left badge-sticky"><?php esc_html_e('置顶', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="item-body">
|
||||
<h2 class="item-heading"><a href="<?php the_permalink(); ?>"><?php echo wp_kses_post($title_html); ?></a></h2>
|
||||
<?php echo $badges_html; ?>
|
||||
<?php echo $meta_html; ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Profile Comment List Item — image-less comment row for user center.
|
||||
*
|
||||
* 通过 set_query_var() 接收:
|
||||
* - aksrt_profile_comment: WP_Comment 对象
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$comment = get_query_var('aksrt_profile_comment');
|
||||
if (!$comment instanceof WP_Comment) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post = get_post((int) $comment->comment_post_ID);
|
||||
if (!$post) {
|
||||
return;
|
||||
}
|
||||
|
||||
$snippet = wp_trim_words(wp_strip_all_tags($comment->comment_content), 30, '…');
|
||||
$post_title = get_the_title($post);
|
||||
$comment_link = get_comment_link($comment);
|
||||
$post_link = get_permalink($post);
|
||||
$date_iso = get_comment_date('c', $comment);
|
||||
$date_label = get_comment_date('Y-m-d', $comment);
|
||||
$time_diff = human_time_diff(strtotime($comment->comment_date), current_time('timestamp'));
|
||||
?>
|
||||
<article class="profile-comment-item">
|
||||
<a href="<?php echo esc_url($comment_link); ?>" class="profile-comment-item__quote-link" aria-label="<?php esc_attr_e('查看评论', 'aksrt'); ?>">
|
||||
<span class="profile-comment-item__quote-mark" aria-hidden="true">“</span>
|
||||
<span class="profile-comment-item__quote-text"><?php echo esc_html($snippet); ?></span>
|
||||
</a>
|
||||
<div class="profile-comment-item__meta">
|
||||
<span class="profile-comment-item__meta-item profile-comment-item__meta-item--post">
|
||||
<i class="far fa-file-alt" aria-hidden="true"></i>
|
||||
<?php esc_html_e('在', 'aksrt'); ?>
|
||||
<a href="<?php echo esc_url($post_link); ?>" class="profile-comment-item__post-link"><?php echo esc_html($post_title); ?></a>
|
||||
</span>
|
||||
<span class="profile-comment-item__meta-sep" aria-hidden="true">·</span>
|
||||
<time class="profile-comment-item__meta-item" datetime="<?php echo esc_attr($date_iso); ?>" title="<?php echo esc_attr($date_label); ?>">
|
||||
<?php
|
||||
/* translators: %s: human time diff */
|
||||
printf(esc_html__('%s前', 'aksrt'), esc_html($time_diff));
|
||||
?>
|
||||
</time>
|
||||
</div>
|
||||
</article>
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* Profile List Item — image-less list row for user center.
|
||||
*
|
||||
* 用于:
|
||||
* - 我的文章 / 我的收藏 / 公开主页文章列表
|
||||
*
|
||||
* 通过 set_query_var() 接收以下参数(可选):
|
||||
* - aksrt_profile_item_action: ['type'=>'edit'|'view'|'unfavorite', 'url'=>'...', 'label'=>'...']
|
||||
* - aksrt_profile_item_status: 文章状态徽章文本(如 "草稿" / "私密")
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$action = get_query_var('aksrt_profile_item_action', []);
|
||||
if (!is_array($action)) {
|
||||
$action = [];
|
||||
}
|
||||
$action_type = isset($action['type']) ? (string) $action['type'] : '';
|
||||
$action_url = isset($action['url']) ? (string) $action['url'] : '';
|
||||
$action_label = isset($action['label']) ? (string) $action['label'] : '';
|
||||
|
||||
$status_label = (string) get_query_var('aksrt_profile_item_status', '');
|
||||
|
||||
$post_id = get_the_ID();
|
||||
$permalink = get_permalink();
|
||||
$title = get_the_title();
|
||||
$date_iso = get_the_date('c');
|
||||
$date_label = get_the_date();
|
||||
$excerpt = wp_trim_words(get_the_excerpt(), 30, '…');
|
||||
$comment_count = (int) get_comments_number();
|
||||
$categories = get_the_category() ?: [];
|
||||
$tags = get_the_tags() ?: [];
|
||||
?>
|
||||
<article <?php post_class('profile-list-item'); ?>>
|
||||
<div class="profile-list-item__main">
|
||||
<div class="profile-list-item__head">
|
||||
<h3 class="profile-list-item__title">
|
||||
<a href="<?php echo esc_url($permalink); ?>"><?php echo esc_html($title); ?></a>
|
||||
<?php if ($status_label) : ?>
|
||||
<span class="profile-list-item__status-badge"><?php echo esc_html($status_label); ?></span>
|
||||
<?php endif; ?>
|
||||
</h3>
|
||||
<time class="profile-list-item__date" datetime="<?php echo esc_attr($date_iso); ?>" title="<?php echo esc_attr($date_label); ?>">
|
||||
<?php echo esc_html($date_label); ?>
|
||||
</time>
|
||||
</div>
|
||||
|
||||
<?php if ($excerpt) : ?>
|
||||
<p class="profile-list-item__excerpt"><?php echo esc_html($excerpt); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="profile-list-item__meta">
|
||||
<?php foreach ($categories as $cat) : ?>
|
||||
<a href="<?php echo esc_url(get_category_link($cat->term_id)); ?>" class="profile-list-item__chip profile-list-item__chip--category">
|
||||
<i class="fas fa-folder" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html($cat->name); ?></span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php foreach (array_slice($tags, 0, 4) as $tag) : ?>
|
||||
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" class="profile-list-item__chip profile-list-item__chip--tag">
|
||||
#<?php echo esc_html($tag->name); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<span class="profile-list-item__meta-spacer"></span>
|
||||
|
||||
<span class="profile-list-item__meta-item profile-list-item__meta-item--comments" title="<?php esc_attr_e('评论数', 'aksrt'); ?>">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>
|
||||
<span><?php echo esc_html((string) $comment_count); ?></span>
|
||||
</span>
|
||||
|
||||
<?php if ($action_type && $action_url) :
|
||||
$action_class = 'profile-list-item__action profile-list-item__action--' . sanitize_html_class($action_type);
|
||||
$icon_svg = '';
|
||||
switch ($action_type) {
|
||||
case 'edit':
|
||||
$icon_svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 1 1 3 3L7 19l-4 1 1-4Z"/></svg>';
|
||||
break;
|
||||
case 'unfavorite':
|
||||
$icon_svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>';
|
||||
break;
|
||||
case 'view':
|
||||
default:
|
||||
$icon_svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12Z"/><circle cx="12" cy="12" r="3"/></svg>';
|
||||
break;
|
||||
}
|
||||
if ('unfavorite' === $action_type) :
|
||||
?>
|
||||
<button type="button" class="<?php echo esc_attr($action_class); ?>" data-post-id="<?php echo esc_attr((string) $post_id); ?>" data-action="unfavorite" title="<?php echo esc_attr($action_label); ?>">
|
||||
<span class="profile-list-item__action-icon"><?php echo $icon_svg; // phpcs:ignore ?></span>
|
||||
<span class="profile-list-item__action-label"><?php echo esc_html($action_label); ?></span>
|
||||
</button>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url($action_url); ?>" class="<?php echo esc_attr($action_class); ?>" title="<?php echo esc_attr($action_label); ?>">
|
||||
<span class="profile-list-item__action-icon"><?php echo $icon_svg; // phpcs:ignore ?></span>
|
||||
<span class="profile-list-item__action-label"><?php echo esc_html($action_label); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* Document Chapter Navigation
|
||||
*
|
||||
* Shows previous/next chapter navigation at the bottom of a document page.
|
||||
* Uses AKSRT_Docs_Presenter for chapter resolution.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$current_id = get_the_ID();
|
||||
|
||||
$presenter = class_exists('AKSRT_Docs_Presenter') ? AKSRT_Docs_Presenter::get_instance() : null;
|
||||
|
||||
if ($presenter) {
|
||||
$nav = $presenter->get_chapter_nav($current_id);
|
||||
$prev_page = $nav['prev'];
|
||||
$next_page = $nav['next'];
|
||||
} else {
|
||||
$parent_id = wp_get_post_parent_id($current_id);
|
||||
$siblings = get_pages([
|
||||
'parent' => $parent_id ?: 0,
|
||||
'sort_column' => 'menu_order, post_title',
|
||||
'sort_order' => 'ASC',
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
|
||||
$current_index = -1;
|
||||
foreach ($siblings as $i => $sibling) {
|
||||
if ((int) $sibling->ID === $current_id) {
|
||||
$current_index = $i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$prev_page = $current_index > 0 ? $siblings[$current_index - 1] : null;
|
||||
$next_page = ($current_index >= 0 && $current_index < count($siblings) - 1)
|
||||
? $siblings[$current_index + 1]
|
||||
: null;
|
||||
}
|
||||
|
||||
if (!$prev_page && !$next_page) return;
|
||||
?>
|
||||
<nav class="aksrt-doc-chapter-nav" aria-label="<?php esc_attr_e('章节导航', 'aksrt'); ?>">
|
||||
<?php if ($prev_page) : ?>
|
||||
<a href="<?php echo esc_url(get_permalink($prev_page->ID)); ?>" class="aksrt-doc-chapter-nav__prev">
|
||||
<span class="aksrt-doc-chapter-nav__label">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
<?php esc_html_e('上一篇', 'aksrt'); ?>
|
||||
</span>
|
||||
<span class="aksrt-doc-chapter-nav__title"><?php echo esc_html($prev_page->post_title); ?></span>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-doc-chapter-nav__prev aksrt-doc-chapter-nav__prev--disabled"></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($next_page) : ?>
|
||||
<a href="<?php echo esc_url(get_permalink($next_page->ID)); ?>" class="aksrt-doc-chapter-nav__next">
|
||||
<span class="aksrt-doc-chapter-nav__label">
|
||||
<?php esc_html_e('下一篇', 'aksrt'); ?>
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</span>
|
||||
<span class="aksrt-doc-chapter-nav__title"><?php echo esc_html($next_page->post_title); ?></span>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-doc-chapter-nav__next aksrt-doc-chapter-nav__next--disabled"></div>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Document Index Card
|
||||
*
|
||||
* Shows a card for a document page on the document navigation index.
|
||||
* Used in the document navigation page to list available documents.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$page_id = get_the_ID();
|
||||
$children = get_pages([
|
||||
'parent' => $page_id,
|
||||
'sort_column' => 'menu_order',
|
||||
'sort_order' => 'ASC',
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
$child_count = count($children);
|
||||
$thumb = get_the_post_thumbnail_url($page_id, 'medium');
|
||||
$excerpt = wp_trim_words(get_the_excerpt(), 30, '...');
|
||||
?>
|
||||
<a href="<?php the_permalink(); ?>" class="aksrt-doc-index-card">
|
||||
<?php if ($thumb) : ?>
|
||||
<div class="aksrt-doc-index-card__thumb">
|
||||
<img src="<?php echo esc_url($thumb); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-doc-index-card__icon">
|
||||
<i class="fas fa-book-open"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-doc-index-card__body">
|
||||
<h3 class="aksrt-doc-index-card__title"><?php the_title(); ?></h3>
|
||||
<?php if ($excerpt) : ?>
|
||||
<p class="aksrt-doc-index-card__desc"><?php echo esc_html($excerpt); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-doc-index-card__meta">
|
||||
<?php if ($child_count > 0) : ?>
|
||||
<span class="aksrt-doc-index-card__count">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<?php printf(esc_html__('%d 篇文章', 'aksrt'), $child_count); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<span class="aksrt-doc-index-card__date">
|
||||
<i class="fas fa-clock"></i>
|
||||
<?php echo esc_html(get_the_date('', $page_id)); ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<i class="fas fa-chevron-right aksrt-doc-index-card__arrow"></i>
|
||||
</a>
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* Docs Mode: Sidebar Navigation
|
||||
*
|
||||
* 文档模式侧边栏:显示文档目录树,当前章节高亮。
|
||||
* Uses AKSRT_Docs_Presenter for tree construction.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$current_id = get_the_ID();
|
||||
$parent_id = wp_get_post_parent_id($current_id);
|
||||
$root_id = $parent_id ?: $current_id;
|
||||
|
||||
$presenter = class_exists('AKSRT_Docs_Presenter') ? AKSRT_Docs_Presenter::get_instance() : null;
|
||||
|
||||
if ($presenter) {
|
||||
$doc_pages = $presenter->get_flat_tree($root_id, 3);
|
||||
} else {
|
||||
$doc_pages = get_pages([
|
||||
'child_of' => $root_id,
|
||||
'sort_column' => 'menu_order, post_title',
|
||||
'sort_order' => 'ASC',
|
||||
'parent' => $root_id,
|
||||
]);
|
||||
}
|
||||
|
||||
$root_page = get_post($root_id);
|
||||
|
||||
// Quick search for docs
|
||||
$doc_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_docs_mode_settings() : [];
|
||||
$show_search = !empty($doc_settings['toc_enabled']);
|
||||
?>
|
||||
<aside class="aksrt-doc-sidebar" role="navigation" aria-label="<?php esc_attr_e('文档导航', 'aksrt'); ?>">
|
||||
<div class="aksrt-doc-sidebar__header">
|
||||
<a href="<?php echo esc_url(get_permalink($root_id)); ?>" class="aksrt-doc-sidebar__root">
|
||||
<i class="fas fa-book aksrt-doc-sidebar__root-icon"></i>
|
||||
<span><?php echo esc_html($root_page->post_title ?? __('文档', 'aksrt')); ?></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<?php if ($show_search) : ?>
|
||||
<div class="aksrt-doc-sidebar__search">
|
||||
<input type="text" class="aksrt-doc-sidebar__search-input" placeholder="<?php esc_attr_e('搜索文档...', 'aksrt'); ?>" aria-label="<?php esc_attr_e('搜索文档', 'aksrt'); ?>">
|
||||
<i class="fas fa-search aksrt-doc-sidebar__search-icon"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($doc_pages)) : ?>
|
||||
<ul class="aksrt-doc-sidebar__nav">
|
||||
<?php foreach ($doc_pages as $dp) :
|
||||
$depth = isset($dp->_depth) ? (int) $dp->_depth : 0;
|
||||
$is_current = ((int) $dp->ID === $current_id);
|
||||
$is_ancestor = ((int) $dp->ID === $parent_id);
|
||||
$li_class = 'aksrt-doc-sidebar__item';
|
||||
if ($is_current) $li_class .= ' is-current';
|
||||
if ($is_ancestor) $li_class .= ' is-ancestor';
|
||||
if ($depth > 0) $li_class .= ' aksrt-doc-sidebar__item--depth-' . $depth;
|
||||
|
||||
$has_children = false;
|
||||
if ($presenter) {
|
||||
$sub = get_pages(['parent' => $dp->ID, 'post_status' => 'publish', 'fields' => 'ids']);
|
||||
$has_children = !empty($sub);
|
||||
} else {
|
||||
$sub_pages = get_pages(['child_of' => $dp->ID, 'sort_column' => 'menu_order', 'sort_order' => 'ASC', 'parent' => $dp->ID]);
|
||||
$has_children = !empty($sub_pages);
|
||||
}
|
||||
$is_open = $is_current || $is_ancestor;
|
||||
?>
|
||||
<li class="<?php echo esc_attr($li_class); ?>" style="<?php echo $depth > 0 ? 'padding-left:' . ($depth * 16) . 'px;' : ''; ?>">
|
||||
<a href="<?php echo esc_url(get_permalink($dp->ID)); ?>" class="aksrt-doc-sidebar__link<?php echo $is_current ? ' is-active' : ''; ?>">
|
||||
<?php if ($has_children) : ?>
|
||||
<i class="fas fa-chevron-<?php echo $is_open ? 'down' : 'right'; ?> aksrt-doc-sidebar__toggle" aria-hidden="true"></i>
|
||||
<?php endif; ?>
|
||||
<span><?php echo esc_html($dp->post_title); ?></span>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</aside>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Docs Mode: Table of Contents
|
||||
*
|
||||
* 文档模式目录:从文章内容中提取 h2/h3 生成右侧目录。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$content = get_the_content();
|
||||
if (empty($content)) return;
|
||||
|
||||
// 提取 h2/h3 标题
|
||||
$headings = [];
|
||||
if (preg_match_all('/<h([2-3])[^>]*(?:id="([^"]*)")?[^>]*>(.*?)<\/h\1>/is', $content, $matches, PREG_SET_ORDER)) {
|
||||
foreach ($matches as $m) {
|
||||
$level = (int) $m[1];
|
||||
$id = !empty($m[2]) ? $m[2] : '';
|
||||
$text = wp_strip_all_tags($m[3]);
|
||||
if ($text === '') continue;
|
||||
if ($id === '') {
|
||||
$id = 'toc-' . sanitize_title($text);
|
||||
}
|
||||
$headings[] = ['level' => $level, 'id' => $id, 'text' => $text];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($headings)) return;
|
||||
?>
|
||||
<nav class="aksrt-doc-toc" aria-label="<?php esc_attr_e('文章目录', 'aksrt'); ?>">
|
||||
<div class="aksrt-doc-toc__title"><?php esc_html_e('目录', 'aksrt'); ?></div>
|
||||
<ul class="aksrt-doc-toc__list">
|
||||
<?php foreach ($headings as $h) : ?>
|
||||
<li class="aksrt-doc-toc__item aksrt-doc-toc__item--h<?php echo esc_attr((string) $h['level']); ?>">
|
||||
<a href="#<?php echo esc_attr($h['id']); ?>"><?php echo esc_html($h['text']); ?></a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* Docs Mode: Document Tree
|
||||
*
|
||||
* 文档模式树形导航:递归展示文档层级结构。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_render_doc_tree')) {
|
||||
function aksrt_render_doc_tree($parent_id, $current_id, $depth = 0) {
|
||||
$children = get_pages([
|
||||
'parent' => $parent_id,
|
||||
'sort_column' => 'menu_order, post_title',
|
||||
'sort_order' => 'ASC',
|
||||
]);
|
||||
if (empty($children)) return;
|
||||
|
||||
$indent = str_repeat(' ', $depth);
|
||||
echo $indent . '<ul class="aksrt-doc-tree__level aksrt-doc-tree__level--' . esc_attr((string) ($depth + 1)) . '">';
|
||||
foreach ($children as $child) {
|
||||
$is_current = ($child->ID === $current_id);
|
||||
$has_children = (int) get_pages(['child_of' => $child->ID, 'parent' => $child->ID, 'hide_empty' => true, 'fields' => 'ids']) > 0;
|
||||
echo $indent . ' <li class="aksrt-doc-tree__item' . ($is_current ? ' is-current' : '') . '">';
|
||||
echo '<a href="' . esc_url(get_permalink($child->ID)) . '">' . esc_html($child->post_title) . '</a>';
|
||||
if ($has_children && $depth < 3) {
|
||||
aksrt_render_doc_tree($child->ID, $current_id, $depth + 1);
|
||||
}
|
||||
echo '</li>';
|
||||
}
|
||||
echo $indent . '</ul>';
|
||||
}
|
||||
}
|
||||
|
||||
$current_id = get_the_ID();
|
||||
$root_id = wp_get_post_parent_id($current_id) ?: $current_id;
|
||||
?>
|
||||
|
||||
<nav class="aksrt-doc-tree" aria-label="<?php esc_attr_e('文档树', 'aksrt'); ?>">
|
||||
<div class="aksrt-doc-tree__root">
|
||||
<a href="<?php echo esc_url(get_permalink($root_id)); ?>"><?php echo esc_html(get_the_title($root_id)); ?></a>
|
||||
</div>
|
||||
<?php aksrt_render_doc_tree($root_id, $current_id); ?>
|
||||
</nav>
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* Download Center Hero Section
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$page_title = get_the_title() ?: __('下载中心', 'aksrt');
|
||||
$page_desc = get_the_excerpt() ?: __('浏览和下载本站提供的各类资源。', 'aksrt');
|
||||
$current_filter = isset($_GET['resource_type']) ? sanitize_key((string) $_GET['resource_type']) : '';
|
||||
$resource_type_labels = function_exists('aksrt_get_pay_types') ? aksrt_get_pay_types() : [];
|
||||
unset($resource_type_labels[AKSRT_Domain_Model::PAY_TYPE_READING]);
|
||||
|
||||
$resource_count_query = new WP_Query([
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => 1,
|
||||
'fields' => 'ids',
|
||||
'meta_query' => [
|
||||
[
|
||||
'key' => AKSRT_Domain_Model::RESOURCE_MARKER_KEY,
|
||||
'value' => '1',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$total_published = (int) $resource_count_query->found_posts;
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
<div class="aksrt-download-hero">
|
||||
<div class="aksrt-download-hero__bg"></div>
|
||||
<div class="aksrt-download-hero__content">
|
||||
<h1 class="aksrt-download-hero__title"><?php echo esc_html($page_title); ?></h1>
|
||||
<?php if ($page_desc) : ?>
|
||||
<p class="aksrt-download-hero__desc"><?php echo esc_html($page_desc); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-download-hero__stats">
|
||||
<div class="aksrt-download-hero__stat">
|
||||
<span class="aksrt-download-hero__stat-num"><?php echo esc_html(number_format_i18n($total_published)); ?></span>
|
||||
<span class="aksrt-download-hero__stat-label"><?php esc_html_e('资源总数', 'aksrt'); ?></span>
|
||||
</div>
|
||||
<?php if (!empty($resource_type_labels)) : ?>
|
||||
<div class="aksrt-download-hero__stat">
|
||||
<span class="aksrt-download-hero__stat-num"><?php echo esc_html(count($resource_type_labels)); ?></span>
|
||||
<span class="aksrt-download-hero__stat-label"><?php esc_html_e('资源类型', 'aksrt'); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($resource_type_labels)) : ?>
|
||||
<div class="aksrt-download-hero__filters">
|
||||
<a href="<?php echo esc_url(get_permalink()); ?>" class="aksrt-download-hero__filter<?php echo $current_filter === '' ? ' aksrt-download-hero__filter--active' : ''; ?>">
|
||||
<?php esc_html_e('全部', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php foreach ($resource_type_labels as $type_key => $type_label) : ?>
|
||||
<a
|
||||
href="<?php echo esc_url(add_query_arg('resource_type', $type_key, get_permalink())); ?>"
|
||||
class="aksrt-download-hero__filter<?php echo $current_filter === $type_key ? ' aksrt-download-hero__filter--active' : ''; ?>"
|
||||
>
|
||||
<?php echo esc_html($type_label); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/**
|
||||
* Download Permission Card
|
||||
*
|
||||
* Shows download status, permission requirements, and action buttons.
|
||||
* Uses AKSRT_Download_State for unified state resolution.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$post_id = get_the_ID();
|
||||
$is_logged_in = is_user_logged_in();
|
||||
|
||||
// Use unified state resolver if available
|
||||
if (class_exists('AKSRT_Download_State')) {
|
||||
$state = AKSRT_Download_State::get_instance()->resolve($post_id);
|
||||
$status = $state['state'];
|
||||
$can_download = $state['can_download'];
|
||||
$status_text = $state['message'];
|
||||
$action_label = $state['action_label'];
|
||||
$action_url = $state['action_url'];
|
||||
$download_cost = $state['cost'];
|
||||
$user_credits = $state['balance'];
|
||||
$login_url = $state['login_url'];
|
||||
} else {
|
||||
// Fallback: legacy logic
|
||||
$download_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_cms_features() : [];
|
||||
$requires_login = !empty($download_settings['download_requires_login']);
|
||||
$requires_credits = !empty($download_settings['download_requires_credits']);
|
||||
$download_cost = (int) ($download_settings['download_cost'] ?? 0);
|
||||
|
||||
$has_downloaded = false;
|
||||
if ($is_logged_in) {
|
||||
$downloaded = get_user_meta(get_current_user_id(), '_aksrt_downloaded_resources', true);
|
||||
$downloaded = is_array($downloaded) ? $downloaded : [];
|
||||
$has_downloaded = in_array($post_id, $downloaded, true);
|
||||
}
|
||||
|
||||
$user_credits = 0;
|
||||
if ($is_logged_in && class_exists('AKSRT_Credits')) {
|
||||
$user_credits = AKSRT_Credits::balance(get_current_user_id());
|
||||
}
|
||||
|
||||
$status = 'available';
|
||||
$status_text = '';
|
||||
$can_download = true;
|
||||
$login_url = wp_login_url(get_permalink($post_id));
|
||||
$action_label = __('立即下载', 'aksrt');
|
||||
$action_url = '';
|
||||
|
||||
if (!$is_logged_in && $requires_login) {
|
||||
$status = 'not_logged_in';
|
||||
$status_text = __('请先登录后下载', 'aksrt');
|
||||
$can_download = false;
|
||||
$action_label = __('登录下载', 'aksrt');
|
||||
$action_url = $login_url;
|
||||
} elseif ($requires_credits && $download_cost > 0 && $user_credits < $download_cost && !$has_downloaded) {
|
||||
$status = 'insufficient_credits';
|
||||
$status_text = sprintf(__('需要 %d 积分,当前余额 %d', 'aksrt'), $download_cost, $user_credits);
|
||||
$can_download = false;
|
||||
$action_label = __('获取积分', 'aksrt');
|
||||
$action_url = home_url('/user/credits');
|
||||
} elseif ($has_downloaded) {
|
||||
$status = 'owned';
|
||||
$status_text = __('已下载,可再次下载', 'aksrt');
|
||||
}
|
||||
}
|
||||
|
||||
// Map state to icon
|
||||
$state_icons = [
|
||||
'available' => ['icon' => 'fa-check-circle', 'color' => 'success'],
|
||||
'owned' => ['icon' => 'fa-download', 'color' => 'success'],
|
||||
'not_logged_in' => ['icon' => 'fa-lock', 'color' => 'warning'],
|
||||
'insufficient_credits' => ['icon' => 'fa-coins', 'color' => 'warning'],
|
||||
'no_permission' => ['icon' => 'fa-ban', 'color' => 'warning'],
|
||||
'pending_delivery' => ['icon' => 'fa-clock', 'color' => 'info'],
|
||||
];
|
||||
$state_info = $state_icons[$status] ?? $state_icons['available'];
|
||||
?>
|
||||
<div class="aksrt-dl-perm-card aksrt-dl-perm-card--<?php echo esc_attr($status); ?>">
|
||||
<div class="aksrt-dl-perm-card__status">
|
||||
<i class="fas <?php echo esc_attr($state_info['icon']); ?> aksrt-dl-perm-card__icon aksrt-dl-perm-card__icon--<?php echo esc_attr($state_info['color']); ?>"></i>
|
||||
<span><?php echo esc_html($status_text); ?></span>
|
||||
</div>
|
||||
|
||||
<?php if (isset($download_cost) && $download_cost > 0) : ?>
|
||||
<div class="aksrt-dl-perm-card__cost">
|
||||
<i class="fas fa-coins"></i>
|
||||
<span><?php printf(esc_html__('下载消耗 %d 积分', 'aksrt'), $download_cost); ?></span>
|
||||
<?php if ($is_logged_in) : ?>
|
||||
<span class="aksrt-dl-perm-card__balance">(<?php printf(esc_html__('当前: %d', 'aksrt'), $user_credits); ?>)</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-dl-perm-card__actions">
|
||||
<?php if ($can_download) : ?>
|
||||
<a href="<?php echo esc_url(get_permalink($post_id)); ?>" class="aksrt-dl-perm-card__btn aksrt-dl-perm-card__btn--primary">
|
||||
<i class="fas fa-download"></i>
|
||||
<?php echo esc_html($action_label); ?>
|
||||
</a>
|
||||
<?php elseif ($action_url !== '') : ?>
|
||||
<a href="<?php echo esc_url($action_url); ?>" class="aksrt-dl-perm-card__btn aksrt-dl-perm-card__btn--primary">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
<?php echo esc_html($action_label); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<span class="aksrt-dl-perm-card__btn aksrt-dl-perm-card__btn--outline aksrt-dl-perm-card__btn--disabled">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<?php echo esc_html($action_label); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* Fixed homepage layout inspired by Zibll.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
aksrt_homepage_render_layout();
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Banner — v4.0 Zibll-Inspired
|
||||
*
|
||||
* 内联轮播条,使用与 header-slider 相同的 Swiper 架构,
|
||||
* 但以圆角卡片形式嵌入内容流中(非全宽)。
|
||||
*
|
||||
* 支持配置:
|
||||
* - 自动播放
|
||||
* - 圆角卡片样式
|
||||
* - 标题/副标题叠加
|
||||
* - 点击跳转
|
||||
*
|
||||
* @package AKSRT
|
||||
* @version 4.0.0
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (class_exists('AKSRT_Settings') && !AKSRT_Settings::homepage_module_banner_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$banners = function_exists('aksrt_get_banners') ? aksrt_get_banners(8, 'banner') : [];
|
||||
if (empty($banners)) return;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$slide_count = count($banners);
|
||||
|
||||
// Swiper config — Banner uses a subset of the global slider config
|
||||
$slider_cfg = function_exists('aksrt_get_slider_config') ? aksrt_get_slider_config() : [];
|
||||
$swiper_config = [
|
||||
'effect' => 'slide', // Banner always uses slide effect
|
||||
'loop' => $slide_count > 1 && ($slider_cfg['loop'] ?? true),
|
||||
'speed' => 500,
|
||||
'autoplay' => $slide_count > 1 ? ['delay' => ($slider_cfg['autoplay_interval'] ?? 5000), 'disableOnInteraction' => false] : false,
|
||||
'pagination' => false,
|
||||
'navigation' => !empty($slider_cfg['navigation']),
|
||||
'keyboard' => ['enabled' => true],
|
||||
'spaceBetween' => ($slider_cfg['space_between'] ?? 0),
|
||||
];
|
||||
?>
|
||||
<div class="home-module home-module--banner">
|
||||
<div class="banner-module">
|
||||
<div class="swiper banner-module__swiper" data-swiper-config="<?php echo esc_attr(wp_json_encode($swiper_config)); ?>">
|
||||
<div class="swiper-wrapper">
|
||||
<?php foreach ($banners as $index => $slide) :
|
||||
$device_vis = $slide['device_visibility'] ?? 'all';
|
||||
$slide_classes = 'swiper-slide';
|
||||
if ($device_vis === 'pc') {
|
||||
$slide_classes .= ' banner-slide--pc-only';
|
||||
} elseif ($device_vis === 'mobile') {
|
||||
$slide_classes .= ' banner-slide--mobile-only';
|
||||
}
|
||||
$link_target = !empty($slide['link_target']) ? $slide['link_target'] : '_self';
|
||||
?>
|
||||
<div class="<?php echo esc_attr($slide_classes); ?>"<?php if (!empty($slide['link'])) : ?> data-link="<?php echo esc_url($slide['link']); ?>" data-target="<?php echo esc_attr($link_target); ?>"<?php endif; ?>>
|
||||
<div class="banner-module__slide-bg">
|
||||
<?php if (!empty($slide['image'])) : ?>
|
||||
<img
|
||||
src="<?php echo esc_url($slide['image']); ?>"
|
||||
alt="<?php echo esc_attr($slide['title'] ?: get_bloginfo('name')); ?>"
|
||||
loading="<?php echo 0 === $index ? 'eager' : 'lazy'; ?>"
|
||||
decoding="async"
|
||||
class="fit-cover"
|
||||
>
|
||||
<?php else : ?>
|
||||
<div class="banner-module__slide-fallback"></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="banner-module__slide-overlay"></div>
|
||||
<?php
|
||||
$show_text = !isset($slide['show_text']) || $slide['show_text'];
|
||||
$has_title = !empty($slide['title']);
|
||||
$has_subtitle = !empty($slide['subtitle']);
|
||||
?>
|
||||
<?php if ($show_text && ($has_title || $has_subtitle)) : ?>
|
||||
<div class="banner-module__content">
|
||||
<?php if ($has_title) : ?>
|
||||
<h3 class="banner-module__title"><?php echo esc_html($slide['title']); ?></h3>
|
||||
<?php endif; ?>
|
||||
<?php if ($has_subtitle) : ?>
|
||||
<p class="banner-module__subtitle"><?php echo esc_html($slide['subtitle']); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($slide_count > 1) : ?>
|
||||
<!-- 前后箭头 -->
|
||||
<div class="banner-module__prev swiper-button-prev"></div>
|
||||
<div class="banner-module__next swiper-button-next"></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if (function_exists('aksrt_render_admin_quick_link')) : ?>
|
||||
<div class="home-module__admin-tools">
|
||||
<?php aksrt_render_admin_quick_link('page-display/header-components', __('顶部组件设置', 'aksrt')); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Button Group
|
||||
*
|
||||
* config: { title?, buttons: [{ label, url, style?, icon? }], align? }
|
||||
*
|
||||
* 按钮组模块,用于 CTA 引导。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
$buttons = isset($cfg['buttons']) && is_array($cfg['buttons']) ? $cfg['buttons'] : [];
|
||||
$align = sanitize_key((string) ($cfg['align'] ?? 'center'));
|
||||
|
||||
if (empty($buttons)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--button-group container" style="text-align:<?php echo esc_attr($align); ?>">
|
||||
<?php if ($title !== '') : ?>
|
||||
<h2 class="home-module__title"><?php echo esc_html($title); ?></h2>
|
||||
<?php endif; ?>
|
||||
<div class="home-module__buttons">
|
||||
<?php foreach ($buttons as $btn) :
|
||||
$label = (string) ($btn['label'] ?? '');
|
||||
$url = (string) ($btn['url'] ?? '#');
|
||||
$style = sanitize_key((string) ($btn['style'] ?? 'primary'));
|
||||
$icon = (string) ($btn['icon'] ?? '');
|
||||
if ($label === '') continue;
|
||||
?>
|
||||
<a href="<?php echo esc_url($url); ?>" class="aksrt-btn aksrt-btn--<?php echo esc_attr($style); ?>">
|
||||
<?php if ($icon !== '') : ?>
|
||||
<i class="<?php echo esc_attr($icon); ?>" aria-hidden="true"></i>
|
||||
<?php endif; ?>
|
||||
<span><?php echo esc_html($label); ?></span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Category
|
||||
*
|
||||
* config: { cat_id, count, layout, columns, title? }
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$cat_id = isset($cfg['cat_id']) ? (int) $cfg['cat_id'] : 0;
|
||||
$count = max(1, min(20, (int) ($cfg['count'] ?? 8)));
|
||||
$layout = (string) ($cfg['layout'] ?? 'card');
|
||||
$columns = max(1, min(6, (int) ($cfg['columns'] ?? 4)));
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
|
||||
if (!in_array($layout, ['card', 'list', 'masonry', 'grid-cms'], true)) {
|
||||
$layout = 'card';
|
||||
}
|
||||
|
||||
$args = [
|
||||
'posts_per_page' => $count,
|
||||
'post_status' => 'publish',
|
||||
'no_found_rows' => true,
|
||||
];
|
||||
if ($cat_id > 0) {
|
||||
$args['cat'] = $cat_id;
|
||||
// 分类页通常希望同时展示资源 post,post 已天然包含资源;旧 CPT 兼容时合并
|
||||
$args['post_type'] = function_exists('aksrt_resource_post_types')
|
||||
? array_unique(array_merge(['post'], aksrt_resource_post_types()))
|
||||
: ['post'];
|
||||
} else {
|
||||
$args['post_type'] = 'post';
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
if (!$query->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
return;
|
||||
}
|
||||
|
||||
$display_title = $title;
|
||||
if ($display_title === '' && $cat_id > 0) {
|
||||
$term = get_term($cat_id, 'category');
|
||||
if ($term && !is_wp_error($term)) $display_title = $term->name;
|
||||
}
|
||||
$more_link = $cat_id > 0 ? get_category_link($cat_id) : '';
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--category container" aria-label="<?php echo esc_attr($display_title ?: __('分类', 'aksrt')); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($display_title ?: __('精选内容', 'aksrt')); ?></h2>
|
||||
<?php if ($more_link) : ?>
|
||||
<a class="home-module__more" href="<?php echo esc_url($more_link); ?>">
|
||||
<?php esc_html_e('查看更多', 'aksrt'); ?> <i class="fas fa-arrow-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
|
||||
<div class="post-grid post-grid--<?php echo esc_attr($layout); ?>" style="--cols:<?php echo (int) $columns; ?>;">
|
||||
<?php
|
||||
set_query_var('aksrt_post_card_layout', $layout);
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
get_template_part('templates/parts/content', 'post-card');
|
||||
}
|
||||
set_query_var('aksrt_post_card_layout', '');
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Category Recommend Cards
|
||||
*
|
||||
* 4 张分类卡片 2×2 布局,每张卡片包含:
|
||||
* 上部:封面图 + 浏览量胶囊 + 分类名/描述 + 文章数 + 更多链接
|
||||
* 下部:5 篇最新文章列表(标题 + 相对发布时间)
|
||||
*
|
||||
* config: { title?, cat_ids[], show_views?, show_dates? }
|
||||
*
|
||||
* 封面图来源:分类 term meta → 最新文章缩略图 → 占位图
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$module_title = (string) ($cfg['title'] ?? __('分类推荐', 'aksrt'));
|
||||
$cat_ids = array_map('absint', (array) ($cfg['cat_ids'] ?? []));
|
||||
$cat_ids = array_slice(array_filter($cat_ids, fn($id) => $id > 0), 0, 4);
|
||||
$show_views = !isset($cfg['show_views']) || !empty($cfg['show_views']);
|
||||
$show_dates = !isset($cfg['show_dates']) || !empty($cfg['show_dates']);
|
||||
|
||||
if (empty($cat_ids)) return;
|
||||
|
||||
// 懒加载配置
|
||||
$lazy_cfg = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_lazyload_config() : ['enabled' => false, 'placeholder_url' => ''];
|
||||
$lazy_on = !empty($lazy_cfg['enabled']);
|
||||
$placeholder = $lazy_cfg['placeholder_url'] ?: (get_template_directory_uri() . '/assets/img/placeholder.svg');
|
||||
|
||||
// 组装卡片数据
|
||||
$cards = [];
|
||||
foreach ($cat_ids as $idx => $cat_id) {
|
||||
$term = get_term($cat_id, 'category');
|
||||
if (!$term || is_wp_error($term)) continue;
|
||||
|
||||
// 封面图
|
||||
$cover_url = class_exists('AKSRT_Settings')
|
||||
? AKSRT_Settings::get_category_cover_url($cat_id)
|
||||
: $placeholder;
|
||||
|
||||
// 分类描述(优先 term meta 推荐描述,其次原生 description)
|
||||
$desc = class_exists('AKSRT_Settings')
|
||||
? AKSRT_Settings::get_category_recommend_desc($cat_id)
|
||||
: (string) $term->description;
|
||||
|
||||
// 5 篇最新文章
|
||||
$posts = get_posts([
|
||||
'category__in' => [$cat_id],
|
||||
'posts_per_page' => 5,
|
||||
'post_status' => 'publish',
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
'no_found_rows' => true,
|
||||
]);
|
||||
|
||||
// 浏览量
|
||||
$views = $show_views ? aksrt_get_category_total_views($cat_id) : 0;
|
||||
|
||||
$cards[] = [
|
||||
'term' => $term,
|
||||
'cover' => $cover_url,
|
||||
'desc' => $desc,
|
||||
'posts' => $posts,
|
||||
'views' => $views,
|
||||
'count' => (int) $term->count,
|
||||
'link' => get_category_link($cat_id),
|
||||
];
|
||||
}
|
||||
|
||||
if (empty($cards)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--cat-cards" aria-label="<?php echo esc_attr($module_title); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($module_title); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="cat-cards-grid">
|
||||
<?php foreach ($cards as $card) : ?>
|
||||
<div class="cat-card">
|
||||
<div class="cat-card__top">
|
||||
<div class="cat-card__banner">
|
||||
<?php if ($show_views && $card['views'] > 0) : ?>
|
||||
<span class="cat-card__views"><?php echo esc_html(function_exists('aksrt_format_number') ? aksrt_format_number($card['views']) : number_format_i18n($card['views'])); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if ($lazy_on) : ?>
|
||||
<span class="aksrt-skeleton"></span>
|
||||
<img class="cat-card__cover aksrt-lazy" data-src="<?php echo esc_url($card['cover']); ?>" src="<?php echo esc_url($placeholder); ?>" alt="<?php echo esc_attr($card['term']->name); ?>">
|
||||
<?php else : ?>
|
||||
<img class="cat-card__cover" src="<?php echo esc_url($card['cover']); ?>" alt="<?php echo esc_attr($card['term']->name); ?>">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="cat-card__info">
|
||||
<div>
|
||||
<div class="cat-card__name"><?php echo esc_html($card['term']->name); ?></div>
|
||||
<?php if ($card['desc'] !== '') : ?>
|
||||
<div class="cat-card__desc"><?php echo esc_html($card['desc']); ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="cat-card__foot">
|
||||
<span><?php printf(esc_html__('%d篇文章', 'aksrt'), $card['count']); ?></span>
|
||||
<a href="<?php echo esc_url($card['link']); ?>" class="cat-card__more"><?php esc_html_e('>更多文章', 'aksrt'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($card['posts'])) : ?>
|
||||
<ul class="cat-card__list">
|
||||
<?php foreach ($card['posts'] as $p) : ?>
|
||||
<li>
|
||||
<a href="<?php echo esc_url(get_permalink($p->ID)); ?>"><?php echo esc_html(get_the_title($p->ID)); ?></a>
|
||||
<?php if ($show_dates) : ?>
|
||||
<span class="cat-card__time"><?php echo esc_html(aksrt_time_ago($p->post_date)); ?></span>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Data Grid
|
||||
*
|
||||
* config: { title?, items: [{ value, label, icon? }], columns? }
|
||||
*
|
||||
* 数据展示网格,用于统计数据、里程碑等。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
$items = isset($cfg['items']) && is_array($cfg['items']) ? $cfg['items'] : [];
|
||||
$columns = max(2, min(6, (int) ($cfg['columns'] ?? 4)));
|
||||
|
||||
if (empty($items)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--data-grid container">
|
||||
<?php if ($title !== '') : ?>
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title); ?></h2>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
<div class="home-module__data-grid" style="grid-template-columns:repeat(<?php echo esc_attr((string) $columns); ?>, 1fr)">
|
||||
<?php foreach ($items as $item) :
|
||||
$value = (string) ($item['value'] ?? '');
|
||||
$label = (string) ($item['label'] ?? '');
|
||||
$icon = (string) ($item['icon'] ?? '');
|
||||
if ($value === '' && $label === '') continue;
|
||||
?>
|
||||
<div class="aksrt-data-cell">
|
||||
<?php if ($icon !== '') : ?>
|
||||
<i class="<?php echo esc_attr($icon); ?>" aria-hidden="true"></i>
|
||||
<?php endif; ?>
|
||||
<span class="aksrt-data-cell__value"><?php echo esc_html($value); ?></span>
|
||||
<span class="aksrt-data-cell__label"><?php echo esc_html($label); ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · FAQ
|
||||
*
|
||||
* config: { title?, items: [{ q, a }], columns? }
|
||||
*
|
||||
* FAQ 手风琴模块。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
$items = isset($cfg['items']) && is_array($cfg['items']) ? $cfg['items'] : [];
|
||||
$columns = max(1, min(3, (int) ($cfg['columns'] ?? 1)));
|
||||
|
||||
if (empty($items)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--faq container">
|
||||
<?php if ($title !== '') : ?>
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title); ?></h2>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
<div class="home-module__faq-grid" style="column-count:<?php echo esc_attr((string) $columns); ?>">
|
||||
<?php foreach ($items as $i => $item) :
|
||||
$q = (string) ($item['q'] ?? '');
|
||||
$a = (string) ($item['a'] ?? '');
|
||||
if ($q === '') continue;
|
||||
?>
|
||||
<details class="aksrt-faq-item">
|
||||
<summary class="aksrt-faq-item__question"><?php echo esc_html($q); ?></summary>
|
||||
<div class="aksrt-faq-item__answer"><?php echo wp_kses_post($a); ?></div>
|
||||
</details>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Friend Links
|
||||
*
|
||||
* config: { title? }
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
|
||||
$friend_links = aksrt_get_friend_links();
|
||||
if (!is_array($friend_links) || empty($friend_links)) return;
|
||||
if (empty($friend_links)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--friends container" aria-label="<?php echo esc_attr($title ?: __('友情链接', 'aksrt')); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title ?: __('友情链接', 'aksrt')); ?></h2>
|
||||
</header>
|
||||
|
||||
<ul class="home-module__friends-list">
|
||||
<?php foreach ($friend_links as $link) :
|
||||
$url = $link['url'] ?? '';
|
||||
$name = $link['name'] ?? '';
|
||||
$description = $link['description'] ?? '';
|
||||
$logo = $link['logo'] ?? '';
|
||||
if (!$url || !$name) continue;
|
||||
?>
|
||||
<li>
|
||||
<a href="<?php echo esc_url($url); ?>" target="_blank" rel="noopener noreferrer external" class="home-module__friend-card">
|
||||
<?php if ($logo) : ?>
|
||||
<img src="<?php echo esc_url($logo); ?>" alt="" class="home-module__friend-avatar"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
<?php endif; ?>
|
||||
<div class="home-module__friend-meta">
|
||||
<strong><?php echo esc_html($name); ?></strong>
|
||||
<?php if ($description) : ?>
|
||||
<span><?php echo esc_html($description); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -0,0 +1,332 @@
|
||||
<?php
|
||||
/**
|
||||
* Home module: header components hero + floating search + icon cards.
|
||||
*
|
||||
* @package AKSRT
|
||||
* @version 4.1.0
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (class_exists('AKSRT_Settings') && !AKSRT_Settings::homepage_module_hero_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Device visibility gate: header_components_device_visibility ('' = all, 'only_pc' = PC only, 'only_sm' = mobile only)
|
||||
$_hero_show_type = '';
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$_hero_slider_cfg = AKSRT_Settings::get_header_components_settings();
|
||||
$_hero_show_type = $_hero_slider_cfg['show_type'] ?? '';
|
||||
}
|
||||
if ($_hero_show_type === 'only_pc' && wp_is_mobile()) {
|
||||
return;
|
||||
}
|
||||
if ($_hero_show_type === 'only_sm' && !wp_is_mobile()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) {
|
||||
$cfg = [];
|
||||
}
|
||||
|
||||
$hero_banners = function_exists('aksrt_get_banners') ? aksrt_get_banners(8, 'hero') : [];
|
||||
|
||||
$settings = function_exists('aksrt_get_all_settings') ? aksrt_get_all_settings() : [];
|
||||
$search_cfg = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_header_components_search_config() : ['show' => false, 'keywords' => [], 'categories' => [], 'type_options' => []];
|
||||
$show_search = !empty($search_cfg['show']) || !empty($cfg['with_search']);
|
||||
$show_cards = !empty($settings['header_components_cards_enabled']);
|
||||
$icon_cards = isset($settings['header_components_icon_cards']) ? (array) $settings['header_components_icon_cards'] : [];
|
||||
$card_bg_mode = !empty($settings['header_components_card_shared_bg']) ? 'shared' : 'individual';
|
||||
$card_blur = !empty($settings['header_components_card_blur']);
|
||||
$filter_blur_devices = isset($settings['header_components_filter_blur_devices']) ? (array) $settings['header_components_filter_blur_devices'] : ($card_blur ? ['pc', 'mobile'] : []);
|
||||
$card_show_devices = isset($settings['header_components_card_show_devices']) ? (array) $settings['header_components_card_show_devices'] : ['pc', 'mobile'];
|
||||
$card_icon_shape = $settings['header_components_card_icon_shape'] ?? 'circle';
|
||||
|
||||
$slide_count = count($hero_banners);
|
||||
$visible_card_count = ($show_cards && !empty($icon_cards)) ? count($icon_cards) : 0;
|
||||
|
||||
$container_classes = ['header-components-container', 'relative', 'card-' . $visible_card_count];
|
||||
if (in_array('pc', $filter_blur_devices, true)) {
|
||||
$container_classes[] = 'has-blur-pc';
|
||||
}
|
||||
if (in_array('mobile', $filter_blur_devices, true)) {
|
||||
$container_classes[] = 'has-blur-mobile';
|
||||
}
|
||||
if (!in_array('pc', $card_show_devices, true)) {
|
||||
$container_classes[] = 'hide-cards-pc';
|
||||
}
|
||||
if (!in_array('mobile', $card_show_devices, true)) {
|
||||
$container_classes[] = 'hide-cards-mobile';
|
||||
}
|
||||
|
||||
$search_placeholder = function_exists('aksrt_get_search_placeholder') ? aksrt_get_search_placeholder() : __('开启精彩搜索', 'aksrt');
|
||||
$search_value = trim((string) get_search_query());
|
||||
$search_type = function_exists('aksrt_get_search_form_type') ? aksrt_get_search_form_type() : 'post';
|
||||
|
||||
$render_hero_search = static function (string $search_id) use ($search_placeholder, $search_value, $search_type, $search_cfg): void {
|
||||
$_kw = $search_cfg['keywords'] ?? [];
|
||||
$_cats = $search_cfg['categories'] ?? [];
|
||||
$_types = $search_cfg['type_options'] ?? [];
|
||||
$_show_cat = !empty($search_cfg['show_input_cat']) && !empty($_cats);
|
||||
$_show_type = !empty($search_cfg['show_type']) && !empty($_types);
|
||||
?>
|
||||
<div class="header-components-search">
|
||||
<div class="search-input">
|
||||
<form role="search" method="get" action="<?php echo esc_url(home_url('/')); ?>" class="search-form" data-aksrt-search-form="hero">
|
||||
<input type="hidden" name="aksrt_search_type" value="<?php echo esc_attr($search_type); ?>">
|
||||
<div class="line-form<?php echo ($_show_cat || $_show_type) ? ' has-addons' : ''; ?>">
|
||||
<?php if ($_show_cat) : ?>
|
||||
<select name="cat" class="header-components-search__cat" aria-label="<?php esc_attr_e('选择分类', 'aksrt'); ?>">
|
||||
<option value=""><?php esc_html_e('全部分类', 'aksrt'); ?></option>
|
||||
<?php foreach ($_cats as $_c) : ?>
|
||||
<option value="<?php echo esc_attr($_c['id']); ?>"><?php echo esc_html($_c['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
<?php if ($_show_type) : ?>
|
||||
<div class="header-components-search__types">
|
||||
<?php foreach ($_types as $_idx => $_t) : ?>
|
||||
<label class="header-components-search__type-label">
|
||||
<input type="radio" name="aksrt_search_type" value="<?php echo esc_attr($_t['key']); ?>"<?php echo $_idx === 0 ? ' checked' : ''; ?> class="header-components-search__type-radio">
|
||||
<span class="header-components-search__type-text"><?php echo esc_html($_t['label']); ?></span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="search-input-text">
|
||||
<label class="screen-reader-text" for="<?php echo esc_attr($search_id); ?>"><?php esc_html_e('搜索', 'aksrt'); ?></label>
|
||||
<input
|
||||
type="search"
|
||||
id="<?php echo esc_attr($search_id); ?>"
|
||||
name="s"
|
||||
class="line-form-input"
|
||||
value="<?php echo esc_attr($search_value); ?>"
|
||||
placeholder=" "
|
||||
autocomplete="off"
|
||||
>
|
||||
<i class="line-form-line"></i>
|
||||
<div class="scale-placeholder<?php echo $search_value !== '' ? ' is-focus' : ''; ?>" default="<?php echo esc_attr($search_placeholder); ?>">
|
||||
<?php echo esc_html($search_placeholder); ?>
|
||||
</div>
|
||||
<div class="abs-right">
|
||||
<button type="submit" class="null header-components-search__submit" aria-label="<?php echo esc_attr__('搜索', 'aksrt'); ?>">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<path d="m21 21-4.3-4.3"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<?php if (!empty($_kw)) : ?>
|
||||
<div class="header-components-search__keywords">
|
||||
<?php foreach ($_kw as $_kw_text) : ?>
|
||||
<a href="<?php echo esc_url(add_query_arg('s', rawurlencode($_kw_text), home_url('/'))); ?>" class="header-components-search__kw-tag"><?php echo esc_html($_kw_text); ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
};
|
||||
|
||||
$render_icon_cards = static function () use ($show_cards, $icon_cards, $card_bg_mode, $card_icon_shape): void {
|
||||
if (!$show_cards || empty($icon_cards)) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="header-components-card">
|
||||
<div class="header-components-card__container container">
|
||||
<?php if ($card_bg_mode === 'shared') : ?>
|
||||
<div class="header-components-card__wrap header-components-card__wrap--shared">
|
||||
<div class="header-components-card__row">
|
||||
<?php foreach ($icon_cards as $card) : ?>
|
||||
<?php $card['icon_shape'] = $card_icon_shape; ?>
|
||||
<div class="header-components-card__item">
|
||||
<?php echo aksrt_render_icon_cover_card($card); ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="header-components-card__row">
|
||||
<?php foreach ($icon_cards as $card) : ?>
|
||||
<?php $card['icon_shape'] = $card_icon_shape; ?>
|
||||
<div class="header-components-card__item">
|
||||
<div class="header-components-card__item-bg">
|
||||
<?php echo aksrt_render_icon_cover_card($card); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
};
|
||||
|
||||
if (!empty($hero_banners)) :
|
||||
$slider_cfg = function_exists('aksrt_get_slider_config') ? aksrt_get_slider_config() : [];
|
||||
$swiper_config = [
|
||||
'effect' => $slider_cfg['effect'] ?? 'fade',
|
||||
'loop' => $slide_count > 1 && ($slider_cfg['loop'] ?? true),
|
||||
'speed' => 600,
|
||||
'autoplay' => $slide_count > 1 ? ['delay' => ($slider_cfg['autoplay_interval'] ?? 5000), 'disableOnInteraction' => false] : false,
|
||||
'keyboard' => ['enabled' => true],
|
||||
];
|
||||
if (!empty($slider_cfg['pagination'])) {
|
||||
$swiper_config['pagination'] = ['clickable' => true];
|
||||
}
|
||||
if (!empty($slider_cfg['navigation'])) {
|
||||
$swiper_config['navigation'] = true;
|
||||
}
|
||||
$pc_height = $slider_cfg['pc_height'] ?? '';
|
||||
$mobile_height = $slider_cfg['mobile_height'] ?? '';
|
||||
$height_style = '';
|
||||
if ($pc_height !== '') {
|
||||
$height_style .= '--pc-height:' . esc_attr($pc_height) . ';';
|
||||
}
|
||||
if ($mobile_height !== '') {
|
||||
$height_style .= '--m-height:' . esc_attr($mobile_height) . ';';
|
||||
}
|
||||
?>
|
||||
<div class="<?php echo esc_attr(implode(' ', $container_classes)); ?>" id="aksrt-header-components"<?php if ($height_style !== '') : ?> style="<?php echo $height_style; ?>"<?php endif; ?>>
|
||||
<div class="swiper header-components slide-header" data-swiper-config="<?php echo esc_attr(wp_json_encode($swiper_config)); ?>">
|
||||
<div class="swiper-wrapper">
|
||||
<?php foreach ($hero_banners as $index => $slide) :
|
||||
$device_vis = $slide['device_visibility'] ?? 'all';
|
||||
$slide_classes = 'swiper-slide';
|
||||
if ($device_vis === 'pc') {
|
||||
$slide_classes .= ' hero-slide--pc-only';
|
||||
} elseif ($device_vis === 'mobile') {
|
||||
$slide_classes .= ' hero-slide--mobile-only';
|
||||
}
|
||||
if (!empty($slide['video_url'])) {
|
||||
$slide_classes .= ' hero-slide--has-video';
|
||||
}
|
||||
$link_target = !empty($slide['link_target']) ? $slide['link_target'] : '_self';
|
||||
$has_layers = !empty($slide['layers']) && is_array($slide['layers']);
|
||||
$text_parallax = !empty($slide['text_parallax']);
|
||||
$text_style = '';
|
||||
if (!empty($slide['text_size_pc'])) {
|
||||
$text_style .= '--hero-text-size-pc:' . esc_attr($slide['text_size_pc']) . ';';
|
||||
}
|
||||
if (!empty($slide['text_size_m'])) {
|
||||
$text_style .= '--hero-text-size-m:' . esc_attr($slide['text_size_m']) . ';';
|
||||
}
|
||||
if ($text_parallax) {
|
||||
$text_style .= '--hero-text-parallax:1;';
|
||||
}
|
||||
?>
|
||||
<div class="<?php echo esc_attr($slide_classes); ?>"<?php if (!empty($slide['link'])) : ?> data-link="<?php echo esc_url($slide['link']); ?>" data-target="<?php echo esc_attr($link_target); ?>"<?php endif; ?>>
|
||||
<div class="header-components__slide-bg">
|
||||
<?php if (!empty($slide['video_url'])) : ?>
|
||||
<video class="header-components__video" autoplay muted loop playsinline preload="auto">
|
||||
<source src="<?php echo esc_url($slide['video_url']); ?>" type="video/mp4">
|
||||
</video>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($slide['image'])) : ?>
|
||||
<img
|
||||
src="<?php echo esc_url($slide['image']); ?>"
|
||||
alt="<?php echo esc_attr($slide['title'] ?: get_bloginfo('name')); ?>"
|
||||
loading="<?php echo 0 === $index ? 'eager' : 'lazy'; ?>"
|
||||
decoding="async"
|
||||
class="fit-cover"
|
||||
>
|
||||
<?php elseif (empty($slide['video_url'])) : ?>
|
||||
<div class="header-components__slide-fallback"></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($has_layers) : ?>
|
||||
<?php foreach ($slide['layers'] as $layer) :
|
||||
if (empty($layer['image'])) continue;
|
||||
$layer_classes = 'header-components__layer';
|
||||
if (!empty($layer['parallax'])) $layer_classes .= ' header-components__layer--parallax';
|
||||
if (!empty($layer['free_size'])) $layer_classes .= ' header-components__layer--free-size';
|
||||
$layer_style = '';
|
||||
if (!empty($layer['align']) && $layer['align'] !== 'center') {
|
||||
$layer_style .= 'background-position:' . esc_attr($layer['align']) . ';';
|
||||
}
|
||||
if (!empty($layer['parallax'])) {
|
||||
$pscale = isset($layer['parallax_scale']) ? (float) $layer['parallax_scale'] : 0.3;
|
||||
$popacity = isset($layer['parallax_opacity']) ? (float) $layer['parallax_opacity'] : 0.6;
|
||||
$layer_style .= '--layer-parallax-scale:' . esc_attr($pscale) . ';';
|
||||
$layer_style .= '--layer-parallax-opacity:' . esc_attr($popacity) . ';';
|
||||
}
|
||||
?>
|
||||
<div class="<?php echo esc_attr($layer_classes); ?>" style="background-image:url('<?php echo esc_url($layer['image']); ?>')<?php echo $layer_style ? ';' . $layer_style : ''; ?>"></div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="header-components__slide-overlay"></div>
|
||||
<?php
|
||||
$show_text = !isset($slide['show_text']) || $slide['show_text'];
|
||||
$has_title = !empty($slide['title']);
|
||||
$has_subtitle = !empty($slide['subtitle']);
|
||||
$has_description = !empty($slide['description']);
|
||||
$text_align = $slide['text_align'] ?? 'left';
|
||||
?>
|
||||
<?php if ($show_text && ($has_title || $has_subtitle || $has_description)) : ?>
|
||||
<div class="header-components__content slide-text<?php echo $text_align !== 'left' ? ' text-' . esc_attr($text_align) : ''; ?><?php echo $text_parallax ? ' has-text-parallax' : ''; ?>"<?php echo $text_style ? ' style="' . $text_style . '"' : ''; ?>>
|
||||
<?php if ($has_title) : ?>
|
||||
<h2 class="header-components__title slide-title"><?php echo esc_html($slide['title']); ?></h2>
|
||||
<?php endif; ?>
|
||||
<?php if ($has_subtitle) : ?>
|
||||
<div class="header-components__subtitle slide-desc"><?php echo esc_html($slide['subtitle']); ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($has_description) : ?>
|
||||
<div class="header-components__description"><?php echo esc_html($slide['description']); ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
|
||||
<?php if ($show_search) : ?>
|
||||
<?php $render_hero_search('header-search-input'); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php $render_icon_cards(); ?>
|
||||
<?php if (function_exists('aksrt_render_admin_quick_link')) : ?>
|
||||
<div class="home-module__admin-tools">
|
||||
<?php aksrt_render_admin_quick_link('page-display/header-components', __('顶部组件设置', 'aksrt')); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php else : ?>
|
||||
<?php
|
||||
$is_admin_user = current_user_can('manage_options');
|
||||
$hero_admin_url = admin_url('admin.php?page=aksrt-settings#/content/hero');
|
||||
?>
|
||||
<div class="<?php echo esc_attr(implode(' ', $container_classes)); ?>" id="aksrt-header-components">
|
||||
<div class="header-components slide-header header-components--gradient">
|
||||
<div class="header-components__content slide-text text-center">
|
||||
<h1 class="header-components__title slide-title"><?php bloginfo('name'); ?></h1>
|
||||
<div class="header-components__subtitle slide-desc"><?php echo esc_html(get_bloginfo('description', 'display')); ?></div>
|
||||
<?php if ($is_admin_user) : ?>
|
||||
<p class="header-components__admin-hint" role="note">
|
||||
<?php esc_html_e('No Hero slides found. Showing fallback site info.', 'aksrt'); ?>
|
||||
<a class="header-components__admin-link" href="<?php echo esc_url($hero_admin_url); ?>">
|
||||
<?php esc_html_e('Go to Content -> Hero Components', 'aksrt'); ?>
|
||||
</a>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($show_search) : ?>
|
||||
<?php $render_hero_search('header-search-input-fallback'); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php $render_icon_cards(); ?>
|
||||
<?php if (function_exists('aksrt_render_admin_quick_link')) : ?>
|
||||
<div class="home-module__admin-tools">
|
||||
<?php aksrt_render_admin_quick_link('page-display/header-components', __('顶部组件设置', 'aksrt')); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Highlight Cards
|
||||
*
|
||||
* config: { title?, items: [{ title, desc, icon?, image?, url? }], columns? }
|
||||
*
|
||||
* 亮点卡片模块,用于产品特性、服务介绍等。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
$items = isset($cfg['items']) && is_array($cfg['items']) ? $cfg['items'] : [];
|
||||
$columns = max(1, min(4, (int) ($cfg['columns'] ?? 3)));
|
||||
|
||||
if (empty($items)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--highlight-cards container">
|
||||
<?php if ($title !== '') : ?>
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title); ?></h2>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
<div class="home-module__highlight-grid" style="grid-template-columns:repeat(<?php echo esc_attr((string) $columns); ?>, 1fr)">
|
||||
<?php foreach ($items as $item) :
|
||||
$item_title = (string) ($item['title'] ?? '');
|
||||
$item_desc = (string) ($item['desc'] ?? '');
|
||||
$item_icon = (string) ($item['icon'] ?? '');
|
||||
$item_image = (string) ($item['image'] ?? '');
|
||||
$item_url = (string) ($item['url'] ?? '');
|
||||
if ($item_title === '') continue;
|
||||
|
||||
$card_tag = $item_url !== '' ? 'a' : 'div';
|
||||
$card_attrs = $item_url !== '' ? ' href="' . esc_url($item_url) . '"' : '';
|
||||
?>
|
||||
<<?php echo esc_attr($card_tag); ?> class="aksrt-highlight-card"<?php echo $card_attrs; ?>>
|
||||
<?php if ($item_image !== '') : ?>
|
||||
<img class="aksrt-highlight-card__image" src="<?php echo esc_url($item_image); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
<?php elseif ($item_icon !== '') : ?>
|
||||
<div class="aksrt-highlight-card__icon"><i class="<?php echo esc_attr($item_icon); ?>"></i></div>
|
||||
<?php endif; ?>
|
||||
<h3 class="aksrt-highlight-card__title"><?php echo esc_html($item_title); ?></h3>
|
||||
<?php if ($item_desc !== '') : ?>
|
||||
<p class="aksrt-highlight-card__desc"><?php echo esc_html($item_desc); ?></p>
|
||||
<?php endif; ?>
|
||||
</<?php echo esc_attr($card_tag); ?>>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Hotspot 热点推荐
|
||||
*
|
||||
* 纯文章列表(无图片),仅桌面端显示。
|
||||
* config: { count, post_type, source, title? }
|
||||
*
|
||||
* source:
|
||||
* 'auto' → 优先读取 aksrt_recommend meta,不足时用最新补充
|
||||
* 'recent' → 按时间倒序
|
||||
* 'views' → 按阅读量排序
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$count = max(3, min(20, (int) ($cfg['count'] ?? 6)));
|
||||
$post_type = (string) ($cfg['post_type'] ?? 'post');
|
||||
$source = (string) ($cfg['source'] ?? 'auto');
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
|
||||
if (!in_array($source, ['auto', 'recent', 'views'], true)) {
|
||||
$source = 'auto';
|
||||
}
|
||||
if (!in_array($post_type, ['post', 'aksrt_resource'], true)) {
|
||||
$post_type = 'post';
|
||||
}
|
||||
|
||||
$is_resource = $post_type === 'aksrt_resource';
|
||||
$ptypes = $is_resource && function_exists('aksrt_resource_post_types')
|
||||
? aksrt_resource_post_types()
|
||||
: [$post_type];
|
||||
|
||||
// 构建查询参数
|
||||
$args = [
|
||||
'post_type' => $ptypes,
|
||||
'posts_per_page' => $count,
|
||||
'post_status' => 'publish',
|
||||
'no_found_rows' => true,
|
||||
];
|
||||
|
||||
if ($source === 'auto') {
|
||||
// 优先推荐文章,不足时用最新补充
|
||||
$args['meta_query'] = [
|
||||
'relation' => 'OR',
|
||||
['key' => 'aksrt_recommend', 'value' => '1', 'compare' => '='],
|
||||
['key' => 'aksrt_recommend', 'compare' => 'NOT EXISTS'],
|
||||
];
|
||||
$args['orderby'] = 'modified';
|
||||
$args['order'] = 'DESC';
|
||||
} elseif ($source === 'views') {
|
||||
$args['meta_key'] = '_aksrt_res_view_count';
|
||||
$args['orderby'] = 'meta_value_num';
|
||||
$args['order'] = 'DESC';
|
||||
} else {
|
||||
$args['orderby'] = 'date';
|
||||
$args['order'] = 'DESC';
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
if (!$query->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
return;
|
||||
}
|
||||
|
||||
$default_title = __('热点推荐', 'aksrt');
|
||||
$display_title = $title ?: $default_title;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--hotspot hotspot--desktop-only" aria-label="<?php echo esc_attr($display_title); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title">
|
||||
<i class="fas fa-fire" aria-hidden="true"></i>
|
||||
<?php echo esc_html($display_title); ?>
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<ol class="hotspot__list">
|
||||
<?php
|
||||
$rank = 1;
|
||||
while ($query->have_posts()) :
|
||||
$query->the_post();
|
||||
$cats = get_the_category();
|
||||
$cat_name = $cats ? $cats[0]->name : '';
|
||||
$views = (int) get_post_meta(get_the_ID(), '_aksrt_res_view_count', true);
|
||||
?>
|
||||
<li class="hotspot__item">
|
||||
<span class="hotspot__num hotspot__num--<?php echo $rank <= 3 ? 'top' : 'normal'; ?>"><?php echo (int) $rank; ?></span>
|
||||
<div class="hotspot__body">
|
||||
<a class="hotspot__title" href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
|
||||
<?php the_title(); ?>
|
||||
</a>
|
||||
<div class="hotspot__meta">
|
||||
<?php if ($cat_name) : ?>
|
||||
<span class="hotspot__cat"><?php echo esc_html($cat_name); ?></span>
|
||||
<?php endif; ?>
|
||||
<span class="hotspot__date"><?php echo esc_html(get_the_date('Y-m-d')); ?></span>
|
||||
<?php if ($views > 0) : ?>
|
||||
<span class="hotspot__views"><?php echo esc_html(number_format_i18n($views)); ?> <?php esc_html_e('阅读', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<?php
|
||||
$rank++;
|
||||
endwhile;
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</ol>
|
||||
</section>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · HTML
|
||||
*
|
||||
* config: { html, title? }
|
||||
*
|
||||
* 已通过 wp_kses_post 在写入时清洗,渲染时直接输出。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$html = (string) ($cfg['html'] ?? '');
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
|
||||
if ($html === '') return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--html container">
|
||||
<?php if ($title !== '') : ?>
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title); ?></h2>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
<div class="home-module__html-body">
|
||||
<?php echo wp_kses_post($html); ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · More (Discover Categories)
|
||||
*
|
||||
* Maps to zibll widget-more capability.
|
||||
* config: { title?, cat_ids[], count, columns, show_post_count, show_latest_posts, latest_count }
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) {
|
||||
$cfg = [];
|
||||
}
|
||||
|
||||
$title = trim((string) ($cfg['title'] ?? ''));
|
||||
$cat_ids = isset($cfg['cat_ids']) && is_array($cfg['cat_ids']) ? array_map('absint', $cfg['cat_ids']) : [];
|
||||
$count = max(1, min(12, (int) ($cfg['count'] ?? 6)));
|
||||
$columns = max(2, min(4, (int) ($cfg['columns'] ?? 3)));
|
||||
$show_post_count = !isset($cfg['show_post_count']) || !empty($cfg['show_post_count']);
|
||||
$show_latest_posts = !isset($cfg['show_latest_posts']) || !empty($cfg['show_latest_posts']);
|
||||
$latest_count = max(1, min(10, (int) ($cfg['latest_count'] ?? 5)));
|
||||
|
||||
// Fetch categories.
|
||||
if (!empty($cat_ids)) {
|
||||
$categories = get_categories([
|
||||
'include' => array_slice($cat_ids, 0, $count),
|
||||
'orderby' => 'include',
|
||||
]);
|
||||
} else {
|
||||
$categories = get_categories([
|
||||
'number' => $count,
|
||||
'orderby' => 'count',
|
||||
'order' => 'DESC',
|
||||
'hide_empty' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
if (empty($categories)) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--more container" aria-label="<?php echo esc_attr($title ?: __('发现更多', 'aksrt')); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title ?: __('发现更多', 'aksrt')); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="home-module__more-grid" style="--cols: <?php echo (int) $columns; ?>;">
|
||||
<?php foreach ($categories as $cat) :
|
||||
$cat_link = get_category_link($cat);
|
||||
$cover = '';
|
||||
if (function_exists('aksrt_get_category_cover')) {
|
||||
$cover = aksrt_get_category_cover($cat->term_id);
|
||||
}
|
||||
?>
|
||||
<div class="home-module__more-card">
|
||||
<a href="<?php echo esc_url($cat_link); ?>" class="home-module__more-link">
|
||||
<?php if ($cover) : ?>
|
||||
<div class="home-module__more-cover">
|
||||
<img src="<?php echo esc_url($cover); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="home-module__more-cover home-module__more-cover--placeholder">
|
||||
<i class="fas fa-folder" aria-hidden="true"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="home-module__more-body">
|
||||
<strong class="home-module__more-name"><?php echo esc_html($cat->name); ?></strong>
|
||||
<?php if ($show_post_count) : ?>
|
||||
<span class="home-module__more-count">
|
||||
<?php
|
||||
/* translators: %d: number of posts */
|
||||
printf(esc_html__('%d 篇文章', 'aksrt'), (int) $cat->count);
|
||||
?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</a>
|
||||
<?php if ($show_latest_posts) :
|
||||
$recent = get_posts([
|
||||
'category' => $cat->term_id,
|
||||
'posts_per_page' => $latest_count,
|
||||
'post_status' => 'publish',
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
]);
|
||||
if (!empty($recent)) :
|
||||
?>
|
||||
<ul class="home-module__more-posts">
|
||||
<?php foreach ($recent as $rp) : ?>
|
||||
<li>
|
||||
<a href="<?php echo esc_url(get_permalink($rp)); ?>"><?php echo esc_html($rp->post_title); ?></a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php
|
||||
endif;
|
||||
endif;
|
||||
?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Partner Marquee
|
||||
*
|
||||
* config: { title?, items: [{ name, image, url? }], speed? }
|
||||
*
|
||||
* 合作伙伴横向滚动模块。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
$items = isset($cfg['items']) && is_array($cfg['items']) ? $cfg['items'] : [];
|
||||
$speed = max(10, min(120, (int) ($cfg['speed'] ?? 30)));
|
||||
|
||||
if (empty($items)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--partner-marquee container">
|
||||
<?php if ($title !== '') : ?>
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title); ?></h2>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-marquee" style="--marquee-duration:<?php echo esc_attr((string) $speed); ?>s">
|
||||
<div class="aksrt-marquee__track">
|
||||
<?php
|
||||
// 渲染两份以实现无缝循环
|
||||
for ($pass = 0; $pass < 2; $pass++) :
|
||||
foreach ($items as $partner) :
|
||||
$name = (string) ($partner['name'] ?? '');
|
||||
$image = (string) ($partner['image'] ?? '');
|
||||
$url = (string) ($partner['url'] ?? '');
|
||||
if ($image === '' && $name === '') continue;
|
||||
|
||||
$tag = $url !== '' ? 'a' : 'span';
|
||||
$attrs = $url !== '' ? ' href="' . esc_url($url) . '" target="_blank" rel="noopener"' : '';
|
||||
?>
|
||||
<<?php echo esc_attr($tag); ?> class="aksrt-marquee__item"<?php echo $attrs; ?>>
|
||||
<?php if ($image !== '') : ?>
|
||||
<img src="<?php echo esc_url($image); ?>" alt="<?php echo esc_attr($name); ?>"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
<?php else : ?>
|
||||
<span><?php echo esc_html($name); ?></span>
|
||||
<?php endif; ?>
|
||||
</<?php echo esc_attr($tag); ?>>
|
||||
<?php
|
||||
endforeach;
|
||||
endfor;
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Product Showcase
|
||||
*
|
||||
* config: { title?, products: [{ title, desc, image, price?, url? }], columns? }
|
||||
*
|
||||
* 产品展示模块,用于商城/资源推荐。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
$products = isset($cfg['products']) && is_array($cfg['products']) ? $cfg['products'] : [];
|
||||
$columns = max(1, min(4, (int) ($cfg['columns'] ?? 3)));
|
||||
|
||||
if (empty($products)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--product-showcase container">
|
||||
<?php if ($title !== '') : ?>
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title); ?></h2>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
<div class="home-module__product-grid" style="grid-template-columns:repeat(<?php echo esc_attr((string) $columns); ?>, 1fr)">
|
||||
<?php foreach ($products as $product) :
|
||||
$p_title = (string) ($product['title'] ?? '');
|
||||
$p_desc = (string) ($product['desc'] ?? '');
|
||||
$p_image = (string) ($product['image'] ?? '');
|
||||
$p_price = (string) ($product['price'] ?? '');
|
||||
$p_url = (string) ($product['url'] ?? '');
|
||||
if ($p_title === '') continue;
|
||||
?>
|
||||
<a href="<?php echo esc_url($p_url ?: '#'); ?>" class="aksrt-product-card">
|
||||
<?php if ($p_image !== '') : ?>
|
||||
<div class="aksrt-product-card__image">
|
||||
<img src="<?php echo esc_url($p_image); ?>" alt="<?php echo esc_attr($p_title); ?>"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__body">
|
||||
<h3 class="aksrt-product-card__title"><?php echo esc_html($p_title); ?></h3>
|
||||
<?php if ($p_desc !== '') : ?>
|
||||
<p class="aksrt-product-card__desc"><?php echo esc_html($p_desc); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($p_price !== '') : ?>
|
||||
<span class="aksrt-product-card__price"><?php echo esc_html($p_price); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Ranking
|
||||
*
|
||||
* config: { metric: 'views|downloads|comments', count, post_type, title? }
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$metric = (string) ($cfg['metric'] ?? 'downloads');
|
||||
$count = max(1, min(20, (int) ($cfg['count'] ?? 6)));
|
||||
$post_type_cfg = (string) ($cfg['post_type'] ?? 'aksrt_resource');
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
|
||||
if (!in_array($metric, ['views', 'downloads', 'comments'], true)) {
|
||||
$metric = 'downloads';
|
||||
}
|
||||
|
||||
$is_resource_module = $post_type_cfg === 'aksrt_resource';
|
||||
|
||||
$args = [
|
||||
'posts_per_page' => $count,
|
||||
'post_status' => 'publish',
|
||||
'no_found_rows' => true,
|
||||
];
|
||||
if ($is_resource_module) {
|
||||
$args['post_type'] = function_exists('aksrt_resource_post_types') ? aksrt_resource_post_types() : ['post'];
|
||||
if (!post_type_exists('aksrt_resource')) {
|
||||
$args['meta_query'] = [[
|
||||
'key' => '_aksrt_is_resource',
|
||||
'value' => '1',
|
||||
'compare' => '=',
|
||||
]];
|
||||
}
|
||||
} else {
|
||||
$args['post_type'] = 'post';
|
||||
}
|
||||
|
||||
switch ($metric) {
|
||||
case 'views':
|
||||
$args['meta_key'] = '_aksrt_res_view_count';
|
||||
$args['orderby'] = 'meta_value_num';
|
||||
$args['order'] = 'DESC';
|
||||
break;
|
||||
case 'comments':
|
||||
$args['orderby'] = 'comment_count';
|
||||
$args['order'] = 'DESC';
|
||||
break;
|
||||
case 'downloads':
|
||||
default:
|
||||
$args['meta_key'] = '_aksrt_res_download_count';
|
||||
$args['orderby'] = 'meta_value_num';
|
||||
$args['order'] = 'DESC';
|
||||
break;
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
if (!$query->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
return;
|
||||
}
|
||||
|
||||
$metric_label = [
|
||||
'views' => __('阅读量', 'aksrt'),
|
||||
'downloads' => __('下载量', 'aksrt'),
|
||||
'comments' => __('评论数', 'aksrt'),
|
||||
][$metric];
|
||||
|
||||
$display_title = $title ?: sprintf(__('%s 排行榜', 'aksrt'), $metric_label);
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--ranking container" aria-label="<?php echo esc_attr($display_title); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title">
|
||||
<i class="fas fa-trophy" aria-hidden="true"></i>
|
||||
<?php echo esc_html($display_title); ?>
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<ol class="home-module__ranking-list">
|
||||
<?php
|
||||
$rank = 1;
|
||||
while ($query->have_posts()) :
|
||||
$query->the_post();
|
||||
$value = 0;
|
||||
if ($metric === 'views') {
|
||||
$value = (int) get_post_meta(get_the_ID(), '_aksrt_res_view_count', true);
|
||||
} elseif ($metric === 'comments') {
|
||||
$value = (int) get_comments_number();
|
||||
} else {
|
||||
$value = (int) get_post_meta(get_the_ID(), '_aksrt_res_download_count', true);
|
||||
}
|
||||
?>
|
||||
<li class="home-module__ranking-item home-module__ranking-item--<?php echo $rank <= 3 ? 'top' : 'normal'; ?>">
|
||||
<span class="home-module__ranking-num"><?php echo (int) $rank; ?></span>
|
||||
<a class="home-module__ranking-link" href="<?php the_permalink(); ?>">
|
||||
<?php the_title(); ?>
|
||||
</a>
|
||||
<span class="home-module__ranking-value"><?php echo esc_html(number_format_i18n($value)); ?></span>
|
||||
</li>
|
||||
<?php
|
||||
$rank++;
|
||||
endwhile;
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</ol>
|
||||
</section>
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Recent
|
||||
*
|
||||
* config: { post_type, count, layout, title? }
|
||||
*
|
||||
* post_type 取值:
|
||||
* 'post' → 最新文章
|
||||
* 'aksrt_resource' → 最新资源(v3.4 起兼容 post + _aksrt_is_resource)
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$post_type = (string) ($cfg['post_type'] ?? 'post');
|
||||
$count = max(1, min(20, (int) ($cfg['count'] ?? 6)));
|
||||
$layout = (string) ($cfg['layout'] ?? 'card');
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
|
||||
if (!in_array($layout, ['card', 'list', 'masonry', 'grid-cms'], true)) {
|
||||
$layout = 'card';
|
||||
}
|
||||
if (!in_array($post_type, ['post', 'aksrt_resource'], true)) $post_type = 'post';
|
||||
|
||||
$is_resource_module = $post_type === 'aksrt_resource';
|
||||
|
||||
$args = [
|
||||
'posts_per_page' => $count,
|
||||
'post_status' => 'publish',
|
||||
'no_found_rows' => true,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
if ($is_resource_module) {
|
||||
$args['post_type'] = function_exists('aksrt_resource_post_types') ? aksrt_resource_post_types() : ['post'];
|
||||
if (!post_type_exists('aksrt_resource')) {
|
||||
$args['meta_query'] = [[
|
||||
'key' => '_aksrt_is_resource',
|
||||
'value' => '1',
|
||||
'compare' => '=',
|
||||
]];
|
||||
}
|
||||
} else {
|
||||
$args['post_type'] = 'post';
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
if (!$query->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
return;
|
||||
}
|
||||
|
||||
$default_title = $is_resource_module ? __('最新资源', 'aksrt') : __('最新文章', 'aksrt');
|
||||
$display_title = $title ?: $default_title;
|
||||
$archive_link = $is_resource_module
|
||||
? (function_exists('aksrt_resource_archive_url') ? aksrt_resource_archive_url() : home_url('/resources/'))
|
||||
: get_permalink(get_option('page_for_posts'));
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--recent container" aria-label="<?php echo esc_attr($display_title); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($display_title); ?></h2>
|
||||
<?php if ($archive_link) : ?>
|
||||
<a class="home-module__more" href="<?php echo esc_url($archive_link); ?>">
|
||||
<?php esc_html_e('查看更多', 'aksrt'); ?> <i class="fas fa-arrow-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
|
||||
<div class="post-grid post-grid--<?php echo esc_attr($layout); ?>">
|
||||
<?php
|
||||
set_query_var('aksrt_post_card_layout', $layout);
|
||||
set_query_var('aksrt_post_card_scene', 'home');
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
get_template_part('templates/parts/content', 'post-card');
|
||||
}
|
||||
set_query_var('aksrt_post_card_layout', '');
|
||||
set_query_var('aksrt_post_card_scene', '');
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Spacing
|
||||
*
|
||||
* config: { height? }
|
||||
*
|
||||
* 间距模块,用于模块间留白。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$height = max(8, min(200, (int) ($cfg['height'] ?? 40)));
|
||||
?>
|
||||
|
||||
<div class="home-module--spacing" style="height:<?php echo esc_attr((string) $height); ?>px" aria-hidden="true"></div>
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Tabs
|
||||
*
|
||||
* config: { cat_ids: int[], count, layout, title? }
|
||||
*
|
||||
* P6 阶段先实现"按 Tab 标题分组渲染",Tab 切换交互在 P9 阶段引入 JS。
|
||||
* 默认行为:渲染选中分类(cat_ids[0])的卡片,其它 Tab 用 data-* 标记,
|
||||
* 配合 cms-home-modules.js 切换 active。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$cat_ids = isset($cfg['cat_ids']) && is_array($cfg['cat_ids']) ? array_map('intval', $cfg['cat_ids']) : [];
|
||||
$cat_ids = array_filter($cat_ids, fn($x) => $x > 0);
|
||||
$count = max(1, min(20, (int) ($cfg['count'] ?? 8)));
|
||||
$layout = (string) ($cfg['layout'] ?? 'grid-cms');
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
|
||||
if (!in_array($layout, ['card', 'list', 'masonry', 'grid-cms'], true)) {
|
||||
$layout = 'grid-cms';
|
||||
}
|
||||
|
||||
if (empty($cat_ids)) {
|
||||
// 没有指定 → 取站点最热的两个分类
|
||||
$top_cats = get_terms([
|
||||
'taxonomy' => 'category',
|
||||
'orderby' => 'count',
|
||||
'order' => 'DESC',
|
||||
'number' => 4,
|
||||
'hide_empty' => true,
|
||||
'fields' => 'ids',
|
||||
]);
|
||||
if (is_wp_error($top_cats)) $top_cats = [];
|
||||
$cat_ids = array_map('intval', $top_cats);
|
||||
}
|
||||
|
||||
if (empty($cat_ids)) return;
|
||||
|
||||
$tabs = [];
|
||||
foreach ($cat_ids as $cid) {
|
||||
$term = get_term($cid, 'category');
|
||||
if (!$term || is_wp_error($term)) continue;
|
||||
$tabs[] = [
|
||||
'id' => $cid,
|
||||
'name' => $term->name,
|
||||
'link' => get_category_link($cid),
|
||||
];
|
||||
}
|
||||
if (empty($tabs)) return;
|
||||
|
||||
$active_id = $tabs[0]['id'];
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--tabs container home-tab-content index-tab-main" aria-label="<?php echo esc_attr($title ?: __('分类切换', 'aksrt')); ?>">
|
||||
<header class="home-module__header home-module__header--tabs">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title ?: __('热门分类', 'aksrt')); ?></h2>
|
||||
<nav class="home-module__tabs" role="tablist" data-aksrt-tabs>
|
||||
<?php foreach ($tabs as $i => $t) : ?>
|
||||
<button type="button"
|
||||
role="tab"
|
||||
class="home-module__tab<?php echo $i === 0 ? ' is-active' : ''; ?>"
|
||||
aria-selected="<?php echo $i === 0 ? 'true' : 'false'; ?>"
|
||||
data-tab-target="cat-<?php echo (int) $t['id']; ?>">
|
||||
<?php echo esc_html($t['name']); ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<?php foreach ($tabs as $i => $t) :
|
||||
$tab_post_types = function_exists('aksrt_resource_post_types')
|
||||
? array_unique(array_merge(['post'], aksrt_resource_post_types()))
|
||||
: ['post'];
|
||||
$query = new WP_Query([
|
||||
'cat' => $t['id'],
|
||||
'post_type' => $tab_post_types,
|
||||
'posts_per_page' => $count,
|
||||
'post_status' => 'publish',
|
||||
'no_found_rows' => true,
|
||||
]);
|
||||
?>
|
||||
<div class="home-module__tab-panel tab-pane<?php echo $i === 0 ? ' is-active' : ''; ?>"
|
||||
role="tabpanel"
|
||||
data-tab-id="cat-<?php echo (int) $t['id']; ?>"
|
||||
<?php echo $i !== 0 ? 'hidden' : ''; ?>>
|
||||
<?php if ($query->have_posts()) : ?>
|
||||
<div class="posts-row ajaxpager tab-content">
|
||||
<?php
|
||||
set_query_var('aksrt_post_card_layout', $layout === 'list' ? 'list' : 'card');
|
||||
set_query_var('aksrt_post_card_scene', 'home');
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
get_template_part('templates/parts/content', 'post-card');
|
||||
}
|
||||
set_query_var('aksrt_post_card_layout', '');
|
||||
set_query_var('aksrt_post_card_scene', '');
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p class="home-module__empty"><?php esc_html_e('该分类暂无内容', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</section>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Tag Cloud
|
||||
*
|
||||
* config: { limit, title? }
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$limit = max(5, min(100, (int) ($cfg['limit'] ?? 30)));
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
|
||||
$tags = get_terms([
|
||||
'taxonomy' => 'post_tag',
|
||||
'orderby' => 'count',
|
||||
'order' => 'DESC',
|
||||
'number' => $limit,
|
||||
'hide_empty' => true,
|
||||
]);
|
||||
if (is_wp_error($tags) || empty($tags)) return;
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--tags container" aria-label="<?php echo esc_attr($title ?: __('热门标签', 'aksrt')); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title ?: __('热门标签', 'aksrt')); ?></h2>
|
||||
</header>
|
||||
|
||||
<ul class="home-module__tag-cloud">
|
||||
<?php foreach ($tags as $tag) : ?>
|
||||
<li>
|
||||
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" class="home-module__tag">
|
||||
<span class="home-module__tag-name">#<?php echo esc_html($tag->name); ?></span>
|
||||
<span class="home-module__tag-count"><?php echo (int) $tag->count; ?></span>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · Text Title
|
||||
*
|
||||
* config: { title, subtitle?, align?, tag? }
|
||||
*
|
||||
* 纯文本标题模块,用于页面分隔和标题引导。
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) $cfg = [];
|
||||
|
||||
$title = (string) ($cfg['title'] ?? '');
|
||||
$subtitle = (string) ($cfg['subtitle'] ?? '');
|
||||
$align = sanitize_key((string) ($cfg['align'] ?? 'left'));
|
||||
$tag = sanitize_key((string) ($cfg['tag'] ?? 'h2'));
|
||||
|
||||
if ($title === '' && $subtitle === '') return;
|
||||
|
||||
$valid_tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
|
||||
if (!in_array($tag, $valid_tags, true)) $tag = 'h2';
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--text-title container" style="text-align:<?php echo esc_attr($align); ?>">
|
||||
<?php if ($title !== '') : ?>
|
||||
<<?php echo esc_attr($tag); ?> class="home-module__title"><?php echo esc_html($title); ?></<?php echo esc_attr($tag); ?>>
|
||||
<?php endif; ?>
|
||||
<?php if ($subtitle !== '') : ?>
|
||||
<p class="home-module__subtitle"><?php echo esc_html($subtitle); ?></p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* Home Module · User Cards
|
||||
*
|
||||
* Maps to zibll widget-user capability.
|
||||
* config: { title?, count, columns, order(recent/posts/manual), user_ids[], show_stats }
|
||||
*/
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$cfg = get_query_var('aksrt_module_config', []);
|
||||
if (!is_array($cfg)) {
|
||||
$cfg = [];
|
||||
}
|
||||
|
||||
$title = trim((string) ($cfg['title'] ?? ''));
|
||||
$count = max(1, min(12, (int) ($cfg['count'] ?? 4)));
|
||||
$columns = max(2, min(6, (int) ($cfg['columns'] ?? 4)));
|
||||
$order = sanitize_key((string) ($cfg['order'] ?? 'recent'));
|
||||
$user_ids = isset($cfg['user_ids']) && is_array($cfg['user_ids']) ? array_map('absint', $cfg['user_ids']) : [];
|
||||
$show_stats = !isset($cfg['show_stats']) || !empty($cfg['show_stats']);
|
||||
|
||||
// Build user query.
|
||||
if ($order === 'manual' && !empty($user_ids)) {
|
||||
$query_args = [
|
||||
'include' => array_slice($user_ids, 0, $count),
|
||||
'orderby' => 'include',
|
||||
'number' => $count,
|
||||
];
|
||||
} elseif ($order === 'posts') {
|
||||
$query_args = [
|
||||
'number' => $count,
|
||||
'orderby' => 'post_count',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
} else {
|
||||
// 'recent' = newest registrations.
|
||||
$query_args = [
|
||||
'number' => $count,
|
||||
'orderby' => 'registered',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
}
|
||||
|
||||
$users = get_users($query_args);
|
||||
if (empty($users)) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<section class="home-module home-module--users container" aria-label="<?php echo esc_attr($title ?: __('推荐用户', 'aksrt')); ?>">
|
||||
<header class="home-module__header">
|
||||
<h2 class="home-module__title"><?php echo esc_html($title ?: __('推荐用户', 'aksrt')); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="home-module__users-grid" style="--cols: <?php echo (int) $columns; ?>;">
|
||||
<?php foreach ($users as $user) :
|
||||
$uid = $user->ID;
|
||||
$avatar = get_avatar_url($uid, ['size' => 96]);
|
||||
$display = $user->display_name ?: $user->user_login;
|
||||
$bio = get_user_meta($uid, 'description', true);
|
||||
$post_cnt = count_user_posts($uid);
|
||||
$profile = function_exists('aksrt_get_user_home_url')
|
||||
? aksrt_get_user_home_url($uid)
|
||||
: get_author_posts_url($uid);
|
||||
?>
|
||||
<div class="home-module__user-card">
|
||||
<a href="<?php echo esc_url($profile); ?>" class="home-module__user-link">
|
||||
<img src="<?php echo esc_url($avatar); ?>" alt="" class="home-module__user-avatar"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
<strong class="home-module__user-name"><?php echo esc_html($display); ?></strong>
|
||||
</a>
|
||||
<?php if ($bio) : ?>
|
||||
<p class="home-module__user-bio"><?php echo esc_html(wp_trim_words($bio, 12, '...')); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($show_stats) : ?>
|
||||
<span class="home-module__user-stats">
|
||||
<span class="home-module__user-stat">
|
||||
<i class="fas fa-file-alt" aria-hidden="true"></i>
|
||||
<?php echo (int) $post_cnt; ?>
|
||||
</span>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* 登录提示模板
|
||||
*
|
||||
* 在需要登录才能访问的内容区域展示。
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @var string $message 提示文字
|
||||
* @var string $redirect 登录后跳转地址
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$message = $args['message'] ?? __('登录后查看完整内容', 'aksrt');
|
||||
$redirect = $args['redirect'] ?? get_permalink();
|
||||
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url($redirect) : wp_login_url($redirect);
|
||||
$register_url = function_exists('aksrt_get_register_url') ? aksrt_get_register_url() : wp_registration_url();
|
||||
$can_register = get_option('users_can_register');
|
||||
?>
|
||||
|
||||
<div class="login-prompt">
|
||||
<div class="login-prompt__inner">
|
||||
<div class="login-prompt__icon">
|
||||
<i class="fas fa-lock"></i>
|
||||
</div>
|
||||
<p class="login-prompt__text"><?php echo esc_html($message); ?></p>
|
||||
<div class="login-prompt__btns">
|
||||
<a href="<?php echo esc_url($login_url); ?>" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-sign-in-alt"></i> <?php esc_html_e('登录', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php if ($can_register) : ?>
|
||||
<a href="<?php echo esc_url($register_url); ?>" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-user-plus"></i> <?php esc_html_e('注册', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
/**
|
||||
* Modal auth dialog.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (is_user_logged_in()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$oauth_providers = [];
|
||||
if (class_exists('AKSRT_OAuth')) {
|
||||
$oauth_providers = AKSRT_OAuth::get_instance()->get_auth_providers_data();
|
||||
}
|
||||
|
||||
$registration_open = true;
|
||||
$email_verification = false;
|
||||
$close_signin = false;
|
||||
$invite_field_mode = 'hidden';
|
||||
$invite_field_hint = '';
|
||||
$invite_prefill = '';
|
||||
$show_qrcode_tab = false;
|
||||
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$registration_open = AKSRT_Settings::registration_enabled();
|
||||
$email_verification = AKSRT_Settings::registration_requires_email_verification();
|
||||
$close_signin = AKSRT_Settings::close_signin();
|
||||
|
||||
$invite_cfg = AKSRT_Settings::get_invite_registration_config();
|
||||
$invite_field_mode = (string) ($invite_cfg['register_field'] ?? 'hidden');
|
||||
$invite_field_hint = $invite_field_mode === 'required'
|
||||
? (string) ($invite_cfg['must_desc'] ?? '')
|
||||
: (string) ($invite_cfg['open_desc'] ?? '');
|
||||
}
|
||||
|
||||
if (!empty($_GET['invite'])) {
|
||||
$invite_prefill = sanitize_key(wp_unslash($_GET['invite']));
|
||||
} elseif (!empty($_COOKIE['aksrt_invite'])) {
|
||||
$invite_prefill = sanitize_key(wp_unslash($_COOKIE['aksrt_invite']));
|
||||
}
|
||||
|
||||
foreach ($oauth_providers as $provider) {
|
||||
if (($provider['name'] ?? '') === 'weixingzh') {
|
||||
$show_qrcode_tab = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$site_name = get_bloginfo('name');
|
||||
$reset_url = function_exists('aksrt_get_reset_password_url') ? aksrt_get_reset_password_url() : wp_lostpassword_url();
|
||||
?>
|
||||
|
||||
<div class="aksrt-modal-auth" id="aksrt-modal-auth" aria-hidden="true" role="dialog" aria-modal="true" aria-label="<?php esc_attr_e('Sign In', 'aksrt'); ?>">
|
||||
<div class="aksrt-modal-auth__overlay"></div>
|
||||
<div class="aksrt-modal-auth__card">
|
||||
<button type="button" class="aksrt-modal-auth__close" aria-label="<?php esc_attr_e('Close', 'aksrt'); ?>">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
|
||||
<div class="aksrt-modal-auth__header">
|
||||
<div class="aksrt-modal-auth__logo">AK</div>
|
||||
<h2 class="aksrt-modal-auth__title"><?php echo esc_html($site_name); ?></h2>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-modal-auth__tabs" role="tablist">
|
||||
<button type="button" class="aksrt-modal-auth__tab is-active" data-tab="login" role="tab" aria-selected="true">
|
||||
<?php esc_html_e('Sign In', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php if ($registration_open) : ?>
|
||||
<button type="button" class="aksrt-modal-auth__tab" data-tab="register" role="tab" aria-selected="false">
|
||||
<?php esc_html_e('Register', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if ($show_qrcode_tab) : ?>
|
||||
<button type="button" class="aksrt-modal-auth__tab" data-tab="qrcode" role="tab" aria-selected="false">
|
||||
<?php esc_html_e('QR Login', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-modal-auth__panel is-active" data-panel="login">
|
||||
<?php if ($close_signin) : ?>
|
||||
<div class="aksrt-modal-auth__error is-success" id="aksrt-modal-login-error">
|
||||
<?php esc_html_e('Password sign-in is currently disabled. Please use one of the social login methods below.', 'aksrt'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<form class="aksrt-modal-auth__form" id="aksrt-modal-login-form">
|
||||
<div class="aksrt-modal-auth__error" id="aksrt-modal-login-error" hidden></div>
|
||||
<?php wp_nonce_field('aksrt_login', '_login_nonce'); ?>
|
||||
|
||||
<div class="aksrt-modal-auth__field">
|
||||
<label for="modal-login-user"><?php esc_html_e('Email / Username', 'aksrt'); ?></label>
|
||||
<input type="text" id="modal-login-user" name="log" autocomplete="username" required placeholder="<?php esc_attr_e('Please enter your email or username', 'aksrt'); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-modal-auth__field">
|
||||
<label for="modal-login-pass"><?php esc_html_e('Password', 'aksrt'); ?></label>
|
||||
<div class="aksrt-modal-auth__pass-wrap">
|
||||
<input type="password" id="modal-login-pass" name="pwd" autocomplete="current-password" required placeholder="<?php esc_attr_e('Please enter your password', 'aksrt'); ?>">
|
||||
<button type="button" class="aksrt-modal-auth__pass-toggle" aria-label="<?php esc_attr_e('Toggle password visibility', 'aksrt'); ?>">
|
||||
<i class="far fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (function_exists('aksrt_render_captcha')) : ?>
|
||||
<?php aksrt_render_captcha('login'); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-modal-auth__actions">
|
||||
<a href="<?php echo esc_url($reset_url); ?>" class="aksrt-modal-auth__link"><?php esc_html_e('Forgot password?', 'aksrt'); ?></a>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="aksrt-modal-auth__submit">
|
||||
<span><?php esc_html_e('Sign In', 'aksrt'); ?></span>
|
||||
<i class="fas fa-spinner fa-spin" hidden></i>
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($registration_open) : ?>
|
||||
<div class="aksrt-modal-auth__panel" data-panel="register">
|
||||
<form class="aksrt-modal-auth__form" id="aksrt-modal-register-form">
|
||||
<div class="aksrt-modal-auth__error" id="aksrt-modal-register-error" hidden></div>
|
||||
<?php wp_nonce_field('aksrt_register', '_register_nonce'); ?>
|
||||
|
||||
<div class="aksrt-modal-auth__field">
|
||||
<label for="modal-reg-user"><?php esc_html_e('Username', 'aksrt'); ?></label>
|
||||
<input type="text" id="modal-reg-user" name="user_login" autocomplete="username" required placeholder="<?php esc_attr_e('Please enter a username', 'aksrt'); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-modal-auth__field">
|
||||
<label for="modal-reg-email"><?php esc_html_e('Email', 'aksrt'); ?></label>
|
||||
<input type="email" id="modal-reg-email" name="user_email" autocomplete="email" required placeholder="<?php esc_attr_e('Please enter your email', 'aksrt'); ?>">
|
||||
</div>
|
||||
|
||||
<div class="aksrt-modal-auth__field">
|
||||
<label for="modal-reg-pass"><?php esc_html_e('Password', 'aksrt'); ?></label>
|
||||
<div class="aksrt-modal-auth__pass-wrap">
|
||||
<input type="password" id="modal-reg-pass" name="user_pass" autocomplete="new-password" required minlength="6" placeholder="<?php esc_attr_e('At least 6 characters', 'aksrt'); ?>">
|
||||
<button type="button" class="aksrt-modal-auth__pass-toggle" aria-label="<?php esc_attr_e('Toggle password visibility', 'aksrt'); ?>">
|
||||
<i class="far fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-modal-auth__field">
|
||||
<label for="modal-reg-pass-confirm"><?php esc_html_e('Confirm Password', 'aksrt'); ?></label>
|
||||
<div class="aksrt-modal-auth__pass-wrap">
|
||||
<input type="password" id="modal-reg-pass-confirm" name="user_pass_confirm" autocomplete="new-password" required minlength="6" placeholder="<?php esc_attr_e('Re-enter your password', 'aksrt'); ?>">
|
||||
<button type="button" class="aksrt-modal-auth__pass-toggle" aria-label="<?php esc_attr_e('Toggle password visibility', 'aksrt'); ?>">
|
||||
<i class="far fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($invite_field_mode !== 'hidden') : ?>
|
||||
<div class="aksrt-modal-auth__field">
|
||||
<label for="modal-reg-invite">
|
||||
<?php esc_html_e('邀请码', 'aksrt'); ?>
|
||||
<?php if ($invite_field_mode === 'optional') : ?>
|
||||
<small><?php esc_html_e('(选填)', 'aksrt'); ?></small>
|
||||
<?php endif; ?>
|
||||
</label>
|
||||
<input type="text" id="modal-reg-invite" name="invite_code" value="<?php echo esc_attr($invite_prefill); ?>" <?php echo $invite_field_mode === 'required' ? 'required' : ''; ?> placeholder="<?php esc_attr_e('请输入邀请码', 'aksrt'); ?>">
|
||||
<?php if ($invite_field_hint !== '') : ?>
|
||||
<p class="aksrt-modal-auth__hint"><?php echo wp_kses_post($invite_field_hint); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<label class="aksrt-modal-auth__checkbox aksrt-modal-auth__agreement">
|
||||
<input type="checkbox" name="agree_terms" value="1" required>
|
||||
<span><?php esc_html_e('I agree to the Terms of Service', 'aksrt'); ?></span>
|
||||
</label>
|
||||
|
||||
<?php if ($email_verification) : ?>
|
||||
<p class="aksrt-modal-auth__hint"><?php esc_html_e('Email verification is required after registration.', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (function_exists('aksrt_render_captcha')) : ?>
|
||||
<?php aksrt_render_captcha('register'); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<button type="submit" class="aksrt-modal-auth__submit">
|
||||
<span><?php esc_html_e('Register', 'aksrt'); ?></span>
|
||||
<i class="fas fa-spinner fa-spin" hidden></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($show_qrcode_tab) : ?>
|
||||
<div class="aksrt-modal-auth__panel" data-panel="qrcode">
|
||||
<div class="aksrt-modal-auth__form">
|
||||
<div class="aksrt-modal-auth__error" id="aksrt-modal-qrcode-error" hidden></div>
|
||||
<div class="aksrt-modal-auth__qr-code"></div>
|
||||
<p class="aksrt-modal-auth__hint"><?php esc_html_e('Use WeChat to scan the QR code and complete sign-in on your phone.', 'aksrt'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($oauth_providers)) : ?>
|
||||
<div class="aksrt-modal-auth__divider">
|
||||
<span><?php esc_html_e('Or continue with', 'aksrt'); ?></span>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-modal-auth__oauth">
|
||||
<?php foreach ($oauth_providers as $provider) :
|
||||
$provider_name = (string) ($provider['name'] ?? '');
|
||||
$label = $provider['label'] ?? $provider_name;
|
||||
$url = $provider['url'] ?? '#';
|
||||
$icon = $provider['icon'] ?? '';
|
||||
?>
|
||||
<a
|
||||
href="<?php echo esc_url($url); ?>"
|
||||
class="aksrt-modal-auth__oauth-btn social-login-item <?php echo esc_attr($provider_name); ?>"
|
||||
data-provider="<?php echo esc_attr($provider_name); ?>"
|
||||
title="<?php echo esc_attr($label); ?>"
|
||||
>
|
||||
<?php echo $icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-modal-auth__footer">
|
||||
<span class="aksrt-modal-auth__footer-text" data-for="login">
|
||||
<?php if ($registration_open) : ?>
|
||||
<?php esc_html_e('No account yet?', 'aksrt'); ?>
|
||||
<button type="button" class="aksrt-modal-auth__switch" data-switch="register"><?php esc_html_e('Register now', 'aksrt'); ?></button>
|
||||
<?php elseif ($show_qrcode_tab) : ?>
|
||||
<?php esc_html_e('Prefer QR sign-in?', 'aksrt'); ?>
|
||||
<button type="button" class="aksrt-modal-auth__switch" data-switch="qrcode"><?php esc_html_e('Open QR Login', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
<?php if ($registration_open) : ?>
|
||||
<span class="aksrt-modal-auth__footer-text" data-for="register" hidden>
|
||||
<?php esc_html_e('Already have an account?', 'aksrt'); ?>
|
||||
<button type="button" class="aksrt-modal-auth__switch" data-switch="login"><?php esc_html_e('Sign in now', 'aksrt'); ?></button>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if ($show_qrcode_tab) : ?>
|
||||
<span class="aksrt-modal-auth__footer-text" data-for="qrcode" hidden>
|
||||
<?php esc_html_e('Want to use your password instead?', 'aksrt'); ?>
|
||||
<button type="button" class="aksrt-modal-auth__switch" data-switch="login"><?php esc_html_e('Back to Sign In', 'aksrt'); ?></button>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* Reusable Page Header Template Part.
|
||||
*
|
||||
* Renders a unified page header for archive / search / page templates.
|
||||
* Style is driven by the global setting `page_header_style` with optional
|
||||
* per-page post-meta override (`page_header_style`).
|
||||
*
|
||||
* Query vars consumed (set via set_query_var before calling get_template_part):
|
||||
* aksrt_ph_style – override style ('' | '1' | '2' | '3'), defaults to global setting
|
||||
* aksrt_ph_eyebrow – eyebrow label text
|
||||
* aksrt_ph_title – title HTML (already escaped by caller)
|
||||
* aksrt_ph_desc – description text
|
||||
* aksrt_ph_cover – cover image URL override
|
||||
* aksrt_ph_extra – extra HTML appended inside the body area (e.g. admin quick-links)
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
// Resolve style: explicit query var > global setting.
|
||||
$ph_style = get_query_var('aksrt_ph_style', null);
|
||||
if ($ph_style === null) {
|
||||
$ph_style = class_exists('AKSRT_Settings')
|
||||
? (AKSRT_Settings::get_other_page_settings()['header_style'] ?? '1')
|
||||
: '1';
|
||||
}
|
||||
|
||||
// '' means "don't show header"
|
||||
if ($ph_style === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$ph_eyebrow = get_query_var('aksrt_ph_eyebrow', '');
|
||||
$ph_title = get_query_var('aksrt_ph_title', '');
|
||||
$ph_desc = get_query_var('aksrt_ph_desc', '');
|
||||
$ph_extra = get_query_var('aksrt_ph_extra', '');
|
||||
|
||||
// Cover image: explicit > global setting > post thumbnail.
|
||||
$ph_cover = get_query_var('aksrt_ph_cover', '');
|
||||
if (empty($ph_cover) && class_exists('AKSRT_Settings')) {
|
||||
$other = AKSRT_Settings::get_other_page_settings();
|
||||
$ph_cover = $other['header_cover_img'] ?? '';
|
||||
}
|
||||
if (empty($ph_cover) && has_post_thumbnail()) {
|
||||
$ph_cover = get_the_post_thumbnail_url(get_the_ID(), 'full');
|
||||
}
|
||||
|
||||
// Map style value to CSS modifier class.
|
||||
$style_class = 'term-page-header--simple';
|
||||
if ($ph_style === '2') {
|
||||
$style_class = 'term-page-header--card';
|
||||
} elseif ($ph_style === '3') {
|
||||
$style_class = 'term-page-header--cover';
|
||||
}
|
||||
|
||||
// Cover inline style (for cover style).
|
||||
$cover_style = '';
|
||||
if ($ph_style === '3' && !empty($ph_cover)) {
|
||||
$cover_style = ' style="background-image:url(\'' . esc_url($ph_cover) . '\')"';
|
||||
}
|
||||
?>
|
||||
|
||||
<header class="page-header term-page-header <?php echo esc_attr($style_class); ?>">
|
||||
<?php if ($ph_style === '3' && !empty($ph_cover)) : ?>
|
||||
<div class="term-page-header__cover-bg"<?php echo $cover_style; /* phpcs:ignore -- escaped above */ ?>>
|
||||
<div class="term-page-header__cover-overlay"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="term-page-header__body<?php echo $ph_style === '3' ? ' term-page-header__body--overlay' : ''; ?>">
|
||||
<div>
|
||||
<?php if ($ph_eyebrow !== '') : ?>
|
||||
<p class="term-page-header__eyebrow"><?php echo esc_html($ph_eyebrow); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<h1 class="entry-title"><?php echo $ph_title; /* phpcs:ignore -- caller must escape */ ?></h1>
|
||||
|
||||
<?php if ($ph_desc !== '') : ?>
|
||||
<p class="term-page-header__desc"><?php echo esc_html($ph_desc); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($ph_extra !== '') : ?>
|
||||
<?php echo $ph_extra; /* phpcs:ignore -- caller must escape */ ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($ph_style === '2' && !empty($ph_cover)) : ?>
|
||||
<div class="term-page-header__cover"<?php echo $cover_style; /* phpcs:ignore -- escaped above */ ?>></div>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
@@ -0,0 +1,400 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: 用户中心
|
||||
* Template Post Type: page
|
||||
*
|
||||
* 单一页面模板,根据场景显示不同内容:
|
||||
* - 登录用户查看自己 → 仪表盘面板(个人信息 / 文章 / 评论 / 收藏 / 通知 / 设置)
|
||||
* - 查看其他用户主页 → 公开用户主页(头像 / 简介 / 文章 / 评论)
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
// 加载共享辅助函数(分页、空状态)
|
||||
require_once AKSRT_DIR . '/templates/parts/user-shared-helpers.php';
|
||||
|
||||
get_header(); ?>
|
||||
|
||||
<div id="toast-container"></div>
|
||||
<script>function showToast(text,d){d=d||2500;var c=document.getElementById('toast-container');if(!c){c=document.createElement('div');c.id='toast-container';document.body.appendChild(c);}var t=document.createElement('div');t.className='toast-item';t.textContent=text;c.appendChild(t);setTimeout(function(){t.classList.add('fade-out');setTimeout(function(){if(t.parentNode)t.parentNode.removeChild(t)},300)},d)}</script>
|
||||
|
||||
<?php // ─── Post/Redirect/Get:处理表单提交后跳转,防止刷新重复提交 ──
|
||||
if ( $_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_POST['action'], $_POST['_profile_nonce'] )
|
||||
&& $_POST['action'] === 'aksrt_save_profile'
|
||||
&& wp_verify_nonce( $_POST['_profile_nonce'], 'aksrt_profile_save' )
|
||||
) {
|
||||
$uid = isset( $_POST['user_id'] ) ? (int) $_POST['user_id'] : 0;
|
||||
if ( $uid && $uid === get_current_user_id() ) {
|
||||
if ( isset( $_POST['nickname'] ) ) {
|
||||
wp_update_user( [ 'ID' => $uid, 'display_name' => sanitize_text_field( $_POST['nickname'] ) ] );
|
||||
}
|
||||
if ( isset( $_POST['description'] ) ) {
|
||||
wp_update_user( [ 'ID' => $uid, 'description' => sanitize_textarea_field( $_POST['description'] ) ] );
|
||||
}
|
||||
$contacts = [];
|
||||
if ( isset( $_POST['contacts'] ) && is_array( $_POST['contacts'] ) ) {
|
||||
foreach ( $_POST['contacts'] as $c ) {
|
||||
$u = isset( $c['url'] ) ? esc_url_raw( $c['url'] ) : '';
|
||||
$i = isset( $c['icon'] ) ? sanitize_key( $c['icon'] ) : '';
|
||||
// 清理 FA5 类名前缀:fab fa-xxx / fabfa-xxx / fa-xxx → xxx
|
||||
$i = preg_replace('/^(fab|fas|far)[\s-]*/', '', $i);
|
||||
$i = preg_replace('/^fa[\s-]*/', '', $i);
|
||||
$i = preg_replace('/^[\s-]+/', '', $i);
|
||||
$i = trim( $i, '- ' );
|
||||
if ( ! $u || ! $i ) continue;
|
||||
$n = aksrt_icon_key_to_name( $i );
|
||||
$contacts[] = [ 'name' => $n, 'url' => $u, 'icon' => $i ];
|
||||
}
|
||||
}
|
||||
update_user_meta( $uid, 'aksrt_user_contacts', $contacts );
|
||||
}
|
||||
wp_safe_redirect( add_query_arg( 'saved', '1', aksrt_get_user_center_url() ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
// ─── 确定目标用户 ─────────────────────────────────────────────
|
||||
// 来源: /user/{昵称} (自定义重写规则)
|
||||
// 注意: get_queried_object_id() 在页面中返回的是页面 ID 而非用户 ID
|
||||
$target_user_id = 0;
|
||||
$target_user_nicename = get_query_var('user_nicename');
|
||||
|
||||
if ( $target_user_nicename ) {
|
||||
$user = get_user_by( 'slug', $target_user_nicename );
|
||||
if ( $user ) {
|
||||
$target_user_id = $user->ID;
|
||||
}
|
||||
}
|
||||
|
||||
// 兜底:检查 queried object
|
||||
if ( ! $target_user_id ) {
|
||||
$qid = get_queried_object_id();
|
||||
if ( $qid && get_userdata( $qid ) ) {
|
||||
$target_user_id = $qid;
|
||||
}
|
||||
}
|
||||
|
||||
$current_user = wp_get_current_user();
|
||||
$target_user = $target_user_id ? get_userdata( $target_user_id ) : null;
|
||||
$is_own_profile = false;
|
||||
|
||||
if ( ! $target_user ) {
|
||||
if ( is_user_logged_in() ) {
|
||||
$target_user = $current_user;
|
||||
$target_user_id = $current_user->ID;
|
||||
$is_own_profile = true;
|
||||
} else {
|
||||
wp_safe_redirect( aksrt_get_login_url( aksrt_get_user_center_url() ) );
|
||||
exit;
|
||||
}
|
||||
} elseif ( is_user_logged_in() && (int) $current_user->ID === (int) $target_user->ID ) {
|
||||
$is_own_profile = true;
|
||||
}
|
||||
|
||||
if ( $target_user_nicename && ! $is_own_profile && function_exists( 'aksrt_get_user_home_url' ) ) {
|
||||
wp_safe_redirect( aksrt_get_user_home_url( $target_user ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = $target_user->ID;
|
||||
$post_count = (int) count_user_posts( $user_id, 'post', true );
|
||||
$comment_count = (int) get_comments( [ 'user_id' => $user_id, 'count' => true, 'status' => 'approve' ] );
|
||||
|
||||
// 加载用户自定义联系方式
|
||||
$user_contacts = get_user_meta( $user_id, 'aksrt_user_contacts', true ) ?: [];
|
||||
if ( ! is_array( $user_contacts ) ) $user_contacts = [];
|
||||
$user_center_settings = class_exists( 'AKSRT_Settings' )
|
||||
? AKSRT_Settings::get_user_center_settings()
|
||||
: [
|
||||
'tabs' => [ 'profile', 'posts', 'comments', 'favorites' ],
|
||||
'avatar_upload' => true,
|
||||
'cover_upload' => true,
|
||||
'social_links' => true,
|
||||
];
|
||||
$user_home_settings = class_exists( 'AKSRT_Settings' )
|
||||
? AKSRT_Settings::get_user_home_settings()
|
||||
: [
|
||||
'tabs' => [ 'posts', 'comments', 'favorites' ],
|
||||
'sidebar' => true,
|
||||
'cover' => true,
|
||||
'follow' => true,
|
||||
'posts_per_page' => 10,
|
||||
];
|
||||
$user_home_manager = class_exists( 'AKSRT_User_Home' ) ? AKSRT_User_Home::get_instance() : null;
|
||||
$profile_signals = $user_home_manager ? $user_home_manager->get_profile_signals( $user_id ) : [];
|
||||
$profile_notice = $user_home_manager ? $user_home_manager->get_profile_notice( $user_id ) : [];
|
||||
$show_report_button = $user_home_manager ? $user_home_manager->show_report_entry() : false;
|
||||
$public_visible_tabs = $user_home_manager
|
||||
? $user_home_manager->get_visible_tabs( false )
|
||||
: [
|
||||
'posts' => [ 'label' => __( '文章', 'aksrt' ) ],
|
||||
'comments' => [ 'label' => __( '评论', 'aksrt' ) ],
|
||||
'favorites' => [ 'label' => __( '收藏', 'aksrt' ) ],
|
||||
];
|
||||
|
||||
// 用户自定义背景图
|
||||
$user_background_url = get_user_meta( $user_id, 'aksrt_background_image', true ) ?: '';
|
||||
$allow_bg_upload = $is_own_profile
|
||||
&& ! empty( $user_center_settings['cover_upload'] )
|
||||
&& class_exists( 'AKSRT_Settings' )
|
||||
&& aksrt_get_setting( 'allow_background_upload', false );
|
||||
$show_avatar_edit = $is_own_profile && ! empty( $user_center_settings['avatar_upload'] );
|
||||
$avatar_settings_url = admin_url( 'profile.php' );
|
||||
$public_home_url = function_exists( 'aksrt_get_user_home_url' ) ? aksrt_get_user_home_url( $target_user ) : home_url( '/' );
|
||||
|
||||
$favorite_post_ids = function_exists( 'aksrt_get_user_interaction_posts' )
|
||||
? aksrt_get_user_interaction_posts( '_aksrt_favorite_posts', $user_id )
|
||||
: [];
|
||||
$favorite_count = count( $favorite_post_ids );
|
||||
$notification_unread_count = $is_own_profile && function_exists( 'aksrt_get_user_unread_notification_count' )
|
||||
? aksrt_get_user_unread_notification_count( $user_id )
|
||||
: 0;
|
||||
$dashboard_tabs = class_exists( 'AKSRT_User_Center' )
|
||||
? AKSRT_User_Center::get_instance()->get_dashboard_tabs()
|
||||
: [
|
||||
'profile' => [ 'label' => __( '个人信息', 'aksrt' ), 'icon' => 'user' ],
|
||||
'posts' => [ 'label' => __( '我的文章', 'aksrt' ), 'icon' => 'file-alt' ],
|
||||
'comments' => [ 'label' => __( '我的评论', 'aksrt' ), 'icon' => 'comment' ],
|
||||
'favorites' => [ 'label' => __( '我的收藏', 'aksrt' ), 'icon' => 'star' ],
|
||||
'settings' => [ 'label' => __( '账号设置', 'aksrt' ), 'icon' => 'cog' ],
|
||||
];
|
||||
$dashboard_tab_keys = array_keys( $dashboard_tabs );
|
||||
$public_tab_keys = array_keys( $public_visible_tabs );
|
||||
if ( empty( $public_tab_keys ) ) {
|
||||
$public_visible_tabs = [
|
||||
'posts' => [ 'label' => __( '文章', 'aksrt' ) ],
|
||||
'comments' => [ 'label' => __( '评论', 'aksrt' ) ],
|
||||
'favorites' => [ 'label' => __( '收藏', 'aksrt' ) ],
|
||||
];
|
||||
$public_tab_keys = array_keys( $public_visible_tabs );
|
||||
}
|
||||
$public_tab_labels = [
|
||||
'posts' => __( '文章', 'aksrt' ),
|
||||
'comments' => __( '评论', 'aksrt' ),
|
||||
'favorites' => __( '收藏', 'aksrt' ),
|
||||
];
|
||||
foreach ( $public_visible_tabs as $public_tab_key => $public_tab_config ) {
|
||||
if ( ! empty( $public_tab_config['label'] ) ) {
|
||||
$public_tab_labels[ $public_tab_key ] = (string) $public_tab_config['label'];
|
||||
}
|
||||
}
|
||||
$public_tab_counts = [
|
||||
'posts' => $post_count,
|
||||
'comments' => $comment_count,
|
||||
'favorites' => $favorite_count,
|
||||
];
|
||||
|
||||
// 消息中心页面 URL
|
||||
$messages_page = get_pages( [ 'meta_key' => '_wp_page_template', 'meta_value' => 'templates/pages/page-messages.php', 'number' => 1 ] );
|
||||
$messages_url = ! empty( $messages_page ) ? get_permalink( $messages_page[0] ) : aksrt_get_user_center_url( 'notif' );
|
||||
|
||||
// ─── 文章状态计数(仅自己模式;用于状态筛选 chip) ────────────
|
||||
$user_status_counts = [
|
||||
'publish' => 0,
|
||||
'draft' => 0,
|
||||
'pending' => 0,
|
||||
'private' => 0,
|
||||
];
|
||||
if ( $is_own_profile ) {
|
||||
global $wpdb;
|
||||
$rows = $wpdb->get_results( $wpdb->prepare(
|
||||
"SELECT post_status, COUNT(*) AS num FROM {$wpdb->posts}
|
||||
WHERE post_author = %d AND post_type = 'post'
|
||||
AND post_status IN ('publish','draft','pending','private')
|
||||
GROUP BY post_status",
|
||||
$user_id
|
||||
) );
|
||||
foreach ( (array) $rows as $row ) {
|
||||
$user_status_counts[ $row->post_status ] = (int) $row->num;
|
||||
}
|
||||
$post_count = (int) array_sum( $user_status_counts );
|
||||
}
|
||||
|
||||
// ─── 分页与筛选参数(自己 / 他人 共享) ────────────────────────
|
||||
$per_page = $is_own_profile ? 10 : max( 5, (int) ( $user_home_settings['posts_per_page'] ?? 10 ) );
|
||||
$default_dashboard_tab = in_array( 'profile', $dashboard_tab_keys, true ) ? 'profile' : ( $dashboard_tab_keys[0] ?? 'profile' );
|
||||
$active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : $default_dashboard_tab;
|
||||
$public_default_tab = $public_tab_keys[0] ?? 'posts';
|
||||
$public_active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : $public_default_tab;
|
||||
// 兼容旧链接:签到 / 邀请已经并入新面板
|
||||
if ( 'signin' === $active_tab ) {
|
||||
$active_tab = 'credits';
|
||||
} elseif ( 'invite' === $active_tab ) {
|
||||
$active_tab = 'settings';
|
||||
}
|
||||
if ( ! in_array( $active_tab, $dashboard_tab_keys, true ) ) {
|
||||
$active_tab = $default_dashboard_tab;
|
||||
}
|
||||
if ( ! in_array( $public_active_tab, $public_tab_keys, true ) ) {
|
||||
$public_active_tab = $public_default_tab;
|
||||
}
|
||||
$posts_page = max( 1, isset( $_GET['posts_page'] ) ? (int) $_GET['posts_page'] : 1 );
|
||||
$comments_page = max( 1, isset( $_GET['comments_page'] ) ? (int) $_GET['comments_page'] : 1 );
|
||||
$favorites_page = max( 1, isset( $_GET['favorites_page'] ) ? (int) $_GET['favorites_page'] : 1 );
|
||||
|
||||
$valid_post_status = [ 'all', 'publish', 'draft', 'pending', 'private' ];
|
||||
$post_status_filter = isset( $_GET['post_status'] ) ? sanitize_key( wp_unslash( $_GET['post_status'] ) ) : 'publish';
|
||||
if ( ! in_array( $post_status_filter, $valid_post_status, true ) ) {
|
||||
$post_status_filter = 'publish';
|
||||
}
|
||||
|
||||
// 空状态图标 SVG(提取以减少重复)
|
||||
$svg_empty_post = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M9 13h6M9 17h6M9 9h1"/></svg>';
|
||||
$svg_empty_comment = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>';
|
||||
$svg_empty_favorite = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>';
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
|
||||
<?php if ( $is_own_profile ) : ?>
|
||||
<!-- ===================== 本人模式:用户中心 ===================== -->
|
||||
<div class="user-center">
|
||||
|
||||
<?php
|
||||
$oauth_action = isset( $_GET['oauth_action'] ) ? sanitize_key( wp_unslash( $_GET['oauth_action'] ) ) : '';
|
||||
$oauth_notice_provider = isset( $_GET['oauth_bound'] ) ? sanitize_key( wp_unslash( $_GET['oauth_bound'] ) ) : '';
|
||||
$oauth_unbound_provider = isset( $_GET['oauth_unbound'] ) ? sanitize_key( wp_unslash( $_GET['oauth_unbound'] ) ) : '';
|
||||
$oauth_notice_names = [
|
||||
'github' => 'GitHub',
|
||||
'gitee' => 'Gitee',
|
||||
'qq' => 'QQ',
|
||||
'google' => 'Google',
|
||||
];
|
||||
?>
|
||||
<?php if ( isset( $_GET['saved'] ) || $oauth_notice_provider || $oauth_unbound_provider ) : ?>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded',function(){
|
||||
<?php if ( $oauth_notice_provider && $oauth_action === 'login' ) : ?>
|
||||
showToast('<?php echo esc_js( sprintf( __( '%s 登录成功', 'aksrt' ), $oauth_notice_names[ $oauth_notice_provider ] ?? ucfirst( $oauth_notice_provider ) ) ); ?>');
|
||||
<?php elseif ( $oauth_notice_provider ) : ?>
|
||||
showToast('<?php echo esc_js( sprintf( __( '%s 绑定成功', 'aksrt' ), $oauth_notice_names[ $oauth_notice_provider ] ?? ucfirst( $oauth_notice_provider ) ) ); ?>');
|
||||
<?php elseif ( $oauth_unbound_provider ) : ?>
|
||||
showToast('<?php echo esc_js( sprintf( __( '%s 已解绑', 'aksrt' ), $oauth_notice_names[ $oauth_unbound_provider ] ?? ucfirst( $oauth_unbound_provider ) ) ); ?>');
|
||||
<?php else : ?>
|
||||
showToast('已保存');
|
||||
<?php endif; ?>
|
||||
if(window.history.replaceState){
|
||||
var u=new URL(window.location);
|
||||
u.searchParams.delete('saved');
|
||||
u.searchParams.delete('oauth_bound');
|
||||
u.searchParams.delete('oauth_unbound');
|
||||
u.searchParams.delete('oauth_action');
|
||||
window.history.replaceState({},'',u);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 头图 + 用户卡 -->
|
||||
<div class="uc-header">
|
||||
<div class="uc-header__cover">
|
||||
<img id="aksrt-cover-img" class="uc-header__cover-img" src="<?php echo esc_url( $user_background_url ? $user_background_url : get_theme_file_uri( 'assets/img/person_background.png' ) ); ?>" alt="">
|
||||
<div class="uc-header__cover-mask"></div>
|
||||
<?php if ( $allow_bg_upload ) : ?>
|
||||
<button type="button" class="uc-header__cover-upload" id="aksrt-upload-bg-btn" title="<?php esc_attr_e( '编辑背景图', 'aksrt' ); ?>">
|
||||
<i class="fas fa-pen" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e( '编辑', 'aksrt' ); ?></span>
|
||||
</button>
|
||||
<input type="file" id="aksrt-bg-file-input" accept="image/jpeg,image/png,image/webp,image/gif" style="display:none">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="uc-header__content">
|
||||
<div class="uc-header__avatar">
|
||||
<?php echo get_avatar( $user_id, 120, '', $target_user->display_name ); ?>
|
||||
</div>
|
||||
<div class="uc-header__info">
|
||||
<h1 class="uc-header__name">
|
||||
<?php echo esc_html( $target_user->display_name ); ?>
|
||||
<?php
|
||||
$vip_badge = function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($user_id) : '';
|
||||
if ($vip_badge) echo $vip_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
</h1>
|
||||
<?php if ( $target_user->description ) : ?>
|
||||
<p class="uc-header__desc"><?php echo esc_html( $target_user->description ); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! empty( $profile_signals ) ) : ?>
|
||||
<div class="aksrt-identity-chips">
|
||||
<?php foreach ( $profile_signals as $signal ) : ?>
|
||||
<span class="aksrt-identity-chip aksrt-identity-chip--<?php echo esc_attr( $signal['tone'] ); ?>">
|
||||
<i class="fas fa-<?php echo esc_attr( $signal['icon'] ); ?>" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html( $signal['label'] ); ?></span>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="uc-header__meta">
|
||||
<span class="uc-header__meta-item" title="<?php esc_attr_e( '用户名', 'aksrt' ); ?>">
|
||||
<i class="fas fa-user" aria-hidden="true"></i> <?php echo esc_html( $target_user->user_login ); ?>
|
||||
</span>
|
||||
<?php if ( $target_user->user_email ) : ?>
|
||||
<span class="uc-header__meta-item" title="<?php esc_attr_e( '邮箱', 'aksrt' ); ?>">
|
||||
<i class="fas fa-envelope" aria-hidden="true"></i> <?php echo esc_html( $target_user->user_email ); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uc-header__actions">
|
||||
<?php if ( $show_avatar_edit ) : ?>
|
||||
<a href="<?php echo esc_url( $avatar_settings_url ); ?>" class="btn-ghost btn-sm">
|
||||
<i class="fas fa-camera" aria-hidden="true"></i> <?php esc_html_e( '更换头像', 'aksrt' ); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<a href="<?php echo esc_url( aksrt_get_user_home_url() ); ?>" class="btn-ghost btn-sm">
|
||||
<i class="fas fa-map-marker-alt" aria-hidden="true"></i> <?php esc_html_e( '我的主页', 'aksrt' ); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 两栏布局 -->
|
||||
<div class="uc-layout">
|
||||
<!-- 左侧边栏 -->
|
||||
<aside class="uc-sidebar">
|
||||
<!-- 数据统计 -->
|
||||
<div class="uc-sidebar__section">
|
||||
<div class="uc-sidebar__title"><?php esc_html_e( '数据统计', 'aksrt' ); ?></div>
|
||||
<div class="uc-stats">
|
||||
<?php foreach ( [ 'posts', 'comments', 'favorites' ] as $stat_tab ) : ?>
|
||||
<?php if ( ! isset( $dashboard_tabs[ $stat_tab ] ) ) { continue; } ?>
|
||||
<?php
|
||||
$stat_count = 'posts' === $stat_tab
|
||||
? $post_count
|
||||
: ( 'comments' === $stat_tab ? $comment_count : $favorite_count );
|
||||
?>
|
||||
<a class="uc-stats__item" href="<?php echo esc_url( add_query_arg( 'tab', $stat_tab, remove_query_arg( 'tab' ) ) ); ?>">
|
||||
<span class="uc-stats__value"><?php echo esc_html( (string) $stat_count ); ?></span>
|
||||
<span class="uc-stats__label"><?php echo esc_html( $dashboard_tabs[ $stat_tab ]['label'] ); ?></span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<a class="uc-stats__item" href="<?php echo esc_url( $messages_url ); ?>">
|
||||
<span class="uc-stats__value"><?php echo esc_html( (string) $notification_unread_count ); ?></span>
|
||||
<span class="uc-stats__label"><?php esc_html_e( '通知', 'aksrt' ); ?></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 我的服务 -->
|
||||
<div class="uc-sidebar__section">
|
||||
<div class="uc-sidebar__title"><?php esc_html_e( '我的服务', 'aksrt' ); ?></div>
|
||||
<div class="uc-sidebar__buttons">
|
||||
<?php foreach ( $dashboard_tabs as $tab_key => $tab ) : ?>
|
||||
<button type="button" class="uc-sidebar__btn" data-tab="<?php echo esc_attr( $tab_key ); ?>">
|
||||
<i class="fas fa-<?php echo esc_attr( $tab['icon'] ); ?>" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html( $tab['label'] ); ?></span>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
<a href="<?php echo esc_url( $messages_url ); ?>" class="uc-sidebar__btn">
|
||||
<i class="fas fa-bell" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e( '消息通知', 'aksrt' ); ?></span>
|
||||
<?php if ( $notification_unread_count > 0 ) : ?>
|
||||
<span class="uc-sidebar__badge"><?php echo esc_html( (string) $notification_unread_count ); ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 交易服务 -->
|
||||
<?php
|
||||
$orders_url = function_exists('aksrt_get_orders_page_url') ? aksrt_get_orders_page_url() : '';
|
||||
$show_vip = class_exists('AKSRT_Settings') && !empty(AKSRT_Settings::get_all()['payment_vip_enabled']);
|
||||
$show_credit_tabs = class_exists('AKSRT_Settings') && AKSRT_Settings::credits_enabled();
|
||||
@@ -0,0 +1,403 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$affiliate_enabled = $show_credit_tabs && !empty(AKSRT_Settings::get_all()['payment_affiliate_enabled']);
|
||||
?>
|
||||
<?php if ($orders_url || $show_vip || $show_credit_tabs) : ?>
|
||||
<div class="uc-sidebar__section">
|
||||
<div class="uc-sidebar__title"><?php esc_html_e('交易服务', 'aksrt'); ?></div>
|
||||
<div class="uc-sidebar__buttons">
|
||||
<?php if ($orders_url) : ?>
|
||||
<a href="<?php echo esc_url($orders_url); ?>" class="uc-sidebar__btn">
|
||||
<i class="fas fa-receipt" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('我的订单', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($show_vip) : ?>
|
||||
<button type="button" class="uc-sidebar__btn" data-tab="credits">
|
||||
<i class="fas fa-crown" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('VIP 会员', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if ($show_credit_tabs) : ?>
|
||||
<button type="button" class="uc-sidebar__btn" data-tab="credits">
|
||||
<i class="fas fa-coins" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html(AKSRT_Settings::get_currency_name()); ?></span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if ($affiliate_enabled) : ?>
|
||||
<button type="button" class="uc-sidebar__btn" data-tab="credits">
|
||||
<i class="fas fa-share-alt" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('推广返佣', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 功能设置 -->
|
||||
<!-- 移动端抽屉触发器 -->
|
||||
<button type="button" class="uc-sidebar__drawer-trigger" id="uc-drawer-trigger" aria-label="<?php esc_attr_e( '打开导航', 'aksrt' ); ?>">
|
||||
<i class="fas fa-bars" aria-hidden="true"></i>
|
||||
</button>
|
||||
</aside>
|
||||
|
||||
<!-- 右侧内容区 -->
|
||||
<div class="uc-content">
|
||||
<!-- 移动端抽屉遮罩 -->
|
||||
<div class="uc-drawer-overlay" id="uc-drawer-overlay"></div>
|
||||
|
||||
<!-- 面板内容 -->
|
||||
<div class="dashboard-tabs uc-mobile-tabs" role="tablist">
|
||||
<?php foreach ( $dashboard_tabs as $tab_key => $tab ) : ?>
|
||||
<button type="button" class="<?php echo $active_tab === $tab_key ? 'is-active' : ''; ?>" data-tab="<?php echo esc_attr( $tab_key ); ?>" role="tab"><?php echo esc_html( $tab['label'] ); ?></button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php
|
||||
$show_credit_tabs = class_exists( 'AKSRT_Settings' ) && AKSRT_Settings::credits_enabled();
|
||||
$show_invite_section = $show_credit_tabs && class_exists( 'AKSRT_Settings' ) && AKSRT_Settings::invite_enabled() && AKSRT_Settings::invite_registration_enabled();
|
||||
$currency_name = $show_credit_tabs ? AKSRT_Settings::get_currency_name() : __( '积分', 'aksrt' );
|
||||
?>
|
||||
|
||||
<!-- ==================== 个人信息(可编辑) ==================== -->
|
||||
<div id="panel-profile" class="dashboard-panel<?php echo 'profile' === $active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'profile' !== $active_tab ? ' hidden' : ''; ?>>
|
||||
<form class="profile-form" id="profile-form" method="post">
|
||||
<?php wp_nonce_field( 'aksrt_profile_save', '_profile_nonce' ); ?>
|
||||
<input type="hidden" name="action" value="aksrt_save_profile">
|
||||
|
||||
<!-- 昵称 -->
|
||||
<div class="widget-card">
|
||||
<h3 class="widget-title"><?php esc_html_e( '昵称', 'aksrt' ); ?></h3>
|
||||
<input type="text" name="nickname" id="profile-nickname"
|
||||
value="<?php echo esc_attr( $target_user->display_name ); ?>"
|
||||
class="profile-input" maxlength="50" required>
|
||||
<p class="profile-hint"><?php esc_html_e( '修改后会同步更新个人主页地址', 'aksrt' ); ?></p>
|
||||
</div>
|
||||
|
||||
<!-- 个人简介 -->
|
||||
<div class="widget-card">
|
||||
<h3 class="widget-title"><?php esc_html_e( '个人简介', 'aksrt' ); ?></h3>
|
||||
<textarea name="description" id="profile-bio" class="profile-input profile-textarea"
|
||||
rows="4" maxlength="500" placeholder="<?php esc_attr_e( '介绍一下自己…', 'aksrt' ); ?>"><?php echo esc_textarea( $target_user->description ); ?></textarea>
|
||||
<p class="profile-hint"><?php esc_html_e( '显示在你的公开用户主页上,最多 500 字', 'aksrt' ); ?></p>
|
||||
</div>
|
||||
|
||||
<?php if ( ! empty( $user_center_settings['social_links'] ) ) : ?>
|
||||
<!-- 联系方式 -->
|
||||
<div class="widget-card">
|
||||
<h3 class="widget-title"><?php esc_html_e( '联系方式', 'aksrt' ); ?></h3>
|
||||
<p class="profile-hint profile-hint--top"><?php esc_html_e( '添加你的社交链接,显示在公开用户主页', 'aksrt' ); ?></p>
|
||||
<div id="contacts-list">
|
||||
<?php foreach ( $user_contacts as $i => $contact ) : ?>
|
||||
<div class="contact-row" data-index="<?php echo (int) $i; ?>">
|
||||
<select name="contacts[<?php echo (int) $i; ?>][icon]" class="profile-input contact-icon">
|
||||
<?php echo aksrt_contact_icon_options( $contact['icon'] ?? '' ); ?>
|
||||
</select>
|
||||
<input type="hidden" name="contacts[<?php echo (int) $i; ?>][name]" value="">
|
||||
<input type="url" name="contacts[<?php echo (int) $i; ?>][url]"
|
||||
value="<?php echo esc_url( $contact['url'] ?? '' ); ?>"
|
||||
class="profile-input contact-url" placeholder="<?php esc_attr_e( '链接 URL', 'aksrt' ); ?>">
|
||||
<button type="button" class="contact-remove" onclick="this.parentElement.remove()" title="<?php esc_attr_e( '删除', 'aksrt' ); ?>">×</button>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<button type="button" class="btn-ghost btn-sm profile-add-contact" id="add-contact-btn">+ <?php esc_html_e( '添加联系方式', 'aksrt' ); ?></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 保存按钮 -->
|
||||
<div class="profile-form__submit">
|
||||
<button type="submit" class="btn-primary btn-lg" id="profile-save-btn">
|
||||
<?php esc_html_e( '保存修改', 'aksrt' ); ?>
|
||||
</button>
|
||||
<span id="profile-save-msg" class="profile-form__submit-msg"></span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 我的文章 ==================== -->
|
||||
<div id="panel-posts" class="dashboard-panel<?php echo 'posts' === $active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'posts' !== $active_tab ? ' hidden' : ''; ?>>
|
||||
<div class="widget-card">
|
||||
<div class="profile-list-header">
|
||||
<h3 class="widget-title widget-title--inline">
|
||||
<?php
|
||||
/* translators: %d: post count */
|
||||
printf( esc_html__( '我的文章(%d 篇)', 'aksrt' ), $post_count );
|
||||
?>
|
||||
</h3>
|
||||
<?php
|
||||
$status_chip_defs = [
|
||||
'publish' => __( '已发布', 'aksrt' ),
|
||||
'draft' => __( '草稿', 'aksrt' ),
|
||||
'pending' => __( '待审', 'aksrt' ),
|
||||
'private' => __( '私密', 'aksrt' ),
|
||||
'all' => __( '全部', 'aksrt' ),
|
||||
];
|
||||
?>
|
||||
<div class="profile-status-filter" role="tablist" aria-label="<?php esc_attr_e( '文章状态筛选', 'aksrt' ); ?>">
|
||||
<?php foreach ( $status_chip_defs as $status_key => $status_text ) :
|
||||
$count_for_chip = ( 'all' === $status_key )
|
||||
? $post_count
|
||||
: ( $user_status_counts[ $status_key ] ?? 0 );
|
||||
if ( 'publish' !== $status_key && 'all' !== $status_key && $count_for_chip < 1 ) {
|
||||
continue;
|
||||
}
|
||||
$chip_url = add_query_arg( [
|
||||
'tab' => 'posts',
|
||||
'post_status' => $status_key,
|
||||
'posts_page' => 1,
|
||||
], remove_query_arg( [ 'posts_page' ] ) );
|
||||
$chip_active = ( $post_status_filter === $status_key );
|
||||
?>
|
||||
<a href="<?php echo esc_url( $chip_url ); ?>" class="profile-status-chip<?php echo $chip_active ? ' is-active' : ''; ?>" role="tab" aria-selected="<?php echo $chip_active ? 'true' : 'false'; ?>">
|
||||
<?php echo esc_html( $status_text ); ?>
|
||||
<span class="profile-status-chip__count"><?php echo esc_html( (string) $count_for_chip ); ?></span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$ps_args = [
|
||||
'author' => $user_id,
|
||||
'post_status' => ( 'all' === $post_status_filter )
|
||||
? [ 'publish', 'draft', 'pending', 'private' ]
|
||||
: $post_status_filter,
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $posts_page,
|
||||
'no_found_rows' => false,
|
||||
'update_post_meta_cache' => false,
|
||||
'update_post_term_cache' => true,
|
||||
];
|
||||
$q = new WP_Query( $ps_args );
|
||||
if ( $q->have_posts() ) : ?>
|
||||
<div class="profile-list">
|
||||
<?php while ( $q->have_posts() ) : $q->the_post();
|
||||
$st = get_post_status();
|
||||
$status_label = '';
|
||||
if ( 'publish' !== $st ) {
|
||||
$st_map = [
|
||||
'draft' => __( '草稿', 'aksrt' ),
|
||||
'pending' => __( '待审', 'aksrt' ),
|
||||
'private' => __( '私密', 'aksrt' ),
|
||||
'future' => __( '定时', 'aksrt' ),
|
||||
];
|
||||
$status_label = $st_map[ $st ] ?? $st;
|
||||
}
|
||||
set_query_var( 'aksrt_profile_item_status', $status_label );
|
||||
|
||||
$edit_link = get_edit_post_link();
|
||||
set_query_var( 'aksrt_profile_item_action', $edit_link ? [
|
||||
'type' => 'edit',
|
||||
'url' => $edit_link,
|
||||
'label' => __( '编辑', 'aksrt' ),
|
||||
] : [] );
|
||||
|
||||
get_template_part( 'templates/parts/content', 'profile-list-item' );
|
||||
endwhile; ?>
|
||||
</div>
|
||||
<?php aksrt_render_profile_pagination( (int) $q->max_num_pages, $posts_page, 'posts_page' ); ?>
|
||||
<?php
|
||||
wp_reset_postdata();
|
||||
set_query_var( 'aksrt_profile_item_action', [] );
|
||||
set_query_var( 'aksrt_profile_item_status', '' );
|
||||
else :
|
||||
aksrt_render_profile_empty(
|
||||
$svg_empty_post,
|
||||
__( '还没有文章', 'aksrt' ),
|
||||
__( '试试发布你的第一篇文章吧。', 'aksrt' ),
|
||||
admin_url( 'post-new.php' ),
|
||||
__( '写文章', 'aksrt' )
|
||||
);
|
||||
endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 我的评论 ==================== -->
|
||||
<div id="panel-comments" class="dashboard-panel<?php echo 'comments' === $active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'comments' !== $active_tab ? ' hidden' : ''; ?>>
|
||||
<div class="widget-card">
|
||||
<div class="profile-list-header">
|
||||
<h3 class="widget-title widget-title--inline">
|
||||
<?php printf( esc_html__( '我的评论(%d 条)', 'aksrt' ), $comment_count ); ?>
|
||||
</h3>
|
||||
</div>
|
||||
<?php
|
||||
$comments_total = $comment_count;
|
||||
$cs = get_comments( [
|
||||
'user_id' => $user_id,
|
||||
'number' => $per_page,
|
||||
'offset' => ( $comments_page - 1 ) * $per_page,
|
||||
'status' => 'approve',
|
||||
'update_comment_meta_cache' => false,
|
||||
] );
|
||||
if ( $cs ) : ?>
|
||||
<div class="profile-comment-list">
|
||||
<?php foreach ( $cs as $c ) :
|
||||
set_query_var( 'aksrt_profile_comment', $c );
|
||||
get_template_part( 'templates/parts/content', 'profile-comment-item' );
|
||||
endforeach;
|
||||
set_query_var( 'aksrt_profile_comment', null ); ?>
|
||||
</div>
|
||||
<?php
|
||||
$comments_total_pages = (int) ceil( $comments_total / $per_page );
|
||||
aksrt_render_profile_pagination( $comments_total_pages, $comments_page, 'comments_page' );
|
||||
?>
|
||||
<?php else :
|
||||
aksrt_render_profile_empty(
|
||||
$svg_empty_comment,
|
||||
__( '暂无评论', 'aksrt' ),
|
||||
__( '在你感兴趣的文章下留下你的看法吧。', 'aksrt' )
|
||||
);
|
||||
endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 我的收藏 ==================== -->
|
||||
<div id="panel-favorites" class="dashboard-panel<?php echo 'favorites' === $active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'favorites' !== $active_tab ? ' hidden' : ''; ?>>
|
||||
<div class="widget-card">
|
||||
<div class="profile-list-header">
|
||||
<h3 class="widget-title widget-title--inline">
|
||||
<?php printf( esc_html__( '我的收藏(%d 篇)', 'aksrt' ), $favorite_count ); ?>
|
||||
</h3>
|
||||
</div>
|
||||
<?php if ( ! empty( $favorite_post_ids ) ) :
|
||||
$favorites_query = new WP_Query( [
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'post__in' => $favorite_post_ids,
|
||||
'orderby' => 'post__in',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $favorites_page,
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => false,
|
||||
'update_post_meta_cache' => false,
|
||||
] );
|
||||
if ( $favorites_query->have_posts() ) : ?>
|
||||
<div class="profile-list" data-list="favorites">
|
||||
<?php while ( $favorites_query->have_posts() ) : $favorites_query->the_post();
|
||||
set_query_var( 'aksrt_profile_item_action', [
|
||||
'type' => 'unfavorite',
|
||||
'url' => '#',
|
||||
'label' => __( '取消收藏', 'aksrt' ),
|
||||
] );
|
||||
set_query_var( 'aksrt_profile_item_status', '' );
|
||||
get_template_part( 'templates/parts/content', 'profile-list-item' );
|
||||
endwhile; ?>
|
||||
</div>
|
||||
<?php aksrt_render_profile_pagination( (int) $favorites_query->max_num_pages, $favorites_page, 'favorites_page' ); ?>
|
||||
<?php
|
||||
wp_reset_postdata();
|
||||
set_query_var( 'aksrt_profile_item_action', [] );
|
||||
else :
|
||||
aksrt_render_profile_empty(
|
||||
$svg_empty_favorite,
|
||||
__( '收藏列表为空', 'aksrt' ),
|
||||
__( '点击文章页面的星标收藏喜欢的内容。', 'aksrt' ),
|
||||
home_url( '/' ),
|
||||
__( '去发现好文', 'aksrt' )
|
||||
);
|
||||
endif;
|
||||
else :
|
||||
aksrt_render_profile_empty(
|
||||
$svg_empty_favorite,
|
||||
__( '收藏列表为空', 'aksrt' ),
|
||||
__( '点击文章页面的星标收藏喜欢的内容。', 'aksrt' ),
|
||||
home_url( '/' ),
|
||||
__( '去发现好文', 'aksrt' )
|
||||
);
|
||||
endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$balance = function_exists( 'aksrt_user_credits' ) ? aksrt_user_credits( $user_id ) : 0;
|
||||
$currency_name = class_exists( 'AKSRT_Settings' ) ? AKSRT_Settings::get_currency_name() : __( '积分', 'aksrt' );
|
||||
$credits_enabled = class_exists( 'AKSRT_Settings' ) && AKSRT_Settings::credits_enabled();
|
||||
$vip_settings = class_exists( 'AKSRT_Settings' ) ? AKSRT_Settings::get_payment_vip_settings() : [];
|
||||
$show_vip_card = ! empty( $vip_settings['enabled'] );
|
||||
$is_vip_user = function_exists( 'aksrt_is_vip' ) && aksrt_is_vip( $user_id );
|
||||
$vip_badge_text = function_exists( 'aksrt_get_vip_badge_text' ) ? aksrt_get_vip_badge_text() : 'VIP';
|
||||
?>
|
||||
<!-- ==================== 账户余额 ==================== -->
|
||||
<div id="panel-credits" class="dashboard-panel<?php echo 'credits' === $active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'credits' !== $active_tab ? ' hidden' : ''; ?>>
|
||||
|
||||
<!-- 余额卡片 -->
|
||||
<div class="uc-balance-card">
|
||||
<div class="uc-balance-card__bg"></div>
|
||||
<div class="uc-balance-card__content">
|
||||
<div class="uc-balance-card__header">
|
||||
<span class="uc-balance-card__label"><?php esc_html_e( '账户余额', 'aksrt' ); ?></span>
|
||||
<span class="uc-balance-card__currency"><?php echo esc_html( $currency_name ); ?></span>
|
||||
</div>
|
||||
<div class="uc-balance-card__amount">
|
||||
<span class="uc-balance-card__value"><?php echo esc_html( aksrt_format_credits( $balance ) ); ?></span>
|
||||
</div>
|
||||
<?php if ( $credits_enabled ) : ?>
|
||||
<div class="uc-balance-card__actions" data-aksrt-signin>
|
||||
<span class="uc-balance-card__sign-status" data-signin-status></span>
|
||||
<button type="button" class="uc-balance-card__sign-btn" data-signin-btn disabled>
|
||||
<i class="fas fa-calendar-check" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e( '签到', 'aksrt' ); ?></span>
|
||||
</button>
|
||||
</div>
|
||||
<p class="uc-balance-card__tip" data-signin-tip></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ( $show_vip_card ) : ?>
|
||||
<!-- VIP 会员卡片 -->
|
||||
<div class="uc-vip-card<?php echo $is_vip_user ? ' uc-vip-card--active' : ''; ?>">
|
||||
<div class="uc-vip-card__bg"></div>
|
||||
<div class="uc-vip-card__content">
|
||||
<div class="uc-vip-card__header">
|
||||
<div class="uc-vip-card__icon">
|
||||
<i class="fas fa-crown" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="uc-vip-card__info">
|
||||
<span class="uc-vip-card__label"><?php echo esc_html( $vip_settings['name'] ?? __( 'VIP会员', 'aksrt' ) ); ?></span>
|
||||
<?php if ( $is_vip_user ) : ?>
|
||||
<span class="uc-vip-card__status uc-vip-card__status--active"><?php esc_html_e( '已开通', 'aksrt' ); ?></span>
|
||||
<?php else : ?>
|
||||
<span class="uc-vip-card__status"><?php esc_html_e( '未开通', 'aksrt' ); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ( $is_vip_user ) : ?>
|
||||
<div class="uc-vip-card__benefits">
|
||||
<span class="uc-vip-card__benefit"><i class="fas fa-download" aria-hidden="true"></i> <?php esc_html_e( '免费下载', 'aksrt' ); ?></span>
|
||||
<span class="uc-vip-card__benefit"><i class="fas fa-crown" aria-hidden="true"></i> <?php esc_html_e( '专属身份', 'aksrt' ); ?></span>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="uc-vip-card__benefits">
|
||||
<span class="uc-vip-card__benefit"><i class="fas fa-download" aria-hidden="true"></i> <?php esc_html_e( '解锁免费下载', 'aksrt' ); ?></span>
|
||||
<span class="uc-vip-card__benefit"><i class="fas fa-tag" aria-hidden="true"></i> <?php esc_html_e( '享专属折扣', 'aksrt' ); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! $is_vip_user ) : ?>
|
||||
<a href="<?php echo esc_url( aksrt_get_user_center_url( 'credits' ) ); ?>" class="uc-vip-card__btn">
|
||||
<?php esc_html_e( '立即开通', 'aksrt' ); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $credits_enabled && function_exists('aksrt_is_captcha_enabled_for') && aksrt_is_captcha_enabled_for('signin') ) : ?>
|
||||
<div class="aksrt-signin-captcha" data-signin-captcha style="margin-bottom:16px;">
|
||||
<?php aksrt_render_captcha('signin'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
// 签到日历可视化
|
||||
$signin_dates = [];
|
||||
if ($credits_enabled && class_exists('AKSRT_Signin')) {
|
||||
$signin_log = AKSRT_Signin::get_instance()->get_recent_signins($user_id, 30);
|
||||
$signin_dates = array_map(function ($entry) {
|
||||
return $entry['signin_date'] ?? '';
|
||||
}, $signin_log);
|
||||
$signin_dates = array_filter($signin_dates);
|
||||
}
|
||||
?>
|
||||
<?php if (!empty($signin_dates)) : ?>
|
||||
@@ -0,0 +1,403 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
<div class="uc-signin-calendar" style="margin-bottom:16px;">
|
||||
<h4 class="uc-signin-calendar__title">
|
||||
<i class="fas fa-calendar-alt" aria-hidden="true"></i>
|
||||
<?php esc_html_e('最近 30 天签到', 'aksrt'); ?>
|
||||
</h4>
|
||||
<div data-aksrt-signin-calendar='<?php echo esc_attr(wp_json_encode(array_values($signin_dates))); ?>'></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 积分流水 -->
|
||||
<div class="uc-transactions">
|
||||
<div class="uc-transactions__header">
|
||||
<h3 class="uc-transactions__title">
|
||||
<i class="fas fa-list-ul" aria-hidden="true"></i>
|
||||
<?php echo esc_html( sprintf( __( '%s明细', 'aksrt' ), $currency_name ) ); ?>
|
||||
</h3>
|
||||
</div>
|
||||
<?php
|
||||
$credits_page = max(1, isset($_GET['credits_page']) ? (int) $_GET['credits_page'] : 1);
|
||||
if ( class_exists( 'AKSRT_Credits' ) ) {
|
||||
$log = AKSRT_Credits::get_log( [ 'user_id' => $user_id, 'page' => $credits_page, 'per_page' => 10 ] );
|
||||
} else {
|
||||
$log = [ 'items' => [], 'total' => 0 ];
|
||||
}
|
||||
if ( ! empty( $log['items'] ) ) :
|
||||
?>
|
||||
<div class="uc-transactions__list">
|
||||
<?php foreach ( $log['items'] as $row ) :
|
||||
$delta = (int) $row['delta'];
|
||||
$delta_class = $delta >= 0 ? 'is-positive' : 'is-negative';
|
||||
?>
|
||||
<div class="uc-transactions__item">
|
||||
<div class="uc-transactions__icon <?php echo esc_attr( $delta_class ); ?>">
|
||||
<i class="fas fa-<?php echo $delta >= 0 ? 'arrow-up' : 'arrow-down'; ?>" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="uc-transactions__info">
|
||||
<div class="uc-transactions__reason">
|
||||
<?php echo esc_html( aksrt_credits_label( (string) $row['reason'] ) ); ?>
|
||||
<?php if ( ! empty( $row['remark'] ) ) : ?>
|
||||
<span class="uc-transactions__remark">(<?php echo esc_html( (string) $row['remark'] ); ?>)</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="uc-transactions__time">
|
||||
<?php echo esc_html( get_date_from_gmt( (string) $row['created_at'], 'Y-m-d H:i' ) ); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uc-transactions__amount">
|
||||
<span class="uc-transactions__delta <?php echo esc_attr( $delta_class ); ?>">
|
||||
<?php echo esc_html( ( $delta > 0 ? '+' : '' ) . $delta ); ?>
|
||||
</span>
|
||||
<span class="uc-transactions__balance">
|
||||
<?php
|
||||
/* translators: %s: 余额 */
|
||||
printf( esc_html__( '余额 %s', 'aksrt' ), esc_html( (string) (int) $row['balance_after'] ) );
|
||||
?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php
|
||||
$total_pages = (int) ceil( (int) ($log['total'] ?? 0) / 10 );
|
||||
if ( $total_pages > 1 ) {
|
||||
aksrt_render_profile_pagination( $total_pages, $credits_page, 'credits_page' );
|
||||
}
|
||||
?>
|
||||
<?php else : ?>
|
||||
<div class="uc-transactions__empty">
|
||||
<div class="uc-transactions__empty-icon">
|
||||
<i class="fas fa-receipt" aria-hidden="true"></i>
|
||||
</div>
|
||||
<p><?php echo esc_html( sprintf( __( '还没有任何%s流水', 'aksrt' ), $currency_name ) ); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 账号设置 ==================== -->
|
||||
<div id="panel-settings" class="dashboard-panel<?php echo 'settings' === $active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'settings' !== $active_tab ? ' hidden' : ''; ?>>
|
||||
<?php
|
||||
$oauth = AKSRT_OAuth::get_instance();
|
||||
$oauth_data = $oauth->get_frontend_bindings_data($user_id);
|
||||
$user_email = $target_user->user_email ?: '';
|
||||
$binding_name_map = [
|
||||
'github' => 'GitHub',
|
||||
'gitee' => 'Gitee',
|
||||
'qq' => 'QQ',
|
||||
'google' => 'Google',
|
||||
];
|
||||
$binding_rows = [];
|
||||
foreach ( (array) ( $oauth_data['bindings'] ?? [] ) as $binding ) {
|
||||
$key = $binding['key'] ?? '';
|
||||
if ( ! $key ) continue;
|
||||
$binding_rows[ $key ] = [
|
||||
'key' => $key,
|
||||
'name' => $binding_name_map[ $key ] ?? ( $binding['name'] ?? ucfirst( $key ) ),
|
||||
'icon' => $binding['icon'] ?? '',
|
||||
'is_bound' => true,
|
||||
'url' => '',
|
||||
];
|
||||
}
|
||||
foreach ( (array) ( $oauth_data['available'] ?? [] ) as $binding ) {
|
||||
$key = $binding['key'] ?? '';
|
||||
if ( ! $key ) continue;
|
||||
$binding_rows[ $key ] = [
|
||||
'key' => $key,
|
||||
'name' => $binding_name_map[ $key ] ?? ( $binding['name'] ?? ucfirst( $key ) ),
|
||||
'icon' => $binding['icon'] ?? '',
|
||||
'is_bound' => false,
|
||||
'url' => $binding['url'] ?? '',
|
||||
];
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- 第三方绑定区域 -->
|
||||
<div class="settings-section">
|
||||
<div class="settings-section__header">
|
||||
<span class="settings-icon"><i class="fas fa-link" aria-hidden="true"></i></span>
|
||||
<h3 class="widget-title settings-section__title"><?php esc_html_e( '社交账号绑定', 'aksrt' ); ?></h3>
|
||||
</div>
|
||||
|
||||
<?php if ( ! empty( $binding_rows ) ) : ?>
|
||||
<p class="settings-hint settings-hint--top"><?php esc_html_e( '点击下方按钮管理第三方账号绑定状态:', 'aksrt' ); ?></p>
|
||||
<div class="binding-list">
|
||||
<?php foreach ( $binding_rows as $binding ) : ?>
|
||||
<?php if ( ! empty( $binding['is_bound'] ) ) : ?>
|
||||
<div class="binding-item">
|
||||
<span class="binding-item__icon"><?php echo $binding['icon']; ?></span>
|
||||
<span class="binding-item__meta">
|
||||
<span class="binding-status">
|
||||
<i class="fas fa-check-circle badge__icon" aria-hidden="true"></i>
|
||||
<?php esc_html_e( '已绑定', 'aksrt' ); ?>
|
||||
</span>
|
||||
<span class="binding-item__name"><?php echo esc_html( $binding['name'] ); ?></span>
|
||||
</span>
|
||||
<button type="button" class="binding-unbind-btn" data-provider="<?php echo esc_attr( $binding['key'] ); ?>">
|
||||
<?php esc_html_e( '解绑', 'aksrt' ); ?>
|
||||
</button>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url( $binding['url'] ); ?>" class="binding-item binding-item--linkable" target="_self">
|
||||
<span class="binding-item__icon"><?php echo $binding['icon']; ?></span>
|
||||
<span class="binding-item__meta">
|
||||
<span class="binding-status binding-status--idle"><?php esc_html_e( '未绑定', 'aksrt' ); ?></span>
|
||||
<span class="binding-item__name"><?php echo esc_html( $binding['name'] ); ?></span>
|
||||
</span>
|
||||
<span class="badge badge--bind"><?php esc_html_e( '绑定', 'aksrt' ); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p class="settings-empty"><?php esc_html_e( '暂无可用的第三方登录服务', 'aksrt' ); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- 安全设置区域 -->
|
||||
<div class="settings-section">
|
||||
<div class="settings-section__header">
|
||||
<span class="settings-icon"><i class="fas fa-lock" aria-hidden="true"></i></span>
|
||||
<h3 class="widget-title settings-section__title"><?php esc_html_e( '安全设置', 'aksrt' ); ?></h3>
|
||||
</div>
|
||||
<div class="security-actions">
|
||||
<!-- 修改密码 -->
|
||||
<div class="security-action-item">
|
||||
<div class="security-action-info">
|
||||
<span class="security-action-icon"><i class="fas fa-lock" aria-hidden="true"></i></span>
|
||||
<div class="security-action-text">
|
||||
<span class="security-action-title"><?php esc_html_e( '修改密码', 'aksrt' ); ?></span>
|
||||
<span class="security-action-desc"><?php esc_html_e( '通过邮箱验证码验证后可更改登录密码', 'aksrt' ); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn-primary btn-sm security-trigger" data-modal="pwd-modal">
|
||||
<?php esc_html_e( '修改', 'aksrt' ); ?>
|
||||
</button>
|
||||
</div>
|
||||
<!-- 更改邮箱 -->
|
||||
<div class="security-action-item">
|
||||
<div class="security-action-info">
|
||||
<span class="security-action-icon"><i class="far fa-envelope" aria-hidden="true"></i></span>
|
||||
<div class="security-action-text">
|
||||
<span class="security-action-title"><?php esc_html_e( '更改邮箱', 'aksrt' ); ?></span>
|
||||
<span class="security-action-desc"><?php esc_html_e( '更新用于接收通知和找回密码的邮箱地址', 'aksrt' ); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn-primary btn-sm security-trigger" data-modal="email-modal">
|
||||
<?php esc_html_e( '更改', 'aksrt' ); ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ( $show_invite_section ) : ?>
|
||||
<div class="settings-section">
|
||||
<div class="settings-section__header">
|
||||
<span class="settings-icon"><i class="fas fa-user-plus" aria-hidden="true"></i></span>
|
||||
<h3 class="widget-title settings-section__title"><?php esc_html_e( '邀请好友', 'aksrt' ); ?></h3>
|
||||
</div>
|
||||
<div class="aksrt-invite-panel" data-aksrt-invite>
|
||||
<div class="aksrt-invite-hero">
|
||||
<div class="aksrt-invite-hero__main">
|
||||
<span class="aksrt-invite-kicker"><?php esc_html_e( '邀请奖励', 'aksrt' ); ?></span>
|
||||
<p class="aksrt-invite-desc">
|
||||
<?php echo esc_html( sprintf( __( '将专属链接分享给好友,好友完成注册与验证后即可获得双向%s奖励。', 'aksrt' ), $currency_name ) ); ?>
|
||||
</p>
|
||||
</div>
|
||||
<div class="aksrt-invite-code-card">
|
||||
<span><?php esc_html_e( '邀请码', 'aksrt' ); ?></span>
|
||||
<strong data-invite-code>--</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-invite-link-row">
|
||||
<input type="text" class="aksrt-invite-link" data-invite-link readonly value="" aria-label="<?php esc_attr_e( '邀请链接', 'aksrt' ); ?>">
|
||||
<button type="button" class="btn-primary btn-sm aksrt-invite-copy" data-invite-copy>
|
||||
<i class="fas fa-copy" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e( '复制链接', 'aksrt' ); ?></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="aksrt-invite-stats" data-invite-stats>
|
||||
<div class="aksrt-invite-stat">
|
||||
<span><?php esc_html_e( '已注册', 'aksrt' ); ?></span>
|
||||
<strong data-stat="registered">0</strong>
|
||||
<small><?php esc_html_e( '通过链接完成注册', 'aksrt' ); ?></small>
|
||||
</div>
|
||||
<div class="aksrt-invite-stat">
|
||||
<span><?php esc_html_e( '已验证', 'aksrt' ); ?></span>
|
||||
<strong data-stat="verified">0</strong>
|
||||
<small><?php esc_html_e( '完成邮箱验证', 'aksrt' ); ?></small>
|
||||
</div>
|
||||
<div class="aksrt-invite-stat">
|
||||
<span><?php esc_html_e( '已奖励', 'aksrt' ); ?></span>
|
||||
<strong data-stat="rewarded">0</strong>
|
||||
<small><?php esc_html_e( '奖励已发放', 'aksrt' ); ?></small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-invite-records">
|
||||
<div class="aksrt-invite-records__header">
|
||||
<h4><?php esc_html_e( '邀请记录', 'aksrt' ); ?></h4>
|
||||
<span data-invite-total><?php esc_html_e( '加载中', 'aksrt' ); ?></span>
|
||||
</div>
|
||||
<div class="aksrt-invite-record-list is-loading" data-invite-list>
|
||||
<div class="aksrt-invite-record-empty">
|
||||
<?php esc_html_e( '正在加载邀请记录...', 'aksrt' ); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 隐藏字段 -->
|
||||
<input type="hidden" id="aksrt-settings-nonce" value="<?php echo wp_create_nonce( 'aksrt_account_settings' ); ?>">
|
||||
<input type="hidden" id="aksrt-oauth-unbind-nonce" value="<?php echo wp_create_nonce( 'aksrt_oauth_unbind' ); ?>">
|
||||
<input type="hidden" id="aksrt-user-email" value="<?php echo esc_attr( $user_email ); ?>">
|
||||
<input type="hidden" id="aksrt-ajax-url" value="<?php echo admin_url( 'admin-ajax.php' ); ?>">
|
||||
<input type="hidden" id="aksrt-login-url" value="<?php echo esc_attr( aksrt_get_login_url() ); ?>">
|
||||
<input type="hidden" id="aksrt-public-nonce" value="<?php echo wp_create_nonce( 'aksrt_public_nonce' ); ?>">
|
||||
</div>
|
||||
|
||||
<!-- ==================== 修改密码弹窗 ==================== -->
|
||||
<div id="pwd-modal" class="aksrt-modal" role="dialog" aria-modal="true" aria-label="<?php esc_attr_e( '修改密码', 'aksrt' ); ?>">
|
||||
<div class="aksrt-modal__overlay" data-close-modal></div>
|
||||
<div class="aksrt-modal__box">
|
||||
<div class="aksrt-modal__header">
|
||||
<div class="aksrt-modal__title-wrap">
|
||||
<span class="aksrt-modal__icon"><i class="fas fa-lock" aria-hidden="true"></i></span>
|
||||
<h4><?php esc_html_e( '修改密码', 'aksrt' ); ?></h4>
|
||||
</div>
|
||||
<button type="button" class="aksrt-modal__close" data-close-modal title="<?php esc_attr_e( '关闭', 'aksrt' ); ?>"><i class="fas fa-times" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
<form id="pwd-form" autocomplete="off" novalidate>
|
||||
<div class="modal-field">
|
||||
<label for="pwd-old"><?php esc_html_e( '原密码', 'aksrt' ); ?></label>
|
||||
<input type="password" id="pwd-old" name="old_password" required minlength="1">
|
||||
<button type="button" class="toggle-pwd" data-target="pwd-old"></button>
|
||||
</div>
|
||||
<div class="modal-field">
|
||||
<label for="pwd-new"><?php esc_html_e( '新密码', 'aksrt' ); ?></label>
|
||||
<input type="password" id="pwd-new" name="new_password" required minlength="6" placeholder="<?php esc_attr_e( '至少6位字符', 'aksrt' ); ?>">
|
||||
<button type="button" class="toggle-pwd" data-target="pwd-new"></button>
|
||||
<div class="pwd-strength" id="pwd-strength-bar">
|
||||
<div class="pwd-strength__fill"></div>
|
||||
</div>
|
||||
<span class="pwd-strength__text" id="pwd-strength-text"></span>
|
||||
</div>
|
||||
<div class="modal-field">
|
||||
<label for="pwd-new-confirm"><?php esc_html_e( '确认新密码', 'aksrt' ); ?></label>
|
||||
<input type="password" id="pwd-new-confirm" name="new_password_confirm" required minlength="6" placeholder="<?php esc_attr_e( '再次输入新密码', 'aksrt' ); ?>">
|
||||
<button type="button" class="toggle-pwd" data-target="pwd-new-confirm"></button>
|
||||
</div>
|
||||
<div class="modal-field modal-field--code">
|
||||
<label for="pwd-code"><?php esc_html_e( '当前邮箱验证码', 'aksrt' ); ?></label>
|
||||
<div class="code-input-group">
|
||||
<input type="text" id="pwd-code" name="email_code" maxlength="6" inputmode="numeric" pattern="[0-9]*" placeholder="6位数字验证码" required>
|
||||
<button type="button" class="btn-ghost btn-sm code-send-btn" id="pwd-send-code"><?php esc_html_e( '发送到当前邮箱', 'aksrt' ); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php aksrt_render_captcha('change_password'); ?>
|
||||
|
||||
<div class="aksrt-modal__footer">
|
||||
<button type="button" class="btn-ghost btn-sm" data-close-modal><?php esc_html_e( '取消', 'aksrt' ); ?></button>
|
||||
<button type="submit" class="btn-primary btn-sm" id="pwd-submit"><?php esc_html_e( '确认修改', 'aksrt' ); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 更改邮箱弹窗 ==================== -->
|
||||
<div id="email-modal" class="aksrt-modal" role="dialog" aria-modal="true" aria-label="<?php esc_attr_e( '更改邮箱', 'aksrt' ); ?>">
|
||||
<div class="aksrt-modal__overlay" data-close-modal></div>
|
||||
<div class="aksrt-modal__box">
|
||||
<div class="aksrt-modal__header">
|
||||
<div class="aksrt-modal__title-wrap">
|
||||
<span class="aksrt-modal__icon"><i class="far fa-envelope" aria-hidden="true"></i></span>
|
||||
<h4><?php esc_html_e( '更改邮箱', 'aksrt' ); ?></h4>
|
||||
</div>
|
||||
<button type="button" class="aksrt-modal__close" data-close-modal title="<?php esc_attr_e( '关闭', 'aksrt' ); ?>"><i class="fas fa-times" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
<form id="email-form" autocomplete="off" novalidate>
|
||||
<div class="modal-field">
|
||||
<label><?php esc_html_e( '当前邮箱', 'aksrt' ); ?></label>
|
||||
<div class="readonly-display"><?php echo esc_html( $user_email ); ?></div>
|
||||
</div>
|
||||
<div class="modal-field">
|
||||
<label for="email-current-password"><?php esc_html_e( '当前密码', 'aksrt' ); ?></label>
|
||||
<input type="password" id="email-current-password" name="current_password" required minlength="1" placeholder="<?php esc_attr_e( '请输入当前登录密码', 'aksrt' ); ?>">
|
||||
<button type="button" class="toggle-pwd" data-target="email-current-password"></button>
|
||||
</div>
|
||||
<div class="modal-field">
|
||||
<label for="email-new"><?php esc_html_e( '新邮箱', 'aksrt' ); ?></label>
|
||||
<input type="email" id="email-new" name="new_email" required placeholder="<?php esc_attr_e( '请输入新的邮箱地址', 'aksrt' ); ?>">
|
||||
</div>
|
||||
<div class="modal-field modal-field--code">
|
||||
<label for="email-code"><?php esc_html_e( '新邮箱验证码', 'aksrt' ); ?></label>
|
||||
<div class="code-input-group">
|
||||
<input type="text" id="email-code" name="email_code" maxlength="6" inputmode="numeric" pattern="[0-9]*" placeholder="6位数字验证码" required>
|
||||
<button type="button" class="btn-ghost btn-sm code-send-btn" id="email-send-code"><?php esc_html_e( '发送到新邮箱', 'aksrt' ); ?></button>
|
||||
</div>
|
||||
<p class="settings-hint settings-hint--bottom"><?php esc_html_e( '验证码将发送到你填写的新邮箱,验证通过后才会正式切换。', 'aksrt' ); ?></p>
|
||||
</div>
|
||||
|
||||
<?php aksrt_render_captcha('change_email'); ?>
|
||||
|
||||
<div class="aksrt-modal__footer">
|
||||
<button type="button" class="btn-ghost btn-sm" data-close-modal><?php esc_html_e( '取消', 'aksrt' ); ?></button>
|
||||
<button type="submit" class="btn-primary btn-sm" id="email-submit"><?php esc_html_e( '确认更改', 'aksrt' ); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.uc-content -->
|
||||
</div><!-- /.uc-layout -->
|
||||
</div><!-- /.user-center -->
|
||||
|
||||
<?php else : ?>
|
||||
<!-- ===================== 他人模式:公开用户主页 ===================== -->
|
||||
<header class="profile-public-header"<?php if ( ! empty( $user_home_settings['cover'] ) && $user_background_url ) echo ' style="--user-bg:url(' . esc_url( $user_background_url ) . ')"'; ?>>
|
||||
<div class="profile-public-left">
|
||||
<?php echo get_avatar( $user_id, 96, '', $target_user->display_name ); ?>
|
||||
<h1><?php echo esc_html( $target_user->display_name ); ?></h1>
|
||||
|
||||
<?php if ( ! empty( $profile_signals ) ) : ?>
|
||||
<div class="aksrt-identity-chips">
|
||||
<?php foreach ( $profile_signals as $signal ) : ?>
|
||||
<span class="aksrt-identity-chip aksrt-identity-chip--<?php echo esc_attr( $signal['tone'] ); ?>">
|
||||
<i class="fas fa-<?php echo esc_attr( $signal['icon'] ); ?>" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html( $signal['label'] ); ?></span>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! empty( $user_contacts ) && ! empty( $user_center_settings['social_links'] ) ) : ?>
|
||||
<div class="profile-public-contacts">
|
||||
<?php if ( function_exists( 'aksrt_render_social_links' ) ) : ?>
|
||||
<?php aksrt_render_social_links( $user_contacts ); ?>
|
||||
<?php else : ?>
|
||||
<?php foreach ( $user_contacts as $c ) : ?>
|
||||
<a href="<?php echo esc_url( $c['url'] ?? '#' ); ?>" target="_blank" rel="noopener" title="<?php echo esc_attr( $c['name'] ?? '' ); ?>">
|
||||
<?php echo esc_html( $c['name'] ?? '' ); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="profile-public-right">
|
||||
<?php if ( $target_user->description ) : ?>
|
||||
<p><?php echo nl2br( esc_html( $target_user->description ) ); ?></p>
|
||||
<?php else : ?>
|
||||
<p class="profile-public-empty"><?php esc_html_e( '这个人很懒,还没有填写个人简介', 'aksrt' ); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="uc-header__actions">
|
||||
<?php if ( ! empty( $user_home_settings['follow'] ) ) : ?>
|
||||
<?php if ( is_user_logged_in() ) : ?>
|
||||
<button type="button" class="btn-outline btn-sm aksrt-user-home__follow-btn" data-aksrt-follow="<?php echo (int) $user_id; ?>" title="<?php esc_attr_e( '关注该用户', 'aksrt' ); ?>">
|
||||
<i class="far fa-heart" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e( '关注', 'aksrt' ); ?></span>
|
||||
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
</button>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url( aksrt_get_login_url( $public_home_url ) ); ?>" class="btn-outline btn-sm aksrt-user-home__follow-btn">
|
||||
<i class="far fa-heart" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e( '登录后关注', 'aksrt' ); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<?php if ( $show_report_button ) : ?>
|
||||
<?php if ( is_user_logged_in() ) : ?>
|
||||
<button type="button" class="btn-ghost btn-sm aksrt-user-home__report-btn" data-aksrt-report='{"target_type":"user","target_id":<?php echo (int) $user_id; ?>}' title="<?php esc_attr_e( '举报该用户', 'aksrt' ); ?>">
|
||||
<i class="far fa-flag" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e( '举报', 'aksrt' ); ?></span>
|
||||
</button>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url( aksrt_get_login_url( $public_home_url ) ); ?>" class="btn-ghost btn-sm aksrt-user-home__report-btn">
|
||||
<i class="far fa-flag" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e( '登录后举报', 'aksrt' ); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<?php if ( ! empty( $profile_notice ) ) : ?>
|
||||
<div class="aksrt-user-home__notice aksrt-user-home__notice--<?php echo esc_attr( $profile_notice['state'] ); ?>">
|
||||
<i class="fas fa-exclamation-circle" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html( $profile_notice['text'] ); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="dashboard dashboard--public" data-default-tab="<?php echo esc_attr( $public_default_tab ); ?>">
|
||||
<div class="dashboard-tabs" role="tablist">
|
||||
<?php foreach ( $public_tab_keys as $public_tab_key ) : ?>
|
||||
<button type="button" class="<?php echo $public_active_tab === $public_tab_key ? 'is-active' : ''; ?>" data-tab="<?php echo esc_attr( $public_tab_key ); ?>" role="tab">
|
||||
<?php echo esc_html( $public_tab_labels[ $public_tab_key ] ?? ucfirst( $public_tab_key ) ); ?>
|
||||
<span class="dashboard-tabs__count"><?php echo esc_html( (string) ( $public_tab_counts[ $public_tab_key ] ?? 0 ) ); ?></span>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ( in_array( 'posts', $public_tab_keys, true ) ) : ?>
|
||||
<div id="panel-posts" class="dashboard-panel<?php echo 'posts' === $public_active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'posts' !== $public_active_tab ? ' hidden' : ''; ?>>
|
||||
<?php
|
||||
$author_posts = new WP_Query( [
|
||||
'author' => $user_id,
|
||||
'posts_per_page' => $per_page,
|
||||
'post_status' => 'publish',
|
||||
'paged' => $posts_page,
|
||||
'no_found_rows' => false,
|
||||
'update_post_meta_cache' => false,
|
||||
] );
|
||||
if ( $author_posts->have_posts() ) : ?>
|
||||
<div class="profile-list">
|
||||
<?php while ( $author_posts->have_posts() ) : $author_posts->the_post();
|
||||
set_query_var( 'aksrt_profile_item_action', [
|
||||
'type' => 'view',
|
||||
'url' => get_permalink(),
|
||||
'label' => __( '阅读', 'aksrt' ),
|
||||
] );
|
||||
set_query_var( 'aksrt_profile_item_status', '' );
|
||||
get_template_part( 'templates/parts/content', 'profile-list-item' );
|
||||
endwhile; ?>
|
||||
</div>
|
||||
<?php
|
||||
aksrt_render_profile_pagination( (int) $author_posts->max_num_pages, $posts_page, 'posts_page' );
|
||||
wp_reset_postdata();
|
||||
set_query_var( 'aksrt_profile_item_action', [] );
|
||||
else :
|
||||
aksrt_render_profile_empty( $svg_empty_post, __( 'TA 还没有发布文章', 'aksrt' ) );
|
||||
endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( in_array( 'comments', $public_tab_keys, true ) ) : ?>
|
||||
<div id="panel-comments" class="dashboard-panel<?php echo 'comments' === $public_active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'comments' !== $public_active_tab ? ' hidden' : ''; ?>>
|
||||
<?php
|
||||
$user_comments = get_comments( [
|
||||
'user_id' => $user_id,
|
||||
'status' => 'approve',
|
||||
'number' => $per_page,
|
||||
'offset' => ( $comments_page - 1 ) * $per_page,
|
||||
'type' => 'comment',
|
||||
'update_comment_meta_cache' => false,
|
||||
] );
|
||||
if ( $user_comments ) : ?>
|
||||
<div class="profile-comment-list">
|
||||
<?php foreach ( $user_comments as $c ) :
|
||||
set_query_var( 'aksrt_profile_comment', $c );
|
||||
get_template_part( 'templates/parts/content', 'profile-comment-item' );
|
||||
endforeach;
|
||||
set_query_var( 'aksrt_profile_comment', null ); ?>
|
||||
</div>
|
||||
<?php
|
||||
$cm_total_pages = (int) ceil( $comment_count / $per_page );
|
||||
aksrt_render_profile_pagination( $cm_total_pages, $comments_page, 'comments_page' );
|
||||
?>
|
||||
<?php else :
|
||||
aksrt_render_profile_empty( $svg_empty_comment, __( 'TA 还没有发表评论', 'aksrt' ) );
|
||||
endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( in_array( 'favorites', $public_tab_keys, true ) ) : ?>
|
||||
<div id="panel-favorites" class="dashboard-panel<?php echo 'favorites' === $public_active_tab ? ' is-active' : ''; ?>" role="tabpanel"<?php echo 'favorites' !== $public_active_tab ? ' hidden' : ''; ?>>
|
||||
<?php
|
||||
if ( ! empty( $favorite_post_ids ) ) {
|
||||
$favorite_query = new WP_Query( [
|
||||
'post_type' => 'post',
|
||||
'post__in' => $favorite_post_ids,
|
||||
'orderby' => 'post__in',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $favorites_page,
|
||||
'no_found_rows' => false,
|
||||
'update_post_meta_cache' => false,
|
||||
] );
|
||||
} else {
|
||||
$favorite_query = null;
|
||||
}
|
||||
|
||||
if ( $favorite_query && $favorite_query->have_posts() ) :
|
||||
?>
|
||||
<div class="profile-list">
|
||||
<?php while ( $favorite_query->have_posts() ) : $favorite_query->the_post();
|
||||
set_query_var( 'aksrt_profile_item_action', [
|
||||
'type' => 'view',
|
||||
'url' => get_permalink(),
|
||||
'label' => __( '阅读', 'aksrt' ),
|
||||
] );
|
||||
set_query_var( 'aksrt_profile_item_status', '' );
|
||||
get_template_part( 'templates/parts/content', 'profile-list-item' );
|
||||
endwhile; ?>
|
||||
</div>
|
||||
<?php
|
||||
aksrt_render_profile_pagination( (int) $favorite_query->max_num_pages, $favorites_page, 'favorites_page' );
|
||||
wp_reset_postdata();
|
||||
set_query_var( 'aksrt_profile_item_action', [] );
|
||||
else :
|
||||
aksrt_render_profile_empty( $svg_empty_favorite, __( 'TA 还没有公开收藏内容', 'aksrt' ) );
|
||||
endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $is_own_profile ) : ?>
|
||||
<!-- 配置对象:供 user-center.js 使用 -->
|
||||
<script>window.aksrtUserCenter = {
|
||||
ajaxUrl: <?php echo wp_json_encode( admin_url( 'admin-ajax.php' ) ); ?>,
|
||||
publicNonce: <?php echo wp_json_encode( wp_create_nonce( 'aksrt_public_nonce' ) ); ?>,
|
||||
settingsNonce: <?php echo wp_json_encode( wp_create_nonce( 'aksrt_account_settings' ) ); ?>,
|
||||
userId: <?php echo (int) $user_id; ?>,
|
||||
defaultTab: <?php echo wp_json_encode( $default_dashboard_tab ); ?>,
|
||||
i18n: {
|
||||
contactUrlPlaceholder: <?php echo wp_json_encode( __( '链接 URL', 'aksrt' ) ); ?>,
|
||||
deleteLabel: <?php echo wp_json_encode( __( '删除', 'aksrt' ) ); ?>,
|
||||
saving: <?php echo wp_json_encode( __( '保存中…', 'aksrt' ) ); ?>,
|
||||
saveBtn: <?php echo wp_json_encode( __( '保存修改', 'aksrt' ) ); ?>,
|
||||
saved: <?php echo wp_json_encode( __( '已保存', 'aksrt' ) ); ?>,
|
||||
saveFailed: <?php echo wp_json_encode( __( '保存失败', 'aksrt' ) ); ?>,
|
||||
networkError: <?php echo wp_json_encode( __( '网络错误,请重试', 'aksrt' ) ); ?>,
|
||||
confirmUnfavorite: <?php echo wp_json_encode( __( '确定取消收藏这篇文章?', 'aksrt' ) ); ?>,
|
||||
unfavorited: <?php echo wp_json_encode( __( '已取消收藏', 'aksrt' ) ); ?>,
|
||||
operationFailed: <?php echo wp_json_encode( __( '操作失败', 'aksrt' ) ); ?>,
|
||||
markedRead: <?php echo wp_json_encode( __( '已标记为已读', 'aksrt' ) ); ?>,
|
||||
notificationDeleted: <?php echo wp_json_encode( __( '已删除通知', 'aksrt' ) ); ?>,
|
||||
allMarkedRead: <?php echo wp_json_encode( __( '已全部标记为已读', 'aksrt' ) ); ?>,
|
||||
selectNotifications: <?php echo wp_json_encode( __( '请先选择要标记的通知', 'aksrt' ) ); ?>,
|
||||
selectedMarkedRead: <?php echo wp_json_encode( __( '已标记所选通知为已读', 'aksrt' ) ); ?>,
|
||||
confirmDeleteNotification: <?php echo wp_json_encode( __( '确定删除这条通知?', 'aksrt' ) ); ?>,
|
||||
confirmBatchDelete: <?php echo wp_json_encode( __( '确定批量删除所选通知?', 'aksrt' ) ); ?>,
|
||||
batchDeleted: <?php echo wp_json_encode( __( '已删除所选通知', 'aksrt' ) ); ?>,
|
||||
sendToCurrentEmail: <?php echo wp_json_encode( __( '发送到当前邮箱', 'aksrt' ) ); ?>,
|
||||
sendToNewEmail: <?php echo wp_json_encode( __( '发送到新邮箱', 'aksrt' ) ); ?>,
|
||||
sendCode: <?php echo wp_json_encode( __( '发送验证码', 'aksrt' ) ); ?>,
|
||||
sending: <?php echo wp_json_encode( __( '发送中...', 'aksrt' ) ); ?>,
|
||||
codeSent: <?php echo wp_json_encode( __( '验证码已发送', 'aksrt' ) ); ?>,
|
||||
sendFailed: <?php echo wp_json_encode( __( '发送失败', 'aksrt' ) ); ?>,
|
||||
fillRequired: <?php echo wp_json_encode( __( '请填写必填项', 'aksrt' ) ); ?>,
|
||||
passwordMismatch: <?php echo wp_json_encode( __( '两次输入的新密码不一致', 'aksrt' ) ); ?>,
|
||||
submitting: <?php echo wp_json_encode( __( '提交中...', 'aksrt' ) ); ?>,
|
||||
confirmUnbind: <?php echo wp_json_encode( __( '确定解除绑定?', 'aksrt' ) ); ?>,
|
||||
unbinding: <?php echo wp_json_encode( __( '解除中...', 'aksrt' ) ); ?>,
|
||||
unbindSuccess: <?php echo wp_json_encode( __( '解除成功', 'aksrt' ) ); ?>,
|
||||
unbindFailed: <?php echo wp_json_encode( __( '解除失败', 'aksrt' ) ); ?>,
|
||||
unbind: <?php echo wp_json_encode( __( '解除', 'aksrt' ) ); ?>
|
||||
}
|
||||
};</script>
|
||||
|
||||
<?php if ( $allow_bg_upload ) : ?>
|
||||
<script>
|
||||
window.aksrtAuthorPage = Object.assign({}, window.aksrtAuthorPage || {}, {
|
||||
coverUpload: {
|
||||
enabled: true,
|
||||
restUrl: <?php echo wp_json_encode( rest_url( 'aksrt/v1/user/background' ) ); ?>,
|
||||
restNonce: <?php echo wp_json_encode( wp_create_nonce( 'wp_rest' ) ); ?>,
|
||||
buttonId: 'aksrt-upload-bg-btn',
|
||||
inputId: 'aksrt-bg-file-input',
|
||||
imageId: 'aksrt-cover-img',
|
||||
fieldName: 'background',
|
||||
maxSize: 2097152,
|
||||
fallbackImage: <?php echo wp_json_encode( AKSRT_URI . '/assets/img/person_background.png' ); ?>,
|
||||
idleText: <?php echo wp_json_encode( __( '编辑', 'aksrt' ) ); ?>,
|
||||
loadingText: <?php echo wp_json_encode( __( '上传中…', 'aksrt' ) ); ?>,
|
||||
tooLargeText: <?php echo wp_json_encode( __( '图片大小不能超过 2MB', 'aksrt' ) ); ?>,
|
||||
successText: <?php echo wp_json_encode( __( '背景图已更新', 'aksrt' ) ); ?>,
|
||||
errorText: <?php echo wp_json_encode( __( '上传失败', 'aksrt' ) ); ?>,
|
||||
networkErrorText: <?php echo wp_json_encode( __( '网络错误,请重试', 'aksrt' ) ); ?>
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
/**
|
||||
* Resource Download Box — v2.0
|
||||
*
|
||||
* 单篇资源页的下载区,模仿 zibll pay-box 双栏布局:
|
||||
* - 左侧:资源缩略图 + 付费类型徽章 + 销量徽章
|
||||
* - 右侧:价格区(原价划线 + 现价 + VIP 价)+ 下载按钮 + 服务保障
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$meta = get_query_var('aksrt_resource_meta', null);
|
||||
if (!is_array($meta)) {
|
||||
$meta = function_exists('aksrt_get_resource_meta') ? aksrt_get_resource_meta(get_the_ID()) : null;
|
||||
}
|
||||
if (!is_array($meta)) return;
|
||||
|
||||
$post_id = get_the_ID();
|
||||
$downloads = is_array($meta['downloads']) ? $meta['downloads'] : [];
|
||||
$pay_type = $meta['pay_type'] ?? 'download';
|
||||
|
||||
$price_label = function_exists('aksrt_resource_price_label')
|
||||
? aksrt_resource_price_label((float) $meta['price'])
|
||||
: ['text' => '', 'free' => true];
|
||||
|
||||
// 下载策略检查
|
||||
$gate = function_exists('aksrt_can_download') ? aksrt_can_download($post_id) : true;
|
||||
$gate_blocked = is_wp_error($gate);
|
||||
$gate_code = $gate_blocked ? $gate->get_error_code() : '';
|
||||
$gate_data = $gate_blocked ? (array) $gate->get_error_data() : [];
|
||||
|
||||
$paid_settings = class_exists('AKSRT_Settings')
|
||||
? AKSRT_Settings::get_paid_content_settings()
|
||||
: ['download_credit' => true, 'download_captcha' => false];
|
||||
|
||||
$cost = function_exists('aksrt_resource_download_cost') ? aksrt_resource_download_cost($post_id) : (int) ceil((float) $meta['price']);
|
||||
$credit_active = !empty($paid_settings['download_credit']) && $cost > 0;
|
||||
$captcha_active = !empty($paid_settings['download_captcha']) || !empty($meta['require_captcha']);
|
||||
if ($captcha_active && function_exists('aksrt_is_captcha_enabled_for') && !aksrt_is_captcha_enabled_for('download')) {
|
||||
$captcha_active = false;
|
||||
}
|
||||
$balance = (int) ($gate_data['balance'] ?? 0);
|
||||
$login_url = (string) ($gate_data['login_url'] ?? wp_login_url(get_permalink($post_id)));
|
||||
|
||||
$is_need_login = $gate_blocked && $gate_code === 'aksrt_need_login';
|
||||
$is_low_credit = $gate_blocked && $gate_code === 'aksrt_credits_insufficient';
|
||||
|
||||
// 缩略图
|
||||
$thumbnail = get_the_post_thumbnail_url($post_id, 'medium') ?: '';
|
||||
$has_thumbnail = $thumbnail !== '';
|
||||
|
||||
// 原价 & VIP 价
|
||||
$original_price = (float) ($meta['original_price'] ?? 0);
|
||||
$vip1_price = (float) ($meta['vip1_price'] ?? 0);
|
||||
$vip2_price = (float) ($meta['vip2_price'] ?? 0);
|
||||
$has_original = $original_price > 0 && $original_price > (float) $meta['price'];
|
||||
$has_vip = $vip1_price > 0 || $vip2_price > 0;
|
||||
|
||||
// 销量
|
||||
$download_count = (int) ($meta['download_count'] ?? 0);
|
||||
$sales_count = (int) ($meta['sales_count'] ?? 0);
|
||||
$display_count = max($download_count, $sales_count);
|
||||
|
||||
// 付费类型徽章
|
||||
$pay_type_badge = function_exists('aksrt_resource_pay_type_badge') ? aksrt_resource_pay_type_badge($pay_type) : '';
|
||||
|
||||
// 货币名称
|
||||
$currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
|
||||
?>
|
||||
|
||||
<section class="widget resource-download-box resource-download-box--v2<?php echo $gate_blocked ? ' is-blocked' : ''; ?>"
|
||||
data-post-id="<?php echo esc_attr((string) $post_id); ?>"
|
||||
data-price="<?php echo esc_attr((string) $meta['price']); ?>"
|
||||
data-credit="<?php echo $credit_active ? '1' : '0'; ?>"
|
||||
data-captcha="<?php echo $captcha_active ? '1' : '0'; ?>"
|
||||
aria-label="<?php esc_attr_e('下载区', 'aksrt'); ?>">
|
||||
|
||||
<?php if ($display_count > 0) : ?>
|
||||
<span class="resource-download-box__sales-badge">
|
||||
<i class="fas fa-fire" aria-hidden="true"></i>
|
||||
<?php
|
||||
/* translators: %s: 下载/销量数 */
|
||||
printf(esc_html__('已售 %s', 'aksrt'), number_format_i18n($display_count));
|
||||
?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="resource-download-box__body">
|
||||
<?php if ($has_thumbnail) : ?>
|
||||
<div class="resource-download-box__thumb-col">
|
||||
<img class="resource-download-box__thumb" src="<?php echo esc_url($thumbnail); ?>" alt="<?php echo esc_attr(get_the_title()); ?>"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
<?php if ($pay_type_badge) : ?>
|
||||
<div class="resource-download-box__pay-tag"><?php echo $pay_type_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="resource-download-box__content-col">
|
||||
<header class="resource-download-box__header">
|
||||
<h2 class="resource-download-box__title">
|
||||
<i class="fas fa-cloud-download-alt" aria-hidden="true"></i>
|
||||
<?php esc_html_e('立即下载', 'aksrt'); ?>
|
||||
</h2>
|
||||
<?php if (!empty($downloads)) : ?>
|
||||
<span class="resource-download-box__count">
|
||||
<?php echo esc_html(sprintf(_n('%s 个下载源', '%s 个下载源', count($downloads), 'aksrt'), number_format_i18n(count($downloads)))); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
|
||||
<!-- 价格区 -->
|
||||
<div class="resource-download-box__pricing">
|
||||
<span class="resource-download-box__price<?php echo $price_label['free'] ? ' is-free' : ''; ?>">
|
||||
<?php echo esc_html($price_label['text']); ?>
|
||||
</span>
|
||||
<?php if ($has_original) : ?>
|
||||
<span class="resource-download-box__original-price">
|
||||
<?php echo esc_html(aksrt_resource_price_amount($original_price) . ' ' . $currency); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php echo $pay_type_badge && !$has_thumbnail ? $pay_type_badge : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
|
||||
<?php if ($has_vip) : ?>
|
||||
<div class="resource-download-box__vip-pricing">
|
||||
<?php if ($vip1_price > 0) : ?>
|
||||
<span class="resource-download-box__vip-badge resource-download-box__vip-badge--1">
|
||||
<i class="fas fa-crown" aria-hidden="true"></i>
|
||||
<?php
|
||||
/* translators: %s: VIP1 价格 */
|
||||
printf(esc_html__('VIP1 %s', 'aksrt'), aksrt_resource_price_amount($vip1_price));
|
||||
?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if ($vip2_price > 0) : ?>
|
||||
<span class="resource-download-box__vip-badge resource-download-box__vip-badge--2">
|
||||
<i class="fas fa-gem" aria-hidden="true"></i>
|
||||
<?php
|
||||
/* translators: %s: VIP2 价格 */
|
||||
printf(esc_html__('VIP2 %s', 'aksrt'), aksrt_resource_price_amount($vip2_price));
|
||||
?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 下载按钮区 -->
|
||||
<?php if (empty($downloads)) : ?>
|
||||
<div class="resource-download-box__notice resource-download-box__notice--empty">
|
||||
<p><i class="fas fa-info-circle" aria-hidden="true"></i> <?php esc_html_e('该资源暂未提供下载链接。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<ul class="resource-download-box__list">
|
||||
<?php foreach ($downloads as $idx => $row) :
|
||||
$label = isset($row['label']) ? (string) $row['label'] : '';
|
||||
if ($label === '') {
|
||||
$label = sprintf(__('下载源 %d', 'aksrt'), $idx + 1);
|
||||
}
|
||||
$type = isset($row['type']) ? (string) $row['type'] : 'direct';
|
||||
$url = isset($row['url']) ? (string) $row['url'] : '';
|
||||
$extract_code = isset($row['extract_code']) ? trim((string) $row['extract_code']) : '';
|
||||
$has_extract = $extract_code !== '';
|
||||
|
||||
$service = function_exists('aksrt_detect_cloud_service') ? aksrt_detect_cloud_service($url) : ['key' => 'other', 'name' => $label, 'color' => '#6b7280'];
|
||||
if (strpos($label, '下载源') === 0 && $service['key'] !== 'other') {
|
||||
$label = $service['name'];
|
||||
}
|
||||
|
||||
if ($is_need_login) {
|
||||
$btn_tag = 'a';
|
||||
$btn_text = __('登录下载', 'aksrt');
|
||||
$btn_icon = 'fa-sign-in-alt';
|
||||
$btn_modifier = ' resource-download-box__btn--login';
|
||||
} elseif ($is_low_credit) {
|
||||
$btn_tag = 'button';
|
||||
$btn_text = sprintf(__('付费下载(%d 积分)', 'aksrt'), $cost);
|
||||
$btn_icon = 'fa-coins';
|
||||
$btn_modifier = ' resource-download-box__btn--credit-low';
|
||||
} elseif ($credit_active && $cost > 0) {
|
||||
$btn_tag = 'button';
|
||||
$btn_text = sprintf(__('下载(%d 积分)', 'aksrt'), $cost);
|
||||
$btn_icon = 'fa-download';
|
||||
$btn_modifier = ' resource-download-box__btn--paid';
|
||||
} else {
|
||||
$btn_tag = 'button';
|
||||
$btn_text = $label;
|
||||
$btn_icon = 'fa-download';
|
||||
$btn_modifier = '';
|
||||
}
|
||||
?>
|
||||
<li class="resource-download-box__item">
|
||||
<?php if ($btn_tag === 'a') : ?>
|
||||
<a
|
||||
class="resource-download-box__btn btn-primary resource-download-box__btn--service-<?php echo esc_attr($service['key']); ?><?php echo esc_attr($btn_modifier); ?>"
|
||||
href="<?php echo esc_url($login_url); ?>"
|
||||
data-source-index="<?php echo esc_attr((string) $idx); ?>"
|
||||
data-source-type="<?php echo esc_attr($type); ?>"
|
||||
style="--service-color: <?php echo esc_attr($service['color']); ?>"
|
||||
>
|
||||
<i class="fas <?php echo esc_attr($btn_icon); ?>" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html($btn_text); ?></span>
|
||||
<span class="resource-download-box__service-badge" style="background: <?php echo esc_attr($service['color']); ?>">
|
||||
<?php echo esc_html($service['name']); ?>
|
||||
</span>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<button
|
||||
type="button"
|
||||
class="resource-download-box__btn btn-primary resource-download-box__btn--service-<?php echo esc_attr($service['key']); ?><?php echo esc_attr($btn_modifier); ?>"
|
||||
data-action="<?php echo $is_low_credit ? 'aksrt-need-credits' : 'aksrt-download'; ?>"
|
||||
data-source-index="<?php echo esc_attr((string) $idx); ?>"
|
||||
data-source-type="<?php echo esc_attr($type); ?>"
|
||||
data-has-extract="<?php echo $has_extract ? '1' : '0'; ?>"
|
||||
data-balance="<?php echo esc_attr((string) $balance); ?>"
|
||||
data-cost="<?php echo esc_attr((string) $cost); ?>"
|
||||
style="--service-color: <?php echo esc_attr($service['color']); ?>"
|
||||
>
|
||||
<i class="fas <?php echo esc_attr($btn_icon); ?>" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html($btn_text); ?></span>
|
||||
<?php if ($is_low_credit) : ?>
|
||||
<small class="resource-download-box__btn-sub">
|
||||
<?php printf(esc_html__('当前余额 %d', 'aksrt'), $balance); ?>
|
||||
</small>
|
||||
<?php else : ?>
|
||||
<span class="resource-download-box__service-badge" style="background: <?php echo esc_attr($service['color']); ?>">
|
||||
<?php echo esc_html($service['name']); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 服务保障 -->
|
||||
<div class="resource-download-box__guarantees">
|
||||
<span class="resource-download-box__guarantee">
|
||||
<i class="fas fa-shield-alt" aria-hidden="true"></i>
|
||||
<?php esc_html_e('安全检测', 'aksrt'); ?>
|
||||
</span>
|
||||
<span class="resource-download-box__guarantee">
|
||||
<i class="fas fa-sync-alt" aria-hidden="true"></i>
|
||||
<?php esc_html_e('持续更新', 'aksrt'); ?>
|
||||
</span>
|
||||
<span class="resource-download-box__guarantee">
|
||||
<i class="fas fa-headset" aria-hidden="true"></i>
|
||||
<?php esc_html_e('售后支持', 'aksrt'); ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($is_need_login) : ?>
|
||||
<p class="resource-download-box__hint resource-download-box__hint--login">
|
||||
<i class="fas fa-info-circle" aria-hidden="true"></i>
|
||||
<?php esc_html_e('登录后可下载此资源。', 'aksrt'); ?>
|
||||
</p>
|
||||
<?php elseif ($is_low_credit) : ?>
|
||||
<p class="resource-download-box__hint resource-download-box__hint--credit">
|
||||
<i class="fas fa-info-circle" aria-hidden="true"></i>
|
||||
<?php printf(esc_html__('当前余额 %1$d 积分,需要 %2$d 积分。可通过签到、阅读、邀请好友等方式获取积分。', 'aksrt'), $balance, $cost); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($captcha_active && function_exists('aksrt_render_captcha')) : ?>
|
||||
<div class="resource-download-box__captcha resource-download-box__captcha--hidden" data-aksrt-download-captcha>
|
||||
<?php aksrt_render_captcha('download'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<footer class="resource-download-box__footer">
|
||||
<p class="resource-download-box__notice-text">
|
||||
<i class="fas fa-info-circle" aria-hidden="true"></i>
|
||||
<?php esc_html_e('请确认资源安全后再使用,本站仅作信息聚合与分享,不对资源内容负责。', 'aksrt'); ?>
|
||||
</p>
|
||||
</footer>
|
||||
</section>
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* Resource Meta Box
|
||||
*
|
||||
* 单篇资源页用:版本/大小/授权/兼容/演示 等元信息表。
|
||||
*
|
||||
* 由 single-aksrt_resource.php 调用:
|
||||
* set_query_var('aksrt_resource_meta', $meta);
|
||||
* get_template_part('templates/parts/resource-meta-box');
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$meta = get_query_var('aksrt_resource_meta', null);
|
||||
if (!is_array($meta)) {
|
||||
$meta = function_exists('aksrt_get_resource_meta') ? aksrt_get_resource_meta(get_the_ID()) : null;
|
||||
}
|
||||
if (!is_array($meta)) return;
|
||||
|
||||
// 字段定义及显示顺序
|
||||
$rows = [
|
||||
'version' => __('版本', 'aksrt'),
|
||||
'size' => __('大小', 'aksrt'),
|
||||
'compat' => __('兼容性', 'aksrt'),
|
||||
'license' => __('授权', 'aksrt'),
|
||||
];
|
||||
|
||||
// 至少要有一个非空字段才渲染
|
||||
$has_any = false;
|
||||
foreach ($rows as $k => $_label) {
|
||||
if (!empty($meta[$k])) { $has_any = true; break; }
|
||||
}
|
||||
$has_demo = !empty($meta['demo_url']);
|
||||
$has_downloads = ($meta['download_count'] ?? 0) > 0;
|
||||
|
||||
if (!$has_any && !$has_demo && !$has_downloads) return;
|
||||
?>
|
||||
|
||||
<aside class="resource-meta-box" aria-label="<?php esc_attr_e('资源信息', 'aksrt'); ?>">
|
||||
<header class="resource-meta-box__header">
|
||||
<h2 class="resource-meta-box__title"><?php esc_html_e('资源信息', 'aksrt'); ?></h2>
|
||||
</header>
|
||||
|
||||
<dl class="resource-meta-box__list">
|
||||
<?php if (!empty($meta['version'])) : ?>
|
||||
<div class="resource-meta-box__row">
|
||||
<dt class="resource-meta-box__key">
|
||||
<i class="<?php echo esc_attr(function_exists('aksrt_resource_meta_icon') ? aksrt_resource_meta_icon('version') : 'fas fa-code-branch'); ?>" aria-hidden="true"></i>
|
||||
<?php echo esc_html($rows['version']); ?>
|
||||
</dt>
|
||||
<dd class="resource-meta-box__val"><?php echo esc_html((string) $meta['version']); ?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($meta['size'])) : ?>
|
||||
<div class="resource-meta-box__row">
|
||||
<dt class="resource-meta-box__key">
|
||||
<i class="<?php echo esc_attr(function_exists('aksrt_resource_meta_icon') ? aksrt_resource_meta_icon('size') : 'fas fa-hdd'); ?>" aria-hidden="true"></i>
|
||||
<?php echo esc_html($rows['size']); ?>
|
||||
</dt>
|
||||
<dd class="resource-meta-box__val"><?php echo esc_html((string) $meta['size']); ?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($meta['compat'])) : ?>
|
||||
<div class="resource-meta-box__row">
|
||||
<dt class="resource-meta-box__key">
|
||||
<i class="<?php echo esc_attr(function_exists('aksrt_resource_meta_icon') ? aksrt_resource_meta_icon('compat') : 'fas fa-laptop'); ?>" aria-hidden="true"></i>
|
||||
<?php echo esc_html($rows['compat']); ?>
|
||||
</dt>
|
||||
<dd class="resource-meta-box__val"><?php echo esc_html((string) $meta['compat']); ?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($has_demo) : ?>
|
||||
<div class="resource-meta-box__row">
|
||||
<dt class="resource-meta-box__key">
|
||||
<i class="<?php echo esc_attr(function_exists('aksrt_resource_meta_icon') ? aksrt_resource_meta_icon('demo_url') : 'fas fa-external-link-alt'); ?>" aria-hidden="true"></i>
|
||||
<?php esc_html_e('演示地址', 'aksrt'); ?>
|
||||
</dt>
|
||||
<dd class="resource-meta-box__val">
|
||||
<a class="resource-meta-box__demo-link" href="<?php echo esc_url($meta['demo_url']); ?>" target="_blank" rel="noopener noreferrer">
|
||||
<?php esc_html_e('打开演示', 'aksrt'); ?>
|
||||
<i class="fas fa-external-link-alt" aria-hidden="true"></i>
|
||||
</a>
|
||||
</dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($meta['license'])) : ?>
|
||||
<div class="resource-meta-box__row">
|
||||
<dt class="resource-meta-box__key">
|
||||
<i class="<?php echo esc_attr(function_exists('aksrt_resource_meta_icon') ? aksrt_resource_meta_icon('license') : 'fas fa-shield-alt'); ?>" aria-hidden="true"></i>
|
||||
<?php echo esc_html($rows['license']); ?>
|
||||
</dt>
|
||||
<dd class="resource-meta-box__val"><?php echo esc_html((string) $meta['license']); ?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($has_downloads) : ?>
|
||||
<div class="resource-meta-box__row">
|
||||
<dt class="resource-meta-box__key">
|
||||
<i class="<?php echo esc_attr(function_exists('aksrt_resource_meta_icon') ? aksrt_resource_meta_icon('download') : 'fas fa-download'); ?>" aria-hidden="true"></i>
|
||||
<?php esc_html_e('下载次数', 'aksrt'); ?>
|
||||
</dt>
|
||||
<dd class="resource-meta-box__val"><?php echo esc_html(number_format_i18n((int) $meta['download_count'])); ?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (($meta['view_count'] ?? 0) > 0) : ?>
|
||||
<div class="resource-meta-box__row">
|
||||
<dt class="resource-meta-box__key">
|
||||
<i class="<?php echo esc_attr(function_exists('aksrt_resource_meta_icon') ? aksrt_resource_meta_icon('views') : 'fas fa-eye'); ?>" aria-hidden="true"></i>
|
||||
<?php esc_html_e('浏览次数', 'aksrt'); ?>
|
||||
</dt>
|
||||
<dd class="resource-meta-box__val"><?php echo esc_html(number_format_i18n((int) $meta['view_count'])); ?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</dl>
|
||||
</aside>
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Resource Related
|
||||
*
|
||||
* 单篇资源页底部的「相关资源」区块。
|
||||
* 取同分类下其它资源(post + _aksrt_is_resource = 1,兼容旧 aksrt_resource CPT),按下载量倒序。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$current_id = get_the_ID();
|
||||
$cat_ids = wp_get_post_categories($current_id, ['fields' => 'ids']);
|
||||
if (empty($cat_ids)) return;
|
||||
|
||||
$post_types = function_exists('aksrt_resource_post_types') ? aksrt_resource_post_types() : ['post'];
|
||||
|
||||
$args = [
|
||||
'post_type' => $post_types,
|
||||
'posts_per_page' => 6,
|
||||
'post__not_in' => [$current_id],
|
||||
'category__in' => array_map('intval', $cat_ids),
|
||||
'meta_key' => '_aksrt_res_download_count',
|
||||
'orderby' => 'meta_value_num',
|
||||
'order' => 'DESC',
|
||||
'no_found_rows' => true,
|
||||
];
|
||||
if (!post_type_exists('aksrt_resource')) {
|
||||
$args['meta_query'] = [
|
||||
'relation' => 'AND',
|
||||
[
|
||||
'key' => '_aksrt_is_resource',
|
||||
'value' => '1',
|
||||
'compare' => '=',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$query = new WP_Query($args);
|
||||
|
||||
if (!$query->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<section class="resource-related" aria-label="<?php esc_attr_e('相关资源', 'aksrt'); ?>">
|
||||
<header class="resource-related__header">
|
||||
<h2 class="resource-related__title"><?php esc_html_e('相关资源', 'aksrt'); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="post-grid post-grid--grid-cms resource-related__grid">
|
||||
<?php
|
||||
set_query_var('aksrt_post_card_layout', 'grid-cms');
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
get_template_part('templates/parts/content', 'post-card');
|
||||
}
|
||||
set_query_var('aksrt_post_card_layout', '');
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* Shared author info bar for single post/resource content.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$extra_class = (string) get_query_var('aksrt_author_bar_class', '');
|
||||
$show_actions = (bool) get_query_var('aksrt_author_bar_actions', false);
|
||||
$show_bio = (bool) get_query_var('aksrt_author_bar_bio', false);
|
||||
$meta_items = get_query_var('aksrt_author_bar_meta_items', []);
|
||||
$meta_items = is_array($meta_items) ? array_values(array_filter($meta_items, static function ($meta_item) {
|
||||
if (is_array($meta_item)) {
|
||||
return !empty($meta_item['text']);
|
||||
}
|
||||
|
||||
return is_string($meta_item) && $meta_item !== '';
|
||||
})) : [];
|
||||
$updated_text = sprintf(
|
||||
esc_html__('%s前更新', 'aksrt'),
|
||||
esc_html(human_time_diff(get_the_modified_time('U'), current_time('timestamp')))
|
||||
);
|
||||
$author_bio = trim((string) get_the_author_meta('description'));
|
||||
$author_id = (int) get_the_author_meta('ID');
|
||||
|
||||
$classes = trim('article-avatar ' . $extra_class . ($show_actions ? ' article-avatar--with-actions' : ''));
|
||||
?>
|
||||
|
||||
<div class="<?php echo esc_attr($classes); ?>">
|
||||
<div class="author-box flex ac">
|
||||
<div class="article-avatar__image">
|
||||
<?php echo get_avatar($author_id, 52, '', esc_attr(get_the_author()), ['class' => 'article-avatar']); ?>
|
||||
</div>
|
||||
<div class="article-avatar__body">
|
||||
<a href="<?php echo esc_url(get_author_posts_url($author_id)); ?>" class="article-avatar__name"><?php the_author(); ?></a>
|
||||
<div class="comt-meta muted-2-color">
|
||||
<item class="post-time"><i class="far fa-clock" aria-hidden="true"></i> <?php echo $updated_text; ?></item>
|
||||
<?php foreach ($meta_items as $meta_item) : ?>
|
||||
<?php
|
||||
$meta_text = is_array($meta_item) ? (string) ($meta_item['text'] ?? '') : (string) $meta_item;
|
||||
$meta_icon = is_array($meta_item) ? (string) ($meta_item['icon'] ?? '') : '';
|
||||
if ($meta_text === '') {
|
||||
continue;
|
||||
}
|
||||
?>
|
||||
<item class="meta-view"><?php if ($meta_icon !== '') : ?><i class="<?php echo esc_attr($meta_icon); ?>" aria-hidden="true"></i> <?php endif; ?><?php echo esc_html($meta_text); ?></item>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php if ($show_bio && $author_bio !== '') : ?>
|
||||
<p class="article-avatar__bio"><?php echo esc_html($author_bio); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($show_actions) : ?>
|
||||
<i class="line-form-line" aria-hidden="true"></i>
|
||||
<div class="single-metabox abs-right" aria-label="<?php esc_attr_e('作者操作', 'aksrt'); ?>">
|
||||
<?php if (is_user_logged_in() && $author_id !== get_current_user_id()) : ?>
|
||||
<button type="button" class="author-action-btn author-action-btn--follow" data-aksrt-follow="<?php echo $author_id; ?>">
|
||||
<i class="far fa-heart" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('关注', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<a href="<?php echo esc_url(add_query_arg('msg_type', 'conversation', function_exists('aksrt_get_messages_url') ? aksrt_get_messages_url() : home_url('/messages/'))); ?>" class="author-action-btn author-action-btn--ghost">
|
||||
<i class="far fa-comment-dots" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('私信', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php elseif (!is_user_logged_in()) : ?>
|
||||
<a href="<?php echo esc_url(function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink())); ?>" class="author-action-btn author-action-btn--follow">
|
||||
<i class="far fa-heart" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('登录后关注', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<div class="post-drop-meta">
|
||||
<button type="button" class="post-drop-meta__toggle author-action-btn author-action-btn--ghost" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-ellipsis-h" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('更多', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<div class="post-drop-meta__menu" aria-hidden="true">
|
||||
<?php if (current_user_can('edit_post', get_the_ID())) : ?>
|
||||
<a href="<?php echo esc_url(get_edit_post_link(get_the_ID())); ?>" class="post-drop-meta__item">
|
||||
<i class="far fa-edit" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('编辑文章', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<button type="button" class="post-drop-meta__item" data-share-copy data-share-url="<?php echo esc_url(get_permalink()); ?>">
|
||||
<i class="fas fa-link" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('复制链接', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<button type="button" class="post-drop-meta__item" data-aksrt-report='{"target_type":"post","target_id":<?php echo (int) get_the_ID(); ?>}'>
|
||||
<i class="far fa-flag" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('举报', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url(function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink())); ?>" class="post-drop-meta__item">
|
||||
<i class="far fa-flag" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('登录后举报', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* Special Page Cover
|
||||
*
|
||||
* Renders the cover section for a special/topic page with
|
||||
* background image, title, summary, and metadata.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$post_id = get_the_ID();
|
||||
$cover_img = get_the_post_thumbnail_url($post_id, 'large');
|
||||
$default_cover = isset($default_cover) ? $default_cover : '';
|
||||
$show_post_count = isset($show_post_count) ? $show_post_count : true;
|
||||
if (empty($cover_img) && !empty($default_cover)) {
|
||||
$cover_img = $default_cover;
|
||||
}
|
||||
$title = get_the_title();
|
||||
$excerpt = get_the_excerpt();
|
||||
$summary_len = isset($summary_len) ? (int) $summary_len : 200;
|
||||
|
||||
if ($excerpt) {
|
||||
$excerpt = wp_trim_words($excerpt, $summary_len, '...');
|
||||
}
|
||||
|
||||
// Per-page meta
|
||||
$cover_color = get_post_meta($post_id, '_aksrt_special_cover_color', true);
|
||||
$cover_style = '';
|
||||
if ($cover_color) {
|
||||
$cover_style = 'background-color:' . sanitize_hex_color($cover_color) . ';';
|
||||
}
|
||||
?>
|
||||
<header class="aksrt-special-cover" <?php echo $cover_style ? 'style="' . esc_attr($cover_style) . '"' : ''; ?>>
|
||||
<?php if ($cover_img) : ?>
|
||||
<div class="aksrt-special-cover__bg">
|
||||
<img src="<?php echo esc_url($cover_img); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('cover') : ' loading="lazy"'; ?> class="aksrt-special-cover__img">
|
||||
<div class="aksrt-special-cover__overlay"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-special-cover__content">
|
||||
<h1 class="aksrt-special-cover__title"><?php echo esc_html($title); ?></h1>
|
||||
|
||||
<?php if ($excerpt) : ?>
|
||||
<p class="aksrt-special-cover__summary"><?php echo esc_html($excerpt); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-special-cover__meta">
|
||||
<span class="aksrt-special-cover__date">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<?php echo esc_html(get_the_date()); ?>
|
||||
</span>
|
||||
<?php
|
||||
if ($show_post_count) :
|
||||
$children = get_pages(['child_of' => $post_id, 'parent' => $post_id, 'post_status' => 'publish', 'fields' => 'ids']);
|
||||
if (!empty($children)) : ?>
|
||||
<span class="aksrt-special-cover__count">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<?php printf(esc_html__('%d 篇文章', 'aksrt'), count($children)); ?>
|
||||
</span>
|
||||
<?php endif; endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* Special Page Grid
|
||||
*
|
||||
* Renders the content grid for a special/topic page.
|
||||
* Supports grid, list, and masonry layouts.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$posts = isset($posts) ? $posts : [];
|
||||
$layout = isset($layout) ? $layout : 'grid';
|
||||
$columns = isset($columns) ? (int) $columns : 2;
|
||||
$show_dates = isset($show_dates) ? $show_dates : true;
|
||||
|
||||
if (empty($posts)) return;
|
||||
?>
|
||||
<div class="aksrt-special-grid aksrt-special-grid--<?php echo esc_attr($layout); ?>" style="--aksrt-cols:<?php echo esc_attr((string) $columns); ?>">
|
||||
<?php foreach ($posts as $post) :
|
||||
setup_postdata($post);
|
||||
$img = get_the_post_thumbnail_url($post->ID, 'medium');
|
||||
?>
|
||||
<article class="aksrt-special-grid__item">
|
||||
<a href="<?php echo esc_url(get_permalink($post->ID)); ?>" class="aksrt-special-grid__link">
|
||||
<?php if ($img) : ?>
|
||||
<div class="aksrt-special-grid__thumb">
|
||||
<img src="<?php echo esc_url($img); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-special-grid__body">
|
||||
<h3 class="aksrt-special-grid__title"><?php echo esc_html($post->post_title); ?></h3>
|
||||
<?php if ($post->post_excerpt) : ?>
|
||||
<p class="aksrt-special-grid__desc"><?php echo esc_html(wp_trim_words($post->post_excerpt, 20)); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($show_dates) : ?>
|
||||
<time class="aksrt-special-grid__date" datetime="<?php echo esc_attr(get_the_date('c', $post->ID)); ?>">
|
||||
<?php echo esc_html(get_the_date('', $post->ID)); ?>
|
||||
</time>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
<?php endforeach; wp_reset_postdata(); ?>
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<!-- 本人中心 partial 模板目录 -->
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* 用户中心 — 我的评论
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$per_page = 15;
|
||||
$paged = max(1, get_query_var('paged'));
|
||||
|
||||
$comments = get_comments([
|
||||
'user_id' => $user_id,
|
||||
'status' => 'approve',
|
||||
'post_status' => 'publish',
|
||||
'number' => $per_page,
|
||||
'offset' => ($paged - 1) * $per_page,
|
||||
'orderby' => 'comment_date_gmt',
|
||||
'order' => 'DESC',
|
||||
'count' => true,
|
||||
]);
|
||||
|
||||
$total_comments = $comments;
|
||||
$comments = get_comments([
|
||||
'user_id' => $user_id,
|
||||
'status' => 'approve',
|
||||
'post_status' => 'publish',
|
||||
'number' => $per_page,
|
||||
'offset' => ($paged - 1) * $per_page,
|
||||
'orderby' => 'comment_date_gmt',
|
||||
'order' => 'DESC',
|
||||
]);
|
||||
$max_pages = ceil($total_comments / $per_page);
|
||||
?>
|
||||
|
||||
<div class="uc-comments" id="uc-comments">
|
||||
<?php if (!empty($comments)) : ?>
|
||||
<div class="uc-comments__list">
|
||||
<?php foreach ($comments as $comment) :
|
||||
$post = get_post($comment->comment_post_ID);
|
||||
if (!$post) continue;
|
||||
?>
|
||||
<div class="uc-comments__item">
|
||||
<div class="uc-comments__header">
|
||||
<a href="<?php echo esc_url(get_permalink($post->ID)); ?>" class="uc-comments__post-title">
|
||||
<?php echo esc_html($post->post_title); ?>
|
||||
</a>
|
||||
<span class="uc-comments__date"><?php echo esc_html(get_comment_date('Y-m-d', $comment)); ?></span>
|
||||
</div>
|
||||
<div class="uc-comments__body">
|
||||
<?php echo function_exists('aksrt_render_comment_content') ? aksrt_render_comment_content((string) get_comment_text($comment)) : wp_kses_post((string) $comment->comment_content); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($max_pages > 1) : ?>
|
||||
<div class="aksrt-pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'base' => str_replace(999999999, '%#%', esc_url(get_pagenum_link(999999999))),
|
||||
'format' => '?paged=%#%',
|
||||
'current' => $paged,
|
||||
'total' => $max_pages,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="empty-state empty-state--sm">
|
||||
<div class="empty-state__icon"><i class="far fa-comment-dots"></i></div>
|
||||
<p class="empty-state__title"><?php esc_html_e('暂无评论', 'aksrt'); ?></p>
|
||||
<p class="empty-state__desc"><?php esc_html_e('去文章下方发表你的看法吧~', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* 用户中心 — 我的积分
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$credits_enabled = class_exists('AKSRT_Settings') && AKSRT_Settings::get_credits_settings()['enabled'] ?? false;
|
||||
|
||||
if (!$credits_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$balance = function_exists('aksrt_get_user_credits') ? aksrt_get_user_credits($user_id) : 0;
|
||||
$currency_name = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_credits_settings()['currency_name'] ?? __('积分', 'aksrt') : __('积分', 'aksrt');
|
||||
|
||||
// 获取积分记录
|
||||
$records = function_exists('aksrt_get_credit_logs') ? aksrt_get_credit_logs($user_id, 20) : [];
|
||||
?>
|
||||
|
||||
<div class="uc-credits" id="uc-credits">
|
||||
<!-- 积分概览 -->
|
||||
<div class="uc-credits__overview">
|
||||
<div class="uc-credits__balance">
|
||||
<span class="uc-credits__balance-num"><?php echo esc_html(number_format($balance, 2)); ?></span>
|
||||
<span class="uc-credits__balance-label"><?php echo esc_html($currency_name); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 积分记录 -->
|
||||
<?php if (!empty($records)) : ?>
|
||||
<div class="uc-credits__records">
|
||||
<h4 class="uc-credits__section-title"><?php esc_html_e('积分记录', 'aksrt'); ?></h4>
|
||||
<div class="uc-credits__list">
|
||||
<?php foreach ($records as $record) : ?>
|
||||
<div class="uc-credits__record">
|
||||
<div class="uc-credits__record-info">
|
||||
<span class="uc-credits__record-desc"><?php echo esc_html($record['description'] ?? ''); ?></span>
|
||||
<span class="uc-credits__record-date"><?php echo esc_html($record['date'] ?? ''); ?></span>
|
||||
</div>
|
||||
<span class="uc-credits__record-amount <?php echo ($record['amount'] ?? 0) > 0 ? 'uc-credits__record-amount--plus' : 'uc-credits__record-amount--minus'; ?>">
|
||||
<?php echo ($record['amount'] ?? 0) > 0 ? '+' : ''; ?><?php echo esc_html(number_format($record['amount'] ?? 0, 2)); ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="empty-state empty-state--sm">
|
||||
<div class="empty-state__icon"><i class="fas fa-coins"></i></div>
|
||||
<p class="empty-state__title"><?php esc_html_e('暂无积分记录', 'aksrt'); ?></p>
|
||||
<p class="empty-state__desc"><?php esc_html_e('每天签到、发布内容都可以获得积分哦~', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* 用户中心 — 仪表盘面板
|
||||
*
|
||||
* 显示当前登录用户的基本信息概览、积分、VIP状态、快捷操作。
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$user = wp_get_current_user();
|
||||
$dashboard = function_exists('aksrt_get_user_dashboard_view')
|
||||
? aksrt_get_user_dashboard_view($user_id, ['viewer_id' => $user_id])
|
||||
: [];
|
||||
|
||||
$credits_enabled = !empty($dashboard['credits_enabled']);
|
||||
$credit_balance = $dashboard['credit_balance'] ?? 0;
|
||||
$currency_name = $dashboard['currency_name'] ?? __('积分', 'aksrt');
|
||||
$is_vip = function_exists('aksrt_is_vip') && aksrt_is_vip($user_id);
|
||||
$post_count = (int) ($dashboard['post_count'] ?? 0);
|
||||
$comment_count = (int) ($dashboard['comment_count'] ?? 0);
|
||||
$favorite_count = (int) ($dashboard['favorite_count'] ?? 0);
|
||||
$order_count = (int) ($dashboard['order_count'] ?? 0);
|
||||
?>
|
||||
|
||||
<div class="uc-dashboard">
|
||||
<!-- 用户信息卡片 -->
|
||||
<div class="uc-dashboard__profile">
|
||||
<div class="uc-dashboard__avatar">
|
||||
<?php echo get_avatar($user_id, 80); ?>
|
||||
<?php if ($is_vip) : ?>
|
||||
<span class="aksrt-vip-badge aksrt-vip-badge--sm">VIP</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="uc-dashboard__info">
|
||||
<h3 class="uc-dashboard__name"><?php echo esc_html($user->display_name); ?></h3>
|
||||
<p class="uc-dashboard__desc">
|
||||
<?php
|
||||
$desc = $user->description ?: __('这个人很懒,什么都没写~', 'aksrt');
|
||||
echo esc_html(wp_trim_words($desc, 30));
|
||||
?>
|
||||
</p>
|
||||
<div class="uc-dashboard__meta">
|
||||
<span><i class="fas fa-calendar-alt"></i> <?php echo esc_html(__('注册于', 'aksrt') . ' ' . date_i18n(get_option('date_format'), strtotime($user->user_registered))); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="<?php echo esc_url(get_edit_profile_url($user_id)); ?>" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fas fa-edit"></i> <?php esc_html_e('编辑资料', 'aksrt'); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- 数据统计 -->
|
||||
<div class="uc-dashboard__stats">
|
||||
<a href="<?php echo esc_url(get_author_posts_url($user_id)); ?>" class="uc-dashboard__stat">
|
||||
<span class="uc-dashboard__stat-num"><?php echo $post_count; ?></span>
|
||||
<span class="uc-dashboard__stat-label"><?php esc_html_e('文章', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<a href="#uc-comments" class="uc-dashboard__stat">
|
||||
<span class="uc-dashboard__stat-num"><?php echo $comment_count; ?></span>
|
||||
<span class="uc-dashboard__stat-label"><?php esc_html_e('评论', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<a href="#uc-favorites" class="uc-dashboard__stat">
|
||||
<span class="uc-dashboard__stat-num"><?php echo $favorite_count; ?></span>
|
||||
<span class="uc-dashboard__stat-label"><?php esc_html_e('收藏', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php if ($credits_enabled) : ?>
|
||||
<a href="#uc-credits" class="uc-dashboard__stat">
|
||||
<span class="uc-dashboard__stat-num"><?php echo esc_html(number_format($credit_balance, 2)); ?></span>
|
||||
<span class="uc-dashboard__stat-label"><?php echo esc_html($currency_name); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- 快捷操作 -->
|
||||
<div class="uc-dashboard__actions">
|
||||
<a href="<?php echo esc_url(get_edit_profile_url($user_id)); ?>" class="uc-dashboard__action">
|
||||
<i class="fas fa-user-edit"></i>
|
||||
<span><?php esc_html_e('编辑资料', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<a href="<?php echo esc_url(get_edit_profile_url($user_id) . '#password'); ?>" class="uc-dashboard__action">
|
||||
<i class="fas fa-key"></i>
|
||||
<span><?php esc_html_e('修改密码', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php if ($order_count > 0) : ?>
|
||||
<a href="<?php echo esc_url(home_url('/orders/')); ?>" class="uc-dashboard__action">
|
||||
<i class="fas fa-shopping-bag"></i>
|
||||
<span><?php esc_html_e('我的订单', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<a href="<?php echo esc_url(wp_logout_url(home_url())); ?>" class="uc-dashboard__action uc-dashboard__action--danger">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
<span><?php esc_html_e('退出登录', 'aksrt'); ?></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* 用户中心 — 我的收藏
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$per_page = 10;
|
||||
$paged = max(1, get_query_var('paged'));
|
||||
|
||||
$favorite_ids = get_user_meta($user_id, 'aksrt_favorite_posts', true);
|
||||
$favorite_ids = is_array($favorite_ids) ? $favorite_ids : [];
|
||||
$total = count($favorite_ids);
|
||||
|
||||
// 分页切片
|
||||
$offset = ($paged - 1) * $per_page;
|
||||
$page_ids = array_slice($favorite_ids, $offset, $per_page);
|
||||
$max_pages = ceil($total / $per_page);
|
||||
?>
|
||||
|
||||
<div class="uc-favorites" id="uc-favorites">
|
||||
<?php if (!empty($page_ids)) : ?>
|
||||
<div class="uc-favorites__list">
|
||||
<?php foreach ($page_ids as $fid) :
|
||||
$post = get_post((int) $fid);
|
||||
if (!$post || $post->post_status !== 'publish') continue;
|
||||
?>
|
||||
<div class="uc-favorites__item">
|
||||
<div class="uc-favorites__content">
|
||||
<h4 class="uc-favorites__title">
|
||||
<a href="<?php echo esc_url(get_permalink($post->ID)); ?>"><?php echo esc_html($post->post_title); ?></a>
|
||||
</h4>
|
||||
<div class="uc-favorites__meta">
|
||||
<span><i class="far fa-clock"></i> <?php echo esc_html(get_the_date('Y-m-d', $post->ID)); ?></span>
|
||||
<span><i class="far fa-eye"></i> <?php echo esc_html(get_post_meta($post->ID, 'aksrt_post_views', true) ?: 0); ?></span>
|
||||
</div>
|
||||
<button class="uc-favorites__remove" data-action="remove-favorite" data-post-id="<?php echo esc_attr($post->ID); ?>">
|
||||
<i class="fas fa-heart-broken"></i> <?php esc_html_e('取消收藏', 'aksrt'); ?>
|
||||
</button>
|
||||
</div>
|
||||
<?php if (has_post_thumbnail($post->ID)) : ?>
|
||||
<a href="<?php echo esc_url(get_permalink($post->ID)); ?>" class="uc-favorites__thumb">
|
||||
<?php echo get_the_post_thumbnail($post->ID, 'thumbnail'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($max_pages > 1) : ?>
|
||||
<div class="aksrt-pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'base' => str_replace(999999999, '%#%', esc_url(get_pagenum_link(999999999))),
|
||||
'format' => '?paged=%#%',
|
||||
'current' => $paged,
|
||||
'total' => $max_pages,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="empty-state empty-state--sm">
|
||||
<div class="empty-state__icon"><i class="far fa-heart"></i></div>
|
||||
<p class="empty-state__title"><?php esc_html_e('暂无收藏', 'aksrt'); ?></p>
|
||||
<p class="empty-state__desc"><?php esc_html_e('看到喜欢的文章,点击收藏按钮即可保存~', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* 用户中心 — 我的文章
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$per_page = 10;
|
||||
$paged = max(1, get_query_var('paged'));
|
||||
|
||||
$query = new WP_Query([
|
||||
'author' => $user_id,
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $paged,
|
||||
'no_found_rows' => false,
|
||||
]);
|
||||
?>
|
||||
|
||||
<div class="uc-posts" id="uc-posts">
|
||||
<?php if ($query->have_posts()) : ?>
|
||||
<div class="uc-posts__list">
|
||||
<?php while ($query->have_posts()) : $query->the_post(); ?>
|
||||
<div class="uc-posts__item">
|
||||
<div class="uc-posts__content">
|
||||
<h4 class="uc-posts__title">
|
||||
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
|
||||
</h4>
|
||||
<div class="uc-posts__meta">
|
||||
<span><i class="far fa-clock"></i> <?php echo esc_html(get_the_date()); ?></span>
|
||||
<span><i class="far fa-eye"></i> <?php echo esc_html(get_post_meta(get_the_ID(), 'aksrt_post_views', true) ?: 0); ?></span>
|
||||
<span><i class="far fa-comment"></i> <?php echo esc_html(get_comments_number()); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php if (has_post_thumbnail()) : ?>
|
||||
<a href="<?php the_permalink(); ?>" class="uc-posts__thumb">
|
||||
<?php the_post_thumbnail('thumbnail'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endwhile; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($query->max_num_pages > 1) : ?>
|
||||
<div class="aksrt-pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'base' => str_replace(999999999, '%#%', esc_url(get_pagenum_link(999999999))),
|
||||
'format' => '?paged=%#%',
|
||||
'current' => $paged,
|
||||
'total' => $query->max_num_pages,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="empty-state empty-state--sm">
|
||||
<div class="empty-state__icon"><i class="far fa-file-alt"></i></div>
|
||||
<p class="empty-state__title"><?php esc_html_e('暂无文章', 'aksrt'); ?></p>
|
||||
<p class="empty-state__desc"><?php esc_html_e('你还没有发布过文章,去写一篇吧~', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php wp_reset_postdata(); ?>
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<!-- 公开用户主页 partial 模板目录 -->
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* 公开用户主页 — 评论列表
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user_id = $args['user_id'] ?? 0;
|
||||
$per_page = $args['per_page'] ?? 15;
|
||||
$paged = max(1, get_query_var('paged'));
|
||||
|
||||
$total = get_comments([
|
||||
'user_id' => $user_id,
|
||||
'status' => 'approve',
|
||||
'post_status' => 'publish',
|
||||
'count' => true,
|
||||
]);
|
||||
|
||||
$comments = get_comments([
|
||||
'user_id' => $user_id,
|
||||
'status' => 'approve',
|
||||
'post_status' => 'publish',
|
||||
'number' => $per_page,
|
||||
'offset' => ($paged - 1) * $per_page,
|
||||
'orderby' => 'comment_date_gmt',
|
||||
'order' => 'DESC',
|
||||
]);
|
||||
|
||||
$max_pages = ceil($total / $per_page);
|
||||
?>
|
||||
|
||||
<div class="uh-comments">
|
||||
<?php if (!empty($comments)) : ?>
|
||||
<div class="uh-comments__list">
|
||||
<?php foreach ($comments as $comment) :
|
||||
$post = get_post($comment->comment_post_ID);
|
||||
if (!$post) continue;
|
||||
?>
|
||||
<div class="uh-comments__item">
|
||||
<div class="uh-comments__header">
|
||||
<a href="<?php echo esc_url(get_permalink($post->ID)); ?>" class="uh-comments__post-title">
|
||||
<?php echo esc_html($post->post_title); ?>
|
||||
</a>
|
||||
<span class="uh-comments__date"><?php echo esc_html(get_comment_date('Y-m-d', $comment)); ?></span>
|
||||
</div>
|
||||
<div class="uh-comments__body">
|
||||
<?php echo function_exists('aksrt_render_comment_content') ? aksrt_render_comment_content((string) get_comment_text($comment)) : wp_kses_post((string) $comment->comment_content); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($max_pages > 1) : ?>
|
||||
<div class="aksrt-pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'base' => str_replace(999999999, '%#%', esc_url(get_pagenum_link(999999999))),
|
||||
'format' => '?tab=comments&paged=%#%',
|
||||
'current' => $paged,
|
||||
'total' => $max_pages,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="empty-state empty-state--sm">
|
||||
<div class="empty-state__icon"><i class="far fa-comment-dots"></i></div>
|
||||
<p class="empty-state__title"><?php esc_html_e('暂无评论', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* 公开用户主页 — Hero 封面区
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user = $args['user'] ?? null;
|
||||
$user_id = $user ? (int) $user->ID : 0;
|
||||
$dashboard = $args['dashboard'] ?? [];
|
||||
$settings = $args['settings'] ?? [];
|
||||
$show_cover = $settings['cover'] ?? true;
|
||||
$show_follow = $settings['follow'] ?? true;
|
||||
$is_own = $dashboard['is_own_profile'] ?? false;
|
||||
$viewer_id = $dashboard['viewer_id'] ?? 0;
|
||||
|
||||
if (!$user) return;
|
||||
|
||||
$cover_url = get_user_meta($user_id, 'aksrt_user_cover', true) ?: '';
|
||||
$avatar = get_avatar_url($user_id, ['size' => 96]);
|
||||
$desc = $user->description ?: '';
|
||||
$is_vip = function_exists('aksrt_is_vip') && aksrt_is_vip($user_id);
|
||||
?>
|
||||
|
||||
<div class="uh-hero <?php echo $cover_url ? 'uh-hero--has-cover' : ''; ?>" <?php echo $cover_url ? 'style="background-image:url(' . esc_url($cover_url) . ')"' : ''; ?>>
|
||||
<div class="uh-hero__overlay"></div>
|
||||
<div class="uh-hero__content">
|
||||
<div class="uh-hero__avatar">
|
||||
<img src="<?php echo esc_url($avatar); ?>" alt="<?php echo esc_attr($user->display_name); ?>" width="96" height="96">
|
||||
<?php if ($is_vip) : ?>
|
||||
<span class="aksrt-vip-badge">VIP</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="uh-hero__info">
|
||||
<h2 class="uh-hero__name">
|
||||
<?php echo esc_html($user->display_name); ?>
|
||||
<?php if ($is_own) : ?>
|
||||
<a href="<?php echo esc_url(get_edit_profile_url($user_id)); ?>" class="uh-hero__edit" title="<?php esc_attr_e('编辑资料', 'aksrt'); ?>">
|
||||
<i class="fas fa-pen"></i>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</h2>
|
||||
<?php if ($desc) : ?>
|
||||
<p class="uh-hero__desc"><?php echo esc_html(wp_trim_words($desc, 50)); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="uh-hero__meta">
|
||||
<span><i class="fas fa-calendar-alt"></i> <?php echo esc_html(date_i18n(get_option('date_format'), strtotime($user->user_registered))); ?></span>
|
||||
<span><i class="fas fa-file-alt"></i> <?php echo esc_html($dashboard['post_count'] ?? 0); ?> <?php esc_html_e('篇文章', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($show_follow && !$is_own && $viewer_id > 0) : ?>
|
||||
<?php
|
||||
$is_following = function_exists('aksrt_is_following') && aksrt_is_following($viewer_id, $user_id);
|
||||
?>
|
||||
<button class="btn <?php echo $is_following ? 'btn-outline-primary' : 'btn-primary'; ?> uh-hero__follow-btn"
|
||||
data-action="toggle-follow"
|
||||
data-target-user="<?php echo esc_attr($user_id); ?>">
|
||||
<i class="fas <?php echo $is_following ? 'fa-user-check' : 'fa-user-plus'; ?>"></i>
|
||||
<?php echo $is_following ? esc_html__('已关注', 'aksrt') : esc_html__('关注', 'aksrt'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* 公开用户主页 — 文章列表
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user_id = $args['user_id'] ?? 0;
|
||||
$per_page = $args['per_page'] ?? 10;
|
||||
$paged = max(1, get_query_var('paged'));
|
||||
|
||||
$query = new WP_Query([
|
||||
'author' => $user_id,
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $paged,
|
||||
'no_found_rows' => false,
|
||||
]);
|
||||
|
||||
if (!$query->have_posts()) :
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
<div class="empty-state empty-state--sm">
|
||||
<div class="empty-state__icon"><i class="far fa-file-alt"></i></div>
|
||||
<p class="empty-state__title"><?php esc_html_e('暂无文章', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php return;
|
||||
endif;
|
||||
?>
|
||||
|
||||
<div class="uh-posts">
|
||||
<?php while ($query->have_posts()) : $query->the_post(); ?>
|
||||
<?php get_template_part('templates/parts/content-post-card'); ?>
|
||||
<?php endwhile; ?>
|
||||
|
||||
<?php if ($query->max_num_pages > 1) : ?>
|
||||
<div class="aksrt-pagination">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'base' => str_replace(999999999, '%#%', esc_url(get_pagenum_link(999999999))),
|
||||
'format' => '?tab=posts&paged=%#%',
|
||||
'current' => $paged,
|
||||
'total' => $query->max_num_pages,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php wp_reset_postdata(); ?>
|
||||
</div>
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* 公开用户主页 — 侧边栏
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$user = $args['user'] ?? null;
|
||||
$user_id = $user ? (int) $user->ID : 0;
|
||||
$dashboard = $args['dashboard'] ?? [];
|
||||
$settings = $args['settings'] ?? [];
|
||||
$show_follow = $settings['follow'] ?? true;
|
||||
$is_own = $dashboard['is_own_profile'] ?? false;
|
||||
$viewer_id = $dashboard['viewer_id'] ?? 0;
|
||||
$contacts = $dashboard['user_contacts'] ?? [];
|
||||
|
||||
if (!$user) return;
|
||||
?>
|
||||
|
||||
<div class="uh-sidebar">
|
||||
<!-- 数据统计 -->
|
||||
<div class="widget">
|
||||
<div class="widget-title"><i class="fas fa-chart-bar"></i> <?php esc_html_e('数据概览', 'aksrt'); ?></div>
|
||||
<div class="widget-content">
|
||||
<div class="uh-sidebar__stats">
|
||||
<div class="uh-sidebar__stat">
|
||||
<span class="uh-sidebar__stat-num"><?php echo esc_html($dashboard['post_count'] ?? 0); ?></span>
|
||||
<span class="uh-sidebar__stat-label"><?php esc_html_e('文章', 'aksrt'); ?></span>
|
||||
</div>
|
||||
<div class="uh-sidebar__stat">
|
||||
<span class="uh-sidebar__stat-num"><?php echo esc_html($dashboard['comment_count'] ?? 0); ?></span>
|
||||
<span class="uh-sidebar__stat-label"><?php esc_html_e('评论', 'aksrt'); ?></span>
|
||||
</div>
|
||||
<div class="uh-sidebar__stat">
|
||||
<span class="uh-sidebar__stat-num"><?php echo esc_html($dashboard['follower_count'] ?? 0); ?></span>
|
||||
<span class="uh-sidebar__stat-label"><?php esc_html_e('粉丝', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 社交链接 -->
|
||||
<?php if (!empty($contacts)) : ?>
|
||||
<div class="widget">
|
||||
<div class="widget-title"><i class="fas fa-link"></i> <?php esc_html_e('社交链接', 'aksrt'); ?></div>
|
||||
<div class="widget-content">
|
||||
<div class="uh-sidebar__contacts">
|
||||
<?php foreach ($contacts as $contact) : ?>
|
||||
<a href="<?php echo esc_url($contact['url'] ?? '#'); ?>" target="_blank" rel="noopener noreferrer" class="uh-sidebar__contact" title="<?php echo esc_attr($contact['name'] ?? ''); ?>">
|
||||
<i class="fab fa-<?php echo esc_attr($contact['icon'] ?? 'link'); ?>"></i>
|
||||
<span><?php echo esc_html($contact['name'] ?? ''); ?></span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 关注/粉丝 -->
|
||||
<?php if ($show_follow && !$is_own && $viewer_id > 0) : ?>
|
||||
<?php
|
||||
$following_ids = function_exists('aksrt_get_following_ids') ? aksrt_get_following_ids($user_id, 6) : [];
|
||||
$follower_ids = function_exists('aksrt_get_follower_ids') ? aksrt_get_follower_ids($user_id, 6) : [];
|
||||
?>
|
||||
<?php if (!empty($following_ids) || !empty($follower_ids)) : ?>
|
||||
<div class="widget">
|
||||
<div class="widget-title"><i class="fas fa-users"></i> <?php esc_html_e('社交关系', 'aksrt'); ?></div>
|
||||
<div class="widget-content">
|
||||
<?php if (!empty($following_ids)) : ?>
|
||||
<div class="uh-sidebar__follow-section">
|
||||
<span class="uh-sidebar__follow-label"><?php esc_html_e('关注', 'aksrt'); ?></span>
|
||||
<div class="uh-sidebar__avatars">
|
||||
<?php foreach ($following_ids as $fid) :
|
||||
$f_user = get_userdata($fid);
|
||||
if (!$f_user) continue;
|
||||
?>
|
||||
<a href="<?php echo esc_url(get_author_posts_url($fid)); ?>">
|
||||
<?php echo get_avatar($fid, 32); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($follower_ids)) : ?>
|
||||
<div class="uh-sidebar__follow-section">
|
||||
<span class="uh-sidebar__follow-label"><?php esc_html_e('粉丝', 'aksrt'); ?></span>
|
||||
<div class="uh-sidebar__avatars">
|
||||
<?php foreach ($follower_ids as $fid) :
|
||||
$f_user = get_userdata($fid);
|
||||
if (!$f_user) continue;
|
||||
?>
|
||||
<a href="<?php echo esc_url(get_author_posts_url($fid)); ?>">
|
||||
<?php echo get_avatar($fid, 32); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* 用户页面共享辅助函数
|
||||
*
|
||||
* 分页渲染和空状态卡片,供本人中心和公开主页共用。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_render_profile_pagination')) {
|
||||
/**
|
||||
* 渲染分页
|
||||
*
|
||||
* @param int $total_pages 总页数
|
||||
* @param int $current 当前页
|
||||
* @param string $param URL 参数名
|
||||
*/
|
||||
function aksrt_render_profile_pagination($total_pages, $current, $param) {
|
||||
if ($total_pages <= 1) {
|
||||
return;
|
||||
}
|
||||
$base = remove_query_arg($param);
|
||||
$base = add_query_arg($param, '%#%', $base);
|
||||
$links = paginate_links([
|
||||
'base' => $base,
|
||||
'format' => '',
|
||||
'current' => $current,
|
||||
'total' => $total_pages,
|
||||
'prev_text' => '<span aria-hidden="true">‹</span><span class="screen-reader-text">' . esc_html__('上一页', 'aksrt') . '</span>',
|
||||
'next_text' => '<span aria-hidden="true">›</span><span class="screen-reader-text">' . esc_html__('下一页', 'aksrt') . '</span>',
|
||||
'mid_size' => 1,
|
||||
'end_size' => 1,
|
||||
]);
|
||||
if ($links) {
|
||||
echo '<nav class="profile-pagination" aria-label="' . esc_attr__('分页', 'aksrt') . '">' . $links . '</nav>'; // phpcs:ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_profile_empty')) {
|
||||
/**
|
||||
* 渲染空状态卡片
|
||||
*/
|
||||
function aksrt_render_profile_empty($icon_svg, $title, $desc = '', $cta_url = '', $cta_label = '') {
|
||||
echo '<div class="profile-empty">';
|
||||
echo '<div class="profile-empty__icon" aria-hidden="true">' . $icon_svg . '</div>'; // phpcs:ignore
|
||||
echo '<h4 class="profile-empty__title">' . esc_html($title) . '</h4>';
|
||||
if ($desc) {
|
||||
echo '<p class="profile-empty__desc">' . esc_html($desc) . '</p>';
|
||||
}
|
||||
if ($cta_url && $cta_label) {
|
||||
echo '<a class="btn-primary btn-sm profile-empty__cta" href="' . esc_url($cta_url) . '">' . esc_html($cta_label) . '</a>';
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/**
|
||||
* Author Hero — shared hero section for author archive and public user homepage.
|
||||
*
|
||||
* Expected variables (passed via get_template_part or set_query_var):
|
||||
* $user (WP_User) Target user object.
|
||||
* $dashboard (array) Data from aksrt_get_user_dashboard_view().
|
||||
* $user_home_settings (array) User home display settings.
|
||||
* $is_author_page (bool) True when rendering on author.php (archive context).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (empty($user) || !($user instanceof WP_User)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user_id = (int) $user->ID;
|
||||
$dashboard = $dashboard ?? [];
|
||||
$settings = $user_home_settings ?? [];
|
||||
$is_author = !empty($is_author_page);
|
||||
$home_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user) : home_url('/');
|
||||
$show_cover = !empty($settings['cover']);
|
||||
$show_follow = !empty($settings['follow']);
|
||||
|
||||
$post_count = (int) ($dashboard['post_count'] ?? 0);
|
||||
$comment_count = (int) ($dashboard['comment_count'] ?? 0);
|
||||
$favorite_count = (int) ($dashboard['favorite_count'] ?? 0);
|
||||
$contacts = $dashboard['user_contacts'] ?? [];
|
||||
$social_on = !empty($dashboard['social_links_on']);
|
||||
$signals = $dashboard['profile_signals'] ?? [];
|
||||
$notice = $dashboard['profile_notice'] ?? null;
|
||||
$show_report = !empty($dashboard['show_report']);
|
||||
$bg_url = $dashboard['background_url'] ?? '';
|
||||
$is_own = !empty($dashboard['is_own_profile']);
|
||||
?>
|
||||
|
||||
<div class="aksrt-author-hero<?php echo $show_cover ? '' : ' aksrt-author-hero--no-cover'; ?>">
|
||||
<?php if ($show_cover) : ?>
|
||||
<div class="aksrt-author-hero__cover">
|
||||
<img class="aksrt-author-hero__cover-img"
|
||||
src="<?php echo esc_url($bg_url ? $bg_url : get_theme_file_uri('assets/img/person_background.png')); ?>"
|
||||
alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('cover') : ' loading="lazy"'; ?>>
|
||||
<div class="aksrt-author-hero__cover-mask"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-author-hero__body">
|
||||
<div class="aksrt-author-hero__avatar">
|
||||
<?php
|
||||
if (function_exists('aksrt_get_avatar_html')) {
|
||||
echo aksrt_get_avatar_html($user_id, 120, ['loading' => 'lazy']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
} else {
|
||||
echo get_avatar($user_id, 120, '', $user->display_name); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-author-hero__info">
|
||||
<h1 class="aksrt-author-hero__name">
|
||||
<?php echo esc_html($user->display_name); ?>
|
||||
<?php
|
||||
$vip_badge = function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($user_id) : '';
|
||||
if ($vip_badge) {
|
||||
echo $vip_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
?>
|
||||
</h1>
|
||||
|
||||
<?php if ($user->description) : ?>
|
||||
<p class="aksrt-author-hero__desc"><?php echo esc_html($user->description); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($signals)) : ?>
|
||||
<div class="aksrt-identity-chips">
|
||||
<?php foreach ($signals as $signal) : ?>
|
||||
<span class="aksrt-identity-chip aksrt-identity-chip--<?php echo esc_attr($signal['tone']); ?>">
|
||||
<i class="fas fa-<?php echo esc_attr($signal['icon']); ?>" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html($signal['label']); ?></span>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="aksrt-author-hero__stats">
|
||||
<span class="aksrt-author-hero__stat">
|
||||
<strong><?php echo esc_html((string) $post_count); ?></strong>
|
||||
<span><?php esc_html_e('文章', 'aksrt'); ?></span>
|
||||
</span>
|
||||
<span class="aksrt-author-hero__stat">
|
||||
<strong><?php echo esc_html((string) $comment_count); ?></strong>
|
||||
<span><?php esc_html_e('评论', 'aksrt'); ?></span>
|
||||
</span>
|
||||
<span class="aksrt-author-hero__stat">
|
||||
<strong><?php echo esc_html((string) $favorite_count); ?></strong>
|
||||
<span><?php esc_html_e('收藏', 'aksrt'); ?></span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($contacts) && $social_on) : ?>
|
||||
<div class="aksrt-author-hero__contacts">
|
||||
<?php if (function_exists('aksrt_render_social_links')) : ?>
|
||||
<?php aksrt_render_social_links($contacts); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-author-hero__actions">
|
||||
<?php if ($is_own) : ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_user_center_url()); ?>" class="btn-ghost btn-sm">
|
||||
<i class="fas fa-cog" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('个人中心', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php elseif ($show_follow) : ?>
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<button type="button" class="btn-outline btn-sm aksrt-author-hero__follow-btn" data-aksrt-follow="<?php echo (int) $user_id; ?>" title="<?php esc_attr_e('关注该用户', 'aksrt'); ?>">
|
||||
<i class="far fa-heart" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('关注', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_login_url($home_url)); ?>" class="btn-outline btn-sm aksrt-author-hero__follow-btn">
|
||||
<i class="far fa-heart" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('登录后关注', 'aksrt'); ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($show_report) : ?>
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
<button type="button" class="btn-ghost btn-sm aksrt-author-hero__report-btn" data-aksrt-report='{"target_type":"user","target_id":<?php echo (int) $user_id; ?>}' title="<?php esc_attr_e('举报该用户', 'aksrt'); ?>">
|
||||
<i class="far fa-flag" aria-hidden="true"></i>
|
||||
</button>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url(aksrt_get_login_url($home_url)); ?>" class="btn-ghost btn-sm aksrt-author-hero__report-btn">
|
||||
<i class="far fa-flag" aria-hidden="true"></i>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($is_author && function_exists('aksrt_render_admin_quick_link')) { aksrt_render_admin_quick_link('page-display/user-home', __('用户主页设置', 'aksrt')); } ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($notice)) : ?>
|
||||
<div class="aksrt-author-hero__notice aksrt-author-hero__notice--<?php echo esc_attr($notice['state']); ?>">
|
||||
<i class="fas fa-exclamation-circle" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html($notice['text']); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* 商品分类归档模板
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$term = get_queried_object();
|
||||
$paged = max(1, (int) get_query_var('paged'));
|
||||
$shop = class_exists('AKSRT_Shop') ? AKSRT_Shop::get_instance() : null;
|
||||
$view = $shop ? $shop->get_product_archive_view([
|
||||
'taxonomy' => 'aksrt_product_cat',
|
||||
'term_id' => $term->term_id,
|
||||
'paged' => $paged,
|
||||
]) : ['products' => [], 'term' => null, 'total' => 0, 'max_pages' => 0];
|
||||
|
||||
$products = $view['products'];
|
||||
$total = $view['total'];
|
||||
$max_pages = $view['max_pages'];
|
||||
$term_name = $term->name ?? '';
|
||||
$term_desc = $term->description ?? '';
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) aksrt_breadcrumbs(); ?>
|
||||
|
||||
<div class="aksrt-product-archive container">
|
||||
<header class="aksrt-product-archive__header">
|
||||
<h1 class="aksrt-product-archive__title"><?php echo esc_html($term_name); ?></h1>
|
||||
<?php if ($term_desc) : ?>
|
||||
<p class="aksrt-product-archive__desc"><?php echo esc_html($term_desc); ?></p>
|
||||
<?php endif; ?>
|
||||
<p class="aksrt-product-archive__count"><?php printf(esc_html__('共 %d 件商品', 'aksrt'), $total); ?></p>
|
||||
</header>
|
||||
|
||||
<?php if (!empty($products)) : ?>
|
||||
<div class="aksrt-product-archive__grid" id="aksrt-product-grid">
|
||||
<?php foreach ($products as $product) : ?>
|
||||
<article class="aksrt-product-card">
|
||||
<a href="<?php echo esc_url($product['permalink']); ?>" class="aksrt-product-card__link">
|
||||
<?php if ($product['image']) : ?>
|
||||
<div class="aksrt-product-card__image">
|
||||
<img src="<?php echo esc_url($product['image']); ?>" alt="<?php echo esc_attr($product['title']); ?>"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-card__image aksrt-product-card__image--placeholder">
|
||||
<i class="fas fa-image"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__body">
|
||||
<h3 class="aksrt-product-card__title"><?php echo esc_html($product['title']); ?></h3>
|
||||
<?php if ($product['excerpt']) : ?>
|
||||
<p class="aksrt-product-card__excerpt"><?php echo esc_html(wp_trim_words($product['excerpt'], 15)); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__footer">
|
||||
<span class="aksrt-product-card__price">¥<?php echo esc_html(number_format($product['price'], 2)); ?></span>
|
||||
<?php if ($product['sales'] > 0) : ?>
|
||||
<span class="aksrt-product-card__sales"><?php printf(esc_html__('已售 %d', 'aksrt'), $product['sales']); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($max_pages > 1) : ?>
|
||||
<nav class="aksrt-product-archive__pagination" aria-label="<?php esc_attr_e('商品分页', 'aksrt'); ?>">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'total' => $max_pages,
|
||||
'current' => $paged,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-archive__empty">
|
||||
<i class="fas fa-box-open"></i>
|
||||
<p><?php esc_html_e('该分类下暂无商品', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
wp_enqueue_script('aksrt-product-archive', get_template_directory_uri() . '/assets/js/product-archive.js', [], AKSRT_VERSION, true);
|
||||
get_footer();
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* 商品标签归档模板
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
$term = get_queried_object();
|
||||
$paged = max(1, (int) get_query_var('paged'));
|
||||
$shop = class_exists('AKSRT_Shop') ? AKSRT_Shop::get_instance() : null;
|
||||
$view = $shop ? $shop->get_product_archive_view([
|
||||
'taxonomy' => 'aksrt_product_tag',
|
||||
'term_id' => $term->term_id,
|
||||
'paged' => $paged,
|
||||
]) : ['products' => [], 'term' => null, 'total' => 0, 'max_pages' => 0];
|
||||
|
||||
$products = $view['products'];
|
||||
$total = $view['total'];
|
||||
$max_pages = $view['max_pages'];
|
||||
$term_name = $term->name ?? '';
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) aksrt_breadcrumbs(); ?>
|
||||
|
||||
<div class="aksrt-product-archive container">
|
||||
<header class="aksrt-product-archive__header">
|
||||
<h1 class="aksrt-product-archive__title">
|
||||
<i class="fas fa-tag"></i>
|
||||
<?php echo esc_html($term_name); ?>
|
||||
</h1>
|
||||
<p class="aksrt-product-archive__count"><?php printf(esc_html__('共 %d 件商品', 'aksrt'), $total); ?></p>
|
||||
</header>
|
||||
|
||||
<?php if (!empty($products)) : ?>
|
||||
<div class="aksrt-product-archive__grid" id="aksrt-product-grid">
|
||||
<?php foreach ($products as $product) : ?>
|
||||
<article class="aksrt-product-card">
|
||||
<a href="<?php echo esc_url($product['permalink']); ?>" class="aksrt-product-card__link">
|
||||
<?php if ($product['image']) : ?>
|
||||
<div class="aksrt-product-card__image">
|
||||
<img src="<?php echo esc_url($product['image']); ?>" alt="<?php echo esc_attr($product['title']); ?>"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-card__image aksrt-product-card__image--placeholder">
|
||||
<i class="fas fa-image"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__body">
|
||||
<h3 class="aksrt-product-card__title"><?php echo esc_html($product['title']); ?></h3>
|
||||
<?php if ($product['excerpt']) : ?>
|
||||
<p class="aksrt-product-card__excerpt"><?php echo esc_html(wp_trim_words($product['excerpt'], 15)); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__footer">
|
||||
<span class="aksrt-product-card__price">¥<?php echo esc_html(number_format($product['price'], 2)); ?></span>
|
||||
<?php if ($product['sales'] > 0) : ?>
|
||||
<span class="aksrt-product-card__sales"><?php printf(esc_html__('已售 %d', 'aksrt'), $product['sales']); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($max_pages > 1) : ?>
|
||||
<nav class="aksrt-product-archive__pagination" aria-label="<?php esc_attr_e('商品分页', 'aksrt'); ?>">
|
||||
<?php
|
||||
echo paginate_links([
|
||||
'total' => $max_pages,
|
||||
'current' => $paged,
|
||||
'prev_text' => '<i class="fas fa-chevron-left"></i>',
|
||||
'next_text' => '<i class="fas fa-chevron-right"></i>',
|
||||
]);
|
||||
?>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-archive__empty">
|
||||
<i class="fas fa-box-open"></i>
|
||||
<p><?php esc_html_e('该标签下暂无商品', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
wp_enqueue_script('aksrt-product-archive', get_template_directory_uri() . '/assets/js/product-archive.js', [], AKSRT_VERSION, true);
|
||||
get_footer();
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode template: [aksrt_archive]
|
||||
*
|
||||
* 紧凑版文章归档(按年月分组)。供 AKSRT_Shortcodes::render_archive() 通过
|
||||
* AKSRT_Templates::render_archive_shortcode() 以输出缓冲方式 include。
|
||||
*
|
||||
* 可用变量:$attrs(短代码属性)、$content。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$limit = isset($attrs['limit']) ? max(0, (int) $attrs['limit']) : 0; // 0 = 全部
|
||||
|
||||
$rows = $wpdb->get_results(
|
||||
"SELECT DISTINCT YEAR(post_date) AS year, MONTH(post_date) AS month, COUNT(*) AS count
|
||||
FROM {$wpdb->posts}
|
||||
WHERE post_type = 'post' AND post_status = 'publish'
|
||||
GROUP BY YEAR(post_date), MONTH(post_date)
|
||||
ORDER BY year DESC, month DESC"
|
||||
); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
|
||||
|
||||
if (empty($rows)) {
|
||||
echo '<div class="aksrt-archives aksrt-archives--shortcode aksrt-archives--empty">'
|
||||
. esc_html__('暂无文章。', 'aksrt') . '</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
$current_year = 0;
|
||||
$shown = 0;
|
||||
?>
|
||||
<div class="aksrt-archives aksrt-archives--shortcode">
|
||||
<?php foreach ($rows as $row) :
|
||||
if ((int) $row->year !== $current_year) :
|
||||
$current_year = (int) $row->year;
|
||||
?>
|
||||
<h2 class="aksrt-archives__year"><?php echo esc_html((string) $current_year); ?></h2>
|
||||
<?php endif; ?>
|
||||
<h3 class="aksrt-archives__month"><?php echo esc_html(sprintf(__('%1$d 月(%2$d 篇)', 'aksrt'), (int) $row->month, (int) $row->count)); ?></h3>
|
||||
<ul class="aksrt-archives__list">
|
||||
<?php
|
||||
$month_posts = get_posts([
|
||||
'year' => (int) $row->year,
|
||||
'monthnum' => (int) $row->month,
|
||||
'posts_per_page' => -1,
|
||||
'post_status' => 'publish',
|
||||
'no_found_rows' => true,
|
||||
]);
|
||||
foreach ($month_posts as $mp) :
|
||||
if ($limit > 0 && $shown >= $limit) {
|
||||
break;
|
||||
}
|
||||
$shown++;
|
||||
?>
|
||||
<li class="aksrt-archives__item">
|
||||
<span class="aksrt-archives__date"><?php echo esc_html(get_the_date('m-d', $mp)); ?></span>
|
||||
<a href="<?php echo esc_url(get_permalink($mp->ID)); ?>" class="aksrt-archives__link"><?php echo esc_html(get_the_title($mp)); ?></a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php if ($limit > 0 && $shown >= $limit) { break; } ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Shortcode template: [aksrt_profile]
|
||||
*
|
||||
* 当前登录用户的资料卡。供 AKSRT_Shortcodes::render_profile() 通过
|
||||
* AKSRT_Templates::render_profile_shortcode() 以输出缓冲方式 include。
|
||||
*
|
||||
* 可用变量:$attrs(短代码属性,支持 user="<ID 或 login>" 指定用户)、$content。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
// 解析目标用户:属性指定 > 当前登录用户。
|
||||
$target = isset($attrs['user']) ? trim((string) $attrs['user']) : '';
|
||||
$user = null;
|
||||
if ($target !== '') {
|
||||
$user = is_numeric($target) ? get_user_by('id', (int) $target) : get_user_by('login', $target);
|
||||
} elseif (is_user_logged_in()) {
|
||||
$user = wp_get_current_user();
|
||||
}
|
||||
|
||||
if (!($user instanceof WP_User) || $user->ID <= 0) {
|
||||
echo '<div class="aksrt-profile-card aksrt-profile-card--shortcode aksrt-profile-card--guest">'
|
||||
. '<p>' . esc_html__('登录后查看个人资料。', 'aksrt') . '</p>';
|
||||
if (function_exists('aksrt_get_login_url')) {
|
||||
echo '<a class="btn-primary btn-sm" href="' . esc_url(aksrt_get_login_url()) . '">' . esc_html__('登录', 'aksrt') . '</a>';
|
||||
}
|
||||
echo '</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
$user_id = (int) $user->ID;
|
||||
$avatar = function_exists('aksrt_get_avatar_url') ? aksrt_get_avatar_url($user_id, ['size' => 96]) : get_avatar_url($user_id, ['size' => 96]);
|
||||
$home_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user) : get_author_posts_url($user_id);
|
||||
$credits = function_exists('aksrt_user_credits') ? (int) aksrt_user_credits($user_id) : 0;
|
||||
$post_count = (int) count_user_posts($user_id, 'post', true);
|
||||
$bio = (string) get_the_author_meta('description', $user_id);
|
||||
$show_credits = class_exists('AKSRT_Settings') ? AKSRT_Settings::credits_enabled() : true;
|
||||
?>
|
||||
<div class="aksrt-profile-card aksrt-profile-card--shortcode">
|
||||
<a class="aksrt-profile-card__avatar" href="<?php echo esc_url($home_url); ?>">
|
||||
<img src="<?php echo esc_url($avatar); ?>" alt="<?php echo esc_attr($user->display_name); ?>" width="64" height="64"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('avatar') : ' loading="lazy"'; ?>>
|
||||
</a>
|
||||
<div class="aksrt-profile-card__body">
|
||||
<a class="aksrt-profile-card__name" href="<?php echo esc_url($home_url); ?>"><?php echo esc_html($user->display_name); ?></a>
|
||||
<?php if ($bio !== '') : ?>
|
||||
<p class="aksrt-profile-card__bio"><?php echo esc_html(wp_trim_words($bio, 24, '…')); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-profile-card__stats">
|
||||
<span class="aksrt-profile-card__stat"><strong><?php echo esc_html(number_format_i18n($post_count)); ?></strong><?php esc_html_e('文章', 'aksrt'); ?></span>
|
||||
<?php if ($show_credits) : ?>
|
||||
<span class="aksrt-profile-card__stat"><strong><?php echo esc_html(number_format_i18n($credits)); ?></strong><?php esc_html_e('积分', 'aksrt'); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in new issue
Block a user