From 6a78b553d665e5b3f001236e35ad1344bc6654c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2026 12:42:57 +0800 Subject: [PATCH] feat(widgets): singular post pay purchase sidebar box Add WidgetPostPayBox (zibll posts_pay parity) with theme skins, paid/unpaid CTAs, sales badge, and registration. --- assets/css/frontend/widget-batch5.css | 38 ++++++ inc/modules/widgets-register.php | 1 + src/AKSRT/Widgets/WidgetPostPayBox.php | 181 +++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 src/AKSRT/Widgets/WidgetPostPayBox.php diff --git a/assets/css/frontend/widget-batch5.css b/assets/css/frontend/widget-batch5.css index ddc37d63..c5d94b39 100644 --- a/assets/css/frontend/widget-batch5.css +++ b/assets/css/frontend/widget-batch5.css @@ -2479,3 +2479,41 @@ a.main-color > .icon-cover-card:hover, .widget-tab-posts__skeleton .placeholder.k1 { width: 80%; } .widget-tab-posts__skeleton .placeholder.s1 { width: 48%; } .posts-mini-lists.aksrt-main-posts { /* zibll mini outer */ } + + +/* batch37-39 residual */ +.aksrt-post-pay-box { position: relative; overflow: hidden; } +.aksrt-post-pay-box .pay-tag.abs-center { + position: absolute; top: 12px; left: 50%; transform: translateX(-50%); + z-index: 2; padding: 2px 10px; border-radius: 999px; background: rgba(0,0,0,.35); color: #fff; font-size: 12px; +} +.aksrt-post-pay-box__hero { position: relative; overflow: hidden; min-height: 120px; color: #fff; } +.aksrt-post-pay-box__blob { opacity: .55; pointer-events: none; } +.aksrt-post-pay-box__blob--a { height: 200px; left: 75%; width: 200px; top: -34%; border-radius: 100%; } +.aksrt-post-pay-box__blob--b { height: 305px; width: 337px; left: -229px; border-radius: 100%; opacity: .7; } +.aksrt-post-pay-box .box-body { position: relative; z-index: 1; } +.aksrt-post-pay-box .img-badge.hot { position: absolute; top: 8px; right: 8px; z-index: 2; } +.aksrt-post-pay-box .but.btn-block { width: 100%; justify-content: center; } +.aksrt-main-posts__skeleton .placeholder-row, +.aksrt-product-tab__skeleton .placeholder-row { + display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; +} +.aksrt-main-posts__skeleton .posts-mini.placeholder-row { flex-direction: row; align-items: center; gap: 10px; } +.aksrt-main-posts__skeleton .thumb-placeholder, +.aksrt-product-tab__skeleton .placeholder.thumb { + width: 72px; height: 54px; border-radius: 8px; background: var(--surface-2, #eee); +} +.aksrt-product-tab__skeleton .placeholder.thumb { width: 100%; height: 100px; } +.aksrt-main-posts__skeleton .placeholder.k1, +.aksrt-main-posts__skeleton .placeholder.t1, +.aksrt-main-posts__skeleton .placeholder.s1, +.aksrt-product-tab__skeleton .placeholder.k1, +.aksrt-product-tab__skeleton .placeholder.s1 { + height: 12px; border-radius: 4px; background: var(--surface-2, #eee); +} +.aksrt-main-posts__skeleton .placeholder.k1, +.aksrt-product-tab__skeleton .placeholder.k1 { width: 80%; } +.aksrt-main-posts__skeleton .placeholder.s1, +.aksrt-product-tab__skeleton .placeholder.s1 { width: 48%; } +.aksrt-main-posts[data-load-mode="ajax"].is-ajax-loading { opacity: .85; } +.widget-search-box.is-affix { position: sticky; top: 72px; } diff --git a/inc/modules/widgets-register.php b/inc/modules/widgets-register.php index fcde9935..3b9ab49b 100644 --- a/inc/modules/widgets-register.php +++ b/inc/modules/widgets-register.php @@ -81,6 +81,7 @@ function aksrt_register_widgets() { register_widget('\AKSRT\Widgets\WidgetFeatureIntro'); register_widget('\AKSRT\Widgets\WidgetTermCards'); register_widget('\AKSRT\Widgets\WidgetPaidPosts'); + register_widget('\AKSRT\Widgets\WidgetPostPayBox'); register_widget('\AKSRT\Widgets\WidgetAuthorCard'); register_widget('\AKSRT\Widgets\WidgetOnelinePosts'); register_widget('\AKSRT\Widgets\WidgetTiltCases'); diff --git a/src/AKSRT/Widgets/WidgetPostPayBox.php b/src/AKSRT/Widgets/WidgetPostPayBox.php new file mode 100644 index 00000000..7128f12b --- /dev/null +++ b/src/AKSRT/Widgets/WidgetPostPayBox.php @@ -0,0 +1,181 @@ + esc_html__('显示当前文章/帖子的付费购买模块,推荐放在详情侧栏。', 'aksrt'), + 'classname' => 'widget_aksrt_post_pay_box', + ] + ); + } + + /** + * @param array $instance + */ + public static function render_html(array $instance = []): string { + if (!is_singular(['post', 'page', 'aksrt_forum_topic', 'aksrt_product'])) { + return ''; + } + $post = get_queried_object(); + if (!$post instanceof \WP_Post) { + return ''; + } + if (!function_exists('aksrt_get_pay_meta') || !function_exists('aksrt_is_paid_post')) { + return ''; + } + if (!aksrt_is_paid_post($post)) { + return ''; + } + + $meta = aksrt_get_pay_meta($post); + $pay_type = (string) ($meta['pay_type'] ?? 'no'); + if ($pay_type === '' || $pay_type === 'no') { + return ''; + } + + $theme = sanitize_html_class((string) ($instance['theme'] ?? 'jb-red')); + if ($theme === '') { + $theme = 'jb-red'; + } + + $has_access = function_exists('aksrt_has_paid_access') ? aksrt_has_paid_access($post) : false; + $priced = function_exists('aksrt_get_user_pay_price') ? aksrt_get_user_pay_price($post) : null; + $pay_modo = is_array($priced) && (($priced['modo'] ?? '') === 'points') ? 'points' : '0'; + $amount = is_array($priced) ? (float) ($priced['amount'] ?? 0) : (float) ($meta['price'] ?? 0); + $currency = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt'); + $cash_symbol = '¥'; + if (class_exists('\AKSRT\Settings\Settings')) { + $paid_s = \AKSRT\Settings\Settings::get_paid_content_settings(); + $cash_symbol = (string) ($paid_s['display']['currency_symbol'] ?? '¥'); + } + $price_text = $pay_modo === 'points' + ? (function_exists('aksrt_format_price') ? aksrt_format_price($amount) : (string) $amount) . ' ' . $currency + : $cash_symbol . (function_exists('aksrt_format_price') ? aksrt_format_price($amount) : number_format($amount, 2, '.', '')); + + $type_labels = [ + 'reading' => __('付费阅读', 'aksrt'), + 'download' => __('付费下载', 'aksrt'), + 'gallery' => __('付费图库', 'aksrt'), + 'video' => __('付费视频', 'aksrt'), + 'vip' => __('会员专属', 'aksrt'), + ]; + $type_label = $type_labels[$pay_type] ?? __('付费内容', 'aksrt'); + $cta_map = [ + 'reading' => __('查看内容', 'aksrt'), + 'download' => __('获取下载', 'aksrt'), + 'gallery' => __('查看图片', 'aksrt'), + 'video' => __('查看视频', 'aksrt'), + 'vip' => __('查看内容', 'aksrt'), + ]; + $cta_label = $cta_map[$pay_type] ?? __('查看内容', 'aksrt'); + + $sales = 0; + if (function_exists('aksrt_get_download_box_meta')) { + $box = aksrt_get_download_box_meta($post); + $sales = (int) ($box['sales_count'] ?? 0); + } + + $login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink($post)); + $is_logged_in = is_user_logged_in(); + $demo = trim((string) ($meta['demo_url'] ?? '')); + + ob_start(); + echo '
'; + echo '' . esc_html($type_label) . ''; + echo '
'; + echo '
'; + echo '
'; + echo '
'; + if ($has_access) { + echo '

'; + echo '' . esc_html__('已解锁', 'aksrt') . ''; + } else { + echo '
'; + if ($amount > 0) { + echo '
' . esc_html($price_text) . '
'; + } else { + echo '
' . esc_html__('免费', 'aksrt') . '
'; + } + echo '
'; + } + echo '
'; + + echo '
'; + if ($has_access) { + echo ''; + } elseif (!$is_logged_in) { + echo ''; + if ($amount > 0 && $pay_modo !== 'points' && function_exists('aksrt_allow_guest_content_pay') && aksrt_allow_guest_content_pay($post)) { + echo '
'; + } + } else { + echo '
'; + } + if ($demo !== '') { + echo ''; + } + echo '
'; + if ($sales > 0) { + echo '' . esc_html(sprintf(/* translators: sales count */ __('已售 %s', 'aksrt'), (string) $sales)) . ''; + } + echo '
'; + return (string) ob_get_clean(); + } + + public function widget($args, $instance): void { + $html = self::render_html($instance); + if ($html === '') { + return; + } + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + + public function form($instance): void { + $theme = sanitize_html_class((string) ($instance['theme'] ?? 'jb-red')); + $opts = [ + 'jb-red' => __('红', 'aksrt'), + 'jb-yellow' => __('橙', 'aksrt'), + 'jb-blue' => __('蓝', 'aksrt'), + 'jb-green' => __('绿', 'aksrt'), + 'jb-purple' => __('紫', 'aksrt'), + 'jb-vip1' => __('会员金', 'aksrt'), + 'jb-vip2' => __('会员灰', 'aksrt'), + ]; + ?> +

+

+ +

+ $theme]; + } +}