feat(widgets): Stats count-up + product oneline swiper-nav
Wire data-aksrt-countup for numeric stats; oneline products use swiper-scroll slides with prev/next; batch12 CSS for video/links/oneline.
This commit is contained in:
1 parent
af8f97ad3c
commit
0cf3d440e2
3 files changed
+167
-3
No files matched your search
@@ -1303,3 +1303,132 @@
|
|||||||
.aksrt-faq__main { grid-template-columns: 1fr; }
|
.aksrt-faq__main { grid-template-columns: 1fr; }
|
||||||
.aksrt-faq__a { padding-left: 14px; }
|
.aksrt-faq__a { padding-left: 14px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- batch12: video shell + bookmark links styles + product oneline swiper ---- */
|
||||||
|
.aksrt-video-widget {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
.aksrt-video-widget.radius8 { border-radius: 10px; }
|
||||||
|
.aksrt-video-widget__frame,
|
||||||
|
.aksrt-video-widget__player,
|
||||||
|
.aksrt-video-widget .aksrt-video {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.aksrt-video-widget__frame {
|
||||||
|
border: 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.aksrt-video-widget.controller-hide .aksrt-video video::-webkit-media-controls {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity .2s ease;
|
||||||
|
}
|
||||||
|
.aksrt-video-widget.controller-hide:hover .aksrt-video video::-webkit-media-controls {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-bookmark-links.links-box {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.style-card .author-minicard,
|
||||||
|
.aksrt-bookmark-links.style-bigcard .author-minicard {
|
||||||
|
flex: 1 1 calc(50% - 12px);
|
||||||
|
min-width: 140px;
|
||||||
|
background: var(--surface-2, #f8fafc);
|
||||||
|
border: 1px solid var(--color-line, #e5e7eb);
|
||||||
|
padding: 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.style-bigcard .author-minicard {
|
||||||
|
flex: 1 1 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links .avatar-img img,
|
||||||
|
.aksrt-bookmark-links .link-img img {
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.style-bigcard .avatar-img img {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.style-image {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.style-image .link-only-img img {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 10px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.style-simple {
|
||||||
|
display: block;
|
||||||
|
line-height: 1.9;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.style-simple a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.style-simple a:hover {
|
||||||
|
color: var(--color-primary, #3b82f6);
|
||||||
|
}
|
||||||
|
.aksrt-bookmark-links.has-box {
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid var(--color-line, #e5e7eb);
|
||||||
|
border-radius: 12px;
|
||||||
|
background: var(--surface-1, #fff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-product-oneline-swiper {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 28px 4px;
|
||||||
|
}
|
||||||
|
.aksrt-product-oneline-swiper .swiper-wrapper {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.aksrt-product-oneline-swiper .swiper-slide {
|
||||||
|
width: auto;
|
||||||
|
max-width: 46%;
|
||||||
|
min-width: 150px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.aksrt-product-oneline-swiper .aksrt-product-card {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.aksrt-product-oneline-swiper .swiper-button-prev,
|
||||||
|
.aksrt-product-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-product-oneline-swiper .swiper-button-prev:after,
|
||||||
|
.aksrt-product-oneline-swiper .swiper-button-next:after {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.aksrt-product-oneline-swiper .swiper-button-prev { left: 0; }
|
||||||
|
.aksrt-product-oneline-swiper .swiper-button-next { right: 0; }
|
||||||
|
.aksrt-product-widget--oneline .aksrt-product-widget__grid {
|
||||||
|
/* legacy flex fallback if swiper unavailable */
|
||||||
|
}
|
||||||
@@ -93,6 +93,7 @@ class WidgetProductList extends \WP_Widget {
|
|||||||
if (!$products->have_posts()) {
|
if (!$products->have_posts()) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
$oneline = $style === 'oneline';
|
||||||
ob_start();
|
ob_start();
|
||||||
while ($products->have_posts()) {
|
while ($products->have_posts()) {
|
||||||
$products->the_post();
|
$products->the_post();
|
||||||
@@ -100,13 +101,15 @@ class WidgetProductList extends \WP_Widget {
|
|||||||
$card = class_exists('\AKSRT\Shop\Shop')
|
$card = class_exists('\AKSRT\Shop\Shop')
|
||||||
? \AKSRT\Shop\Shop::get_instance()->build_product_card_view($pid)
|
? \AKSRT\Shop\Shop::get_instance()->build_product_card_view($pid)
|
||||||
: [];
|
: [];
|
||||||
|
if ($oneline) {
|
||||||
|
echo '<div class="swiper-slide ajax-item">';
|
||||||
|
}
|
||||||
if (function_exists('get_template_part') && !empty($card['id'])) {
|
if (function_exists('get_template_part') && !empty($card['id'])) {
|
||||||
get_template_part('templates/parts/shop/product', 'card', [
|
get_template_part('templates/parts/shop/product', 'card', [
|
||||||
'product' => $card,
|
'product' => $card,
|
||||||
'show_sales' => true,
|
'show_sales' => true,
|
||||||
]);
|
]);
|
||||||
continue;
|
} else {
|
||||||
}
|
|
||||||
// Fallback mini card.
|
// Fallback mini card.
|
||||||
$price = (float) ($card['price'] ?? 0);
|
$price = (float) ($card['price'] ?? 0);
|
||||||
$image = (string) ($card['image'] ?? '');
|
$image = (string) ($card['image'] ?? '');
|
||||||
@@ -125,6 +128,10 @@ class WidgetProductList extends \WP_Widget {
|
|||||||
}
|
}
|
||||||
echo '</div></div></div>';
|
echo '</div></div></div>';
|
||||||
}
|
}
|
||||||
|
if ($oneline) {
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
wp_reset_postdata();
|
wp_reset_postdata();
|
||||||
return (string) ob_get_clean();
|
return (string) ob_get_clean();
|
||||||
}
|
}
|
||||||
@@ -231,12 +238,25 @@ class WidgetProductList extends \WP_Widget {
|
|||||||
|
|
||||||
$style_class = 'aksrt-product-widget--' . $style;
|
$style_class = 'aksrt-product-widget--' . $style;
|
||||||
echo '<div class="aksrt-product-widget ' . esc_attr($style_class) . '" data-aksrt-product-widget data-aksrt-product-config="' . esc_attr(wp_json_encode($cfg)) . '">';
|
echo '<div class="aksrt-product-widget ' . esc_attr($style_class) . '" data-aksrt-product-widget data-aksrt-product-config="' . esc_attr(wp_json_encode($cfg)) . '">';
|
||||||
|
|
||||||
|
if ($style === 'oneline') {
|
||||||
|
// zibll-style horizontal swiper-scroll (shared slider.js Type A).
|
||||||
|
echo '<div class="swiper-container swiper-scroll aksrt-product-oneline-swiper">';
|
||||||
|
echo '<div class="swiper-wrapper product-lists-row">';
|
||||||
|
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
echo '</div>';
|
||||||
|
echo '<div class="swiper-button-prev" aria-label="' . esc_attr__('上一页', 'aksrt') . '"></div>';
|
||||||
|
echo '<div class="swiper-button-next" aria-label="' . esc_attr__('下一页', 'aksrt') . '"></div>';
|
||||||
|
echo '</div>';
|
||||||
|
} else {
|
||||||
// Items sit directly under .ajaxpager so ajax-list inject/append works (zibll product-lists-row).
|
// Items sit directly under .ajaxpager so ajax-list inject/append works (zibll product-lists-row).
|
||||||
echo '<div class="ajaxpager aksrt-product-widget__grid product-lists-row" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($ajax_url) . '">';
|
echo '<div class="ajaxpager aksrt-product-widget__grid product-lists-row" data-aksrt-ajaxpager data-aksrt-ajax-url="' . esc_url($ajax_url) . '">';
|
||||||
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped — cards escaped upstream
|
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped — cards escaped upstream
|
||||||
echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
echo '<div class="post_ajax_loader" data-aksrt-ajax-loader data-aksrt-ajax-loader-hide hidden></div>';
|
echo '<div class="post_ajax_loader" data-aksrt-ajax-loader data-aksrt-ajax-loader-hide hidden></div>';
|
||||||
echo '</div></div>';
|
echo '</div>';
|
||||||
|
}
|
||||||
|
echo '</div>';
|
||||||
|
|
||||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,22 @@ class WidgetStats extends \WP_Widget {
|
|||||||
if ($s['prefix'] !== '') {
|
if ($s['prefix'] !== '') {
|
||||||
echo '<span class="aksrt-stats__prefix">' . esc_html($s['prefix']) . '</span>';
|
echo '<span class="aksrt-stats__prefix">' . esc_html($s['prefix']) . '</span>';
|
||||||
}
|
}
|
||||||
|
// Wire effects.js count-up when number is numeric.
|
||||||
|
$raw_num = preg_replace('/[^\d.]/', '', (string) $s['number']);
|
||||||
|
$is_numeric = $raw_num !== '' && is_numeric($raw_num);
|
||||||
|
if ($is_numeric) {
|
||||||
|
$dec = 0;
|
||||||
|
if (str_contains((string) $raw_num, '.')) {
|
||||||
|
$dec = strlen(substr(strrchr((string) $raw_num, '.'), 1));
|
||||||
|
}
|
||||||
|
printf(
|
||||||
|
'<span class="aksrt-stats__number" data-aksrt-countup data-target="%s" data-duration="1600" data-decimals="%d">0</span>',
|
||||||
|
esc_attr((string) $raw_num),
|
||||||
|
(int) $dec
|
||||||
|
);
|
||||||
|
} else {
|
||||||
echo '<span class="aksrt-stats__number" data-target="' . esc_attr($s['number']) . '">' . esc_html($s['number']) . '</span>';
|
echo '<span class="aksrt-stats__number" data-target="' . esc_attr($s['number']) . '">' . esc_html($s['number']) . '</span>';
|
||||||
|
}
|
||||||
if ($s['unit'] !== '') {
|
if ($s['unit'] !== '') {
|
||||||
echo '<span class="aksrt-stats__unit">' . esc_html($s['unit']) . '</span>';
|
echo '<span class="aksrt-stats__unit">' . esc_html($s['unit']) . '</span>';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user