feat(widgets): category recommend/tabs residual + batch22-24 CSS

Use graphic_card heroes and mini post strips for category recommend,
prefer shared mini list in category block sidebar fallback, admin empty
for product tabs, and forum/user residual styles.
This commit is contained in:
2026-07-21 10:39:17 +08:00
parent 8b5ca8f287
commit 4368a3c586
5 changed files with 184 additions and 67 deletions
+83
View File
@@ -2296,3 +2296,86 @@ a.main-color > .icon-cover-card:hover,
}
.tag-cloud.aksrt-tag-cloud a { transition: transform .15s ease; }
.tag-cloud.aksrt-tag-cloud a:hover { transform: translateY(-1px); }
/* batch22-24 forum/user residual */
.forum-posts.mini.aksrt-ftopic-mini,
.forum-posts.detail.aksrt-ftopic-detail {
display: block;
position: relative;
padding: 12px 0;
border-bottom: 1px solid var(--color-line-soft, #f0f1f3);
}
.forum-posts.mini.aksrt-ftopic-mini:last-child,
.forum-posts.detail.aksrt-ftopic-detail:last-child { border-bottom: 0; }
.forum-posts .forum-posts-header .avatar-img img,
.forum-posts .avatar-img img {
width: 28px; height: 28px; border-radius: 50%; object-fit: cover; display: block;
}
.forum-posts.detail .avatar-img img { width: 40px; height: 40px; }
.forum-posts .forum-title { margin: 0; font-size: 14px; font-weight: 600; line-height: 1.4; }
.forum-posts .forum-title a { color: inherit; text-decoration: none; }
.forum-posts .forum-title a:hover { color: var(--theme-color, #f04494); }
.forum-posts .item-meta { gap: 2px; }
.forum-posts .forum-excerpt { line-height: 1.5; }
.forum-posts badge.img-badge { z-index: 2; }
.plate-lists .plate-item,
.aksrt-plate-lists .plate-item {
display: flex;
gap: 12px;
align-items: flex-start;
padding: 10px 0;
border-bottom: 1px solid var(--color-line-soft, #f0f1f3);
color: inherit;
text-decoration: none;
}
.plate-lists .plate-item:last-child { border-bottom: 0; }
.plate-thumb,
.aksrt-plate-item__thumb {
width: 48px; height: 48px; border-radius: 10px; overflow: hidden;
flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
background: var(--surface-2, #f3f4f6); color: #999;
}
.plate-thumb img, .aksrt-plate-item__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.panel-plate.scroll-plate,
.aksrt-plate-cards {
display: flex; gap: 12px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: thin;
}
.plate-card, .aksrt-plate-card {
flex: 0 0 160px; width: 160px; text-decoration: none; color: inherit;
}
.plate-card .plate-thumb, .aksrt-plate-card__cover {
width: 100%; aspect-ratio: 1; border-radius: 12px; overflow: hidden;
background: var(--surface-2, #f3f4f6); display: flex; align-items: center; justify-content: center;
}
.plate-card .plate-thumb img, .aksrt-plate-card__cover img { width: 100%; height: 100%; object-fit: cover; }
.moderator-box.aksrt-plate-mods__list,
.aksrt-plate-mods__list { display: flex; flex-direction: column; gap: 12px; }
.aksrt-plate-mods.style-grid .aksrt-plate-mods__list {
display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 12px;
}
.aksrt-plate-mods__item { gap: 4px; }
.aksrt-plate-mods__avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; display: block; }
.aksrt-plate-mods.style-grid .aksrt-plate-mods__item { text-align: center; }
.aksrt-plate-mods.style-grid .aksrt-plate-mods__avatar { width: 48px; height: 48px; margin: 0 auto 6px; }
.user-ranking-box .user-ranking-item,
.aksrt-user-ranking-box .user-ranking-item { position: relative; }
.user-ranking-item .avatar-img img { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; display: block; }
.user-ranking-item .badg { white-space: nowrap; }
.aksrt-category-recommend__card[data-aksrt-animate] { will-change: transform, opacity; }
.aksrt-category-recommend__posts.posts-mini-wrap { margin-top: 8px; }
.aksrt-plate-info.plate-info-sidebar { overflow: hidden; }
.aksrt-plate-info__cover.plate-thumb {
width: 100%; height: 110px; border-radius: 12px; overflow: hidden;
background: var(--surface-2, #f3f4f6); display: flex; align-items: center; justify-content: center;
}
.aksrt-plate-info__cover.plate-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.aksrt-plate-info__stats.count-mates { gap: 8px; flex-wrap: wrap; }
.aksrt-ftag-list { display: flex; flex-wrap: wrap; gap: 8px; }
.aksrt-ftag-item.is-card { min-width: 120px; justify-content: space-between; }
+17 -16
View File
@@ -215,25 +215,26 @@ if (!function_exists('aksrt_home_widget_render_post_grid')) {
return;
}
// Fallback: simple sidebar list
// Fallback: shared mini list (lazy thumbs + meta).
if (function_exists('aksrt_render_mini_list')) {
echo '<div class="widget-tab-posts__list widget-tab-posts__list--mini aksrt-home-widget__sidebar-list">';
aksrt_render_mini_list($query, ['context' => 'sidebar', 'show_thumb' => true]);
echo '</div>';
return;
}
echo '<ul class="widget-tab-posts__list aksrt-home-widget__sidebar-list">';
$ph = get_template_directory_uri() . '/assets/img/placeholder.svg';
while ($query->have_posts()) {
$query->the_post();
?>
<li class="widget-tab-posts__item">
<?php if (has_post_thumbnail()) : ?>
<a href="<?php the_permalink(); ?>" class="widget-tab-posts__thumb">
<?php the_post_thumbnail('thumbnail', ['loading' => 'lazy', 'class' => 'fit-cover']); ?>
</a>
<?php endif; ?>
<div class="widget-tab-posts__info">
<a href="<?php the_permalink(); ?>" class="widget-tab-posts__title"><?php the_title(); ?></a>
<span class="widget-tab-posts__meta">
<?php echo esc_html(human_time_diff(get_the_time('U'), current_time('timestamp')) . __('前', 'aksrt')); ?>
</span>
</div>
</li>
<?php
$thumb = get_the_post_thumbnail_url(get_the_ID(), 'thumbnail');
echo '<li class="widget-tab-posts__item">';
if ($thumb) {
echo '<a href="' . esc_url(get_permalink()) . '" class="widget-tab-posts__thumb"><img class="fit-cover aksrt-lazy lazyload" data-src="' . esc_url($thumb) . '" src="' . esc_url($ph) . '" alt="" loading="lazy" /></a>';
}
echo '<div class="widget-tab-posts__info">';
echo '<a href="' . esc_url(get_permalink()) . '" class="widget-tab-posts__title">' . esc_html(get_the_title()) . '</a>';
echo '<span class="widget-tab-posts__meta">' . esc_html(human_time_diff(get_the_time('U'), current_time('timestamp')) . __('前', 'aksrt')) . '</span>';
echo '</div></li>';
}
echo '</ul>';
wp_reset_postdata();
+76 -50
View File
@@ -48,56 +48,82 @@ class CategoryRecommendWidget extends \WP_Widget {
ob_start();
printf('<div class="aksrt-category-recommend__grid ajax-item" style="--aksrt-recommend-columns:%d;">', (int) $columns);
foreach ($cards as $card) {
?>
<article class="aksrt-category-recommend__card">
<div class="aksrt-category-recommend__hero">
<a href="<?php echo esc_url($card['link']); ?>">
<?php if ($lazy['enabled']) : ?>
<span class="aksrt-skeleton"></span>
<img class="aksrt-category-recommend__cover aksrt-lazy" data-src="<?php echo esc_url($card['cover']); ?>" src="<?php echo esc_url($lazy['placeholder_url']); ?>" alt="<?php echo esc_attr($card['name']); ?>">
<?php else : ?>
<img class="aksrt-category-recommend__cover" src="<?php echo esc_url($card['cover']); ?>" alt="<?php echo esc_attr($card['name']); ?>">
<?php endif; ?>
</a>
<span class="aksrt-category-recommend__badge"><?php echo esc_html(sprintf(_n('%d 篇文章', '%d 篇文章', $card['count'], 'aksrt'), $card['count'])); ?></span>
<?php if ($show_views && $card['views'] > 0) : ?>
<span class="aksrt-category-recommend__views">
<i class="fas fa-eye" aria-hidden="true"></i>
<?php echo esc_html(function_exists('aksrt_format_number') ? aksrt_format_number($card['views']) : number_format_i18n($card['views'])); ?>
</span>
<?php endif; ?>
</div>
<div class="aksrt-category-recommend__body">
<div class="aksrt-category-recommend__meta">
<h4 class="aksrt-category-recommend__name">
<a href="<?php echo esc_url($card['link']); ?>"><?php echo esc_html($card['name']); ?></a>
</h4>
<?php if ($show_description && $card['description'] !== '') : ?>
<p class="aksrt-category-recommend__desc"><?php echo esc_html($card['description']); ?></p>
<?php endif; ?>
</div>
<ul class="aksrt-category-recommend__posts">
<?php foreach ($card['posts'] as $post_item) : ?>
<li class="aksrt-category-recommend__post">
<a class="aksrt-category-recommend__post-link" href="<?php echo esc_url($post_item['link']); ?>">
<?php echo esc_html($post_item['title']); ?>
</a>
<?php if ($show_dates && $post_item['date'] !== '') : ?>
<span class="aksrt-category-recommend__date"><?php echo esc_html($post_item['date']); ?></span>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php if ($show_more) : ?>
<div class="aksrt-home-widget__footer">
<a class="aksrt-home-widget__more" href="<?php echo esc_url($card['link']); ?>">
<?php esc_html_e('查看更多', 'aksrt'); ?>
</a>
</div>
<?php endif; ?>
</div>
</article>
<?php
$cover = (string) ($card['cover'] ?? '');
$link = (string) ($card['link'] ?? '');
$name = (string) ($card['name'] ?? '');
$badge = sprintf(_n('%d 篇文章', '%d 篇文章', (int) $card['count'], 'aksrt'), (int) $card['count']);
$more = '';
if ($show_views && (int) $card['views'] > 0) {
$v = function_exists('aksrt_format_number') ? aksrt_format_number((int) $card['views']) : number_format_i18n((int) $card['views']);
$more = '<span class="aksrt-category-recommend__views"><i class="fa fa-eye" aria-hidden="true"></i> ' . esc_html((string) $v) . '</span>';
}
echo '<article class="aksrt-category-recommend__card" data-aksrt-animate="fade-up">';
if (function_exists('aksrt_graphic_card') && $cover !== '') {
echo aksrt_graphic_card([ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'type' => 'style-2',
'class' => 'aksrt-category-recommend__hero mb10',
'img' => $cover,
'alt' => $name,
'link' => ['url' => $link],
'text1' => $name,
'text2' => $show_description ? (string) $card['description'] : '',
'text3' => $badge,
'more' => $more,
'lazy' => true,
]);
} else {
echo '<div class="aksrt-category-recommend__hero">';
echo '<a href="' . esc_url($link) . '">';
if ($lazy['enabled']) {
echo '<span class="aksrt-skeleton"></span>';
echo '<img class="aksrt-category-recommend__cover aksrt-lazy" data-src="' . esc_url($cover) . '" src="' . esc_url($lazy['placeholder_url']) . '" alt="' . esc_attr($name) . '">';
} else {
echo '<img class="aksrt-category-recommend__cover" src="' . esc_url($cover) . '" alt="' . esc_attr($name) . '">';
}
echo '</a>';
echo '<span class="aksrt-category-recommend__badge">' . esc_html($badge) . '</span>';
echo $more; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '</div>';
echo '<div class="aksrt-category-recommend__meta">';
echo '<h4 class="aksrt-category-recommend__name"><a href="' . esc_url($link) . '">' . esc_html($name) . '</a></h4>';
if ($show_description && $card['description'] !== '') {
echo '<p class="aksrt-category-recommend__desc">' . esc_html((string) $card['description']) . '</p>';
}
echo '</div>';
}
echo '<div class="aksrt-category-recommend__body">';
// Prefer shared mini list when post IDs available.
if (!empty($card['post_ids']) && function_exists('aksrt_render_mini_list')) {
$q = new \WP_Query([
'post_type' => 'any',
'post__in' => array_map('intval', (array) $card['post_ids']),
'orderby' => 'post__in',
'posts_per_page' => count((array) $card['post_ids']),
'ignore_sticky_posts' => true,
'no_found_rows' => true,
]);
echo '<div class="aksrt-category-recommend__posts posts-mini-wrap">';
aksrt_render_mini_list($q, ['context' => 'widget', 'show_thumb' => true, 'show_meta' => $show_dates]);
echo '</div>';
wp_reset_postdata();
} else {
echo '<ul class="aksrt-category-recommend__posts">';
foreach ($card['posts'] as $post_item) {
echo '<li class="aksrt-category-recommend__post">';
echo '<a class="aksrt-category-recommend__post-link" href="' . esc_url($post_item['link']) . '">' . esc_html($post_item['title']) . '</a>';
if ($show_dates && $post_item['date'] !== '') {
echo '<span class="aksrt-category-recommend__date">' . esc_html($post_item['date']) . '</span>';
}
echo '</li>';
}
echo '</ul>';
}
if ($show_more) {
echo '<div class="aksrt-home-widget__footer">';
echo '<a class="aksrt-home-widget__more" href="' . esc_url($link) . '">' . esc_html__('查看更多', 'aksrt') . '</a>';
echo '</div>';
}
echo '</div></article>';
}
echo '</div>';
return (string) ob_get_clean();
+1 -1
View File
@@ -130,7 +130,7 @@ class CategoryTabsWidget extends \WP_Widget {
if(showMore&&more){
html+='<div class="aksrt-home-widget__footer"><a class="aksrt-home-widget__more" href="'+more+'">查看更多</a></div>';
}
panel.innerHTML=html||'<p class="widget-empty">暂无文章</p>';
panel.innerHTML=html||'<div class="ajax-item widget-empty muted-2-color">暂无文章</div>';
panel.setAttribute('data-loaded','1');
panel.classList.remove('is-ajax-loading');
}).catch(function(){panel.classList.remove('is-ajax-loading');});
+7
View File
@@ -49,6 +49,13 @@ class WidgetProductTab extends \WP_Widget {
$paginate = sanitize_key((string) ($instance['paginate'] ?? 'ajax'));
$tabs = self::parse_tabs($tabs_raw);
if (!$tabs) {
if (current_user_can('manage_options')) {
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo function_exists('aksrt_get_widget_null')
? aksrt_get_widget_null(__('请至少配置一个 TAB', 'aksrt')) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
: '<p class="widget-empty">' . esc_html__('请至少配置一个 TAB', 'aksrt') . '</p>';
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
return;
}