fix(widgets): align tabbed post layouts with reference
This commit is contained in:
1 parent
17515cf9c5
commit
fd034ff055
16 files changed
+1256
-37
No files matched your search
@@ -23,12 +23,12 @@ final class FrontendRenderer {
|
||||
}
|
||||
|
||||
AssetManager::enqueue_for($definition);
|
||||
if (in_array($definition->slug(), ['user_card', 'author_card'], true)) {
|
||||
self::render_user_widget($definition, $instance, $widget, $content);
|
||||
if (in_array($definition->slug(), ['user_card', 'author_card', 'tab_posts'], true)) {
|
||||
self::render_reference_widget($definition, $instance, $widget, $content);
|
||||
return;
|
||||
}
|
||||
if (in_array($definition->slug(), [
|
||||
'post_pay', 'tab_posts', 'posts', 'oneline_posts', 'hot_posts',
|
||||
'post_pay', 'posts', 'oneline_posts', 'hot_posts',
|
||||
'slider', 'slider_media_combo', 'icon_cards', 'icon_cover_cards',
|
||||
'buttons', 'notice', 'term_cards', 'term_aggregation', 'media_cards',
|
||||
'combo_info', 'partners', 'recent_comments', 'posts_toc',
|
||||
@@ -85,8 +85,11 @@ final class FrontendRenderer {
|
||||
echo (string) ($args['after_widget'] ?? '</section>'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
private static function render_user_widget(WidgetDefinition $definition, array $instance, SchemaWidget $widget, string $content): void {
|
||||
$classes = ['zib-widget-wrap', 'aksrt-user-widget-wrap', 'aksrt-' . str_replace('_', '-', $definition->slug()) . '-wrap'];
|
||||
private static function render_reference_widget(WidgetDefinition $definition, array $instance, SchemaWidget $widget, string $content): void {
|
||||
$classes = ['zib-widget-wrap', 'aksrt-' . str_replace('_', '-', $definition->slug()) . '-wrap'];
|
||||
if (in_array($definition->slug(), ['user_card', 'author_card'], true)) {
|
||||
$classes[] = 'aksrt-user-widget-wrap';
|
||||
}
|
||||
$device_class = WidgetVisibility::device_class($instance);
|
||||
if ($device_class !== '') {
|
||||
$classes[] = $device_class;
|
||||
@@ -97,11 +100,10 @@ final class FrontendRenderer {
|
||||
|
||||
$content_classes = ['widget-content'];
|
||||
if (!empty($instance['animation_in'])) {
|
||||
$content_classes[] = 'aksrt-widget--animate';
|
||||
$content_classes[] = 'aksrt-widget--animate-' . sanitize_html_class((string) $instance['animation_in']);
|
||||
$content_classes[] = 'obs-animate ani-' . sanitize_html_class((string) $instance['animation_in']);
|
||||
}
|
||||
if (!empty($instance['animation_repeat'])) {
|
||||
$content_classes[] = 'aksrt-widget--animate-repeat';
|
||||
$content_classes[] = 'obs-animate-repeat';
|
||||
}
|
||||
|
||||
$style = self::style($instance);
|
||||
|
||||
@@ -8,6 +8,13 @@ defined('ABSPATH') || exit;
|
||||
* Shared list/card/mini markup and pagination payloads (reference parity).
|
||||
*/
|
||||
final class PostRenderer {
|
||||
/** Keep the shell, skeleton and every AJAX page on the widget's selected layout. */
|
||||
public static function style(array $instance, string $slug): string {
|
||||
$default = $slug === 'tab_posts' ? 'mini' : ($slug === 'oneline_posts' ? 'card' : 'list');
|
||||
$style = (string) ($instance['style'] ?? $default);
|
||||
return in_array($style, ['list', 'card', 'mini'], true) ? $style : $default;
|
||||
}
|
||||
|
||||
public static function payload(array $instance, string $slug, int $page = 1, string $segment = ''): array {
|
||||
$segment_config = $slug === 'tab_posts' ? PostQuery::segment($instance, $segment) : [];
|
||||
$query = PostQuery::build($instance, $page, $segment_config);
|
||||
@@ -28,18 +35,24 @@ final class PostRenderer {
|
||||
if (!$query->have_posts()) {
|
||||
return function_exists('aksrt_widget_ajax_null') ? aksrt_widget_ajax_null() : RendererHelpers::empty_state(__('暂无内容', 'aksrt'));
|
||||
}
|
||||
$style = (string) ($instance['style'] ?? 'card');
|
||||
$mode = in_array($style, ['list', 'card', 'mini'], true) ? $style : 'card';
|
||||
$mode = self::style($instance, $slug);
|
||||
$mini_opt = (array) ($instance['mini_opt'] ?? []);
|
||||
$config = [
|
||||
'type' => $mode === 'card' ? 'card' : 'list',
|
||||
// Reference widgets render their own stream, independently of the
|
||||
// surrounding homepage/archive's joined rows and author context.
|
||||
'no_margin' => false,
|
||||
'is_home' => false,
|
||||
'is_category' => false,
|
||||
'is_tag' => false,
|
||||
'is_author' => false,
|
||||
'is_search' => false,
|
||||
'is_mult_thumb' => 'disable',
|
||||
'is_no_thumb' => 'disable',
|
||||
'show_number' => in_array('show_number', $mini_opt, true),
|
||||
'show_thumb' => in_array('show_thumb', $mini_opt, true),
|
||||
'show_meta' => in_array('show_meta', $mini_opt, true),
|
||||
'number_offset' => ($page - 1) * max(1, (int) ($instance['count'] ?? 8)),
|
||||
'widget_style' => $mode,
|
||||
];
|
||||
if ($slug === 'oneline_posts') {
|
||||
return self::oneline($query, $config, $mode);
|
||||
@@ -93,17 +106,41 @@ final class PostRenderer {
|
||||
}
|
||||
if ($mode === 'number' || $mode === 'numbered') {
|
||||
$links = '';
|
||||
$start = max(1, min($page - 2, $max_pages - 4));
|
||||
$end = min($max_pages, max($start + 4, $page + 2));
|
||||
for ($number = $start; $number <= $end; $number++) {
|
||||
$mobile = wp_is_mobile();
|
||||
$mid_size = $mobile ? 0 : 2;
|
||||
if ($page > 1) {
|
||||
$links .= self::page_link($page - 1, '<i class="fa fas fa-angle-left em12" aria-hidden="true"></i><span class="hide-sm ml6">' . esc_html__('上一页', 'aksrt') . '</span>', 'prev');
|
||||
}
|
||||
$dots = false;
|
||||
for ($number = 1; $number <= $max_pages; $number++) {
|
||||
if ($number === $page) {
|
||||
$links .= '<span class="page-numbers current">' . $number . '</span>';
|
||||
$dots = true;
|
||||
continue;
|
||||
}
|
||||
$links .= '<a class="next-page page-numbers" ajaxpager-target=".widget-ajaxpager" ajax-replace="true" data-widget-page="' . $number . '" role="button" tabindex="0" href="#page-' . $number . '">' . $number . '</a>';
|
||||
if ($number === 1 || $number === $max_pages || abs($number - $page) <= $mid_size) {
|
||||
$links .= self::page_link($number, (string) $number);
|
||||
$dots = true;
|
||||
} elseif ($dots) {
|
||||
$links .= '<span class="page-numbers dots">…</span>';
|
||||
$dots = false;
|
||||
}
|
||||
}
|
||||
if ($page < $max_pages) {
|
||||
$links .= self::page_link($page + 1, '<span class="hide-sm mr6">' . esc_html__('下一页', 'aksrt') . '</span><i class="fa fas fa-angle-right em12" aria-hidden="true"></i>', 'next');
|
||||
}
|
||||
if ($max_pages > ($mobile ? 4 : 8)) {
|
||||
$links .= '<span class="pag-jump page-numbers"><input autocomplete="off" min="1" max="' . $max_pages . '" current="' . $page . '" type="' . ($mobile ? 'number' : 'text') . '" inputmode="numeric" class="form-control jump-input" data-widget-jump aria-label="' . esc_attr__('跳转页码', 'aksrt') . '"><span class="hi de-sm mr6 jump-text">' . esc_html__('跳转', 'aksrt') . '</span><button type="button" class="jump-icon fa fas fa-angle-double-right em12" data-widget-jump-go aria-label="' . esc_attr__('跳转', 'aksrt') . '"></button></span>';
|
||||
}
|
||||
return '<div class="pagenav ajax-pag" role="navigation" aria-label="' . esc_attr__('文章分页', 'aksrt') . '">' . $links . '</div>';
|
||||
}
|
||||
if ($page >= $max_pages) {
|
||||
return '';
|
||||
}
|
||||
return '<div class="text-center theme-pagination ajax-pag"><div no-scroll="true" ajaxpager-target=".widget-ajaxpager" class="next-page"><a role="button" tabindex="0" href="#next" data-next-page="' . (int) ($page + 1) . '">' . esc_html__('加载更多', 'aksrt') . '</a></div></div>';
|
||||
}
|
||||
|
||||
private static function page_link(int $page, string $label, string $class = ''): string {
|
||||
return '<a class="next-page page-numbers' . ($class !== '' ? ' ' . esc_attr($class) : '') . '" ajaxpager-target=".widget-ajaxpager" ajax-replace="true" data-widget-page="' . $page . '" role="button" tabindex="0" href="#page-' . $page . '">' . $label . '</a>';
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,9 @@ defined('ABSPATH') || exit;
|
||||
/** Render article discovery and paid-content widgets (reference parity). */
|
||||
final class ContentRenderer {
|
||||
public static function render(string $slug, array $instance, array $context = []): string {
|
||||
if (in_array($slug, ['tab_posts', 'posts', 'oneline_posts'], true)) {
|
||||
$instance['style'] = PostRenderer::style($instance, $slug);
|
||||
}
|
||||
switch ($slug) {
|
||||
case 'term_cards': return self::term_cards($instance);
|
||||
case 'term_aggregation': return self::term_aggregation($instance);
|
||||
@@ -24,7 +27,7 @@ final class ContentRenderer {
|
||||
|
||||
private static function posts(array $instance, array $context, string $slug): string {
|
||||
$widget_id = (string) ($context['widget_id'] ?? '');
|
||||
$style = in_array(($instance['style'] ?? 'list'), ['list', 'card', 'mini'], true) ? (string) $instance['style'] : 'list';
|
||||
$style = $instance['style'];
|
||||
if ($slug === 'oneline_posts') {
|
||||
// Reference parity: the swiper row is fully rendered server-side.
|
||||
$query = \AKSRT\WidgetSystem\PostQuery::build(array_merge($instance, ['paginate' => '']), 1, []);
|
||||
@@ -73,7 +76,7 @@ final class ContentRenderer {
|
||||
}
|
||||
|
||||
private static function tab_posts(array $instance, array $context): string {
|
||||
$style = in_array(($instance['style'] ?? 'mini'), ['list', 'card', 'mini'], true) ? (string) $instance['style'] : 'mini';
|
||||
$style = $instance['style'];
|
||||
$tabs = array_values((array) ($instance['tabs'] ?? []));
|
||||
if (!$tabs) {
|
||||
return '';
|
||||
@@ -88,7 +91,7 @@ final class ContentRenderer {
|
||||
if (!is_array($tab) || trim((string) ($tab['title'] ?? '')) === '') continue;
|
||||
$tab_id = 'aksrt-tab-' . $key . '-' . $visible_index;
|
||||
$selected = $visible_index === 0;
|
||||
$buttons .= '<li class="' . ($selected ? 'active' : '') . '"><a' . ($selected ? '' : ' data-ajax') . ' data-toggle="tab" href="#' . esc_attr($panel_id . '-' . $visible_index) . '" role="tab" id="' . esc_attr($tab_id) . '" aria-controls="' . esc_attr($panel_id . '-' . $visible_index) . '" aria-selected="' . ($selected ? 'true' : 'false') . '" tabindex="' . ($selected ? '0' : '-1') . '" data-segment="' . (int) $index . '">' . wp_kses_post((string) $tab['title']) . '</a></li>';
|
||||
$buttons .= '<li class="' . ($selected ? 'active' : '') . '"><a href="#' . esc_attr($panel_id . '-' . $visible_index) . '" role="tab" id="' . esc_attr($tab_id) . '" aria-controls="' . esc_attr($panel_id . '-' . $visible_index) . '" aria-selected="' . ($selected ? 'true' : 'false') . '" tabindex="' . ($selected ? '0' : '-1') . '" data-segment="' . (int) $index . '">' . wp_kses_post((string) $tab['title']) . '</a></li>';
|
||||
if ($selected) {
|
||||
$body = self::ajaxpager($instance, 'tab_posts', $widget_id, 1, (string) $index);
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user