diff --git a/assets/css/frontend/widget-batch5.css b/assets/css/frontend/widget-batch5.css index ded92c65..61d5b6d6 100644 --- a/assets/css/frontend/widget-batch5.css +++ b/assets/css/frontend/widget-batch5.css @@ -1702,3 +1702,126 @@ .term-aggregation .hide-sm { display: none !important; } .aksrt-oneline-swiper .swiper-slide { max-width: 72%; min-width: 140px; } } + +/* ===== Batch14: recent comments mini + friend links + iframe + cover ===== */ + +.comment-mini-lists.widget-recent-comments, +.comment-mini-lists.zib-widget { + padding: 4px 0; +} +.comment-mini-lists .posts-mini { + display: flex; + align-items: flex-start; + gap: 0; + padding: 10px 0; + border-bottom: 1px solid var(--color-line, rgba(0,0,0,.06)); +} +.comment-mini-lists .posts-mini:last-child { + border-bottom: 0; +} +.comment-mini-lists .avatar-img { + flex: 0 0 auto; + --this-size: 36px; +} +.comment-mini-lists .avatar-img img.avatar { + width: 36px; + height: 36px; + border-radius: 50%; + object-fit: cover; + display: block; +} +.comment-mini-lists .posts-mini-con { + min-width: 0; + flex: 1; +} +.comment-mini-lists .posts-mini-con > p.flex { + display: flex; + justify-content: space-between; + align-items: center; + margin: 0 0 4px; + gap: 8px; +} +.comment-mini-lists .icon-spot:before { + content: "·"; + margin: 0 6px; + opacity: .5; +} +.comment-mini-lists a.muted-color { + color: var(--muted-2-color, #666); + text-decoration: none; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + line-height: 1.5; +} +.comment-mini-lists a.muted-color:hover { + color: var(--theme-color, var(--focus-color, #f04494)); +} + +/* Friend links reuse bookmark-links styles */ +.aksrt-friend-links.links-box { + display: flex; + flex-wrap: wrap; + gap: 10px; +} +.aksrt-friend-links.style-simple { + gap: 6px 12px; +} +.aksrt-friend-links.style-image { + gap: 8px; +} + +/* Iframe lazy shell */ +.wp-block-embed.is-type-video.relative-h, +.aksrt-iframe-embed .relative-h { + position: relative; + overflow: hidden; + border-radius: 8px; + background: #0f172a; +} +.aksrt-iframe-ratio { + position: relative; + width: 100%; + height: 0; +} +.aksrt-iframe-ratio iframe, +.aksrt-iframe-el { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + border: 0; +} + +/* Cover cards row already covered by term-cards col rules — scope shared */ +.widget-graphic-cover .row.gutters-5 { + display: flex; + flex-wrap: wrap; + margin: 0 -4px; +} +.widget-graphic-cover .row.gutters-5 > [class*="col-"] { + padding: 0 4px; + box-sizing: border-box; +} +.widget-graphic-cover .col-sm-12 { width: 100%; } +.widget-graphic-cover .col-sm-6 { width: 50%; } +.widget-graphic-cover .col-sm-4 { width: 33.333%; } +.widget-graphic-cover .col-sm-3 { width: 25%; } +.widget-graphic-cover .col-sm-2 { width: 16.666%; } +@media (max-width: 767px) { + .widget-graphic-cover .col-xs-12 { width: 100%; } + .widget-graphic-cover .col-xs-6 { width: 50%; } + .widget-graphic-cover .col-xs-4 { width: 33.333%; } +} +.widget-graphic-cover .this-font { + font-size: var(--font-size, 18px); + font-weight: var(--font-weight, 600); + color: var(--color, #fff); +} +@media (max-width: 767px) { + .widget-graphic-cover .this-font { + font-size: var(--font-size-sm, 14px); + font-weight: var(--font-weight-sm, 600); + } +} diff --git a/src/AKSRT/Widgets/WidgetCoverCards.php b/src/AKSRT/Widgets/WidgetCoverCards.php index 61dc1f52..23937c9b 100644 --- a/src/AKSRT/Widgets/WidgetCoverCards.php +++ b/src/AKSRT/Widgets/WidgetCoverCards.php @@ -1,5 +1,7 @@ __('图片背景 + 文字叠加的卡片网格。', 'aksrt')] - ); - } + public function __construct() { + parent::__construct( + 'aksrt_cover_cards', + __('图文封面卡片', 'aksrt'), + ['description' => __('图片/视频封面 + 文字叠加的图文卡片(共享 graphic_card)。', 'aksrt')] + ); + } - public function widget($args, $instance): void { - $title = !empty($instance['title']) ? $instance['title'] : ''; - $items_json = !empty($instance['items']) ? $instance['items'] : '[]'; - $columns = max(1, min(4, (int) ($instance['columns'] ?? 2))); + /** + * @param array $args + * @param array $instance + */ + public function widget($args, $instance): void { + $title = !empty($instance['title']) ? (string) $instance['title'] : ''; + $items = $this->normalize($instance['items'] ?? []); + if (!$items) { + return; + } - $items = json_decode($items_json, true); - if (!is_array($items) || empty($items)) return; + $pc_row = max(1, min(6, (int) ($instance['pc_row'] ?? $instance['columns'] ?? 2))); + $m_row = max(1, min(3, (int) ($instance['m_row'] ?? 1))); + $height_scale = max(30, min(120, (int) ($instance['height_scale'] ?? 70))); + $mask_opacity = max(0, min(80, (int) ($instance['mask_opacity'] ?? 20))); + $font_size_pc = max(12, min(32, (int) ($instance['font_size_pc'] ?? 18))); + $font_size_m = max(11, min(24, (int) ($instance['font_size_m'] ?? 14))); + $font_bold = !empty($instance['font_bold']); + $font_color = sanitize_hex_color((string) ($instance['font_color'] ?? '')) ?: ''; - echo $args['before_widget']; + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - if ($title) { - echo $args['before_title'] . esc_html($title) . $args['after_title']; - } + if ($title !== '') { + echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } - echo '
'; + $is_row = count($items) > 1; + $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 : ''); - foreach ($items as $item) { - $image = esc_url($item['image'] ?? ''); - $video = esc_url($item['video'] ?? ''); - $link = esc_url($item['link'] ?? ''); - $card_title = sanitize_text_field($item['title'] ?? ''); - $desc = sanitize_text_field($item['desc'] ?? ''); - $overlay = sanitize_hex_color($item['overlay'] ?? ''); - $text_color = sanitize_hex_color($item['text_color'] ?? ''); - $height = sanitize_text_field($item['height'] ?? ''); + $style = ''; + if ($font_size_pc !== 14) { + $style .= '--font-size:' . $font_size_pc . 'px;'; + } + if ($font_size_m !== 14) { + $style .= '--font-size-sm:' . $font_size_m . 'px;'; + } + if ($font_bold) { + $style .= '--font-weight:bold;--font-weight-sm:bold;'; + } + if ($font_color !== '') { + $style .= '--color:' . $font_color . ';--color-sm:' . $font_color . ';'; + } - $card_style = ''; - if ($height) $card_style .= 'height:' . esc_attr($height) . ';'; + echo '
'; + if ($is_row) { + echo '
'; + } - $overlay_style = ''; - if ($overlay) $overlay_style .= 'background:' . esc_attr($overlay) . ';'; + foreach ($items as $item) { + $hide = sanitize_key((string) ($item['hide'] ?? '')); + if ($hide === 'pc' || $hide === 'm') { + $is_mobile = function_exists('wp_is_mobile') ? wp_is_mobile() : false; + if ((!$is_mobile && $hide === 'pc') || ($is_mobile && $hide === 'm')) { + continue; + } + } + $card_title = (string) ($item['title'] ?? ''); + $more = $card_title !== '' + ? '
' . esc_html($card_title) . '
' + : ''; - $text_style = ''; - if ($text_color) $text_style .= 'color:' . esc_attr($text_color) . ';'; + $card = [ + 'class' => 'noshadow mb10', + 'img' => (string) ($item['image'] ?? ''), + 'video' => (string) ($item['video'] ?? ''), + 'alt' => wp_strip_all_tags($card_title), + 'link' => [ + 'url' => (string) ($item['link'] ?? ''), + 'target' => (string) ($item['target'] ?? ''), + ], + 'lazy' => true, + 'more' => $more, + 'height_scale' => !empty($item['height']) && is_numeric($item['height']) + ? (int) $item['height'] + : $height_scale, + 'mask_opacity' => isset($item['mask']) ? (int) $item['mask'] : $mask_opacity, + ]; - echo '
'; + if ($is_row) { + echo '
'; + } + if (function_exists('aksrt_graphic_card')) { + echo aksrt_graphic_card($card); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + if ($is_row) { + echo '
'; + } + } - if ($video) { - echo '
'; - echo ''; - echo '
'; - } elseif ($image) { - echo '
'; - echo '' . esc_attr($card_title) . ''; - echo '
'; - } + if ($is_row) { + echo '
'; + } + echo '
'; - if ($overlay_style) { - echo '
'; - } + echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } - echo '
'; + /** + * @param mixed $raw + * @return array> + */ + private function normalize($raw): array { + if (is_string($raw)) { + $decoded = json_decode($raw, true); + $raw = is_array($decoded) ? $decoded : []; + } + if (!is_array($raw)) { + return []; + } + $out = []; + foreach ($raw as $row) { + if (!is_array($row)) { + continue; + } + $image = esc_url_raw(trim((string) ($row['image'] ?? ''))); + $video = esc_url_raw(trim((string) ($row['video'] ?? ''))); + if ($image === '' && $video === '') { + continue; + } + $out[] = [ + 'title' => sanitize_text_field((string) ($row['title'] ?? '')), + 'desc' => sanitize_text_field((string) ($row['desc'] ?? '')), + 'image' => $image, + 'video' => $video, + 'link' => esc_url_raw(trim((string) ($row['link'] ?? ''))), + 'target' => sanitize_text_field((string) ($row['target'] ?? '')), + 'hide' => sanitize_key((string) ($row['hide'] ?? '')), + 'height' => isset($row['height']) ? (int) $row['height'] : 0, + 'mask' => isset($row['mask']) ? (int) $row['mask'] : null, + ]; + if (count($out) >= 12) { + break; + } + } + return $out; + } - if ($link) { - echo ''; - } + /** + * @param array $instance + */ + public function form($instance): void { + $items = $this->normalize($instance['items'] ?? []); + $json = wp_json_encode($items, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + ?> +

+ +

+

+ + +

+

+ + +

+

+ + +

+ ' . esc_html($card_title) . ''; - } - if ($desc) { - echo '

' . esc_html($desc) . '

'; - } - - if ($link) { - echo '
'; - } - - echo '
'; - echo '
'; - } - - echo '
'; - - echo $args['after_widget']; - } - - public function form($instance): void { - $title = !empty($instance['title']) ? $instance['title'] : ''; - $items = !empty($instance['items']) ? $instance['items'] : '[]'; - $columns = !empty($instance['columns']) ? (int) $instance['columns'] : 2; - ?> -

- - -

-

- - -

-

- - - -

- $new_instance + * @param array $old_instance + * @return array + */ + public function update($new_instance, $old_instance): array { + return [ + 'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')), + '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))), + 'height_scale' => max(30, min(120, (int) ($new_instance['height_scale'] ?? 70))), + 'mask_opacity' => max(0, min(80, (int) ($new_instance['mask_opacity'] ?? 20))), + 'font_size_pc' => max(12, min(32, (int) ($new_instance['font_size_pc'] ?? 18))), + 'font_size_m' => max(11, min(24, (int) ($new_instance['font_size_m'] ?? 14))), + 'font_bold' => !empty($new_instance['font_bold']) ? 1 : 0, + 'font_color' => sanitize_hex_color((string) ($new_instance['font_color'] ?? '')) ?: '', + 'items' => $this->normalize($new_instance['items'] ?? []), + ]; + } }