feat(forum): rebuild forum home page

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Fable 5 committed 2026-11-11 14:41:02 +08:00
1 parent 51d5b8a2a1
commit 024ecddfed
16 files changed
+1061 -198

No files matched your search

+33 -121
View File
@@ -24,10 +24,6 @@ final class View {
echo '<aside class="jio-forum__aside">';
if (is_user_logged_in()) {
echo '<a class="jio-forum__new" href="' . esc_url(Core::edit_url()) . '">发布帖子</a>';
if ($context === 'home' && jio_get_setting('jio_forum_user_plates', true)) {
echo '<button type="button" class="jio-forum__action jio-forum__create-plate" data-forum-open="plate">创建版块</button>';
echo '<dialog class="jio-forum__dialog" data-forum-dialog="plate"><form data-forum-form="plate"><h2>创建版块</h2><label>名称<input name="title" required maxlength="80"></label><label>介绍<textarea name="content" rows="5"></textarea></label><p class="jio-forum__message" role="status"></p><div class="jio-forum__dialog-actions"><button type="button" data-forum-close>取消</button><button type="submit" class="jio-forum__primary">提交</button></div></form></dialog>';
}
} else {
echo '<a class="jio-forum__new" href="' . esc_url(jio_get_login_url(Core::edit_url())) . '">登录后发帖</a>';
}
@@ -44,37 +40,7 @@ final class View {
}
public static function home(): void {
self::open('论坛', 'home');
\Jio\WidgetSystem\WidgetAreas::render('forum_home_top_fluid');
echo '<div class="jio-forum__layout"><div class="jio-forum__main">';
$name = (string) jio_get_setting('jio_forum_forum_name', '论坛');
echo '<header class="jio-forum__hero"><h1>' . esc_html($name) . '</h1></header>';
if (Access::is_admin(get_current_user_id())) {
$pending = get_posts(['post_type' => Core::PLATE, 'post_status' => 'pending', 'posts_per_page' => 20]);
if ($pending) {
echo '<section class="jio-forum__pending"><h2>待审核版块</h2>';
foreach ($pending as $plate) {
echo '<div><span>' . esc_html($plate->post_title) . '</span><button type="button" data-forum-action="plate-audit" data-id="' . (int) $plate->ID . '">通过审核</button></div>';
}
echo '</section>';
}
self::term_management();
}
self::tabs();
$categories = get_terms(['taxonomy' => Core::CATEGORY, 'hide_empty' => false]);
if (is_array($categories) && $categories) {
echo '<div class="jio-forum__chips">';
foreach ($categories as $category) {
echo '<a href="' . esc_url(get_term_link($category)) . '">' . esc_html($category->name) . '</a>';
}
echo '</div>';
}
self::posts(['post_type' => Core::POST, 'post_status' => 'publish'], 'home');
echo '</div>';
self::sidebar('home');
echo '</div>';
\Jio\WidgetSystem\WidgetAreas::render('forum_home_bottom_fluid');
self::close();
HomeView::render();
}
public static function listing(): void {
@@ -90,7 +56,7 @@ final class View {
if ($plate) {
echo '<div class="jio-forum__description">' . wp_kses_post(wpautop($plate->post_excerpt ?: $plate->post_content)) . '</div>';
echo '<p class="jio-forum__stats">' . (int) get_post_meta($plate->ID, '_jio_forum_follow_count', true) . ' 人关注</p>';
self::action('follow', $plate->ID, Access::follows(get_current_user_id(), $plate->ID) ? '已关注' : '关注版块');
echo Cards::follow_button($plate->ID, 'but c-blue'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if (Access::is_moderator(get_current_user_id(), $plate->ID)) {
self::plate_editor($plate);
}
@@ -128,14 +94,12 @@ final class View {
self::close();
}
/** Listing pages (plate / taxonomy) use a fixed, always-available tab set. */
public static function tabs(): void {
$tabs = ['latest' => '最新', 'popular' => '热门', 'essence' => '精华', 'question' => '问答', 'vote' => '投票', 'plates' => '版块', 'follow' => '已关注'];
$enabled = (array) jio_get_setting('jio_forum_home_tabs', array_keys($tabs));
$tabs = ['latest' => '最新', 'popular' => '热门', 'essence' => '精华', 'question' => '问答', 'vote' => '投票'];
$base_url = is_singular(Core::PLATE) ? get_permalink(get_queried_object_id()) : (is_tax([Core::CATEGORY, Core::TOPIC, Core::TAG]) ? get_term_link(get_queried_object()) : Core::home_url());
echo '<nav class="jio-forum__tabs" aria-label="论坛栏目">';
foreach ($tabs as $key => $label) {
if (!in_array($key, $enabled, true)) continue;
if ($key === 'follow' && !is_user_logged_in()) continue;
$url = add_query_arg('forum_view', $key, $base_url);
$selected = (string) ($_GET['forum_view'] ?? 'latest') === $key;
echo '<a class="' . ($selected ? 'is-active' : '') . '" href="' . esc_url($url) . '">' . esc_html($label) . '</a>';
@@ -145,13 +109,8 @@ final class View {
public static function posts(array $args, string $context = 'home'): void {
$view = sanitize_key((string) ($_GET['forum_view'] ?? 'latest'));
if ($view === 'plates') {
self::plates([]);
return;
}
if ($view === 'follow') {
$ids = self::user_marked_ids(get_current_user_id(), '_jio_forum_follow_');
$args['meta_query'][] = ['key' => '_jio_forum_plate_id', 'value' => $ids ?: [0], 'compare' => 'IN'];
if (!in_array($view, ['latest', 'popular', 'essence', 'question', 'vote'], true)) {
$view = 'latest';
}
if (in_array($view, ['question', 'vote'], true)) {
$args['meta_query'][] = ['key' => '_jio_forum_type', 'value' => $view];
@@ -163,77 +122,43 @@ final class View {
$args['paged'] = max(1, (int) get_query_var('paged', 1));
$args['orderby'] = 'date';
$args['order'] = 'DESC';
$args['jio_forum_list'] = in_array($view, ['latest', 'popular', 'question', 'vote', 'essence', 'follow'], true) ? $view : 'latest';
$args['jio_forum_list'] = $view;
$query = new \WP_Query($args);
\Jio\WidgetSystem\WidgetAreas::render('forum_' . $context . '_top_content');
echo '<div class="jio-forum__list">';
if (!$query->have_posts()) {
echo '<p class="jio-forum__empty">暂无帖子</p>';
echo '<div class="jio-forum__list">' . jio_get_null('暂无帖子') . '</div>';
} else {
Cards::prime($query->posts);
echo '<div class="jio-forum__list">';
foreach ($query->posts as $post) {
echo Cards::post_detail($post, 'ajax-item'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo '</div>';
}
while ($query->have_posts()) {
$query->the_post();
self::post_card(get_post());
}
wp_reset_postdata();
echo '</div>';
self::pagination($query);
\Jio\WidgetSystem\WidgetAreas::render('forum_' . $context . '_bottom_content');
}
public static function plates(array $args): void {
$query = new \WP_Query(array_merge(['post_type' => Core::PLATE, 'post_status' => 'publish', 'posts_per_page' => 20], $args));
echo '<div class="jio-forum__plates">';
while ($query->have_posts()) {
$query->the_post();
$plate = get_post();
self::plate_card($plate);
if (!$query->have_posts()) {
echo jio_get_null('暂无版块'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return;
}
PlateStats::prime($query->posts ? wp_list_pluck($query->posts, 'ID') : []);
echo '<div class="plate-lists">';
foreach ($query->posts as $plate) {
echo Cards::plate_item($plate); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
wp_reset_postdata();
echo '</div>';
}
public static function plate_card(\WP_Post $plate): void {
$url = get_permalink($plate);
echo '<article class="jio-forum__plate"><a class="jio-forum__plate-cover" href="' . esc_url($url) . '">';
if (jio_get_setting('jio_forum_show_plate_cover', true) && has_post_thumbnail($plate)) {
echo get_the_post_thumbnail($plate, 'jio-card');
}
echo '</a><div><h2><a href="' . esc_url($url) . '">' . esc_html($plate->post_title) . '</a></h2><p>' . esc_html(wp_trim_words(wp_strip_all_tags($plate->post_excerpt ?: $plate->post_content), 22)) . '</p><small>' . (int) get_post_meta($plate->ID, '_jio_forum_follow_count', true) . ' 人关注</small></div></article>';
echo Cards::plate_item($plate); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
public static function post_card(\WP_Post $post): void {
$plate_id = (int) get_post_meta($post->ID, '_jio_forum_plate_id', true);
$type = (string) get_post_meta($post->ID, '_jio_forum_type', true);
echo '<article class="jio-forum__post"><a class="jio-forum__avatar" href="' . esc_url(get_author_posts_url((int) $post->post_author)) . '">' . get_avatar((int) $post->post_author, 44) . '</a><div class="jio-forum__post-body">';
echo '<div class="jio-forum__post-top"><span>' . esc_html(get_the_author_meta('display_name', (int) $post->post_author)) . '</span><time datetime="' . esc_attr(get_the_date(DATE_W3C, $post)) . '">' . esc_html(get_the_date('', $post)) . '</time></div>';
$url = $post->post_status === 'publish' ? get_permalink($post) : Core::edit_url($post->ID);
echo '<h2><a href="' . esc_url($url) . '">' . esc_html($post->post_title) . '</a></h2>';
$excerpt = Access::can_view(get_current_user_id(), $post->ID) ? wp_trim_words(wp_strip_all_tags($post->post_excerpt ?: $post->post_content), 30) : '内容已隐藏';
echo '<p>' . esc_html($excerpt) . '</p>';
echo '<div class="jio-forum__post-meta">';
if (get_post_meta($post->ID, '_jio_forum_pinned', true)) {
echo '<span class="jio-forum__badge">置顶</span>';
}
if ($type !== '') {
echo '<span class="jio-forum__badge">' . esc_html($type === 'question' ? '问答' : '投票') . '</span>';
}
if ($type === 'question' && get_post_meta($post->ID, '_jio_forum_adopted_comment', true)) {
echo '<span class="jio-forum__badge">已解决</span>';
}
if (get_post_meta($post->ID, '_jio_forum_essence', true)) {
echo '<span class="jio-forum__badge">精华</span>';
}
if ($plate_id > 0) {
echo '<a href="' . esc_url(get_permalink($plate_id)) . '">' . esc_html(get_the_title($plate_id)) . '</a>';
}
echo '<span>' . (int) get_post_meta($post->ID, '_jio_forum_views', true) . ' 阅读</span>';
echo '<span>' . (int) $post->comment_count . ' 回复</span>';
echo '<span>' . (int) get_post_meta($post->ID, '_jio_forum_score', true) . ' 评分</span>';
echo '<span>' . (int) get_post_meta($post->ID, '_jio_forum_favorite_count', true) . ' 收藏</span></div></div></article>';
$hot = get_comments(['post_id' => $post->ID, 'status' => 'approve', 'number' => 1, 'meta_key' => '_jio_forum_hot', 'meta_value' => '1']);
if ($hot) {
echo '<div class="jio-forum__hot-reply">热门回复:' . esc_html(wp_trim_words(wp_strip_all_tags($hot[0]->comment_content), 25)) . '</div>';
}
echo Cards::post_detail($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
public static function replies(int $post_id): void {
@@ -278,18 +203,6 @@ final class View {
echo '</section>';
}
private static function term_management(): void {
echo '<section class="jio-forum__term-management"><h2>分类与话题</h2><form data-forum-form="term"><label>类型<select name="type"><option value="category">版块分类</option><option value="topic">论坛话题</option><option value="tag">论坛标签</option></select></label><label>名称<input name="name" required maxlength="60"></label><p class="jio-forum__message" role="status"></p><button type="submit" class="jio-forum__action">添加</button></form>';
foreach (['category' => Core::CATEGORY, 'topic' => Core::TOPIC, 'tag' => Core::TAG] as $label => $taxonomy) {
$terms = get_terms(['taxonomy' => $taxonomy, 'hide_empty' => false, 'number' => 30]);
if (!is_array($terms)) continue;
foreach ($terms as $term) {
echo '<div class="jio-forum__term-row"><span>' . esc_html($term->name) . '</span><button type="button" data-forum-action="term-edit" data-id="' . (int) $term->term_id . '">编辑</button><button type="button" data-forum-action="term-delete" data-id="' . (int) $term->term_id . '">删除</button></div>';
}
}
echo '</section>';
}
private static function plate_editor(\WP_Post $plate): void {
$id = $plate->ID;
echo '<button type="button" class="jio-forum__action" data-forum-open="plate-edit-' . $id . '">编辑版块</button>';
@@ -371,17 +284,16 @@ final class View {
$query = new \WP_Query($args);
echo '<div class="jio-forum__list">';
if (!$query->have_posts()) echo '<p class="jio-forum__empty">暂无内容</p>';
while ($query->have_posts()) {
$query->the_post();
$post = get_post();
if ($post->post_type === Core::POST) self::post_card($post);
else {
$url = $post->post_status === 'publish' ? get_permalink($post) : '';
echo '<div class="jio-forum__user-row">' . ($url ? '<a href="' . esc_url($url) . '">' : '<span>') . esc_html($post->post_title) . ($url ? '</a>' : '</span>') . ($url ? '' : '<small>待审核</small>') . '</div>';
if ($owner && !$url) self::plate_editor($post);
Cards::prime($query->posts);
foreach ($query->posts as $post) {
if ($post->post_type === Core::POST) {
echo Cards::post_detail($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
continue;
}
$url = $post->post_status === 'publish' ? get_permalink($post) : '';
echo '<div class="jio-forum__user-row">' . ($url ? '<a href="' . esc_url($url) . '">' : '<span>') . esc_html($post->post_title) . ($url ? '</a>' : '</span>') . ($url ? '' : '<small>待审核</small>') . '</div>';
if ($owner && !$url) self::plate_editor($post);
}
wp_reset_postdata();
echo '</div></div>';
}
}