feat(forum): plate lists widget payload + REST

Shared query_payload for plate lists and
/forum/frontend/widgets/plates for remote refresh.
This commit is contained in:
2026-07-20 20:50:58 +08:00
parent c52651f647
commit 425ca6cd2e
2 changed files with 91 additions and 24 deletions
+23
View File
@@ -252,6 +252,11 @@ class Forum {
'callback' => [$this, 'rest_widget_topics'], 'callback' => [$this, 'rest_widget_topics'],
'permission_callback' => '__return_true', 'permission_callback' => '__return_true',
]); ]);
register_rest_route('aksrt/v1', '/forum/frontend/widgets/plates', [
'methods' => 'GET',
'callback' => [$this, 'rest_widget_plates'],
'permission_callback' => '__return_true',
]);
} }
public function rest_widget_topics(\WP_REST_Request $request) { public function rest_widget_topics(\WP_REST_Request $request) {
@@ -278,6 +283,24 @@ class Forum {
], 200); ], 200);
} }
public function rest_widget_plates(\WP_REST_Request $request) {
if (!class_exists('\AKSRT\Widgets\WidgetForumPlateLists')) {
return new \WP_REST_Response(['success' => false, 'message' => 'widget unavailable'], 500);
}
$instance = [
'showposts' => max(1, min(30, (int) ($request->get_param('showposts') ?? $request->get_param('count') ?? 8))),
'orderby' => sanitize_key((string) ($request->get_param('orderby') ?? 'menu_order')),
'style' => sanitize_key((string) ($request->get_param('style') ?? 'default')),
'filter' => sanitize_key((string) ($request->get_param('filter') ?? '')),
'cat' => sanitize_text_field((string) ($request->get_param('cat') ?? '')),
];
$payload = \AKSRT\Widgets\WidgetForumPlateLists::query_payload($instance);
return new \WP_REST_Response([
'success' => true,
'html' => (string) ($payload['html'] ?? ''),
], 200);
}
public function render_board_cards(array $boards): void { public function render_board_cards(array $boards): void {
+68 -24
View File
@@ -1,6 +1,6 @@
<?php <?php
/** /**
* Forum plate list (zibll zib_bbs_widget_ui_plate_lists lite). * Forum plate list (zibll zib_bbs_widget_ui_plate_lists + ajax).
* *
* @package AKSRT * @package AKSRT
*/ */
@@ -16,20 +16,18 @@ class WidgetForumPlateLists extends \WP_Widget {
'aksrt_forum_plate_lists', 'aksrt_forum_plate_lists',
esc_html__('论坛 - 版块列表(Plate)', 'aksrt'), esc_html__('论坛 - 版块列表(Plate)', 'aksrt'),
[ [
'description' => esc_html__('展示论坛 plate 版块列表,支持排序与卡片样式。', 'aksrt'), 'description' => esc_html__('展示论坛 plate 版块列表,支持排序/卡片/AJAX。', 'aksrt'),
'classname' => 'widget_aksrt_forum_plate_lists', 'classname' => 'widget_aksrt_forum_plate_lists',
] ]
); );
} }
public function widget($args, $instance): void { /**
if (!post_type_exists('aksrt_forum_plate')) { * @return array
return; */
} public static function build_query_args(array $instance): array {
$limit = max(1, min(30, (int) ($instance['showposts'] ?? 8))); $limit = max(1, min(30, (int) ($instance['showposts'] ?? 8)));
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'menu_order')); $orderby = sanitize_key((string) ($instance['orderby'] ?? 'menu_order'));
$style = sanitize_key((string) ($instance['style'] ?? 'default'));
$filter = sanitize_key((string) ($instance['filter'] ?? '')); $filter = sanitize_key((string) ($instance['filter'] ?? ''));
$cat_raw = (string) ($instance['cat'] ?? ''); $cat_raw = (string) ($instance['cat'] ?? '');
$cat_ids = array_values(array_filter(array_map('intval', preg_split('/[\s,]+/', $cat_raw) ?: []))); $cat_ids = array_values(array_filter(array_map('intval', preg_split('/[\s,]+/', $cat_raw) ?: [])));
@@ -39,6 +37,7 @@ class WidgetForumPlateLists extends \WP_Widget {
'post_status' => 'publish', 'post_status' => 'publish',
'posts_per_page' => $limit, 'posts_per_page' => $limit,
'order' => 'ASC', 'order' => 'ASC',
'no_found_rows' => true,
]; ];
switch ($orderby) { switch ($orderby) {
@@ -81,8 +80,61 @@ class WidgetForumPlateLists extends \WP_Widget {
]]; ]];
} }
$plates = get_posts($query_args); return $query_args;
}
public static function render_items_html(array $plates, string $style = 'default'): string {
if (!$plates) { if (!$plates) {
return '';
}
ob_start();
$self = new self();
if ($style === 'card') {
echo '<div class="aksrt-plate-cards ajax-item">';
foreach ($plates as $post) {
if ($post instanceof \WP_Post) {
$self->render_card($post);
}
}
echo '</div>';
} else {
echo '<div class="aksrt-plate-lists ajax-item">';
foreach ($plates as $post) {
if ($post instanceof \WP_Post) {
$self->render_row($post);
}
}
echo '</div>';
}
return (string) ob_get_clean();
}
/**
* @return array{html:string}
*/
public static function query_payload(array $instance): array {
if (!post_type_exists('aksrt_forum_plate')) {
return ['html' => ''];
}
$style = sanitize_key((string) ($instance['style'] ?? 'default'));
$plates = get_posts(self::build_query_args($instance));
$html = self::render_items_html($plates ?: [], $style === 'card' ? 'card' : 'default');
if ($html === '') {
$html = function_exists('aksrt_get_ajax_null')
? aksrt_get_ajax_null(__('暂无版块', 'aksrt'))
: '<p class="aksrt-plate-empty ajax-item">' . esc_html__('暂无版块', 'aksrt') . '</p>';
}
return ['html' => $html];
}
public function widget($args, $instance): void {
if (!post_type_exists('aksrt_forum_plate')) {
return;
}
$style = sanitize_key((string) ($instance['style'] ?? 'default'));
$payload = self::query_payload($instance);
if ($payload['html'] === '') {
return; return;
} }
@@ -92,24 +144,16 @@ class WidgetForumPlateLists extends \WP_Widget {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} }
if ($style === 'card') { // IAS-like: first paint is SSR; optional remote refresh via rest for customize.
echo '<div class="aksrt-plate-cards">'; $rest = rest_url('aksrt/v1/forum/frontend/widgets/plates');
foreach ($plates as $post) { echo '<div class="widget-plate-lists ajaxpager mb20" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($rest) . '">';
$this->render_card($post); echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} echo '</div>';
echo '</div>';
} else {
echo '<div class="aksrt-plate-lists">';
foreach ($plates as $post) {
$this->render_row($post);
}
echo '</div>';
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} }
private function render_row(\WP_Post $post): void { public function render_row(\WP_Post $post): void {
$id = (int) $post->ID; $id = (int) $post->ID;
$url = get_permalink($id); $url = get_permalink($id);
$thumb = get_the_post_thumbnail_url($id, 'thumbnail'); $thumb = get_the_post_thumbnail_url($id, 'thumbnail');
@@ -136,7 +180,7 @@ class WidgetForumPlateLists extends \WP_Widget {
echo '</div></a>'; echo '</div></a>';
} }
private function render_card(\WP_Post $post): void { public function render_card(\WP_Post $post): void {
$id = (int) $post->ID; $id = (int) $post->ID;
$url = get_permalink($id); $url = get_permalink($id);
$thumb = get_the_post_thumbnail_url($id, 'medium'); $thumb = get_the_post_thumbnail_url($id, 'medium');