fix(frontend): align layouts posts and widgets with zibll

This commit is contained in:
2026-08-17 21:47:40 +08:00
parent 526364b438
commit 5d45eb053b
27 changed files with 3222 additions and 2777 deletions
+312
View File
@@ -0,0 +1,312 @@
<?php
/**
* Shared post renderer helpers.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_renderer_collect_post_data')) {
/**
* Aggregate the runtime data needed by all renderer modes.
*
* @param array<string,mixed> $cfg Renderer config.
* @return array<string,mixed>
*/
function aksrt_renderer_collect_post_data(array $cfg): array {
$post_id = (int) get_the_ID();
if ($post_id <= 0) {
return [];
}
$lazy = aksrt_renderer_lazyload_config();
$lazy['enabled'] = !empty($lazy['enabled']) && !empty($cfg['thumb_lazy']);
$images = aksrt_renderer_resolve_images($post_id, $cfg);
$gallery_images = array_slice($images['gallery'], 0, $cfg['multi_thumb_limit']);
$is_mult_thumb = !empty($cfg['multi_thumb_enabled'])
&& count($gallery_images) >= (int) $cfg['multi_thumb_min']
&& $cfg['mode'] === 'list';
$author_id = (int) get_post_field('post_author', $post_id);
$categories = get_the_category($post_id) ?: [];
$tags = get_the_tags($post_id) ?: [];
$custom_excerpt = class_exists('\AKSRT\Core\PostMetaBox')
? (string) \AKSRT\Core\PostMetaBox::get_meta_value($post_id, 'custom_excerpt', '')
: '';
$custom_subtitle = (string) get_post_meta($post_id, '_subtitle', true);
$excerpt_source = $custom_excerpt !== '' ? $custom_excerpt : (string) get_the_excerpt($post_id);
if ($excerpt_source === '') {
$excerpt_source = (string) get_post_field('post_content', $post_id, 'raw');
}
$excerpt = wp_trim_words(wp_strip_all_tags($excerpt_source), $cfg['excerpt_words'], '...');
$resource_meta = function_exists('aksrt_get_resource_meta') ? aksrt_get_resource_meta($post_id) : [];
$resource_strip = function_exists('aksrt_resource_meta_strip') ? aksrt_resource_meta_strip($resource_meta) : [];
return [
'post_id' => $post_id,
'permalink' => get_permalink($post_id),
'title' => get_the_title($post_id),
'subtitle' => $custom_subtitle,
'excerpt' => $excerpt,
'img_url' => $images['primary'],
'has_img' => !empty($images['has_thumb']),
'has_real_img' => !empty($images['has_real']),
'gallery_images' => $gallery_images,
'is_mult_thumb' => $is_mult_thumb,
'is_video_cover' => !empty(get_post_meta($post_id, '_aksrt_featured_video', true)) || !empty(get_post_meta($post_id, '_video_url', true)),
'author_id' => $author_id,
'avatar_url' => get_avatar_url($author_id, ['size' => 40]),
'author_name' => get_the_author(),
'categories' => $categories,
'tags' => $tags,
'comment_count' => (int) get_comments_number($post_id),
'views' => function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($post_id) : 0,
'likes' => function_exists('aksrt_get_post_likes') ? (int) aksrt_get_post_likes($post_id) : 0,
'time_ago' => human_time_diff((int) get_the_time('U', $post_id), current_time('timestamp')),
'resource_badge' => function_exists('aksrt_resource_card_badge_text') ? (string) aksrt_resource_card_badge_text($post_id) : '',
'resource_strip' => $resource_strip,
'is_resource' => function_exists('aksrt_is_resource_post') ? aksrt_is_resource_post($post_id) : false,
'is_sticky' => is_sticky($post_id),
'lazy' => $lazy,
'thumb_ratio_css' => aksrt_renderer_thumb_ratio_value((string) $cfg['thumb_ratio']),
'thumb_ratio_key' => (string) $cfg['thumb_ratio'],
];
}
}
if (!function_exists('aksrt_renderer_article_attrs')) {
/**
* Build the article wrapper attributes.
*
* @param string[] $classes CSS classes.
* @param array<string,mixed> $data Collected post data.
* @return string
*/
function aksrt_renderer_article_attrs(array $classes, array $data): string {
$classes[] = 'thumb-ratio--' . str_replace(':', '-', (string) $data['thumb_ratio_key']);
return sprintf(
'class="%s" style="%s"',
esc_attr(implode(' ', array_unique(array_filter($classes)))),
esc_attr('--aksrt-thumb-ratio:' . $data['thumb_ratio_css'])
);
}
}
if (!function_exists('aksrt_renderer_thumb')) {
/**
* Render the primary thumbnail.
*
* @param array<string,mixed> $data Collected post data.
* @param array<string,mixed> $cfg Renderer config.
* @return string
*/
function aksrt_renderer_thumb(array $data, array $cfg): string {
if (!$cfg['show_thumb'] || empty($data['has_img'])) {
return '';
}
$lazy = $data['lazy'];
$img = (string) $data['img_url'];
$title = (string) $data['title'];
$href = (string) $data['permalink'];
$is_sticky = !empty($data['is_sticky']);
$has_real_img = !empty($data['has_real_img']);
if ($has_real_img && !empty($lazy['enabled'])) {
$img_html = '<span class="aksrt-skeleton"></span>'
. '<img class="' . (!empty($cfg['thumb_fit']) && $cfg['thumb_fit'] === 'contain' ? 'fit-contain' : 'fit-cover') . ' aksrt-lazy lazyload" data-src="' . esc_url($img) . '" src="' . esc_url($lazy['placeholder_url']) . '" alt="' . esc_attr($title) . '">';
} else {
$img_html = '<img class="' . (!empty($cfg['thumb_fit']) && $cfg['thumb_fit'] === 'contain' ? 'fit-contain' : 'fit-cover') . '" src="' . esc_url($img) . '" alt="' . esc_attr($title) . '"' . ($has_real_img ? ' loading="lazy"' : '') . '>';
}
$sticky_html = ($is_sticky && !empty($cfg['badge_show']))
? '<badge class="img-badge left jb-red">' . esc_html__('置顶', 'aksrt') . '</badge>'
: '';
$format_badge = '';
if (!empty($data['is_mult_thumb']) && !empty($data['gallery_images'])) {
$format_badge = '<badge class="b-black opacity8 abs-right">' . esc_html(count($data['gallery_images'])) . '</badge>';
} elseif (!empty($data['is_video_cover'])) {
$format_badge = '<badge class="b-black opacity8 abs-right"><i class="fas fa-play-circle" aria-hidden="true"></i></badge>';
}
$empty_class = $has_real_img ? '' : ' item-thumbnail--fallback';
$target_attr = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
if ($cfg['mode'] === 'list') {
$graphic_class = 'post-graphic';
if (($cfg['list_img_position'] ?? 'left') === 'right') {
$graphic_class .= ' order1';
}
return '<div class="' . esc_attr($graphic_class) . '"><div class="item-thumbnail' . esc_attr($empty_class) . '"><a href="' . esc_url($href) . '" rel="bookmark"' . $target_attr . '>'
. $img_html . '</a>' . $sticky_html . $format_badge . '</div></div>';
}
return '<div class="item-thumbnail' . esc_attr($empty_class) . '"><a href="' . esc_url($href) . '" rel="bookmark"' . $target_attr . '>'
. $img_html . '</a>' . $sticky_html . $format_badge . '</div>';
}
}
if (!function_exists('aksrt_renderer_mult_thumb')) {
/**
* Render the multi-image strip used by list cards.
*
* @param array<string,mixed> $data Collected post data.
* @return string
*/
function aksrt_renderer_mult_thumb(array $data): string {
if (empty($data['is_mult_thumb']) || empty($data['gallery_images'])) {
return '';
}
$lazy = $data['lazy'];
$html = '<a class="thumb-items contain" href="' . esc_url($data['permalink']) . '" aria-label="' . esc_attr($data['title']) . '">';
foreach (array_slice($data['gallery_images'], 0, 4) as $image) {
$html .= '<span>';
if (!empty($lazy['enabled'])) {
$html .= '<span class="aksrt-skeleton"></span>'
. '<img class="fit-cover aksrt-lazy lazyload" data-src="' . esc_url($image) . '" src="' . esc_url($lazy['placeholder_url']) . '" alt="">';
} else {
$html .= '<img class="fit-cover" src="' . esc_url($image) . '" alt="" loading="lazy">';
}
$html .= '</span>';
}
$html .= '</a>';
return $html;
}
}
if (!function_exists('aksrt_renderer_badges')) {
/**
* Render taxonomy and resource badges.
*
* @param array<string,mixed> $data Collected post data.
* @param array<string,mixed> $cfg Renderer config.
* @return string
*/
function aksrt_renderer_badges(array $data, array $cfg): string {
$items = [];
if (!empty($cfg['show_resource_badge']) && $data['resource_badge'] !== '') {
$items[] = '<a href="' . esc_url($data['permalink']) . '#posts-pay" class="meta-pay but jb-yellow">' . esc_html($data['resource_badge']) . '</a>';
}
if (!empty($cfg['show_badges']) && !empty($cfg['badge_show']) && $cfg['category_limit'] > 0) {
foreach (array_slice($data['categories'], 0, $cfg['category_limit']) as $category) {
$items[] = '<a href="' . esc_url(get_category_link($category->term_id)) . '" class="but"><i class="far fa-folder-open" aria-hidden="true"></i> ' . esc_html($category->name) . '</a>';
}
}
if (!empty($cfg['show_tags']) && $cfg['tag_limit'] > 0) {
foreach (array_slice($data['tags'], 0, $cfg['tag_limit']) as $tag) {
$items[] = '<a href="' . esc_url(get_tag_link($tag->term_id)) . '" class="but">#' . esc_html($tag->name) . '</a>';
}
}
if (!empty($data['is_resource'])) {
$items[] = '<span class="but jb-vip">VIP</span>';
}
if (empty($items)) {
return '';
}
return '<div class="item-tags scroll-x no-scrollbar">' . implode('', $items) . '</div>';
}
}
if (!function_exists('aksrt_renderer_resource_strip')) {
/**
* Render compact resource meta chips.
*
* @param array<string,mixed> $data Collected post data.
* @return string
*/
function aksrt_renderer_resource_strip(array $data): string {
if (empty($data['resource_strip']) || !is_array($data['resource_strip'])) {
return '';
}
$html = '<ul class="item-cms-strip">';
foreach ($data['resource_strip'] as $item) {
$html .= '<li>' . esc_html((string) $item) . '</li>';
}
$html .= '</ul>';
return $html;
}
}
if (!function_exists('aksrt_renderer_meta')) {
/**
* Render the meta bar.
*
* @param array<string,mixed> $data Collected post data.
* @param array<string,mixed> $cfg Renderer config.
* @return string
*/
function aksrt_renderer_meta(array $data, array $cfg): string {
if (!$cfg['show_meta']) {
return '';
}
$format_number = function_exists('aksrt_format_number') ? 'aksrt_format_number' : 'strval';
if ($cfg['mode'] === 'mini') {
$items = [];
if (!empty($cfg['show_date'])) {
$items[] = '<span class="meta-item">' . esc_html($data['time_ago']) . '</span>';
}
if (!empty($cfg['show_views'])) {
$items[] = '<span class="meta-item"><i class="fas fa-eye" aria-hidden="true"></i> ' . esc_html($format_number($data['views'])) . '</span>';
}
if (empty($items)) {
return '';
}
return '<div class="item-meta">' . implode('<span class="meta-dot" aria-hidden="true"></span>', $items) . '</div>';
}
$left = [];
if (!empty($cfg['show_author'])) {
$left[] = '<item class="meta-author flex ac"><img src="' . esc_url($data['avatar_url']) . '" alt="" class="avatar-mini" width="20" height="20" loading="lazy"><name class="meta-name">' . esc_html($data['author_name']) . '</name></item>';
}
if (!empty($cfg['show_date'])) {
$left[] = '<item class="meta-time">' . esc_html($data['time_ago']) . '</item>';
}
$right = [];
if (!empty($cfg['show_comments'])) {
$right[] = '<item class="meta-view"><i class="fas fa-comment" aria-hidden="true"></i> ' . esc_html((string) $data['comment_count']) . '</item>';
}
if (!empty($cfg['show_views'])) {
$right[] = '<item class="meta-view"><i class="fas fa-eye" aria-hidden="true"></i> ' . esc_html($format_number($data['views'])) . '</item>';
}
if (!empty($cfg['show_likes'])) {
$right[] = '<item class="meta-view"><i class="fas fa-thumbs-up" aria-hidden="true"></i> ' . esc_html($format_number($data['likes'])) . '</item>';
}
if (empty($left) && empty($right)) {
return '';
}
$html = '<div class="item-meta muted-2-color flex jsb ac">';
if (!empty($left)) {
$html .= '<div class="meta-author-group flex ac">' . implode('<span class="meta-dot" aria-hidden="true"></span>', $left) . '</div>';
}
if (!empty($right)) {
$html .= '<div class="meta-right">' . implode('', $right) . '</div>';
}
$html .= '</div>';
return $html;
}
}