feat(widgets): user minicards + term graphic cards/aggregation depth
User lists render author-minicard rows; term cards/aggregation consume aksrt_graphic_card with style-1..4, meta CTA, and orderby-aware post rows.
This commit is contained in:
@@ -1432,3 +1432,273 @@
|
||||
.aksrt-product-widget--oneline .aksrt-product-widget__grid {
|
||||
/* legacy flex fallback if swiper unavailable */
|
||||
}
|
||||
|
||||
/* ===== Batch13: oneline posts swiper-scroll + user minicards + term graphic ===== */
|
||||
|
||||
.widget-main-post.aksrt-oneline-posts {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.aksrt-oneline-swiper {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: 0 28px 4px;
|
||||
}
|
||||
.aksrt-oneline-swiper .swiper-wrapper {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
.aksrt-oneline-swiper .swiper-slide {
|
||||
width: auto;
|
||||
max-width: 46%;
|
||||
min-width: 160px;
|
||||
height: auto;
|
||||
}
|
||||
.widget-main-post.style-mini .aksrt-oneline-swiper .swiper-slide {
|
||||
max-width: 280px;
|
||||
min-width: 220px;
|
||||
}
|
||||
.widget-main-post.style-list .aksrt-oneline-swiper .swiper-slide {
|
||||
max-width: 320px;
|
||||
min-width: 240px;
|
||||
}
|
||||
.aksrt-oneline-swiper .posts-item,
|
||||
.aksrt-oneline-swiper .posts-mini {
|
||||
height: 100%;
|
||||
margin: 0 8px 0 0;
|
||||
}
|
||||
.aksrt-oneline-swiper .swiper-button-prev,
|
||||
.aksrt-oneline-swiper .swiper-button-next {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin-top: 0;
|
||||
top: 42%;
|
||||
border-radius: 50%;
|
||||
background: var(--surface-1, #fff);
|
||||
border: 1px solid var(--color-line, #e5e7eb);
|
||||
color: var(--color-ink, #111);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,.06);
|
||||
}
|
||||
.aksrt-oneline-swiper .swiper-button-prev:after,
|
||||
.aksrt-oneline-swiper .swiper-button-next:after {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.aksrt-oneline-swiper .swiper-button-prev { left: 0; }
|
||||
.aksrt-oneline-swiper .swiper-button-next { right: 0; }
|
||||
|
||||
/* User lists → author-minicard */
|
||||
.aksrt-user-lists .user_lists {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard {
|
||||
display: block;
|
||||
padding: 12px 14px;
|
||||
border-radius: 8px;
|
||||
background: var(--surface-1, #fff);
|
||||
border: 1px solid var(--color-line, #e5e7eb);
|
||||
overflow: hidden;
|
||||
}
|
||||
.aksrt-user-lists.is-bare .author-minicard {
|
||||
background: transparent;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard > ul.list-inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard > ul.list-inline > li {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard .avatar-img img.avatar {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard dl {
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard dt.flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard dd {
|
||||
margin: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard .abs-blur-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
opacity: .18;
|
||||
pointer-events: none;
|
||||
}
|
||||
.aksrt-user-lists .author-minicard .abs-blur-bg img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
filter: blur(18px);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
.aksrt-user-lists .author-minicard .relative {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Graphic card polish */
|
||||
.graphic {
|
||||
background: var(--surface-2, #f3f4f6);
|
||||
}
|
||||
.graphic .graphic-mask {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: #000;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
.graphic .graphic-text,
|
||||
.graphic .abs-center {
|
||||
z-index: 2;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
.graphic .title-h-center {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.graphic badge.b-black,
|
||||
.graphic .img-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
background: rgba(0,0,0,.55);
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.graphic video.fit-cover {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.hover-zoom-img .graphic img.fit-cover,
|
||||
.hover-zoom-img.graphic img.fit-cover {
|
||||
transition: transform .45s ease;
|
||||
}
|
||||
.hover-zoom-img:hover .graphic img.fit-cover,
|
||||
.hover-zoom-img.graphic:hover img.fit-cover {
|
||||
transform: scale(1.06);
|
||||
}
|
||||
.aksrt-term-cards .row.gutters-5 {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -4px;
|
||||
}
|
||||
.aksrt-term-cards .row.gutters-5 > [class*="col-"] {
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.aksrt-term-cards .col-sm-12 { width: 100%; }
|
||||
.aksrt-term-cards .col-sm-6 { width: 50%; }
|
||||
.aksrt-term-cards .col-sm-4 { width: 33.333%; }
|
||||
.aksrt-term-cards .col-sm-3 { width: 25%; }
|
||||
.aksrt-term-cards .col-sm-2 { width: 16.666%; }
|
||||
@media (max-width: 767px) {
|
||||
.aksrt-term-cards .col-xs-12 { width: 100%; }
|
||||
.aksrt-term-cards .col-xs-6 { width: 50%; }
|
||||
.aksrt-term-cards .col-xs-4 { width: 33.333%; }
|
||||
}
|
||||
|
||||
/* Term aggregation (zibll term-aggregation) */
|
||||
.term-aggregation.aksrt-term-agg__card,
|
||||
.zib-widget.term-aggregation {
|
||||
padding: 14px;
|
||||
border-radius: 10px;
|
||||
background: var(--surface-1, #fff);
|
||||
border: 1px solid var(--color-line, #e5e7eb);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.aksrt-term-agg {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
grid-template-columns: repeat(var(--aksrt-ta-cols, 1), minmax(0, 1fr));
|
||||
}
|
||||
.term-aggregation .hover-zoom-img.flex {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0;
|
||||
}
|
||||
.term-aggregation .term-img {
|
||||
width: 38%;
|
||||
max-width: 180px;
|
||||
min-width: 110px;
|
||||
}
|
||||
.term-aggregation .term-img .graphic {
|
||||
margin: 0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.term-aggregation .term-title {
|
||||
min-width: 0;
|
||||
padding-left: 4px;
|
||||
}
|
||||
.term-aggregation .term-title > a {
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
.term-aggregation .term-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
.term-aggregation .icon-circle {
|
||||
position: relative;
|
||||
padding-left: 14px;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
.term-aggregation .icon-circle:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: var(--theme-color, var(--focus-color, #f04494));
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.term-aggregation .but.c-blue {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
border-radius: 999px;
|
||||
padding: 2px 10px;
|
||||
font-size: 12px;
|
||||
background: rgba(59,130,246,.1);
|
||||
color: #2563eb;
|
||||
text-decoration: none;
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.aksrt-term-agg { grid-template-columns: 1fr; }
|
||||
.term-aggregation .term-img { max-width: 120px; min-width: 88px; width: 34%; }
|
||||
.term-aggregation .hide-sm { display: none !important; }
|
||||
.aksrt-oneline-swiper .swiper-slide { max-width: 72%; min-width: 140px; }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Term aggregation cards (zibll zib_widget_ui_term_lists_card lite).
|
||||
* Term aggregation cards (zibll zib_widget_ui_term_lists_card → zib_term_aggregation).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -16,7 +16,7 @@ class WidgetTermAggregation extends \WP_Widget {
|
||||
'aksrt_term_aggregation',
|
||||
esc_html__('AKSRT 分类聚合', 'aksrt'),
|
||||
[
|
||||
'description' => esc_html__('分类封面 + 最新文章列表聚合卡。', 'aksrt'),
|
||||
'description' => esc_html__('分类封面 + 描述 + 更多文章 CTA + 文章列表聚合卡。', 'aksrt'),
|
||||
'classname' => 'widget_aksrt_term_aggregation',
|
||||
]
|
||||
);
|
||||
@@ -37,15 +37,68 @@ class WidgetTermAggregation extends \WP_Widget {
|
||||
return array_values(array_unique($ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WP_Term $term
|
||||
*/
|
||||
private static function term_cover_url(\WP_Term $term): string {
|
||||
if (class_exists(WidgetTermCards::class) && method_exists(WidgetTermCards::class, 'term_cover_url')) {
|
||||
return WidgetTermCards::term_cover_url($term);
|
||||
}
|
||||
$img_id = (int) get_term_meta($term->term_id, 'thumbnail_id', true);
|
||||
if (!$img_id) {
|
||||
$img_id = (int) get_term_meta($term->term_id, '_aksrt_cover', true);
|
||||
}
|
||||
if ($img_id) {
|
||||
$url = wp_get_attachment_image_url($img_id, 'medium');
|
||||
if ($url) {
|
||||
return (string) $url;
|
||||
}
|
||||
}
|
||||
$url = (string) get_term_meta($term->term_id, '_aksrt_cover_url', true);
|
||||
return $url !== '' ? $url : get_template_directory_uri() . '/assets/img/placeholder.svg';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sum of post views under a term (best-effort).
|
||||
*/
|
||||
private static function term_views_sum(int $term_id, string $taxonomy): int {
|
||||
$q = new \WP_Query([
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => 50,
|
||||
'fields' => 'ids',
|
||||
'no_found_rows' => true,
|
||||
'update_post_meta_cache' => true,
|
||||
'update_post_term_cache' => false,
|
||||
'tax_query' => [[
|
||||
'taxonomy' => $taxonomy,
|
||||
'field' => 'term_id',
|
||||
'terms' => $term_id,
|
||||
]],
|
||||
]);
|
||||
$sum = 0;
|
||||
foreach ($q->posts as $pid) {
|
||||
$sum += function_exists('aksrt_get_post_views')
|
||||
? (int) aksrt_get_post_views((int) $pid)
|
||||
: (int) get_post_meta((int) $pid, 'aksrt_post_views', true);
|
||||
}
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public static function render_html(array $instance): string {
|
||||
$taxonomy = sanitize_key((string) ($instance['taxonomy'] ?? 'category'));
|
||||
if (!taxonomy_exists($taxonomy)) {
|
||||
$taxonomy = 'category';
|
||||
}
|
||||
$term_ids = self::parse_ids_static((string) ($instance['term_ids'] ?? ''));
|
||||
$count = max(1, min(12, (int) ($instance['count'] ?? 4)));
|
||||
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'date'));
|
||||
$columns = max(1, min(3, (int) ($instance['columns'] ?? 1)));
|
||||
$count = max(1, min(12, (int) ($instance['count'] ?? 4)));
|
||||
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'date'));
|
||||
$columns = max(1, min(3, (int) ($instance['columns'] ?? 1)));
|
||||
$target_blank = !empty($instance['target_blank']);
|
||||
$tgt = $target_blank ? ' target="_blank" rel="noopener noreferrer"' : '';
|
||||
|
||||
if (!$term_ids) {
|
||||
$terms = get_terms([
|
||||
@@ -74,16 +127,38 @@ class WidgetTermAggregation extends \WP_Widget {
|
||||
if (is_wp_error($link)) {
|
||||
continue;
|
||||
}
|
||||
$cover = '';
|
||||
$img_id = (int) get_term_meta($term_id, 'thumbnail_id', true);
|
||||
if (!$img_id) {
|
||||
$img_id = (int) get_term_meta($term_id, '_aksrt_cover', true);
|
||||
|
||||
$cover = self::term_cover_url($term);
|
||||
$views = self::term_views_sum((int) $term->term_id, $taxonomy);
|
||||
$more_badge = '<badge class="img-badge px12"><i class="fa fa-fire" aria-hidden="true"></i> ' . esc_html((string) $views) . '</badge>';
|
||||
|
||||
$img_html = '';
|
||||
if (function_exists('aksrt_graphic_card')) {
|
||||
$img_html = aksrt_graphic_card([
|
||||
'type' => '',
|
||||
'class' => '',
|
||||
'img' => $cover,
|
||||
'alt' => $term->name,
|
||||
'link' => [
|
||||
'url' => $link,
|
||||
'target' => $target_blank ? '_blank' : '',
|
||||
],
|
||||
'lazy' => true,
|
||||
'height_scale' => 70,
|
||||
'mask_opacity' => 0,
|
||||
'more' => $more_badge,
|
||||
]);
|
||||
}
|
||||
if ($img_id) {
|
||||
$cover = wp_get_attachment_image_url($img_id, 'medium') ?: '';
|
||||
}
|
||||
if ($cover === '') {
|
||||
$cover = (string) get_term_meta($term_id, '_aksrt_cover_url', true);
|
||||
|
||||
$description = trim((string) $term->description);
|
||||
if ($description === '' && current_user_can('manage_categories')) {
|
||||
$edit = get_edit_term_link((int) $term->term_id, $taxonomy);
|
||||
$description = esc_html__('请在后台为该分类添加描述。', 'aksrt');
|
||||
if ($edit) {
|
||||
$description .= ' <a href="' . esc_url($edit) . '">' . esc_html__('立即编辑', 'aksrt') . '</a>';
|
||||
}
|
||||
} else {
|
||||
$description = esc_html($description);
|
||||
}
|
||||
|
||||
$posts_q = [
|
||||
@@ -91,39 +166,75 @@ class WidgetTermAggregation extends \WP_Widget {
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $count,
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => true,
|
||||
'no_found_rows' => false,
|
||||
'tax_query' => [[
|
||||
'taxonomy' => $taxonomy,
|
||||
'field' => 'term_id',
|
||||
'terms' => $term_id,
|
||||
'terms' => (int) $term->term_id,
|
||||
]],
|
||||
];
|
||||
if ($orderby === 'views') {
|
||||
$posts_q['meta_key'] = 'aksrt_post_views';
|
||||
$posts_q['orderby'] = 'meta_value_num';
|
||||
$posts_q['order'] = 'DESC';
|
||||
$posts_q['orderby'] = 'meta_value_num';
|
||||
$posts_q['order'] = 'DESC';
|
||||
} elseif ($orderby === 'like') {
|
||||
$posts_q['meta_key'] = 'aksrt_post_likes';
|
||||
$posts_q['orderby'] = 'meta_value_num';
|
||||
$posts_q['order'] = 'DESC';
|
||||
} elseif ($orderby === 'comment_count') {
|
||||
$posts_q['orderby'] = 'comment_count';
|
||||
$posts_q['order'] = 'DESC';
|
||||
} elseif ($orderby === 'modified') {
|
||||
$posts_q['orderby'] = 'modified';
|
||||
$posts_q['order'] = 'DESC';
|
||||
$posts_q['order'] = 'DESC';
|
||||
} else {
|
||||
$posts_q['orderby'] = 'date';
|
||||
$posts_q['order'] = 'DESC';
|
||||
$posts_q['order'] = 'DESC';
|
||||
}
|
||||
$q = new \WP_Query($posts_q);
|
||||
$found = (int) $q->found_posts;
|
||||
|
||||
echo '<div class="zib-widget term-aggregation mb10 aksrt-term-agg__card">';
|
||||
echo '<div class="mb20 hover-zoom-img flex px12-sm">';
|
||||
echo '<div class="term-img flex0 em09-sm">' . $img_html . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<div class="term-title ml10 flex xx flex1 jsb">';
|
||||
echo '<a class="em14 key-color text-ellipsis"' . $tgt . ' href="' . esc_url($link) . '">' . esc_html($term->name) . '</a>';
|
||||
echo '<div class="text-ellipsis-2 muted-color">' . $description . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<div class="term-meta flex jsb ac">';
|
||||
echo '<span class="px12 muted-3-color text-ellipsis"><i class="fa fa-file-text-o fa-fw" aria-hidden="true"></i>'
|
||||
. esc_html(sprintf(
|
||||
/* translators: %s: article count */
|
||||
__('%s篇文章', 'aksrt'),
|
||||
(string) $found
|
||||
))
|
||||
. '</span>';
|
||||
echo '<a class="but p2-10 px12 c-blue hide-sm shrink0"' . $tgt . ' href="' . esc_url($link) . '"><i class="fa fa-angle-right" aria-hidden="true"></i>' . esc_html__('更多文章', 'aksrt') . '</a>';
|
||||
echo '</div></div></div>';
|
||||
|
||||
echo '<div class="aksrt-term-agg__card">';
|
||||
echo '<a class="aksrt-term-agg__head" href="' . esc_url($link) . '">';
|
||||
echo '<div class="aksrt-term-agg__cover' . ($cover ? '' : ' is-empty') . '"' . ($cover ? ' style="background-image:url(' . esc_url($cover) . ')"' : '') . '></div>';
|
||||
echo '<div class="aksrt-term-agg__name">' . esc_html($term->name) . '</div>';
|
||||
echo '<div class="aksrt-term-agg__count">' . esc_html(sprintf(_n('%d 篇', '%d 篇', (int) $term->count, 'aksrt'), (int) $term->count)) . '</div>';
|
||||
echo '</a>';
|
||||
if ($q->have_posts()) {
|
||||
echo '<ul class="aksrt-term-agg__posts">';
|
||||
while ($q->have_posts()) {
|
||||
$q->the_post();
|
||||
echo '<li><a href="' . esc_url(get_permalink()) . '">' . esc_html(get_the_title()) . '</a></li>';
|
||||
$pid = get_the_ID();
|
||||
$title = get_the_title($pid);
|
||||
$meta = '';
|
||||
if ($orderby === 'views') {
|
||||
$v = function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($pid) : (int) get_post_meta($pid, 'aksrt_post_views', true);
|
||||
$meta = '<i class="fa fa-eye mr3" aria-hidden="true"></i>' . esc_html((string) $v);
|
||||
} elseif ($orderby === 'like') {
|
||||
$v = function_exists('aksrt_get_post_likes') ? (int) aksrt_get_post_likes($pid) : (int) get_post_meta($pid, 'aksrt_post_likes', true);
|
||||
$meta = '<i class="fa fa-heart mr3" aria-hidden="true"></i>' . esc_html((string) $v);
|
||||
} elseif ($orderby === 'comment_count') {
|
||||
$meta = '<i class="fa fa-comment-o mr3" aria-hidden="true"></i>' . esc_html((string) get_comments_number($pid));
|
||||
} else {
|
||||
$ts = $orderby === 'modified' ? get_the_modified_time('U', $pid) : get_the_time('U', $pid);
|
||||
$ago = human_time_diff((int) $ts, current_time('timestamp'));
|
||||
$meta = '<i class="fa fa-clock-o mr3" aria-hidden="true"></i>' . esc_html($ago);
|
||||
}
|
||||
echo '<div class="mt10 flex jsb ac">';
|
||||
echo '<div class="text-ellipsis"><a class="icon-circle mln3"' . $tgt . ' href="' . esc_url(get_permalink($pid)) . '">' . esc_html($title) . '</a></div>';
|
||||
echo '<div class="em09 muted-3-color flex0 ml10">' . $meta . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</ul>';
|
||||
wp_reset_postdata();
|
||||
}
|
||||
echo '</div>';
|
||||
@@ -132,6 +243,10 @@ class WidgetTermAggregation extends \WP_Widget {
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $args
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public function widget($args, $instance): void {
|
||||
$html = self::render_html($instance);
|
||||
if ($html === '') {
|
||||
@@ -146,11 +261,9 @@ class WidgetTermAggregation extends \WP_Widget {
|
||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
/** @return array<int,int> */
|
||||
private function parse_ids(string $raw): array {
|
||||
return self::parse_ids_static($raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public function form($instance): void {
|
||||
$taxs = get_taxonomies(['public' => true], 'objects');
|
||||
?>
|
||||
@@ -187,25 +300,36 @@ class WidgetTermAggregation extends \WP_Widget {
|
||||
<option value="date" <?php selected(($instance['orderby'] ?? 'date'), 'date'); ?>><?php esc_html_e('时间', 'aksrt'); ?></option>
|
||||
<option value="modified" <?php selected(($instance['orderby'] ?? ''), 'modified'); ?>><?php esc_html_e('更新', 'aksrt'); ?></option>
|
||||
<option value="views" <?php selected(($instance['orderby'] ?? ''), 'views'); ?>><?php esc_html_e('浏览', 'aksrt'); ?></option>
|
||||
<option value="like" <?php selected(($instance['orderby'] ?? ''), 'like'); ?>><?php esc_html_e('点赞', 'aksrt'); ?></option>
|
||||
<option value="comment_count" <?php selected(($instance['orderby'] ?? ''), 'comment_count'); ?>><?php esc_html_e('评论', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('target_blank')); ?>" value="1" <?php checked(!empty($instance['target_blank'])); ?>> <?php esc_html_e('新窗口打开', 'aksrt'); ?></label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $new_instance
|
||||
* @param array<string,mixed> $old_instance
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function update($new_instance, $old_instance): array {
|
||||
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'date'));
|
||||
if (!in_array($orderby, ['date', 'modified', 'views'], true)) {
|
||||
if (!in_array($orderby, ['date', 'modified', 'views', 'like', 'comment_count'], true)) {
|
||||
$orderby = 'date';
|
||||
}
|
||||
return [
|
||||
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
|
||||
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')),
|
||||
'term_ids' => sanitize_text_field((string) ($new_instance['term_ids'] ?? '')),
|
||||
'count' => max(1, min(12, (int) ($new_instance['count'] ?? 4))),
|
||||
'columns' => max(1, min(3, (int) ($new_instance['columns'] ?? 1))),
|
||||
'orderby' => $orderby,
|
||||
'auto_terms' => max(1, min(4, (int) ($new_instance['auto_terms'] ?? 2))),
|
||||
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
|
||||
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')),
|
||||
'term_ids' => sanitize_text_field((string) ($new_instance['term_ids'] ?? '')),
|
||||
'count' => max(1, min(12, (int) ($new_instance['count'] ?? 4))),
|
||||
'columns' => max(1, min(3, (int) ($new_instance['columns'] ?? 1))),
|
||||
'orderby' => $orderby,
|
||||
'auto_terms' => max(1, min(4, (int) ($new_instance['auto_terms'] ?? 2))),
|
||||
'target_blank' => !empty($new_instance['target_blank']) ? 1 : 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Taxonomy term cards (zibll zib_widget_ui_term_card lite).
|
||||
* Taxonomy term graphic cards (zibll zib_widget_ui_term_card → zib_graphic_card).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -16,7 +16,7 @@ class WidgetTermCards extends \WP_Widget {
|
||||
'aksrt_term_cards',
|
||||
esc_html__('AKSRT 分类/标签卡片', 'aksrt'),
|
||||
[
|
||||
'description' => esc_html__('以卡片展示分类或标签。', 'aksrt'),
|
||||
'description' => esc_html__('以图文封面卡片展示分类或标签(style-1..4)。', 'aksrt'),
|
||||
'classname' => 'widget_aksrt_term_cards',
|
||||
]
|
||||
);
|
||||
@@ -37,15 +37,49 @@ class WidgetTermCards extends \WP_Widget {
|
||||
return array_values(array_unique($ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve term cover URL.
|
||||
*/
|
||||
public static function term_cover_url(\WP_Term $term): string {
|
||||
$thumb = '';
|
||||
$img_id = (int) get_term_meta($term->term_id, 'thumbnail_id', true);
|
||||
if (!$img_id) {
|
||||
$img_id = (int) get_term_meta($term->term_id, '_aksrt_cover', true);
|
||||
}
|
||||
if ($img_id) {
|
||||
$thumb = (string) (wp_get_attachment_image_url($img_id, 'medium_large') ?: wp_get_attachment_image_url($img_id, 'medium') ?: '');
|
||||
}
|
||||
if ($thumb === '') {
|
||||
$thumb = (string) get_term_meta($term->term_id, '_aksrt_cover_url', true);
|
||||
}
|
||||
if ($thumb === '') {
|
||||
// Lightweight default gradient placeholder as data URI is heavy — use theme placeholder.
|
||||
$thumb = get_template_directory_uri() . '/assets/img/placeholder.svg';
|
||||
}
|
||||
return $thumb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public static function render_html(array $instance): string {
|
||||
$taxonomy = sanitize_key((string) ($instance['taxonomy'] ?? 'category'));
|
||||
if (!taxonomy_exists($taxonomy)) {
|
||||
$taxonomy = 'category';
|
||||
}
|
||||
$number = max(1, min(30, (int) ($instance['number'] ?? 8)));
|
||||
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'count'));
|
||||
$include = self::parse_ids_static((string) ($instance['include'] ?? ''));
|
||||
$number = max(1, min(30, (int) ($instance['number'] ?? 8)));
|
||||
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'count'));
|
||||
$include = self::parse_ids_static((string) ($instance['include'] ?? ''));
|
||||
$hide_empty = !isset($instance['hide_empty']) || !empty($instance['hide_empty']);
|
||||
$type = sanitize_key((string) ($instance['type'] ?? 'style-1'));
|
||||
if (!in_array($type, ['style-1', 'style-2', 'style-3', 'style-4'], true)) {
|
||||
$type = 'style-1';
|
||||
}
|
||||
$height_scale = max(30, min(120, (int) ($instance['height_scale'] ?? 60)));
|
||||
$mask_opacity = max(0, min(80, (int) ($instance['mask_opacity'] ?? 10)));
|
||||
$pc_row = max(1, min(6, (int) ($instance['pc_row'] ?? $instance['columns'] ?? 2)));
|
||||
$m_row = max(1, min(3, (int) ($instance['m_row'] ?? 1)));
|
||||
$target_blank = !empty($instance['target_blank']);
|
||||
|
||||
$term_args = [
|
||||
'taxonomy' => $taxonomy,
|
||||
@@ -67,42 +101,94 @@ class WidgetTermCards extends \WP_Widget {
|
||||
: '<p class="widget-empty ajax-item">' . esc_html__('暂无分类', 'aksrt') . '</p>';
|
||||
}
|
||||
|
||||
$cols = max(1, min(4, (int) ($instance['columns'] ?? 2)));
|
||||
$icon = $taxonomy === 'category'
|
||||
? '<i class="fa fa-folder-open-o mr6" aria-hidden="true"></i>'
|
||||
: '<i class="fa fa-cube mr6" aria-hidden="true"></i>';
|
||||
|
||||
$is_row = count($terms) > 1;
|
||||
// Bootstrap-like col classes already used elsewhere; keep numeric CSS vars as fallback.
|
||||
$pc_span = max(1, (int) floor(12 / $pc_row));
|
||||
$m_span = max(1, (int) floor(12 / $m_row));
|
||||
$row_class = 'col-sm-' . $pc_span . ($m_row > 1 ? ' col-xs-' . $m_span : '');
|
||||
|
||||
ob_start();
|
||||
echo '<div class="aksrt-term-cards ajax-item" style="--aksrt-tc-cols:' . esc_attr((string) $cols) . '">';
|
||||
echo '<div class="aksrt-term-cards ajax-item' . ($is_row ? ' mb10' : ' mb20') . '">';
|
||||
if ($is_row) {
|
||||
echo '<div class="row gutters-5">';
|
||||
}
|
||||
foreach ($terms as $term) {
|
||||
if (!($term instanceof \WP_Term)) {
|
||||
continue;
|
||||
}
|
||||
$link = get_term_link($term);
|
||||
if (is_wp_error($link)) {
|
||||
continue;
|
||||
}
|
||||
$thumb = '';
|
||||
if (function_exists('get_term_meta')) {
|
||||
$img_id = (int) get_term_meta($term->term_id, 'thumbnail_id', true);
|
||||
if (!$img_id) {
|
||||
$img_id = (int) get_term_meta($term->term_id, '_aksrt_cover', true);
|
||||
}
|
||||
if ($img_id) {
|
||||
$thumb = wp_get_attachment_image_url($img_id, 'medium') ?: '';
|
||||
}
|
||||
if ($thumb === '') {
|
||||
$thumb = (string) get_term_meta($term->term_id, '_aksrt_cover_url', true);
|
||||
$name = mb_strlen($term->name) > 16 ? mb_substr($term->name, 0, 16) . '…' : $term->name;
|
||||
$desc = trim((string) $term->description);
|
||||
if (mb_strlen($desc) > 24) {
|
||||
$desc = mb_substr($desc, 0, 24) . '…';
|
||||
}
|
||||
$count = (int) $term->count;
|
||||
$count_label = sprintf(
|
||||
/* translators: %d: post count */
|
||||
_n('%d篇文章', '%d篇文章', $count, 'aksrt'),
|
||||
$count
|
||||
);
|
||||
|
||||
$text1 = $name;
|
||||
$text2 = $desc;
|
||||
$text3 = $icon . esc_html($count_label);
|
||||
if ($type === 'style-2' || $type === 'style-4') {
|
||||
$text3 = '<item data-toggle="tooltip" title="' . esc_attr(sprintf(__('共%d篇文章', 'aksrt'), $count)) . '">' . $icon . $count . '</item>';
|
||||
}
|
||||
if ($type === 'style-3' || $type === 'style-4') {
|
||||
$text1 = $icon . esc_html($name);
|
||||
if ($type === 'style-3') {
|
||||
$text3 = '<i class="fa mr6 fa-file-text-o" aria-hidden="true"></i>' . esc_html($count_label);
|
||||
}
|
||||
}
|
||||
echo '<a class="aksrt-term-card" href="' . esc_url($link) . '">';
|
||||
if ($thumb !== '') {
|
||||
echo '<div class="aksrt-term-card__cover" style="background-image:url(' . esc_url($thumb) . ')"></div>';
|
||||
|
||||
$card_args = [
|
||||
'type' => $type,
|
||||
'class' => 'mb10',
|
||||
'img' => self::term_cover_url($term),
|
||||
'alt' => $name . ($desc !== '' ? '-' . $desc : ''),
|
||||
'link' => [
|
||||
'url' => $link,
|
||||
'target' => $target_blank ? '_blank' : '',
|
||||
],
|
||||
'text1' => $text1,
|
||||
'text2' => $text2,
|
||||
'text3' => $text3,
|
||||
'lazy' => true,
|
||||
'height_scale' => $height_scale,
|
||||
'mask_opacity' => $mask_opacity,
|
||||
];
|
||||
|
||||
if ($is_row) {
|
||||
echo '<div class="' . esc_attr($row_class) . '">';
|
||||
}
|
||||
if (function_exists('aksrt_graphic_card')) {
|
||||
echo aksrt_graphic_card($card_args); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
} else {
|
||||
echo '<div class="aksrt-term-card__cover is-empty"></div>';
|
||||
echo '<a class="aksrt-term-card" href="' . esc_url($link) . '"><div class="aksrt-term-card__name">' . esc_html($name) . '</div></a>';
|
||||
}
|
||||
echo '<div class="aksrt-term-card__body">';
|
||||
echo '<div class="aksrt-term-card__name">' . esc_html($term->name) . '</div>';
|
||||
echo '<div class="aksrt-term-card__count">' . esc_html(sprintf(_n('%d 篇', '%d 篇', (int) $term->count, 'aksrt'), (int) $term->count)) . '</div>';
|
||||
echo '</div></a>';
|
||||
if ($is_row) {
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
if ($is_row) {
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</div>';
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $args
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public function widget($args, $instance): void {
|
||||
$html = self::render_html($instance);
|
||||
if ($html === '') {
|
||||
@@ -117,11 +203,9 @@ class WidgetTermCards extends \WP_Widget {
|
||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
/** @return array<int,int> */
|
||||
private function parse_ids(string $raw): array {
|
||||
return self::parse_ids_static($raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public function form($instance): void {
|
||||
$taxs = get_taxonomies(['public' => true], 'objects');
|
||||
?>
|
||||
@@ -143,8 +227,29 @@ class WidgetTermCards extends \WP_Widget {
|
||||
<label><?php esc_html_e('数量', 'aksrt'); ?>
|
||||
<input class="tiny-text" type="number" min="1" max="30" name="<?php echo esc_attr($this->get_field_name('number')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['number'] ?? 8))); ?>">
|
||||
</label>
|
||||
<label><?php esc_html_e('列数', 'aksrt'); ?>
|
||||
<input class="tiny-text" type="number" min="1" max="4" name="<?php echo esc_attr($this->get_field_name('columns')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['columns'] ?? 2))); ?>">
|
||||
<label><?php esc_html_e('PC 列', 'aksrt'); ?>
|
||||
<input class="tiny-text" type="number" min="1" max="6" name="<?php echo esc_attr($this->get_field_name('pc_row')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['pc_row'] ?? $instance['columns'] ?? 2))); ?>">
|
||||
</label>
|
||||
<label><?php esc_html_e('移动列', 'aksrt'); ?>
|
||||
<input class="tiny-text" type="number" min="1" max="3" name="<?php echo esc_attr($this->get_field_name('m_row')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['m_row'] ?? 1))); ?>">
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><?php esc_html_e('卡片样式', 'aksrt'); ?>
|
||||
<select name="<?php echo esc_attr($this->get_field_name('type')); ?>">
|
||||
<option value="style-1" <?php selected(($instance['type'] ?? 'style-1'), 'style-1'); ?>><?php esc_html_e('样式 1(左下标题)', 'aksrt'); ?></option>
|
||||
<option value="style-2" <?php selected(($instance['type'] ?? ''), 'style-2'); ?>><?php esc_html_e('样式 2(居中)', 'aksrt'); ?></option>
|
||||
<option value="style-3" <?php selected(($instance['type'] ?? ''), 'style-3'); ?>><?php esc_html_e('样式 3(左下多层)', 'aksrt'); ?></option>
|
||||
<option value="style-4" <?php selected(($instance['type'] ?? ''), 'style-4'); ?>><?php esc_html_e('样式 4(图+下方文案)', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><?php esc_html_e('高度占比 %', 'aksrt'); ?>
|
||||
<input class="tiny-text" type="number" min="30" max="120" name="<?php echo esc_attr($this->get_field_name('height_scale')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['height_scale'] ?? 60))); ?>">
|
||||
</label>
|
||||
<label><?php esc_html_e('遮罩 0-80', 'aksrt'); ?>
|
||||
<input class="tiny-text" type="number" min="0" max="80" name="<?php echo esc_attr($this->get_field_name('mask_opacity')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['mask_opacity'] ?? 10))); ?>">
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
@@ -162,20 +267,36 @@ class WidgetTermCards extends \WP_Widget {
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_empty')); ?>" value="1" <?php checked(!isset($instance['hide_empty']) || !empty($instance['hide_empty'])); ?>> <?php esc_html_e('隐藏空分类', 'aksrt'); ?></label>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_empty')); ?>" value="1" <?php checked(!isset($instance['hide_empty']) || !empty($instance['hide_empty'])); ?>> <?php esc_html_e('隐藏空分类', 'aksrt'); ?></label><br>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('target_blank')); ?>" value="1" <?php checked(!empty($instance['target_blank'])); ?>> <?php esc_html_e('新窗口打开', 'aksrt'); ?></label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $new_instance
|
||||
* @param array<string,mixed> $old_instance
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function update($new_instance, $old_instance): array {
|
||||
$type = sanitize_key((string) ($new_instance['type'] ?? 'style-1'));
|
||||
if (!in_array($type, ['style-1', 'style-2', 'style-3', 'style-4'], true)) {
|
||||
$type = 'style-1';
|
||||
}
|
||||
return [
|
||||
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
|
||||
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')),
|
||||
'number' => max(1, min(30, (int) ($new_instance['number'] ?? 8))),
|
||||
'columns' => max(1, min(4, (int) ($new_instance['columns'] ?? 2))),
|
||||
'orderby' => in_array(($new_instance['orderby'] ?? ''), ['count', 'name', 'id'], true) ? $new_instance['orderby'] : 'count',
|
||||
'include' => sanitize_text_field((string) ($new_instance['include'] ?? '')),
|
||||
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,
|
||||
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
|
||||
'taxonomy' => sanitize_key((string) ($new_instance['taxonomy'] ?? 'category')),
|
||||
'number' => max(1, min(30, (int) ($new_instance['number'] ?? 8))),
|
||||
'pc_row' => max(1, min(6, (int) ($new_instance['pc_row'] ?? 2))),
|
||||
'm_row' => max(1, min(3, (int) ($new_instance['m_row'] ?? 1))),
|
||||
'columns' => max(1, min(6, (int) ($new_instance['pc_row'] ?? $new_instance['columns'] ?? 2))),
|
||||
'type' => $type,
|
||||
'height_scale' => max(30, min(120, (int) ($new_instance['height_scale'] ?? 60))),
|
||||
'mask_opacity' => max(0, min(80, (int) ($new_instance['mask_opacity'] ?? 10))),
|
||||
'orderby' => in_array(($new_instance['orderby'] ?? ''), ['count', 'name', 'id'], true) ? $new_instance['orderby'] : 'count',
|
||||
'include' => sanitize_text_field((string) ($new_instance['include'] ?? '')),
|
||||
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,
|
||||
'target_blank' => !empty($new_instance['target_blank']) ? 1 : 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Registered user list (zibll widget_ui_user_lists + remote HTML).
|
||||
* Registered user list (zibll widget_ui_user_lists → zib_author_card).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -16,7 +16,7 @@ class WidgetUserLists extends \WP_Widget {
|
||||
'aksrt_user_lists',
|
||||
esc_html__('AKSRT 用户列表', 'aksrt'),
|
||||
[
|
||||
'description' => esc_html__('展示站点用户头像网格,支持排序与筛选。', 'aksrt'),
|
||||
'description' => esc_html__('展示站点用户迷你名片(头像/身份/关注/简介)。', 'aksrt'),
|
||||
'classname' => 'widget_aksrt_user_lists',
|
||||
]
|
||||
);
|
||||
@@ -37,13 +37,17 @@ class WidgetUserLists extends \WP_Widget {
|
||||
return array_values(array_unique($ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public static function render_html(array $instance): string {
|
||||
$number = max(1, min(50, (int) ($instance['number'] ?? 8)));
|
||||
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'user_registered'));
|
||||
$order = strtoupper((string) ($instance['order'] ?? 'DESC')) === 'ASC' ? 'ASC' : 'DESC';
|
||||
$include = self::parse_ids_static((string) ($instance['include'] ?? ''));
|
||||
$exclude = self::parse_ids_static((string) ($instance['exclude'] ?? ''));
|
||||
$number = max(1, min(50, (int) ($instance['number'] ?? 8)));
|
||||
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'user_registered'));
|
||||
$order = strtoupper((string) ($instance['order'] ?? 'DESC')) === 'ASC' ? 'ASC' : 'DESC';
|
||||
$include = self::parse_ids_static((string) ($instance['include'] ?? ''));
|
||||
$exclude = self::parse_ids_static((string) ($instance['exclude'] ?? ''));
|
||||
$hide_box = !empty($instance['hide_box']);
|
||||
$blur_bg = !empty($instance['blur_bg']);
|
||||
|
||||
$query = [
|
||||
'number' => $number,
|
||||
@@ -102,26 +106,36 @@ class WidgetUserLists extends \WP_Widget {
|
||||
}
|
||||
|
||||
ob_start();
|
||||
$wrap = $hide_box ? 'aksrt-user-lists is-bare ajax-item' : 'aksrt-user-lists ajax-item';
|
||||
echo '<div class="' . esc_attr($wrap) . '">';
|
||||
// zibll: optional zib-widget + text-center user_lists of author-minicard.
|
||||
$outer = $hide_box ? 'aksrt-user-lists is-bare ajax-item' : 'aksrt-user-lists zib-widget ajax-item';
|
||||
echo '<div class="' . esc_attr($outer) . '">';
|
||||
echo '<div class="text-center user_lists">';
|
||||
foreach ($users as $user) {
|
||||
$uid = (int) $user->ID;
|
||||
$avatar = function_exists('aksrt_get_avatar_url')
|
||||
? aksrt_get_avatar_url($uid, ['size' => 96])
|
||||
: get_avatar_url($uid, ['size' => 96]);
|
||||
$home = function_exists('aksrt_get_user_home_url')
|
||||
? aksrt_get_user_home_url($uid)
|
||||
: get_author_posts_url($uid);
|
||||
$name = $user->display_name ?: $user->user_nicename;
|
||||
echo '<a class="aksrt-user-lists__item" href="' . esc_url($home) . '" title="' . esc_attr($name) . '">';
|
||||
echo '<img class="aksrt-user-lists__avatar" src="' . esc_url($avatar) . '" alt="' . esc_attr($name) . '" loading="lazy" width="48" height="48" />';
|
||||
echo '<span class="aksrt-user-lists__name">' . esc_html($name) . '</span>';
|
||||
echo '</a>';
|
||||
if (function_exists('aksrt_author_minicard')) {
|
||||
echo aksrt_author_minicard($uid, 'mb10', $blur_bg); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
} else {
|
||||
$avatar = function_exists('aksrt_get_avatar_url')
|
||||
? aksrt_get_avatar_url($uid, ['size' => 96])
|
||||
: get_avatar_url($uid, ['size' => 96]);
|
||||
$home = function_exists('aksrt_get_user_home_url')
|
||||
? aksrt_get_user_home_url($uid)
|
||||
: get_author_posts_url($uid);
|
||||
$name = $user->display_name ?: $user->user_nicename;
|
||||
echo '<a class="author-minicard radius8" href="' . esc_url($home) . '">';
|
||||
echo '<img class="avatar" src="' . esc_url($avatar) . '" alt="" loading="lazy" width="42" height="42" /> ';
|
||||
echo esc_html($name);
|
||||
echo '</a>';
|
||||
}
|
||||
}
|
||||
echo '</div>';
|
||||
echo '</div></div>';
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $args
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public function widget($args, $instance): void {
|
||||
$html = self::render_html($instance);
|
||||
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
@@ -136,10 +150,9 @@ class WidgetUserLists extends \WP_Widget {
|
||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
private function parse_ids(string $raw): array {
|
||||
return self::parse_ids_static($raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public function form($instance): void {
|
||||
?>
|
||||
<p>
|
||||
@@ -182,11 +195,17 @@ class WidgetUserLists extends \WP_Widget {
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_box')); ?>" value="1" <?php checked(!empty($instance['hide_box'])); ?>> <?php esc_html_e('不显示背景盒子', 'aksrt'); ?></label>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_box')); ?>" value="1" <?php checked(!empty($instance['hide_box'])); ?>> <?php esc_html_e('不显示背景盒子', 'aksrt'); ?></label><br>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('blur_bg')); ?>" value="1" <?php checked(!empty($instance['blur_bg'])); ?>> <?php esc_html_e('头像模糊背景', 'aksrt'); ?></label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $new_instance
|
||||
* @param array<string,mixed> $old_instance
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function update($new_instance, $old_instance): array {
|
||||
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'user_registered'));
|
||||
$allowed = ['user_registered', 'display_name', 'post_count', 'last_login', 'followed-user-count'];
|
||||
@@ -201,6 +220,7 @@ class WidgetUserLists extends \WP_Widget {
|
||||
'orderby' => $orderby,
|
||||
'order' => strtoupper((string) ($new_instance['order'] ?? 'DESC')) === 'ASC' ? 'ASC' : 'DESC',
|
||||
'hide_box' => !empty($new_instance['hide_box']) ? 1 : 0,
|
||||
'blur_bg' => !empty($new_instance['blur_bg']) ? 1 : 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user