feat(forum): frontend 1:1 list/tabs/urls/enqueue

Wire Zibll-style board sort tabs, shared topic rows, page-template
URLs, forum asset enqueue on home/plate, home synthesis load-more,
and topic last_reply meta for last-reply ordering. No dual-read.
This commit is contained in:
2026-07-12 08:38:31 +08:00
parent df6b224dd3
commit 780c8cb4f7
23 changed files with 843 additions and 481 deletions
+201
View File
@@ -454,3 +454,204 @@
color: var(--color-primary);
}
/* Board sort tabs */
.aksrt-forum-board__tabs {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 0 0 16px;
padding: 8px;
border-radius: var(--radius-xl, 12px);
background: var(--surface-1, #fff);
box-shadow: var(--shadow-sm);
}
.aksrt-forum-board__tab {
display: inline-flex;
align-items: center;
padding: 8px 14px;
border-radius: 999px;
color: var(--color-ink-3, #5c6370);
text-decoration: none;
font-size: 14px;
font-weight: 600;
transition: background .15s ease, color .15s ease;
}
.aksrt-forum-board__tab:hover {
background: rgba(240, 68, 148, 0.08);
color: var(--color-primary, #f04494);
}
.aksrt-forum-board__tab.is-active {
background: var(--color-primary, #f04494);
color: #fff;
}
.aksrt-forum-board__governance--footer {
margin-top: 28px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 16px;
}
.aksrt-forum-topic-row {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 14px 16px;
margin-bottom: 10px;
border-radius: var(--radius-xl, 12px);
background: var(--surface-1, #fff);
box-shadow: var(--shadow-sm);
}
.aksrt-forum-topic-row__avatar img {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
}
.aksrt-forum-topic-row__body {
flex: 1;
min-width: 0;
}
.aksrt-forum-topic-row__title-wrap {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px;
}
.aksrt-forum-topic-row__title {
margin: 0;
font-size: 16px;
font-weight: 700;
}
.aksrt-forum-topic-row__title a {
color: var(--color-ink);
text-decoration: none;
}
.aksrt-forum-topic-row__meta {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 6px;
color: var(--color-ink-4, #8a909c);
font-size: 12px;
}
.aksrt-forum-topic-row__badge {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 999px;
font-size: 12px;
font-weight: 700;
line-height: 1.4;
}
.aksrt-forum-topic-row__badge--sticky { background: rgba(255, 149, 0, 0.12); color: #c77700; }
.aksrt-forum-topic-row__badge--featured { background: rgba(240, 68, 148, 0.12); color: #f04494; }
.aksrt-forum-topic-row__badge--question { background: rgba(47, 128, 237, 0.12); color: #2f80ed; }
.aksrt-forum-topic-row__badge--question.is-solved { background: rgba(39, 174, 96, 0.12); color: #27ae60; }
.aksrt-forum-topic-row__cover {
position: relative;
width: 84px;
height: 60px;
flex: 0 0 auto;
border-radius: 10px;
overflow: hidden;
background: var(--surface-2, #f5f6f8);
}
.aksrt-forum-topic-row__cover img {
width: 100%;
height: 100%;
object-fit: cover;
}
.aksrt-forum-topic-row__cover .fa-play-circle,
.aksrt-forum-topic-row__cover-count {
position: absolute;
right: 6px;
bottom: 6px;
color: #fff;
text-shadow: 0 1px 2px rgba(0,0,0,.35);
}
.aksrt-forum-board-card__grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 12px;
}
.aksrt-forum-board-card {
display: flex;
flex-direction: column;
overflow: hidden;
border-radius: var(--radius-xl, 12px);
background: var(--surface-1, #fff);
box-shadow: var(--shadow-sm);
text-decoration: none;
color: inherit;
}
.aksrt-forum-board-card__cover {
display: block;
height: 96px;
background-size: cover;
background-position: center;
}
.aksrt-forum-board-card__cover--empty {
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, rgba(240,68,148,.08), rgba(47,128,237,.08));
color: var(--color-primary, #f04494);
font-size: 24px;
}
.aksrt-forum-board-card__body {
display: flex;
flex-direction: column;
gap: 6px;
padding: 12px 14px 14px;
}
.aksrt-forum-board-card__title {
font-weight: 700;
}
.aksrt-forum-board-card__desc,
.aksrt-forum-board-card__meta {
font-size: 12px;
color: var(--color-ink-4, #8a909c);
}
.aksrt-forum__empty,
.aksrt-forum-board__empty,
.aksrt-forum-tag__empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 10px;
padding: 48px 20px;
text-align: center;
color: var(--color-ink-4, #8a909c);
}
.aksrt-forum__empty a,
.aksrt-forum-board__empty a {
color: var(--color-primary, #f04494);
font-weight: 600;
text-decoration: none;
}
+56
View File
@@ -1322,6 +1322,61 @@
}
}
function bindBoardSortTabs() {
var root = document.querySelector('.aksrt-forum-board[data-plate-id], .aksrt-forum-board[data-board-id]');
if (!root) return;
var list = root.querySelector('.js-aksrt-board-topic-list');
var tabs = root.querySelectorAll('.js-aksrt-board-sort-tab');
if (!list || !tabs.length) return;
var plateId = root.getAttribute('data-plate-id') || '';
var boardId = root.getAttribute('data-board-id') || '';
var nonce = root.getAttribute('data-nonce') || (window.aksrtForumGovernance && aksrtForumGovernance.publicNonce) || (window.aksrtData && aksrtData.nonce) || '';
var ajaxUrl = (window.aksrtForumGovernance && aksrtForumGovernance.ajaxUrl) || (window.aksrtData && aksrtData.ajaxUrl) || '';
function loadSort(sort, pushUrl) {
if (!ajaxUrl) return;
list.style.opacity = '0.55';
var fd = new FormData();
fd.append('action', 'aksrt_forum_board_topics');
fd.append('nonce', nonce);
fd.append('page', '1');
fd.append('orderby', sort);
if (plateId) fd.append('plate_id', plateId);
if (boardId) fd.append('board_id', boardId);
fetch(ajaxUrl, { method: 'POST', body: fd, credentials: 'same-origin' })
.then(function (r) { return r.json(); })
.then(function (res) {
list.style.opacity = '1';
if (!res || !res.success) return;
list.innerHTML = res.data.html || '';
root.setAttribute('data-active-sort', sort);
tabs.forEach(function (t) {
t.classList.toggle('is-active', (t.getAttribute('data-sort') || '') === sort);
});
if (pushUrl && window.history && history.replaceState) {
try {
var u = new URL(window.location.href);
u.searchParams.set('forum_sort', sort);
history.replaceState({}, '', u.toString());
} catch (e) {}
}
})
.catch(function () { list.style.opacity = '1'; });
}
tabs.forEach(function (tab) {
tab.addEventListener('click', function (e) {
e.preventDefault();
var sort = tab.getAttribute('data-sort') || 'date';
if (sort === (root.getAttribute('data-active-sort') || '')) return;
loadSort(sort, true);
});
});
}
function boot() {
var composeForm = document.querySelector('.js-aksrt-forum-compose-form');
if (composeForm) {
@@ -1358,6 +1413,7 @@
document.querySelectorAll('.js-aksrt-unlock-topic').forEach(bindUnlockButton);
bindForumCommentEngine();
bindForumHomeTabs();
bindBoardSortTabs();
document.querySelectorAll('.js-aksrt-edit-plate').forEach(bindEditPlateButton);
document.querySelectorAll('.js-aksrt-delete-plate').forEach(bindDeletePlateButton);
var reportModal = document.querySelector('#aksrt-report-modal');
+1
View File
@@ -31,6 +31,7 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-single.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-archive.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-archive-filters.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-comments.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-forum.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-slider.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-vip.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-i18n-switch.php';
+12
View File
@@ -235,6 +235,14 @@ class AKSRT_Forum {
$this->view_builder()->ajax_home_tab();
}
public function ajax_board_topics(): void {
$this->view_builder()->ajax_board_topics();
}
public function render_board_cards(array $boards): void {
$this->view_builder()->render_board_cards($boards);
}
public function render_topic_row(array $topic): void {
$this->view_builder()->render_topic_row($topic);
}
@@ -365,6 +373,10 @@ class AKSRT_Forum {
add_action('wp_ajax_aksrt_forum_home_tab', [$this, 'ajax_home_tab']);
add_action('wp_ajax_nopriv_aksrt_forum_home_tab', [$this, 'ajax_home_tab']);
// Public plate/board topic list (sort tabs)
add_action('wp_ajax_aksrt_forum_board_topics', [$this, 'ajax_board_topics']);
add_action('wp_ajax_nopriv_aksrt_forum_board_topics', [$this, 'ajax_board_topics']);
add_action('admin_init', [$this, 'maybe_migrate_boards'], 25);
add_filter('template_include', [$this, 'template_routing']);
add_action('wp', [$this, 'maybe_refresh_recommend_on_view']);
@@ -9,10 +9,46 @@ trait AKSRT_Forum_Board_Service_Part_2 {
*/
public function get_board_view(int $board_id, array $args = []): array {
$user_id = (int) ($args['user_id'] ?? get_current_user_id());
$page = max(1, (int) ($args['paged'] ?? 1));
$page = max(1, (int) ($args['paged'] ?? $args['page'] ?? 1));
$orderby = sanitize_key((string) ($args['orderby'] ?? $args['sort'] ?? ''));
$board_page = class_exists('AKSRT_Settings')
? (AKSRT_Settings::get_forum_settings()['board_page'] ?? [])
: [];
$tabs = is_array($board_page['tabs'] ?? null) ? $board_page['tabs'] : [
['label' => '全部', 'sort' => 'date'],
['label' => '推荐', 'sort' => 'featured'],
['label' => '最新回复', 'sort' => 'last_reply'],
['label' => '热门', 'sort' => 'hot'],
['label' => '精华', 'sort' => 'essence'],
];
$allowed_sorts = [];
foreach ($tabs as $tab) {
$sort = sanitize_key((string) ($tab['sort'] ?? ''));
if ($sort !== '') {
$allowed_sorts[] = $sort;
}
}
if ($orderby === '' || !in_array($orderby, $allowed_sorts, true)) {
$active_index = max(0, (int) ($board_page['tab_active_index'] ?? 0));
$orderby = sanitize_key((string) ($tabs[$active_index]['sort'] ?? 'date'));
if ($orderby === '') {
$orderby = 'date';
}
}
$compose_url = function_exists('aksrt_get_forum_compose_url')
? aksrt_get_forum_compose_url(['board' => $board_id])
: home_url('/');
$top_info = !isset($board_page['top_info']) || !empty($board_page['top_info']);
if ($this->forum->is_plate_cpt_active()) {
return $this->get_plate_view_compat($board_id, $user_id, $page);
$view = $this->get_plate_view_compat($board_id, $user_id, $page, $orderby);
$view['tabs'] = $tabs;
$view['active_sort'] = $orderby;
$view['top_info'] = $top_info;
$view['compose_url'] = $compose_url;
return $view;
}
$board = get_term($board_id, 'aksrt_forum_board');
@@ -27,6 +63,10 @@ trait AKSRT_Forum_Board_Service_Part_2 {
'permissions' => [],
'application' => null,
'board_options' => [],
'tabs' => $tabs,
'active_sort' => $orderby,
'top_info' => $top_info,
'compose_url' => function_exists('aksrt_get_forum_compose_url') ? aksrt_get_forum_compose_url() : home_url('/'),
];
}
@@ -36,6 +76,7 @@ trait AKSRT_Forum_Board_Service_Part_2 {
'limit' => 20,
'status' => 'publish',
'viewer_user_id' => $user_id,
'orderby' => $orderby,
]);
$sticky_topics = $this->forum->get_sticky_topics_for_board($board_id);
@@ -75,13 +116,17 @@ trait AKSRT_Forum_Board_Service_Part_2 {
],
'application' => $user_id > 0 ? $this->forum->get_board_application_for_user($user_id, $board_id) : null,
'board_options' => $this->get_boards(),
'tabs' => $tabs,
'active_sort' => $orderby,
'top_info' => $top_info,
'compose_url' => $compose_url,
];
}
/**
* Plate CPT board view (backwards-compatible with get_board_view return shape).
*/
private function get_plate_view_compat(int $plate_id, int $user_id, int $page): array {
private function get_plate_view_compat(int $plate_id, int $user_id, int $page, string $orderby = 'date'): array {
$plate = $this->get_plate($plate_id);
if (!$plate) {
return [
@@ -123,6 +168,7 @@ trait AKSRT_Forum_Board_Service_Part_2 {
'limit' => 20,
'status' => 'publish',
'viewer_user_id' => $user_id,
'orderby' => $orderby,
]);
$sticky_topics = $this->get_sticky_topics_for_plate($plate_id);
@@ -34,6 +34,10 @@ class AKSRT_Forum_Comment_Service {
if ((int) $comment->comment_approved !== 1) return;
$commenter_id = (int) $comment->user_id;
if ($commenter_id <= 0) return;
// Topic-level last_reply for board sort tabs.
update_post_meta((int) $post->ID, '_aksrt_last_reply', (string) $comment->comment_date);
$this->forum->notify_topic_reply((int) $post->ID, $commenter_id);
}
@@ -379,6 +379,7 @@ class AKSRT_Forum_Draft_Service {
update_post_meta($draft_id, '_aksrt_featured', '0');
update_post_meta($draft_id, '_aksrt_locked', '0');
update_post_meta($draft_id, '_aksrt_views', 0);
update_post_meta($draft_id, '_aksrt_last_reply', (string) get_post_field('post_date', $draft_id));
$bbs_type = get_post_meta($draft_id, '_aksrt_bbs_type', true) ?: AKSRT_Forum::BBS_TYPE_STANDARD;
if ($bbs_type === AKSRT_Forum::BBS_TYPE_QUESTION) {
@@ -403,7 +404,7 @@ class AKSRT_Forum_Draft_Service {
: __('主题已提交审核,审核通过后对外展示', 'aksrt'),
'redirect' => $post_status === 'publish'
? get_permalink($draft_id)
: add_query_arg('compose_status', 'pending', home_url('/forums/')),
: add_query_arg('compose_status', 'pending', aksrt_get_forum_home_url()),
];
}
}
@@ -135,7 +135,7 @@ class AKSRT_Forum_Moderation_Service {
: __('已拒绝', 'aksrt');
$payload = [
'title' => __('版主申请结果', 'aksrt'),
'target_url' => isset($board['url']) ? (string) $board['url'] : home_url('/forums/'),
'target_url' => isset($board['url']) ? (string) $board['url'] : aksrt_get_forum_home_url(),
];
$clean_note = sanitize_textarea_field($note);
if ($clean_note !== '') {
@@ -354,7 +354,7 @@ class AKSRT_Forum_Score_Service {
}
$label = $action_labels[$action] ?? __('治理动作已执行', 'aksrt');
$target_url = $action === 'delete' ? home_url('/forums/') : get_permalink($topic_id);
$target_url = $action === 'delete' ? aksrt_get_forum_home_url() : get_permalink($topic_id);
$payload = [
'title' => $label,
'target_url' => $target_url,
@@ -167,6 +167,7 @@ class AKSRT_Forum_Topic_Service {
update_post_meta($post_id, '_aksrt_featured', '0');
update_post_meta($post_id, '_aksrt_locked', '0');
update_post_meta($post_id, '_aksrt_views', 0);
update_post_meta($post_id, '_aksrt_last_reply', (string) get_post_field('post_date', $post_id));
update_post_meta($post_id, '_aksrt_bbs_type', $bbs_type);
if ($bbs_type === AKSRT_Forum::BBS_TYPE_QUESTION) {
update_post_meta($post_id, '_aksrt_question_status', AKSRT_Forum::QUESTION_UNSOLVED);
@@ -196,7 +197,7 @@ class AKSRT_Forum_Topic_Service {
: __('主题已提交审核,审核通过后对外展示', 'aksrt'),
'redirect' => $post_status === 'publish'
? get_permalink($post_id)
: add_query_arg('compose_status', 'pending', home_url('/forums/')),
: add_query_arg('compose_status', 'pending', aksrt_get_forum_home_url()),
];
}
@@ -34,35 +34,55 @@ class AKSRT_Forum_View_Builder {
$visibility = sanitize_key((string) ($args['visibility'] ?? ''));
$review_status = sanitize_key((string) ($args['review_status'] ?? ''));
$author_id = (int) ($args['author_id'] ?? 0);
$orderby = sanitize_key((string) ($args['orderby'] ?? 'date'));
$orderby = sanitize_key((string) ($args['orderby'] ?? ($args['sort'] ?? 'date')));
$viewer_user_id = (int) ($args['viewer_user_id'] ?? get_current_user_id());
$include_hidden = !empty($args['include_hidden']);
// Settings tab aliases: hot→views, essence/featured→featured filter.
if ($orderby === 'hot') {
$orderby = 'views';
}
$query_args = [
'post_type' => 'aksrt_forum_topic',
'posts_per_page' => $limit,
'offset' => $offset,
'post_status' => $this->forum->normalize_post_status_query($status),
'order' => 'DESC',
'ignore_sticky_posts' => true,
'post_type' => 'aksrt_forum_topic',
'posts_per_page' => $limit,
'offset' => $offset,
'post_status' => $this->forum->normalize_post_status_query($status),
'order' => 'DESC',
'ignore_sticky_posts'=> true,
];
$meta_query = [];
if ($orderby === 'views') {
$query_args['orderby'] = 'meta_value_num';
$query_args['orderby'] = 'meta_value_num';
$query_args['meta_key'] = '_aksrt_views';
} elseif ($orderby === 'recommend') {
$query_args['orderby'] = 'meta_value_num';
$query_args['orderby'] = 'meta_value_num';
$query_args['meta_key'] = '_aksrt_recommend_score';
} elseif ($orderby === 'comment_count') {
$query_args['orderby'] = 'comment_count';
} elseif ($orderby === 'score') {
$query_args['orderby'] = 'meta_value_num';
$query_args['orderby'] = 'meta_value_num';
$query_args['meta_key'] = '_aksrt_score';
} elseif ($orderby === 'favorites') {
$query_args['orderby'] = 'meta_value_num';
$query_args['orderby'] = 'meta_value_num';
$query_args['meta_key'] = '_aksrt_favorite_count';
} elseif ($orderby === 'last_reply') {
$query_args['orderby'] = 'meta_value';
$query_args['meta_key'] = '_aksrt_last_reply';
$query_args['meta_type']= 'DATETIME';
} elseif ($orderby === 'featured' || $orderby === 'essence') {
// 推荐 / 精华 share _aksrt_featured (Zibll essence = featured).
$meta_query[] = [
'key' => '_aksrt_featured',
'value' => '1',
'compare' => '=',
];
$query_args['orderby'] = 'date';
} else {
$query_args['orderby'] = 'date';
$orderby = 'date';
}
if ($keyword !== '') {
@@ -76,14 +96,14 @@ class AKSRT_Forum_View_Builder {
$plate_id = (int) ($args['plate_id'] ?? 0);
$plate_ids = $args['plate_ids'] ?? [];
if (!empty($plate_ids) && is_array($plate_ids)) {
$query_args['meta_query'][] = [
$meta_query[] = [
'key' => '_aksrt_plate_id',
'value' => array_map('intval', $plate_ids),
'type' => 'NUMERIC',
'compare' => 'IN',
];
} elseif ($plate_id > 0) {
$query_args['meta_query'][] = [
$meta_query[] = [
'key' => '_aksrt_plate_id',
'value' => $plate_id,
'type' => 'NUMERIC',
@@ -92,29 +112,31 @@ class AKSRT_Forum_View_Builder {
} elseif ($board_id > 0) {
$query_args['tax_query'] = [[
'taxonomy' => 'aksrt_forum_board',
'field' => 'term_id',
'terms' => $board_id,
'field' => 'term_id',
'terms' => $board_id,
]];
}
$meta_query = [];
if ($visibility !== '') {
$meta_query[] = [
'key' => '_aksrt_visibility',
'value' => $visibility,
'key' => '_aksrt_visibility',
'value' => $visibility,
'compare' => '=',
];
}
if ($review_status !== '') {
$meta_query[] = [
'key' => '_aksrt_review_status',
'value' => $review_status,
'key' => '_aksrt_review_status',
'value' => $review_status,
'compare' => '=',
];
}
if (!empty($meta_query)) {
if (count($meta_query) > 1) {
$meta_query['relation'] = 'AND';
}
$query_args['meta_query'] = $meta_query;
}
@@ -129,7 +151,7 @@ class AKSRT_Forum_View_Builder {
}
$topic = $this->forum->build_topic_payload($post, $viewer_user_id);
if (!$include_hidden && !$topic['can_view']) {
if (!$include_hidden && empty($topic['can_view'])) {
continue;
}
@@ -139,10 +161,11 @@ class AKSRT_Forum_View_Builder {
wp_reset_postdata();
return [
'items' => $items,
'total' => (int) $query->found_posts,
'items' => $items,
'total' => (int) $query->found_posts,
'max_pages' => (int) $query->max_num_pages,
'page' => $page,
'page' => $page,
'orderby' => $orderby,
];
}
@@ -152,16 +175,12 @@ class AKSRT_Forum_View_Builder {
public function get_home_view(int $user_id = 0): array {
$boards = $this->forum->get_boards();
$stats = $this->get_stats();
$recent = $this->get_topic_list([
'limit' => 10,
'status' => 'publish',
'viewer_user_id' => $user_id,
]);
$synthesis = $this->get_synthesis_stream(1, 15, $user_id);
$hot = $this->get_topic_list([
'limit' => 8,
'status' => 'publish',
'limit' => 8,
'status' => 'publish',
'viewer_user_id' => $user_id,
'orderby' => 'views',
'orderby' => 'views',
]);
$applications = [];
@@ -181,20 +200,23 @@ class AKSRT_Forum_View_Builder {
$quick_posts = !empty($config['homepage']['quick_posts']);
return [
'boards' => $boards,
'recent_topics' => $recent['items'],
'hot_topics' => $hot['items'],
'stats' => $stats,
'permissions' => [
'can_compose' => $user_id > 0 && $this->forum->forum_user_can($user_id, 'compose_post'),
'can_manage' => $this->forum->is_forum_admin($user_id),
'can_create_plate' => $this->forum->forum_user_can($user_id, 'plate_create'),
'user_tier' => $user_id > 0 ? $this->forum->get_user_plate_tier($user_id, 0) : AKSRT_Forum::TIER_NONE,
'boards' => $boards,
'recent_topics' => $synthesis['items'],
'synthesis' => $synthesis,
'hot_topics' => $hot['items'],
'stats' => $stats,
'permissions' => [
'can_compose' => $user_id > 0 && $this->forum->forum_user_can($user_id, 'compose_post'),
'can_manage' => $this->forum->is_forum_admin($user_id),
'can_create_plate'=> $this->forum->forum_user_can($user_id, 'plate_create'),
'user_tier' => $user_id > 0 ? $this->forum->get_user_plate_tier($user_id, 0) : AKSRT_Forum::TIER_NONE,
],
'applications' => $applications,
'home_tabs' => $home_tabs,
'active_index' => $active_index,
'quick_posts' => $quick_posts,
'applications' => $applications,
'home_tabs' => $home_tabs,
'active_index' => $active_index,
'quick_posts' => $quick_posts,
'compose_url' => function_exists('aksrt_get_forum_compose_url') ? aksrt_get_forum_compose_url() : home_url('/'),
'home_url' => function_exists('aksrt_get_forum_home_url') ? aksrt_get_forum_home_url() : home_url('/'),
];
}
@@ -274,13 +296,17 @@ class AKSRT_Forum_View_Builder {
$result = $this->get_pending_stream($user_id, $page);
break;
case 'plate':
ob_start();
$this->render_board_cards($this->forum->get_boards());
$html = ob_get_clean();
wp_send_json_success([
'html' => '',
'html' => $html,
'type' => 'plate',
'boards' => $this->forum->get_boards(),
'total' => 0,
'total' => count($this->forum->get_boards()),
'max_pages' => 1,
'page' => 1,
'has_more' => false,
]);
return;
default:
@@ -293,7 +319,7 @@ class AKSRT_Forum_View_Builder {
$this->render_topic_row($topic);
}
} else {
echo '<div class="aksrt-forum__empty"><i class="far fa-comment-dots"></i><p>' . esc_html__('暂无内容', 'aksrt') . '</p></div>';
echo '<div class="aksrt-forum__empty"><i class="far fa-comment-dots"></i><p>' . esc_html__('内容空空如也', 'aksrt') . '</p></div>';
}
$html = ob_get_clean();
@@ -307,14 +333,127 @@ class AKSRT_Forum_View_Builder {
]);
}
/**
* Public AJAX: plate/board topic list with sort tabs.
*/
public function ajax_board_topics(): void {
check_ajax_referer('aksrt_public_nonce', 'nonce');
$plate_id = (int) ($_POST['plate_id'] ?? $_GET['plate_id'] ?? 0);
$board_id = (int) ($_POST['board_id'] ?? $_GET['board_id'] ?? 0);
$page = max(1, (int) ($_POST['page'] ?? $_GET['page'] ?? 1));
$orderby = sanitize_key((string) ($_POST['orderby'] ?? $_POST['sort'] ?? $_GET['orderby'] ?? $_GET['sort'] ?? 'date'));
$limit = max(1, min(50, (int) ($_POST['limit'] ?? $_GET['limit'] ?? 20)));
$user_id = get_current_user_id();
$allowed = ['date', 'featured', 'essence', 'last_reply', 'hot', 'views', 'recommend', 'comment_count', 'score', 'favorites'];
if (!in_array($orderby, $allowed, true)) {
$orderby = 'date';
}
$list_args = [
'page' => $page,
'limit' => $limit,
'status' => 'publish',
'viewer_user_id' => $user_id,
'orderby' => $orderby,
];
if ($plate_id > 0) {
$list_args['plate_id'] = $plate_id;
} elseif ($board_id > 0) {
$list_args['board_id'] = $board_id;
}
$result = $this->get_topic_list($list_args);
ob_start();
if (!empty($result['items'])) {
foreach ($result['items'] as $topic) {
$this->render_topic_row($topic);
}
} else {
$compose = function_exists('aksrt_get_forum_compose_url')
? aksrt_get_forum_compose_url($plate_id > 0 ? ['board' => $plate_id] : ($board_id > 0 ? ['board' => $board_id] : []))
: '';
echo '<div class="aksrt-forum-board__empty aksrt-forum__empty">';
echo '<i class="fas fa-comments"></i>';
echo '<p>' . esc_html__('内容空空如也', 'aksrt') . '</p>';
if ($compose !== '') {
echo '<a href="' . esc_url($compose) . '">' . esc_html__('发布第一个主题', 'aksrt') . '</a>';
}
echo '</div>';
}
$html = ob_get_clean();
wp_send_json_success([
'html' => $html,
'total' => $result['total'],
'max_pages' => $result['max_pages'],
'page' => $page,
'orderby' => $orderby,
'has_more' => $page < $result['max_pages'],
]);
}
/**
* Render plate/board cards grid (home plate tab).
*
* @param array<int, array<string, mixed>> $boards
*/
public function render_board_cards(array $boards): void {
$names = $this->forum->get_config()['names'] ?? [];
$name_topic = $names['posts'] ?? __('主题', 'aksrt');
if (empty($boards)) {
echo '<div class="aksrt-forum__empty"><i class="far fa-folder-open"></i><p>' . esc_html__('内容空空如也', 'aksrt') . '</p></div>';
return;
}
echo '<div class="aksrt-forum-board-card__grid">';
foreach ($boards as $board) {
$url = (string) ($board['url'] ?? '#');
$name = (string) ($board['name'] ?? '');
$desc = (string) ($board['description'] ?? '');
$count = (int) ($board['post_count'] ?? $board['topic_count'] ?? 0);
$cover = (string) ($board['cover_url'] ?? $board['thumbnail_url'] ?? '');
?>
<a class="aksrt-forum-board-card" href="<?php echo esc_url($url); ?>">
<?php if ($cover !== '') : ?>
<span class="aksrt-forum-board-card__cover" style="background-image:url(<?php echo esc_url($cover); ?>)"></span>
<?php else : ?>
<span class="aksrt-forum-board-card__cover aksrt-forum-board-card__cover--empty"><i class="fas fa-comments"></i></span>
<?php endif; ?>
<span class="aksrt-forum-board-card__body">
<span class="aksrt-forum-board-card__title"><?php echo esc_html($name); ?></span>
<?php if ($desc !== '') : ?>
<span class="aksrt-forum-board-card__desc"><?php echo esc_html(wp_trim_words($desc, 18, '…')); ?></span>
<?php endif; ?>
<span class="aksrt-forum-board-card__meta">
<i class="fas fa-list-alt"></i>
<?php printf(esc_html__('%1$d 个%2$s', 'aksrt'), $count, esc_html($name_topic)); ?>
</span>
</span>
</a>
<?php
}
echo '</div>';
}
/**
* Render a single topic row (reusable for AJAX and initial render).
*/
public function render_topic_row(array $topic): void {
$board = !empty($topic['boards'][0]) ? $topic['boards'][0] : null;
$names = $this->forum->get_config()['names'] ?? [];
$sticky_level = (int) ($topic['sticky_level'] ?? (!empty($topic['sticky']) ? 1 : 0));
$row_class = 'aksrt-forum-topic-row';
if ($sticky_level > 0) {
$row_class .= ' is-sticky is-sticky-' . $sticky_level;
}
if (!empty($topic['featured'])) {
$row_class .= ' is-featured';
}
$cover = $topic['cover'] ?? null;
?>
<article class="aksrt-forum-topic-row">
<article class="<?php echo esc_attr($row_class); ?>">
<div class="aksrt-forum-topic-row__avatar">
<?php if (!empty($topic['author']['avatar_url'])) : ?>
<img src="<?php echo esc_url((string) $topic['author']['avatar_url']); ?>" alt="" width="40" height="40" loading="lazy">
@@ -322,14 +461,19 @@ class AKSRT_Forum_View_Builder {
</div>
<div class="aksrt-forum-topic-row__body">
<div class="aksrt-forum-topic-row__title-wrap">
<?php if (!empty($topic['sticky'])) : ?>
<span class="aksrt-forum-topic-row__badge aksrt-forum-topic-row__badge--sticky"><?php esc_html_e('置顶', 'aksrt'); ?></span>
<?php if ($sticky_level > 0) : ?>
<span class="aksrt-forum-topic-row__badge aksrt-forum-topic-row__badge--sticky"><?php echo esc_html((string) ($topic['sticky_label'] ?? __('置顶', 'aksrt'))); ?></span>
<?php endif; ?>
<?php if (!empty($topic['featured'])) : ?>
<span class="aksrt-forum-topic-row__badge aksrt-forum-topic-row__badge--featured"><?php esc_html_e('精华', 'aksrt'); ?></span>
<?php endif; ?>
<?php if (($topic['bbs_type'] ?? '') === 'question') : ?>
<span class="aksrt-forum-topic-row__badge aksrt-forum-topic-row__badge--question"><?php echo esc_html($names['question_badge'] ?? __('提问', 'aksrt')); ?></span>
<?php $q_status = (int) ($topic['question_status'] ?? 0); ?>
<span class="aksrt-forum-topic-row__badge aksrt-forum-topic-row__badge--question<?php echo $q_status === 1 ? ' is-solved' : ''; ?>">
<?php echo $q_status === 1
? esc_html($names['question_ok_badge'] ?? __('已解决', 'aksrt'))
: esc_html($names['question_badge'] ?? __('提问', 'aksrt')); ?>
</span>
<?php endif; ?>
<h3 class="aksrt-forum-topic-row__title">
<a href="<?php echo esc_url((string) ($topic['permalink'] ?? '#')); ?>"><?php echo esc_html((string) ($topic['title'] ?? '')); ?></a>
@@ -345,6 +489,21 @@ class AKSRT_Forum_View_Builder {
<span><i class="fas fa-comment"></i> <?php echo esc_html(number_format_i18n((int) ($topic['comment_count'] ?? 0))); ?></span>
</div>
</div>
<?php if (is_array($cover) && !empty($cover['type'])) : ?>
<div class="aksrt-forum-topic-row__cover">
<?php if (($cover['type'] ?? '') === 'video') : ?>
<?php if (!empty($cover['poster'])) : ?>
<img src="<?php echo esc_url((string) $cover['poster']); ?>" alt="" loading="lazy">
<?php endif; ?>
<i class="fas fa-play-circle"></i>
<?php elseif (($cover['type'] ?? '') === 'slide' && !empty($cover['images'][0])) : ?>
<img src="<?php echo esc_url((string) $cover['images'][0]); ?>" alt="" loading="lazy">
<span class="aksrt-forum-topic-row__cover-count"><i class="fas fa-images"></i></span>
<?php elseif (!empty($cover['url'])) : ?>
<img src="<?php echo esc_url((string) $cover['url']); ?>" alt="" loading="lazy">
<?php endif; ?>
</div>
<?php endif; ?>
</article>
<?php
}
@@ -178,7 +178,7 @@ trait AKSRT_Forum_Topic_Service_Part_1 {
$post->post_title
), [
'title' => __('帖子已删除', 'aksrt'),
'target_url' => home_url('/forums/'),
'target_url' => aksrt_get_forum_home_url(),
'reason' => $note,
]);
}
@@ -239,7 +239,7 @@ trait AKSRT_Forum_Topic_Service_Part_4 {
wp_send_json_success([
'message' => (string) ($result['message'] ?? __('主题已提交', 'aksrt')),
'post_id' => (int) ($result['post_id'] ?? 0),
'redirect' => (string) ($result['redirect'] ?? home_url('/forums/')),
'redirect' => (string) ($result['redirect'] ?? aksrt_get_forum_home_url()),
]);
}
@@ -341,8 +341,16 @@ trait AKSRT_Scripts_Part_1b {
);
}
// Forum pages
if (is_page_template('templates/pages/page-forums.php') || is_tax('aksrt_forum_board') || is_tax('aksrt_forum_tag') || is_singular('aksrt_forum_topic') || is_page_template('templates/forum/forum-compose.php')) {
// Forum pages (home / plate / board tax / tag / topic / compose / plate-cat)
$is_forum_surface = is_page_template('templates/pages/page-forums.php')
|| is_page_template('templates/forum/forum-compose.php')
|| is_tax('aksrt_forum_board')
|| is_tax('aksrt_forum_tag')
|| is_tax('aksrt_plate_cat')
|| is_singular('aksrt_forum_topic')
|| is_singular('aksrt_forum_plate');
if ($is_forum_surface) {
wp_enqueue_style(
'aksrt-forum',
$base_uri . '/assets/css/frontend/forum.css',
@@ -438,7 +446,7 @@ trait AKSRT_Scripts_Part_1b {
}
}
if (is_tax('aksrt_forum_board') || is_singular('aksrt_forum_topic') || is_singular('aksrt_forum_plate') || is_tax('aksrt_plate_cat') || is_page_template('templates/forum/forum-compose.php')) {
if ($is_forum_surface) {
$forum_governance_js = get_template_directory() . '/assets/js/forum-governance.js';
if (file_exists($forum_governance_js)) {
wp_enqueue_script(
@@ -449,9 +457,15 @@ trait AKSRT_Scripts_Part_1b {
true
);
wp_localize_script('aksrt-forum-governance', 'aksrtForumGovernance', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'restUrl' => esc_url_raw(rest_url()),
'restNonce' => wp_create_nonce('wp_rest'),
'ajaxUrl' => admin_url('admin-ajax.php'),
'restUrl' => esc_url_raw(rest_url()),
'restNonce' => wp_create_nonce('wp_rest'),
'publicNonce' => wp_create_nonce('aksrt_public_nonce'),
'i18n' => [
'empty' => __('内容空空如也', 'aksrt'),
'loadMore' => __('加载更多', 'aksrt'),
'loading' => __('加载中…', 'aksrt'),
],
]);
}
+98
View File
@@ -0,0 +1,98 @@
<?php
/**
* Forum frontend URL helpers.
*
* Page-template assignment is the source of truth for forum home / compose URLs.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_get_page_url_by_template')) :
/**
* Resolve the first published page that uses a given page template file.
*
* @param string $template_file Relative theme template path (e.g. templates/pages/page-forums.php).
*/
function aksrt_get_page_url_by_template(string $template_file): string {
$template_file = ltrim(str_replace('\\', '/', $template_file), '/');
if ($template_file === '') {
return '';
}
static $cache = [];
if (array_key_exists($template_file, $cache)) {
return $cache[$template_file];
}
$pages = get_posts([
'post_type' => 'page',
'post_status' => 'publish',
'posts_per_page' => 1,
'orderby' => 'menu_order title',
'order' => 'ASC',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'meta_key' => '_wp_page_template',
'meta_value' => $template_file,
]);
$url = '';
if (!empty($pages[0]) && $pages[0] instanceof WP_Post) {
$permalink = get_permalink($pages[0]);
if (is_string($permalink) && $permalink !== '') {
$url = $permalink;
}
}
$cache[$template_file] = $url;
return $url;
}
endif;
if (!function_exists('aksrt_get_forum_home_url')) :
/**
* Public forum home URL (page template AKSRT - 论坛).
*/
function aksrt_get_forum_home_url(): string {
$url = aksrt_get_page_url_by_template('templates/pages/page-forums.php');
return $url !== '' ? $url : home_url('/');
}
endif;
if (!function_exists('aksrt_get_forum_compose_url')) :
/**
* Public forum compose URL (page template AKSRT - 发帖).
*
* @param array<string, scalar> $args Optional query args (board, plate, …).
*/
function aksrt_get_forum_compose_url(array $args = []): string {
$url = aksrt_get_page_url_by_template('templates/forum/forum-compose.php');
if ($url === '') {
$url = home_url('/');
}
// Normalize plate → board for compose form contract.
if (isset($args['plate']) && !isset($args['board'])) {
$args['board'] = $args['plate'];
unset($args['plate']);
}
$clean = [];
foreach ($args as $key => $value) {
$key = sanitize_key((string) $key);
if ($key === '') {
continue;
}
if (is_bool($value)) {
$clean[$key] = $value ? '1' : '0';
} else {
$clean[$key] = (string) $value;
}
}
return !empty($clean) ? add_query_arg($clean, $url) : $url;
}
endif;
+64 -259
View File
@@ -1,6 +1,6 @@
<?php
/**
* Forum board template.
* Forum board template (legacy taxonomy archive).
*
* @package AKSRT
*/
@@ -14,9 +14,12 @@ $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));
$forum_sort = isset($_GET['forum_sort']) ? sanitize_key(wp_unslash((string) $_GET['forum_sort'])) : '';
$view = $forum ? $forum->get_board_view($board_id, [
'user_id' => $current_user_id,
'paged' => $paged,
'paged' => $paged,
'orderby' => $forum_sort,
]) : [
'board' => null,
'topics' => [],
@@ -26,6 +29,10 @@ $view = $forum ? $forum->get_board_view($board_id, [
'permissions' => [],
'application' => null,
'board_options' => [],
'tabs' => [],
'active_sort' => 'date',
'top_info' => true,
'compose_url' => function_exists('aksrt_get_forum_compose_url') ? aksrt_get_forum_compose_url() : home_url('/'),
];
$board_data = $view['board'] ?? null;
@@ -33,308 +40,106 @@ $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');
$tabs = is_array($view['tabs'] ?? null) ? $view['tabs'] : [];
$active_sort = sanitize_key((string) ($view['active_sort'] ?? 'date'));
$top_info = !isset($view['top_info']) || !empty($view['top_info']);
$compose_url = (string) ($view['compose_url'] ?? aksrt_get_forum_compose_url(['board' => $board_id]));
$board_url = !empty($board_data['url']) ? (string) $board_data['url'] : (is_wp_error(get_term_link($board)) ? '' : (string) get_term_link($board));
$nonce = wp_create_nonce('aksrt_public_nonce');
$max_pages = (int) ($view['pagination']['max_pages'] ?? 1);
// 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 content-shell" tabindex="-1">
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
<div class="aksrt-forum-board container">
<div class="aksrt-forum-board__hero">
<div class="aksrt-forum-board container"
data-board-id="<?php echo esc_attr((string) $board_id); ?>"
data-nonce="<?php echo esc_attr($nonce); ?>"
data-active-sort="<?php echo esc_attr($active_sort); ?>">
<?php if ($top_info) : ?>
<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>
<h1 class="aksrt-forum-board__title"><?php echo esc_html((string) ($board_data['name'] ?? ($board->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>
<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>
</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'); ?>
<i class="fas fa-pen"></i> <?php esc_html_e('发布新主题', 'aksrt'); ?>
</a>
<?php endif; ?>
</div>
</div>
<div class="aksrt-forum-board__summary">
<div class="aksrt-forum-board__summary-item">
<span class="aksrt-forum-board__summary-label"><?php echo esc_html($name_topic); ?></span>
<strong><?php echo esc_html(number_format_i18n((int) ($board_data['topic_count'] ?? 0))); ?></strong>
</div>
<div class="aksrt-forum-board__summary-item">
<span class="aksrt-forum-board__summary-label"><?php echo esc_html($name_reply); ?></span>
<strong><?php echo esc_html(number_format_i18n((int) ($board_data['reply_count'] ?? 0))); ?></strong>
</div>
<div class="aksrt-forum-board__summary-item">
<span class="aksrt-forum-board__summary-label"><?php esc_html_e('版主', 'aksrt'); ?></span>
<strong><?php echo esc_html(number_format_i18n(count($moderators))); ?></strong>
</div>
</div>
</div>
<div class="content-layout<?php echo empty($moderators) && empty($application) && empty($permissions['can_moderate']) ? ' content-layout--no-sidebar' : ''; ?> aksrt-forum-board__layout">
<div class="content-layout__primary">
<section class="aksrt-forum-board__governance aksrt-forum-board__governance--inline">
<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 endif; ?>
<?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-badge"><?php echo esc_html((string) ($topic['sticky_label'] ?? __('置顶', 'aksrt'))); ?></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 if (!empty($tabs)) : ?>
<nav class="aksrt-forum-board__tabs" aria-label="<?php esc_attr_e('版块栏目', 'aksrt'); ?>">
<?php foreach ($tabs as $tab) :
$sort = sanitize_key((string) ($tab['sort'] ?? 'date'));
$label = (string) ($tab['label'] ?? $sort);
$tab_url = add_query_arg('forum_sort', $sort, $board_url);
$is_active = $sort === $active_sort;
?>
<?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>
<a class="aksrt-forum-board__tab js-aksrt-board-sort-tab<?php echo $is_active ? ' is-active' : ''; ?>"
href="<?php echo esc_url($tab_url); ?>"
data-sort="<?php echo esc_attr($sort); ?>">
<?php echo esc_html($label); ?>
</a>
<?php endforeach; ?>
</nav>
<?php endif; ?>
<?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 class="aksrt-forum-board__topics">
<div class="aksrt-forum-topics__list js-aksrt-board-topic-list">
<?php if (!empty($topics) && $forum) : ?>
<?php foreach ($topics as $topic) { $forum->render_topic_row($topic); } ?>
<?php else : ?>
<div class="aksrt-forum-board__empty aksrt-forum__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; ?>
<?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 if ($max_pages > 1) : ?>
<div class="aksrt-forum-board__pagination">
<?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>',
'add_args' => $active_sort !== '' ? ['forum_sort' => $active_sort] : [],
]);
?>
</div>
<?php endif; ?>
</div>
<aside class="content-layout__sidebar aksrt-forum-board__sidebar">
<div class="aksrt-forum-board__governance-card aksrt-forum-board__governance-card--sidebar">
<h2 class="aksrt-forum-board__section-title"><?php esc_html_e('版块说明', 'aksrt'); ?></h2>
<p><?php echo esc_html((string) ($board_data['description'] ?? __('这里展示版块简介、讨论方向与基础规则。', 'aksrt'))); ?></p>
</div>
<?php if (!empty($moderators)) : ?>
<div class="aksrt-forum-board__governance-card aksrt-forum-board__governance-card--sidebar">
<h2 class="aksrt-forum-board__section-title"><?php esc_html_e('版主团队', 'aksrt'); ?></h2>
<div class="aksrt-forum-board__moderators aksrt-forum-board__moderators--stacked">
<?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>
</div>
<?php endif; ?>
</aside>
</div>
</div>
</main>
+1 -1
View File
@@ -74,7 +74,7 @@ $initial_content = $draft_data ? $draft_data['content'] : '';
?>
</p>
</div>
<a href="<?php echo esc_url(home_url('/forums/')); ?>" class="aksrt-forum-compose__back">
<a href="<?php echo esc_url(aksrt_get_forum_home_url()); ?>" class="aksrt-forum-compose__back">
<i class="fas fa-arrow-left"></i> <?php printf(esc_html__('返回%s', 'aksrt'), esc_html($forum_name)); ?>
</a>
</div>
+1 -1
View File
@@ -97,7 +97,7 @@ if (is_array($cat_moderator_ids)) {
</div>
<div class="aksrt-forum-plate-cat__back">
<a href="<?php echo esc_url(home_url('/forums/')); ?>">
<a href="<?php echo esc_url(aksrt_get_forum_home_url()); ?>">
<i class="fas fa-arrow-left"></i> <?php printf(esc_html__('返回%s', 'aksrt'), esc_html($forum_name)); ?>
</a>
</div>
+93 -117
View File
@@ -13,19 +13,25 @@ $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));
$forum_sort = isset($_GET['forum_sort']) ? sanitize_key(wp_unslash((string) $_GET['forum_sort'])) : '';
$view = $forum ? $forum->get_board_view($plate_id, [
'user_id' => $current_user_id,
'paged' => $paged,
'orderby' => $forum_sort,
]) : [
'board' => null,
'topics' => [],
'board' => null,
'topics' => [],
'sticky_topics' => [],
'moderators' => [],
'pagination' => ['page' => 1, 'max_pages' => 1, 'total' => 0],
'permissions' => [],
'application' => null,
'moderators' => [],
'pagination' => ['page' => 1, 'max_pages' => 1, 'total' => 0],
'permissions' => [],
'application' => null,
'board_options' => [],
'tabs' => [],
'active_sort' => 'date',
'top_info' => true,
'compose_url' => function_exists('aksrt_get_forum_compose_url') ? aksrt_get_forum_compose_url() : home_url('/'),
];
$board_data = $view['board'] ?? null;
@@ -34,13 +40,19 @@ $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/'));
$tabs = is_array($view['tabs'] ?? null) ? $view['tabs'] : [];
$active_sort = sanitize_key((string) ($view['active_sort'] ?? 'date'));
$top_info = !isset($view['top_info']) || !empty($view['top_info']);
$compose_url = (string) ($view['compose_url'] ?? (function_exists('aksrt_get_forum_compose_url') ? aksrt_get_forum_compose_url(['board' => $plate_id]) : home_url('/')));
$plate_url = !empty($board_data['url']) ? (string) $board_data['url'] : (string) get_permalink($plate_id);
$nonce = wp_create_nonce('aksrt_public_nonce');
$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;
$max_pages = (int) ($view['pagination']['max_pages'] ?? 1);
?>
<main id="main-content" class="site-main content-shell" tabindex="-1">
@@ -65,7 +77,12 @@ $is_followed = $forum && $current_user_id > 0 ? $forum->is_user_following_pla
</div>
<?php else : ?>
<div class="aksrt-forum-board container">
<div class="aksrt-forum-board container"
data-plate-id="<?php echo esc_attr((string) $plate_id); ?>"
data-nonce="<?php echo esc_attr($nonce); ?>"
data-active-sort="<?php echo esc_attr($active_sort); ?>">
<?php if ($top_info) : ?>
<div class="aksrt-forum-board__header">
<div class="aksrt-forum-board__info">
<?php if (!empty($board_data['cover_url'])) : ?>
@@ -90,7 +107,7 @@ $is_followed = $forum && $current_user_id > 0 ? $forum->is_user_following_pla
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>
<i class="fas fa-heart"></i>
<?php echo $is_followed ? esc_html__('已关注', 'aksrt') : esc_html__('关注', 'aksrt'); ?>
</button>
<?php endif; ?>
@@ -125,6 +142,7 @@ $is_followed = $forum && $current_user_id > 0 ? $forum->is_user_following_pla
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if (!empty($board_data['content'])) : ?>
<div class="aksrt-forum-board__content entry-content">
@@ -132,7 +150,72 @@ $is_followed = $forum && $current_user_id > 0 ? $forum->is_user_following_pla
</div>
<?php endif; ?>
<section class="aksrt-forum-board__governance">
<?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; ?>
<?php if (!empty($tabs)) : ?>
<nav class="aksrt-forum-board__tabs" aria-label="<?php esc_attr_e('版块栏目', 'aksrt'); ?>">
<?php foreach ($tabs as $tab) :
$sort = sanitize_key((string) ($tab['sort'] ?? 'date'));
$label = (string) ($tab['label'] ?? $sort);
$tab_url = add_query_arg('forum_sort', $sort, $plate_url);
$is_active = $sort === $active_sort;
?>
<a class="aksrt-forum-board__tab js-aksrt-board-sort-tab<?php echo $is_active ? ' is-active' : ''; ?>"
href="<?php echo esc_url($tab_url); ?>"
data-sort="<?php echo esc_attr($sort); ?>"
<?php echo $is_active ? 'aria-current="page"' : ''; ?>>
<?php echo esc_html($label); ?>
</a>
<?php endforeach; ?>
</nav>
<?php endif; ?>
<div class="aksrt-forum-board__topics">
<div class="aksrt-forum-topics__list js-aksrt-board-topic-list">
<?php if (!empty($topics) && $forum) : ?>
<?php foreach ($topics as $topic) { $forum->render_topic_row($topic); } ?>
<?php else : ?>
<div class="aksrt-forum-board__empty aksrt-forum__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>
<?php if ($max_pages > 1) : ?>
<div class="aksrt-forum-board__pagination">
<?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>',
'add_args' => $active_sort !== '' ? ['forum_sort' => $active_sort] : [],
]);
?>
</div>
<?php endif; ?>
</div>
<section class="aksrt-forum-board__governance aksrt-forum-board__governance--footer">
<div class="aksrt-forum-board__governance-card">
<h2 class="aksrt-forum-board__section-title"><?php esc_html_e('版主团队', 'aksrt'); ?></h2>
<?php if (!empty($moderators)) : ?>
@@ -197,113 +280,6 @@ $is_followed = $forum && $current_user_id > 0 ? $forum->is_user_following_pla
<?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; ?>
+6 -31
View File
@@ -24,7 +24,7 @@ $term_name = $term->name ?? '';
$term_desc = $term->description ?? '';
?>
<main id="main-content" class="site-main container" tabindex="-1">
<main id="main-content" class="site-main content-shell" tabindex="-1">
<div class="aksrt-forum-tag container">
<header class="aksrt-forum-tag__header">
@@ -38,34 +38,9 @@ $term_desc = $term->description ?? '';
<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; ?>
<?php if (!empty($topics) && $forum) : ?>
<div class="aksrt-forum-topics__list aksrt-forum-tag__list">
<?php foreach ($topics as $topic) { $forum->render_topic_row($topic); } ?>
</div>
<?php if ($max_pages > 1) : ?>
@@ -81,9 +56,9 @@ $term_desc = $term->description ?? '';
</nav>
<?php endif; ?>
<?php else : ?>
<div class="aksrt-forum-tag__empty">
<div class="aksrt-forum-tag__empty aksrt-forum__empty">
<i class="fas fa-comments"></i>
<p><?php esc_html_e('该标签下暂无话题', 'aksrt'); ?></p>
<p><?php esc_html_e('内容空空如也', 'aksrt'); ?></p>
</div>
<?php endif; ?>
</div>
+2 -2
View File
@@ -117,7 +117,7 @@ $comments_enabled = !empty($permissions['can_reply']);
<?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>
<a href="<?php echo esc_url(aksrt_get_forum_home_url()); ?>"><?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; ?>
@@ -157,7 +157,7 @@ $comments_enabled = !empty($permissions['can_reply']);
<div class="aksrt-forum-topic__meta">
<span class="aksrt-forum-topic__board-link-wrap">
<i class="fas fa-layer-group"></i>
<a class="aksrt-forum-topic__board-link" href="<?php echo esc_url((string) ($board['url'] ?? home_url('/forums/'))); ?>"><?php echo esc_html((string) ($board['name'] ?? $bc_forum_name)); ?></a>
<a class="aksrt-forum-topic__board-link" href="<?php echo esc_url((string) ($board['url'] ?? aksrt_get_forum_home_url())); ?>"><?php echo esc_html((string) ($board['name'] ?? $bc_forum_name)); ?></a>
</span>
<span class="aksrt-forum-topic__author">
<?php if (!empty($topic['author']['avatar_url'])) : ?>
+15 -2
View File
@@ -28,11 +28,13 @@ $view = $forum ? $forum->get_home_view($current_user_id) : [
$boards = $view['boards'] ?? [];
$recent_topics = $view['recent_topics'] ?? [];
$synthesis = is_array($view['synthesis'] ?? null) ? $view['synthesis'] : ['items' => $recent_topics, 'max_pages' => 1, 'page' => 1, 'total' => count($recent_topics)];
$synthesis_max = max(1, (int) ($synthesis['max_pages'] ?? 1));
$hot_topics = $view['hot_topics'] ?? [];
$stats = $view['stats'] ?? [];
$permissions = $view['permissions'] ?? [];
$applications = $view['applications'] ?? [];
$compose_url = home_url('/compose/');
$compose_url = aksrt_get_forum_compose_url();
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
$forum_names = $forum_settings['names'] ?? [];
@@ -258,10 +260,21 @@ if ($active_tab_type === '') {
if ($forum) { $forum->render_topic_row($topic); }
} ?>
</div>
<?php if ($synthesis_max > 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) $synthesis_max); ?>" data-tab="synthesis">
<i class="fas fa-chevron-down"></i> <?php esc_html_e('加载更多', 'aksrt'); ?>
</button>
</div>
<?php endif; ?>
<?php else : ?>
<div class="aksrt-forum__empty">
<i class="fas fa-feather-alt"></i>
<p><?php esc_html_e('还没有公开主题,欢迎创建第一个讨论。', 'aksrt'); ?></p>
<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; ?>
<?php endif; ?>
+1 -1
View File
@@ -18,7 +18,7 @@ extract($args, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_ext
<h2 class="uh-forum__section-title-main"><?php esc_html_e('论坛内容', 'aksrt'); ?></h2>
<p class="uh-forum__section-desc"><?php esc_html_e('在用户主页中保留论坛维度,但仍以内容流和身份展示为主。', 'aksrt'); ?></p>
</div>
<a class="uh-forum__section-link" href="<?php echo esc_url(home_url('/forums/')); ?>"><?php esc_html_e('进入社区', 'aksrt'); ?></a>
<a class="uh-forum__section-link" href="<?php echo esc_url(aksrt_get_forum_home_url()); ?>"><?php esc_html_e('进入社区', 'aksrt'); ?></a>
</div>
<?php
$forum_page = max(1, isset($_GET['forum_page']) ? (int) $_GET['forum_page'] : 1);