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:
@@ -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'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user