进行了一些小修复

This commit is contained in:
2026-08-26 15:11:25 +08:00
parent d37c34f71c
commit ae10b3d3fd
16 changed files with 278 additions and 417 deletions
+1
View File
@@ -36,6 +36,7 @@
!/tests/widget-system/pay-orders-filter-contract.test.cjs
!/tests/widget-system/front-submit-editor-contract.test.cjs
!/tests/widget-system/comment-smilies-removal-contract.test.cjs
!/tests/widget-system/pay-card-contract.test.cjs
!/tests/asset-ledger/
!/tests/asset-ledger/*.php
!/tests/visual/docker-compose.zibll.yml
+52
View File
@@ -0,0 +1,52 @@
/* Canonical Zibll 9.0 paid-content card shell. */
.zib-widget.pay-box {
clear: both;
margin-bottom: 20px;
padding: 15px;
background-color: var(--main-bg-color);
border-radius: var(--main-radius);
box-shadow: 0 0 10px var(--main-shadow);
}
.pay-widget__orb {
position: absolute;
border-radius: 100%;
}
.pay-widget__orb--right {
top: -34%;
left: 75%;
width: 200px;
height: 200px;
}
.pay-widget__orb--left {
left: -229px;
width: 337px;
height: 305px;
opacity: .7;
}
.pay-thumb-placeholder {
position: absolute;
inset: 0;
display: grid;
place-items: center;
color: rgba(255, 255, 255, .82);
background: linear-gradient(135deg, #59616d, #272b31);
font-size: 40px;
}
.pay-box .pay-attr {
margin-top: 10px;
}
.pay-box .pay-attr-item {
display: flex;
justify-content: space-between;
gap: 12px;
}
.pay-box .muted-2-color + .muted-2-color {
margin-left: 10px;
}
-12
View File
@@ -226,18 +226,6 @@
.single-head-cover .cover-meta.single-metabox {
display: flex; flex-wrap: wrap; gap: 8px 12px; font-size: 12px; color: var(--color-ink-4);
}
/* Pay box root — legacy #posts-pay.aksrt-panel.pay-box */
#posts-pay.aksrt-panel,
#posts-pay.pay-box,
.aksrt-single-pay-box {
margin: 16px 0 20px;
}
#posts-pay .aksrt-paywall,
.aksrt-single-pay-box .pay-box,
.aksrt-single-pay-box .aksrt-paywall {
margin: 0;
}
/* Cover meta pills + title-h-left */
.single-cover-con .article-title.title-h-left,
.single-cover .article-title.title-h-left {
@@ -119,117 +119,5 @@
opacity: .85;
}
/* ---- Paid fragment purchase card ---- */
.aksrt-paywall {
position: relative;
margin: 24px 0;
}
.aksrt-paywall__card {
position: relative;
z-index: 0;
display: grid;
grid-template-columns: auto minmax(0, 1fr) auto;
align-items: center;
gap: 18px;
padding: 22px 24px;
background: linear-gradient(135deg, var(--surface-1, #fff) 0%, var(--surface-2, #f8fafc) 100%);
border: 1px solid var(--color-line, #e5e7eb);
border-radius: var(--radius-lg, 14px);
box-shadow: 0 10px 28px rgba(15, 23, 42, .08);
}
.aksrt-paywall--fragment .aksrt-paywall__card {
border-style: dashed;
border-color: color-mix(in srgb, var(--color-primary, #f04494) 42%, var(--color-line, #e5e7eb));
}
.aksrt-paywall__icon {
display: grid;
place-items: center;
width: 44px;
height: 44px;
flex: 0 0 auto;
border-radius: 50%;
color: var(--color-primary, #f04494);
background: color-mix(in srgb, var(--color-primary, #f04494) 12%, transparent);
font-size: 20px;
}
.aksrt-paywall__body { min-width: 0; }
.aksrt-paywall__title {
margin: 0 0 4px;
color: var(--color-ink, #15171a);
font-size: 17px;
font-weight: 700;
}
.aksrt-paywall__desc {
margin: 0;
color: var(--color-ink-3, #525866);
font-size: 14px;
line-height: 1.6;
}
.aksrt-paywall__price { margin-top: 8px; }
.aksrt-paywall__price-amount { color: var(--color-error, #ef4444); font-size: 20px; font-weight: 700; }
.aksrt-paywall__price-member { color: var(--color-primary, #f04494); font-size: 16px; font-weight: 700; }
.aksrt-paywall__price-free { color: var(--color-success, #10b981); font-size: 16px; font-weight: 700; }
.aksrt-paywall__price-original { margin-left: 8px; color: var(--color-ink-4, #8a8f98); font-size: 13px; text-decoration: line-through; }
.aksrt-paywall__actions {
position: relative;
z-index: 1;
display: flex;
flex: 0 0 auto;
flex-direction: column;
align-items: center;
gap: 8px;
text-align: center;
}
.aksrt-paywall__btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
min-height: 40px;
white-space: nowrap;
cursor: pointer;
}
.aksrt-paywall__btn:focus-visible,
.aksrt-paywall__login-link:focus-visible {
outline: 3px solid color-mix(in srgb, var(--color-primary, #f04494) 35%, transparent);
outline-offset: 3px;
}
.aksrt-paywall__hint,
.aksrt-paywall__login-link {
margin: 0;
color: var(--color-ink-4, #8a8f98);
font-size: 12px;
line-height: 1.5;
}
.aksrt-paywall__login-link { text-decoration: underline; }
.aksrt-gallery-locked { filter: blur(8px); pointer-events: none; user-select: none; }
.aksrt-paywall-preview { margin: 0 0 16px; padding: 14px 16px; border-left: 3px solid var(--color-primary, #f04494); background: var(--surface-2, #f8fafc); border-radius: 0 10px 10px 0; color: var(--color-ink-2, #374151); line-height: 1.7; }
.aksrt-paywall-preview p:last-child { margin-bottom: 0; }
.aksrt-paid-gallery__overlay .but, .aksrt-paid-video__placeholder .but { margin-top: 10px; }
@media (max-width: 680px) {
.aksrt-paywall__card {
grid-template-columns: auto minmax(0, 1fr);
padding: 18px;
}
.aksrt-paywall__actions {
grid-column: 1 / -1;
align-items: stretch;
width: 100%;
}
.aksrt-paywall__btn { width: 100%; }
}
-1
View File
@@ -125,7 +125,6 @@
.aksrt-term-aggregation { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 15px; }.aksrt-term-aggregation__card { padding: 15px; border-radius: var(--aksrt-widget-radius); background: var(--main-bg-color,#fff); box-shadow: 0 0 10px var(--main-shadow,rgba(116,116,116,.08)); }.aksrt-term-aggregation header a { display: flex; justify-content: space-between; }.aksrt-term-aggregation header span { color: var(--muted-color,#8a8c98); font-size: 13px; }.aksrt-term-aggregation ul { display: grid; gap: 10px; margin: 14px 0 0; padding: 0; list-style: none; }.aksrt-term-aggregation li a { display: flex; align-items: center; gap: 10px; }.aksrt-term-aggregation li img { width: 55px; height: 42px; border-radius: 6px; object-fit: cover; }
.aksrt-widget-items { position: relative; min-height: 40px; }.aksrt-widget-items.is-loading { opacity: .72; pointer-events: none; }.aksrt-widget-skeleton { height: 180px; border-radius: 10px; background: linear-gradient(90deg,rgba(127,127,127,.08),rgba(127,127,127,.17),rgba(127,127,127,.08)); background-size: 200% 100%; animation: aksrt-shimmer 1.2s infinite; }.aksrt-widget-load-more { display: block; min-width: 120px; margin: 18px auto 0; padding: 9px 18px; border: 0; border-radius: 999px; background: rgba(127,127,127,.12); color: inherit; cursor: pointer; }.aksrt-widget-pagination { display:flex;justify-content:center;gap:6px;margin-top:18px; }.aksrt-widget-pagination button { min-width:34px;height:34px;border:0;border-radius:8px;background:rgba(127,127,127,.1);color:inherit;cursor:pointer; }.aksrt-widget-pagination button[aria-current="page"] { background:var(--focus-color,#ff5473);color:#fff; }@keyframes aksrt-shimmer { to { background-position: -200% 0; } }
.aksrt-widget-oneline .swiper-slide { width: min(300px,78vw); }.aksrt-widget-tabs__nav { display: flex; gap: 8px; margin-bottom: 15px; overflow-x: auto; }.aksrt-widget-tabs__nav button { flex: none; padding: 7px 14px; border: 0; border-radius: 999px; background: rgba(127,127,127,.1); color: inherit; cursor: pointer; }.aksrt-widget-tabs__nav button[aria-selected="true"] { background: var(--focus-color,#ff5473); color: #fff; }
.aksrt-post-pay { padding: 20px; border-radius: var(--aksrt-widget-radius); text-align: center; }.aksrt-post-pay.is-authorized { background: rgba(34,197,94,.1); }.aksrt-post-pay > i { display: block; margin-bottom: 9px; color: #22c55e; font-size: 30px; }.aksrt-post-pay p { color: var(--muted-color,#8a8c98); }
.aksrt-pricing-card { position: relative; display: flex; flex-direction: column; padding: 20px; border: 1px solid var(--main-border-color,rgba(127,127,127,.13)); border-radius: var(--main-radius,8px); background: var(--main-bg-color,#fff); box-shadow: 0 0 10px var(--main-shadow,rgba(116,116,116,.08)); }.aksrt-pricing-card.is-featured { border-color: var(--focus-color,#ff5473); }.aksrt-pricing-card__badge { position: absolute; top: 12px; right: 12px; padding: 4px 9px; border-radius: 999px; background: var(--focus-color,#ff5473); color: #fff; font-size: 12px; }.aksrt-pricing-card h3 { margin: 0 0 12px; }.aksrt-pricing-card__price { font-size: 34px; font-weight: 800; }.aksrt-pricing-card p { color: var(--muted-color,#8a8c98); }.aksrt-pricing-card ul { flex: 1; display: grid; gap: 9px; margin: 15px 0 22px; padding: 0; list-style: none; }.aksrt-pricing-card li i { margin-right: 8px; color: #22c55e; }
.aksrt-reviews .swiper-slide { width: min(390px,86vw); height: auto; }.aksrt-review-card { height: 100%; padding: 20px; border-radius: var(--main-radius,8px); background: var(--main-bg-color,#fff); box-shadow: 0 0 10px var(--main-shadow,rgba(116,116,116,.08)); }.aksrt-review-card__rating { color: #f6b73c; }.aksrt-review-card blockquote { min-height: 80px; margin: 15px 0; line-height: 1.75; }.aksrt-review-card footer { display: flex; align-items: center; gap: 11px; }.aksrt-review-card__avatar { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; }.aksrt-review-card footer span { display: flex; flex-direction: column; }.aksrt-review-card footer small { color: var(--muted-color,#8a8c98); }
+1 -6
View File
@@ -240,15 +240,10 @@ add_action('init', function () {
// ============================================================
/**
* 未付费内容:替换为付费墙。
* 未购买的图库/视频正文只保留公开预览;购买卡由 single 模板渲染。
*/
add_filter('the_content', 'aksrt_paid_content_filter', 20);
/**
* 已付费内容增强:追加图库轮播/视频播放器。
*/
add_filter('the_content', 'aksrt_paid_content_enhance', 25);
/**
* 付费/资源文章使用统一的 single.php。
*/
+144 -244
View File
@@ -157,25 +157,6 @@ if (!function_exists('aksrt_get_pay_meta')) {
if (!function_exists('aksrt_default_pay_meta')) {
function aksrt_default_pay_meta(): array {
return \AKSRT\Core\DomainModel::default_pay_meta();
return [
'pay_type' => AKSRT_PAY_TYPE_NO,
'price' => 0.0,
'original_price' => 0.0,
'vip1_price' => 0.0,
'vip2_price' => 0.0,
'version' => '',
'size' => '',
'license' => '',
'compat' => '',
'demo_url' => '',
'downloads' => [],
'require_login' => false,
'require_captcha' => false,
'attributes' => [],
'gallery' => [],
'video_url' => '',
];
}
}
@@ -1195,101 +1176,127 @@ if (!function_exists('aksrt_get_pay_attributes_html')) {
// ============================================================
if (!function_exists('aksrt_get_paywall_html')) {
function aksrt_get_paywall_html(WP_Post $post, bool $is_fragment = false): string {
function aksrt_get_paywall_html(WP_Post $post, array $args = []): string {
$is_widget = ($args['layout'] ?? 'article') === 'widget';
$theme = sanitize_html_class((string) ($args['theme'] ?? 'jb-red')) ?: 'jb-red';
$meta = aksrt_get_pay_meta($post);
$pay_type = $meta['pay_type'];
$priced = function_exists('aksrt_get_user_pay_price') ? aksrt_get_user_pay_price($post) : null;
$pay_modo = is_array($priced) ? ((($priced['modo'] ?? '0') === 'points') ? 'points' : '0') : ((($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0');
$price = is_array($priced)
? ($priced['amount'] ?? ($pay_modo === 'points' ? 0 : '0.00'))
: ($pay_modo === 'points' ? (int) ($meta['points_price'] ?? 0) : (string) ($meta['price'] ?? '0.00'));
$price_minor = aksrt_asset_price_minor($price, $pay_modo);
$vip_level = is_array($priced) ? (int) ($priced['vip_level'] ?? 0) : 0;
$currency = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt');
$cash_symbol = '¥';
if (class_exists('\AKSRT\Settings\Settings')) {
$paid = \AKSRT\Settings\Settings::get_paid_content_settings();
$cash_symbol = (string) ($paid['display']['currency_symbol'] ?? '¥');
}
$price_text = $pay_modo === 'points'
? (aksrt_format_price($price) . ' ' . $currency)
: ($cash_symbol . aksrt_format_price($price));
$pay_type = (string) ($meta['pay_type'] ?? AKSRT_PAY_TYPE_NO);
if ($pay_type === AKSRT_PAY_TYPE_NO) return '';
$type_labels = [
AKSRT_PAY_TYPE_READING => ['icon' => 'fa-lock', 'label' => __('付费阅读', 'aksrt'), 'desc' => __('付费后即可查看完整内容', 'aksrt')],
AKSRT_PAY_TYPE_GALLERY => ['icon' => 'fa-image', 'label' => __('付费图库', 'aksrt'), 'desc' => __('付费后即可查看全部图片', 'aksrt')],
AKSRT_PAY_TYPE_VIDEO => ['icon' => 'fa-play-circle', 'label' => __('付费视频', 'aksrt'), 'desc' => __('付费后即可观看完整视频', 'aksrt')],
];
$type_info = $type_labels[$pay_type] ?? $type_labels[AKSRT_PAY_TYPE_READING];
if ($is_fragment && $pay_type === AKSRT_PAY_TYPE_READING) {
$type_info['desc'] = __('付费后即可查看此片段内容', 'aksrt');
}
$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();
$original_price = $pay_modo === 'points'
? max(0, (int) ($meta['original_price'] ?? 0))
: (string) ($meta['original_price'] ?? '0.00');
$original_minor = aksrt_asset_price_minor($original_price, $pay_modo);
$has_original = $original_minor > 0 && $original_minor > $price_minor;
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
$priced = aksrt_get_user_pay_price($post);
$modo = (string) ($priced['modo'] ?? '0');
$amount = $priced['amount'] ?? 0;
$amount_minor = aksrt_asset_price_minor($amount, $modo);
$price_label = aksrt_get_pay_price_label($post);
$price_text = (string) ($price_label['text'] ?? __('免费', 'aksrt'));
$pay_limit = (int) ($priced['pay_limit'] ?? ($meta['pay_limit'] ?? 0));
$vip_level = (int) ($priced['vip_level'] ?? 0);
$member_blocked = $pay_limit > 0 && $vip_level < $pay_limit;
$vip_url = function_exists('aksrt_get_user_center_tab_url')
? aksrt_get_user_center_tab_url('credits')
: (function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url() : home_url('/'));
$type_labels = [
AKSRT_PAY_TYPE_READING => __('付费阅读', 'aksrt'),
AKSRT_PAY_TYPE_DOWNLOAD => __('付费下载', 'aksrt'),
AKSRT_PAY_TYPE_GALLERY => __('付费图库', 'aksrt'),
AKSRT_PAY_TYPE_VIDEO => __('付费视频', 'aksrt'),
AKSRT_PAY_TYPE_VIP => __('VIP 专属', 'aksrt'),
];
$type_label = $type_labels[$pay_type] ?? __('付费内容', 'aksrt');
$order_types = [
AKSRT_PAY_TYPE_READING => 1,
AKSRT_PAY_TYPE_DOWNLOAD => 2,
AKSRT_PAY_TYPE_GALLERY => 5,
AKSRT_PAY_TYPE_VIDEO => 6,
AKSRT_PAY_TYPE_VIP => 4,
];
$order_type = (int) ($order_types[$pay_type] ?? 1);
$title = get_the_title($post);
$doc = trim((string) ($args['message'] ?? ''));
if ($doc === '') {
$doc = sprintf(__('此内容为%s,请付费后查看', 'aksrt'), $type_label);
}
$sales = max(0, (int) ($meta['virtual_sales'] ?? 0));
$sales += max(0, (int) get_post_meta($post->ID, \AKSRT\Core\DomainModel::RESOURCE_SALES_VOLUME_KEY, true));
$tag = $is_widget
? '<badge class="pay-tag abs-center">' . esc_html($type_label) . '</badge>'
: '<div class="pay-tag abs-center">' . esc_html($type_label) . '</div>';
$block_class = $is_widget ? ' btn-block' : '';
$button = '';
if (!is_user_logged_in()) {
if ($pay_limit <= 0 && $amount_minor > 0 && $modo === '0' && aksrt_allow_guest_content_pay($post)) {
$button = '<button type="button" class="but jb-red padding-lg cashier-link' . $block_class . '" data-aksrt-pay-content="' . esc_attr((string) $post->ID) . '"><i class="fa fa-shopping-cart" aria-hidden="true"></i> ' . esc_html__('立即购买', 'aksrt') . '</button>';
} else {
$button = '<a href="' . esc_url(wp_login_url(get_permalink($post))) . '" class="but jb-blue padding-lg' . $block_class . '"><i class="fa fa-sign-in" aria-hidden="true"></i> ' . esc_html__('登录购买', 'aksrt') . '</a>';
}
} elseif ($member_blocked) {
$vip_url = aksrt_get_user_center_tab_url('vip');
$button = '<a href="' . esc_url($vip_url) . '" class="but jb-vip' . max(1, min(2, $pay_limit)) . ' padding-lg' . $block_class . '"><i class="fa fa-certificate" aria-hidden="true"></i> ' . esc_html__('开通会员后可查看', 'aksrt') . '</a>';
} elseif ($amount_minor > 0) {
$button = '<button type="button" class="but ' . ($modo === 'points' ? 'jb-yellow' : 'jb-red') . ' padding-lg cashier-link' . $block_class . '" data-aksrt-pay-content="' . esc_attr((string) $post->ID) . '"><i class="fa fa-shopping-cart" aria-hidden="true"></i> ' . esc_html__('立即购买', 'aksrt') . '</button>';
} else {
$button = '<button type="button" class="but jb-blue padding-lg cashier-link' . $block_class . '" data-aksrt-pay-content="' . esc_attr((string) $post->ID) . '"><i class="fa fa-eye" aria-hidden="true"></i> ' . esc_html__('查看内容', 'aksrt') . '</button>';
}
$price_color = ($price_label['free'] ?? false) ? 'c-green' : ($modo === 'points' ? 'c-yellow' : 'c-red');
$price = '<div class="price-box"><div class="' . esc_attr($price_color) . '"><b class="em3x">' . esc_html($price_text) . '</b></div></div>';
$vip_items = [];
$base_minor = aksrt_asset_price_minor($priced['base'] ?? $amount, $modo);
foreach ([1, 2] as $level) {
$key = $modo === 'points' ? 'vip' . $level . '_points' : 'vip' . $level . '_price';
$value = $meta[$key] ?? 0;
$vip_minor = aksrt_asset_price_minor($value, $modo);
if ($vip_minor > 0 && ($base_minor <= 0 || $vip_minor < $base_minor)) {
$vip_items[] = '<span class="but vip-price"><span class="vip-price-text">' . esc_html(sprintf(__('VIP%d', 'aksrt'), $level)) . '</span><span class="em12 ml3">' . esc_html(aksrt_format_price($value)) . '</span></span>';
}
}
$vip = implode('', $vip_items);
if (count($vip_items) > 1) {
$vip = '<span class="vip-price-buts but-average inline">' . $vip . '</span>';
}
$attrs = aksrt_get_pay_attributes_html($post, 'pay-attr');
$count = $sales > 0 ? '<badge class="img-badge hot jb-blue px12">' . esc_html(sprintf(__('已售 %s', 'aksrt'), $sales)) . '</badge>' : '';
$service = aksrt_get_pay_service_html('muted-2-color');
$demo = aksrt_get_demo_link_html($post, 'but jb-yellow padding-lg');
$demo_row = $demo !== '' ? '<div class="mt10">' . $demo . '</div>' : '';
$discount = $modo === '0' ? aksrt_get_post_rebate_discount($post) : '0.00';
$discount_text = aksrt_asset_price_minor($discount, '0') > 0
? sprintf(__('推广优惠 %s', 'aksrt'), (string) ($priced['currency'] ?? '¥') . aksrt_format_price($discount))
: '';
$discount_banner = $discount_text !== '' ? '<div class="text-center padding-6 jb-yellow px12">' . esc_html($discount_text) . '</div>' : '';
ob_start();
?>
<div class="aksrt-paywall<?php echo $is_fragment ? ' aksrt-paywall--fragment' : ''; ?>" data-post-id="<?php echo esc_attr((string) $post->ID); ?>" data-pay-type="<?php echo esc_attr($pay_type); ?>" data-pay-modo="<?php echo esc_attr($pay_modo); ?>">
<div class="aksrt-paywall__card" role="group" aria-label="<?php esc_attr_e('付费内容购买', 'aksrt'); ?>">
<div class="aksrt-paywall__icon">
<i class="fa <?php echo esc_attr($type_info['icon']); ?>" aria-hidden="true"></i>
</div>
<div class="aksrt-paywall__body">
<h3 class="aksrt-paywall__title"><?php echo esc_html($type_info['label']); ?></h3>
<p class="aksrt-paywall__desc"><?php echo esc_html($type_info['desc']); ?></p>
<div class="aksrt-paywall__price">
<?php if ($member_blocked) : ?>
<span class="aksrt-paywall__price-member"><?php esc_html_e('会员专属', 'aksrt'); ?></span>
<?php elseif ($price > 0) : ?>
<span class="aksrt-paywall__price-amount"><?php echo esc_html($price_text); ?></span>
<?php if ($has_original) : ?>
<span class="aksrt-paywall__price-original"><?php echo esc_html(($pay_modo === 'points' ? aksrt_format_price($original_price) . ' ' . $currency : $cash_symbol . aksrt_format_price($original_price))); ?></span>
<?php endif; ?>
<?php else : ?>
<span class="aksrt-paywall__price-free"><?php esc_html_e('免费', 'aksrt'); ?></span>
<?php endif; ?>
</div>
</div>
<div class="aksrt-paywall__actions">
<?php if (!$is_logged_in) : ?>
<?php if ($pay_limit <= 0 && $price > 0 && $pay_modo !== 'points' && function_exists('aksrt_allow_guest_content_pay') && aksrt_allow_guest_content_pay($post)) : ?>
<button type="button" class="but <?php echo $pay_modo === 'points' ? 'jb-yellow' : 'jb-red'; ?> padding-lg cashier-link aksrt-paywall__btn" data-aksrt-pay-content="<?php echo esc_attr((string) $post->ID); ?>">
<i class="fa fas fa-shopping-cart" aria-hidden="true"></i> <?php printf(esc_html__('游客购买(%s)', 'aksrt'), $price_text); ?>
</button>
<a href="<?php echo esc_url($login_url); ?>" class="aksrt-paywall__login-link"><?php esc_html_e('已有账号?登录后购买', 'aksrt'); ?></a>
<?php else : ?>
<a href="<?php echo esc_url($login_url); ?>" class="but jb-red padding-lg aksrt-paywall__btn">
<i class="fa fas fa-sign-in-alt" aria-hidden="true"></i> <?php esc_html_e('登录后购买', 'aksrt'); ?>
</a>
<?php endif; ?>
<?php elseif ($member_blocked) : ?>
<a href="<?php echo esc_url($vip_url); ?>" class="but jb-vip padding-lg aksrt-paywall__btn">
<i class="fa fas fa-certificate" aria-hidden="true"></i> <?php esc_html_e('开通会员后可查看', 'aksrt'); ?>
</a>
<?php elseif ($price > 0) : ?>
<button type="button" class="but <?php echo $pay_modo === 'points' ? 'jb-yellow' : 'jb-red'; ?> padding-lg cashier-link aksrt-paywall__btn" data-aksrt-pay-content="<?php echo esc_attr((string) $post->ID); ?>">
<i class="fa fas fa-shopping-cart" aria-hidden="true"></i> <?php printf(esc_html__('立即购买(%s)', 'aksrt'), $price_text); ?>
</button>
<?php endif; ?>
<p class="aksrt-paywall__hint">
<i class="fa fas fa-shield-alt" aria-hidden="true"></i> <?php esc_html_e('购买后永久有效,支持重复查看', 'aksrt'); ?>
</p>
</div>
</div>
</div>
<?php
return ob_get_clean();
if ($is_widget && aksrt_has_paid_access($post)) {
$view_labels = [
AKSRT_PAY_TYPE_DOWNLOAD => '<i class="fa fa-download fa-fw" aria-hidden="true"></i>' . esc_html__('获取下载地址', 'aksrt'),
AKSRT_PAY_TYPE_GALLERY => '<i class="fa fa-file-image-o fa-fw" aria-hidden="true"></i>' . esc_html__('查看图片', 'aksrt'),
AKSRT_PAY_TYPE_VIDEO => '<i class="fa fa-play-circle fa-fw" aria-hidden="true"></i>' . esc_html__('查看视频', 'aksrt'),
];
$view_label = $view_labels[$pay_type] ?? '<i class="fa fa-dot-circle-o fa-fw" aria-hidden="true"></i>' . esc_html__('查看内容', 'aksrt');
return '<div class="zib-widget pay-box pay-widget paid-box order-type-' . $order_type . '" style="padding:0">' . $tag . '<div class="relative-h ' . esc_attr($theme) . '" style="background-size:120%"><div class="pay-widget__orb pay-widget__orb--right ' . esc_attr($theme) . '"></div><div class="pay-widget__orb pay-widget__orb--left ' . esc_attr($theme) . '"></div><div class="relative box-body"><div class="text-center mt10 box-body"><p><i class="fa fa-shopping-bag fa-3x" aria-hidden="true"></i></p><b class="em14">' . esc_html__('已购买', 'aksrt') . '</b></div></div></div><div class="box-body"><div class="px12 muted-2-color">' . $service . '</div><div class="mt10"><a href="#posts-pay" class="but padding-lg btn-block ' . esc_attr($theme) . '">' . $view_label . '</a></div>' . $demo_row . $attrs . '</div>' . $count . '</div>';
}
if ($is_widget) {
return '<div class="zib-widget pay-box pay-widget order-type-' . $order_type . '" style="padding:0">' . $tag . '<div class="relative-h ' . esc_attr($theme) . '" style="background-size:120%"><div class="pay-widget__orb pay-widget__orb--right ' . esc_attr($theme) . '"></div><div class="pay-widget__orb pay-widget__orb--left ' . esc_attr($theme) . '"></div><div class="relative box-body"><div class="text-center mt10">' . $price . '</div></div><div class="relative">' . $vip . '</div></div>' . $discount_banner . '<div class="box-body"><div class="px12 muted-2-color">' . $service . '</div><div class="mt10">' . $button . '</div>' . $demo_row . $attrs . '</div>' . $count . '</div>';
}
$thumb = get_the_post_thumbnail($post, 'medium', ['class' => 'fit-cover', 'alt' => '']);
if ($thumb === '') {
$thumb = '<div class="pay-thumb-placeholder"><i class="fa fa-lock" aria-hidden="true"></i></div>';
}
$graphic_actions = '';
if ($demo !== '' || $discount_text !== '') {
$graphic_actions = '<div class="abs-center text-center left-bottom">';
$graphic_actions .= $demo !== '' ? '<div>' . $demo . '</div>' : '';
$graphic_actions .= $discount_text !== '' ? '<div class="padding-6 jb-red px12 hidden-xs">' . esc_html($discount_text) . '</div>' : '';
$graphic_actions .= '</div>';
}
$discount_mobile = $discount_text !== '' ? '<div class="visible-xs-block badg c-red px12 mb6">' . esc_html($discount_text) . '</div>' : '';
if ($pay_type === AKSRT_PAY_TYPE_GALLERY) {
$gallery_count = count((array) ($meta['gallery'] ?? []));
$graphic = '<div class="flex0 relative mr20 hide-sm pay-thumb"><div class="graphic"><div class="blur-10 absolute">' . $thumb . '</div><div class="absolute graphic-mask" style="opacity:.3"></div><div class="abs-center text-center">' . esc_html(sprintf(__('共%s张图片', 'aksrt'), $gallery_count)) . '<br>' . esc_html__('请付费后查看', 'aksrt') . '</div>' . $graphic_actions . '</div></div>';
} elseif ($pay_type === AKSRT_PAY_TYPE_VIDEO) {
$graphic = '<div class="flex0 relative mr20 hide-sm pay-thumb"><div class="graphic">' . $thumb . '<div class="absolute graphic-mask" style="opacity:.2"></div><div class="abs-center text-center"><i class="fa fa-play-circle-o fa-4x opacity8" aria-hidden="true"></i></div>' . $graphic_actions . '</div></div>';
} else {
$graphic = '<div class="flex0 relative mr20 hide-sm pay-thumb"><div class="graphic">' . $thumb . $graphic_actions . '</div></div>';
}
$demo_mobile = $demo !== '' ? '<div class="mt10 visible-xs-block">' . $demo . '</div>' : '';
return '<div class="zib-widget pay-box order-type-' . $order_type . '" id="posts-pay"><div class="flex pay-flexbox">' . $graphic . '<div class="flex-auto-h flex xx jsb"><dt class="text-ellipsis pay-title">' . esc_html($title) . '</dt><div class="mt6 em09 muted-2-color">' . wp_kses_post($doc) . '</div><div>' . $price . '</div>' . $discount_mobile . ($vip !== '' ? '<div>' . $vip . '</div>' : '') . '<div class="text-right mt10">' . $button . '</div></div></div><div class="px12 muted-2-color mt10 text-right">' . $service . '</div>' . $demo_mobile . $attrs . $tag . $count . '</div>';
}
}
@@ -1305,51 +1312,23 @@ if (!function_exists('aksrt_render_paid_gallery')) {
$images = $meta['gallery'] ?? [];
if (empty($images)) return '';
$has_access = aksrt_has_paid_access($post);
$base_uri = get_template_directory_uri();
if (!aksrt_has_paid_access($post)) return '';
ob_start();
?>
<div class="aksrt-paid-gallery" data-post-id="<?php echo esc_attr((string) $post->ID); ?>">
<?php if ($has_access) : ?>
<!-- 已付费:Swiper 轮播 -->
<div class="new-swiper aksrt-paid-gallery__swiper" data-loop="true">
<div class="swiper-wrapper">
<?php foreach ($images as $img_url) : ?>
<div class="swiper-slide">
<img<?php echo aksrt_get_lazy_attr('lazy_other', (string) $img_url, '', aksrt_get_lazy_thumb('lg')); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> alt="">
</div>
<?php endforeach; ?>
</div>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<div class="new-swiper aksrt-paid-gallery__swiper" data-loop="true">
<div class="swiper-wrapper">
<?php foreach ($images as $img_url) : ?>
<div class="swiper-slide">
<img<?php echo aksrt_get_lazy_attr('lazy_other', (string) $img_url, '', aksrt_get_lazy_thumb('lg')); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> alt="">
</div>
<?php endforeach; ?>
</div>
<?php else : ?>
<!-- 未付费:仅首图模糊预览,不输出完整图库 URL 列表 -->
<div class="aksrt-paid-gallery__locked">
<div class="aksrt-paid-gallery__preview">
<img<?php echo aksrt_get_lazy_attr('lazy_other', (string) $images[0], 'aksrt-gallery-locked', aksrt_get_lazy_thumb('lg')); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> alt="">
</div>
<div class="aksrt-paid-gallery__overlay">
<i class="fa fas fa-image" aria-hidden="true"></i>
<p><?php
printf(
/* translators: %d: image count */
esc_html__('共 %d 张图片,付费后可查看', 'aksrt'),
count($images)
);
?></p>
<?php $price_label = function_exists('aksrt_get_pay_price_label') ? aksrt_get_pay_price_label($post) : ['text' => '']; ?>
<?php if (!empty($price_label['text'])) : ?>
<span class="aksrt-paid-gallery__price"><?php echo esc_html((string) $price_label['text']); ?></span>
<?php endif; ?>
<button type="button" class="but jb-red padding-lg cashier-link" data-aksrt-pay-content="<?php echo esc_attr((string) $post->ID); ?>">
<i class="fa fas fa-shopping-cart" aria-hidden="true"></i> <?php esc_html_e('立即购买', 'aksrt'); ?>
</button>
</div>
</div>
<?php endif; ?>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
</div>
<?php
@@ -1369,42 +1348,22 @@ if (!function_exists('aksrt_render_paid_video')) {
$video_url = $meta['video_url'] ?? '';
if (empty($video_url)) return '';
$has_access = aksrt_has_paid_access($post);
if (!aksrt_has_paid_access($post)) return '';
ob_start();
?>
<div class="aksrt-paid-video" data-post-id="<?php echo esc_attr((string) $post->ID); ?>">
<?php if ($has_access) : ?>
<!-- 已付费:视频播放器 -->
<div class="aksrt-paid-video__player">
<?php if (preg_match('/\.(mp4|webm|ogg)$/i', $video_url)) : ?>
<video controls preload="metadata"<?php echo aksrt_is_lazy('lazy_posts_content') ? ' class="lazyload" src="" data-src="' . esc_url($video_url) . '"' : ' src="' . esc_url($video_url) . '"'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> style="width:100%;border-radius:var(--radius-lg);">
<?php esc_html_e('您的浏览器不支持视频播放。', 'aksrt'); ?>
</video>
<?php else : ?>
<div class="aksrt-paid-video__embed">
<iframe<?php echo aksrt_is_lazy('lazy_posts_content') ? ' class="lazyload" src="" data-src="' . esc_url($video_url) . '"' : ' src="' . esc_url($video_url) . '"'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> frameborder="0" allowfullscreen></iframe>
</div>
<?php endif; ?>
</div>
<?php else : ?>
<!-- 未付费:锁定预览(不输出真实视频地址) -->
<div class="aksrt-paid-video__locked">
<div class="aksrt-paid-video__placeholder">
<i class="fa fas fa-play-circle" aria-hidden="true"></i>
<p><?php esc_html_e('付费后即可观看完整视频', 'aksrt'); ?></p>
<?php $price_label = function_exists('aksrt_get_pay_price_label') ? aksrt_get_pay_price_label($post) : ['text' => '']; ?>
<?php if (!empty($price_label['text'])) : ?>
<span class="aksrt-paid-video__price"><?php echo esc_html((string) $price_label['text']); ?></span>
<?php endif; ?>
<p style="margin-top:14px;">
<button type="button" class="but jb-red padding-lg cashier-link" data-aksrt-pay-content="<?php echo esc_attr((string) $post->ID); ?>">
<i class="fa fas fa-shopping-cart" aria-hidden="true"></i> <?php esc_html_e('立即购买', 'aksrt'); ?>
</button>
</p>
</div>
</div>
<?php endif; ?>
<div class="aksrt-paid-video__player">
<?php if (preg_match('/\.(mp4|webm|ogg)$/i', $video_url)) : ?>
<video controls preload="metadata"<?php echo aksrt_is_lazy('lazy_posts_content') ? ' class="lazyload" src="" data-src="' . esc_url($video_url) . '"' : ' src="' . esc_url($video_url) . '"'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> style="width:100%;border-radius:var(--radius-lg);">
<?php esc_html_e('您的浏览器不支持视频播放。', 'aksrt'); ?>
</video>
<?php else : ?>
<div class="aksrt-paid-video__embed">
<iframe<?php echo aksrt_is_lazy('lazy_posts_content') ? ' class="lazyload" src="" data-src="' . esc_url($video_url) . '"' : ' src="' . esc_url($video_url) . '"'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> frameborder="0" allowfullscreen></iframe>
</div>
<?php endif; ?>
</div>
</div>
<?php
return ob_get_clean();
@@ -1439,59 +1398,10 @@ if (!function_exists('aksrt_paid_content_filter')) {
return $content;
}
// free_preview teaser + paywall. Never render full gallery/video media when unpaid.
// Only the configured teaser remains in the article body. The single
// template owns the one canonical purchase card for gallery/video.
$preview = trim((string) ($meta['free_preview'] ?? ''));
$out = '';
if ($preview !== '') {
$out .= '<div class="aksrt-paywall-preview">' . wp_kses_post($preview) . '</div>';
}
$out .= aksrt_get_paywall_html($post);
if ($pay_type === AKSRT_PAY_TYPE_GALLERY) {
$out .= aksrt_render_paid_gallery($post);
} elseif ($pay_type === AKSRT_PAY_TYPE_VIDEO) {
$out .= aksrt_render_paid_video($post);
}
return $out;
}
}
// 已付费的内容增强
if (!function_exists('aksrt_paid_content_enhance')) {
function aksrt_paid_content_enhance(string $content): string {
if (is_admin() || !is_singular() || !in_the_loop() || !is_main_query()) {
return $content;
}
global $post;
if (!($post instanceof WP_Post)) {
return $content;
}
$meta = aksrt_get_pay_meta($post);
$pay_type = (string) ($meta['pay_type'] ?? AKSRT_PAY_TYPE_NO);
if ($pay_type === AKSRT_PAY_TYPE_NO) {
return $content;
}
if (!aksrt_has_paid_access($post)) {
return $content;
}
if ($pay_type === AKSRT_PAY_TYPE_GALLERY && strpos($content, 'aksrt-paid-gallery') === false) {
$gallery_html = aksrt_render_paid_gallery($post);
if ($gallery_html) {
$content .= $gallery_html;
}
}
if ($pay_type === AKSRT_PAY_TYPE_VIDEO && strpos($content, 'aksrt-paid-video') === false) {
$video_html = aksrt_render_paid_video($post);
if ($video_html) {
$content .= $video_html;
}
}
return $content;
return $preview !== '' ? '<div class="aksrt-paywall-preview">' . wp_kses_post($preview) . '</div>' : '';
}
}
@@ -1511,20 +1421,10 @@ add_action('wp_head', function (): void {
.aksrt-paid-gallery{margin:24px 0}
.aksrt-paid-gallery__swiper{border-radius:var(--radius-lg);overflow:hidden}
.aksrt-paid-gallery__swiper img{width:100%;height:auto;display:block}
.aksrt-paid-gallery__locked{position:relative;border-radius:var(--radius-lg);overflow:hidden}
.aksrt-paid-gallery__preview img{width:100%;display:block}
.aksrt-paid-gallery__overlay{position:absolute;inset:0;background:rgba(0,0,0,.5);display:flex;flex-direction:column;align-items:center;justify-content:center;color:#fff;gap:12px}
.aksrt-paid-gallery__overlay i{font-size:48px;opacity:.8}
.aksrt-paid-gallery__overlay p{font-size:16px;margin:0}
.aksrt-paid-gallery__price{font-size:20px;font-weight:700;background:rgba(255,255,255,.2);padding:6px 16px;border-radius:20px}
.aksrt-paid-video{margin:24px 0}
.aksrt-paid-video__embed{position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:var(--radius-lg)}
.aksrt-paid-video__embed iframe{position:absolute;top:0;left:0;width:100%;height:100%;border:none}
.aksrt-paid-video__locked{background:var(--surface-2);border-radius:var(--radius-lg);padding:60px 20px;text-align:center}
.aksrt-paid-video__placeholder i{font-size:64px;color:var(--color-ink-4);margin-bottom:16px}
.aksrt-paid-video__placeholder p{font-size:16px;color:var(--color-ink-3);margin:0 0 12px}
.aksrt-paid-video__price{font-size:20px;font-weight:700;color:var(--color-error)}
</style>
<?php
});
+10 -13
View File
@@ -753,32 +753,29 @@ if (!function_exists('aksrt_single_render_pay_box')) :
}
$pay_type = (string) ($ctx['pay_type'] ?? 'no');
if (!empty($ctx['has_download']) || $pay_type === 'download') {
echo '<div class="aksrt-panel pay-box pay-type-download" id="posts-pay">';
get_template_part('templates/parts/resource-download-box');
echo '</div>';
return;
}
if (!function_exists('aksrt_get_pay_meta')) {
return;
}
$has_access = function_exists('aksrt_has_paid_access') ? aksrt_has_paid_access($post) : false;
$paid_class = $has_access ? 'paid-box' : 'pay-box';
echo '<div class="aksrt-panel ' . esc_attr($paid_class) . ' pay-type-' . esc_attr($pay_type) . '" id="posts-pay">';
if ($has_access) {
if ($pay_type === 'gallery' && function_exists('aksrt_render_paid_gallery')) {
if ($pay_type === 'download') {
get_template_part('templates/parts/resource-download-box');
return;
}
$order_type = $pay_type === 'gallery' ? 5 : ($pay_type === 'video' ? 6 : 4);
echo '<div class="zib-widget pay-box paid-box order-type-' . esc_attr((string) $order_type) . '" id="posts-pay">';
if ($pay_type === 'gallery') {
echo aksrt_render_paid_gallery($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} elseif ($pay_type === 'video' && function_exists('aksrt_render_paid_video')) {
} elseif ($pay_type === 'video') {
echo aksrt_render_paid_video($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
echo '<div class="box-body"><span class="badg c-green hollow badg-sm mr6">' . esc_html__('已解锁', 'aksrt') . '</span><b>' . esc_html(get_the_title($post)) . '</b></div>';
}
} elseif (function_exists('aksrt_get_paywall_html')) {
echo '</div>';
} else {
echo aksrt_get_paywall_html($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo '</div>';
}
endif;
+1 -3
View File
@@ -69,13 +69,12 @@ if (!function_exists('aksrt_single_build_context')) :
}
$show_cover = !empty($settings['show_cover']) && (string) ($settings['cover_url'] ?? '') !== '';
$has_download = function_exists('aksrt_is_downloadable_content') && aksrt_is_downloadable_content($post_id);
$pay_meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($post_id) : ['pay_type' => 'no'];
$pay_type = (string) ($pay_meta['pay_type'] ?? 'no');
$is_paid_post = function_exists('aksrt_is_paid_post') && aksrt_is_paid_post($post_id);
// Paid-reading purchase is rendered inline by each payshow shortcode.
// Keep the article-level module for download, gallery, video and VIP only.
$show_pay_box = $has_download || ($is_paid_post && !in_array($pay_type, ['no', 'download', 'reading'], true));
$show_pay_box = $is_paid_post && !in_array($pay_type, ['no', 'reading'], true);
$breadcrumbs_html = '';
if (!empty($settings['breadcrumbs']) && function_exists('aksrt_breadcrumbs')) {
@@ -136,7 +135,6 @@ if (!function_exists('aksrt_single_build_context')) :
'front_content' => (string) ($settings['front_content'] ?? ''),
'after_content' => (string) ($settings['after_content'] ?? ''),
'content_maxheight' => !empty($settings['maxheight_enabled']) ? max(0, (int) ($settings['maxheight'] ?? 0)) : 0,
'has_download' => $has_download,
'show_pay_box' => $show_pay_box,
'pay_type' => $pay_type,
'is_paid_post' => $is_paid_post,
+1
View File
@@ -197,6 +197,7 @@ trait ScriptsPart1b {
'needs_cover' => 'single-post/cover',
'needs_related_toc' => 'single-post/related-toc',
'has_hidden_content' => 'single-post/hidden-content',
'needs_pay_box' => 'pay-box',
];
$single_feature_handles = [];
foreach ($single_features as $requirement => $part) {
+2
View File
@@ -28,6 +28,7 @@ trait ScriptsPart1c {
'has_toc' => false,
'has_video' => false,
'has_hidden_content' => false,
'needs_pay_box' => false,
'needs_cover' => false,
'needs_navigation' => false,
'needs_related_toc' => false,
@@ -112,6 +113,7 @@ trait ScriptsPart1c {
$requirements['has_toc'] = $is_article && $heading_count >= 2;
$requirements['has_video'] = $has_video;
$requirements['has_hidden_content'] = $has_hidden_content || $has_yiyan || $has_inserted_content;
$requirements['needs_pay_box'] = $is_paid_content_single || (bool) preg_match('/\[(?:payshow|hidecontent)\b|wp:aksrt\/paid-fragment/i', $content);
$requirements['needs_cover'] = $is_article && (
$show_cover
|| !empty($settings['breadcrumbs'])
+1 -16
View File
@@ -120,22 +120,7 @@ class Shortcodes {
}
$message = $atts['message'] ?: __('此内容需付费后查看', 'aksrt');
if (function_exists('aksrt_get_paywall_html')) {
$paywall = aksrt_get_paywall_html($post, true);
if ($message !== '') {
$paywall = str_replace(
'<p class="aksrt-paywall__desc">',
'<p class="aksrt-paywall__desc">' . esc_html($message) . ' ',
$paywall
);
}
return $paywall;
}
return '<div class="aksrt-hidden-content aksrt-hidden-content--locked aksrt-hidden-content--payshow">'
. '<div class="aksrt-hidden-content__message"><i class="fa fas fa-lock" aria-hidden="true"></i><span>'
. esc_html($message)
. '</span></div></div>';
return aksrt_get_paywall_html($post, ['message' => $message]);
}
/**
+5
View File
@@ -23,6 +23,9 @@ final class AssetManager {
public static function enqueue_for(WidgetDefinition $definition): void {
self::register();
if ($definition->slug() === 'post_pay') {
wp_enqueue_style('aksrt-pay-box');
}
foreach ($definition->assets() as $asset) {
self::enqueue_optional($asset);
}
@@ -50,8 +53,10 @@ final class AssetManager {
$root = get_template_directory();
$uri = get_template_directory_uri();
$css = $root . '/assets/widgets/frontend.css';
$pay_css = $root . '/assets/css/frontend/pay-box.css';
$js = $root . '/assets/widgets/frontend.js';
wp_register_style(self::STYLE_HANDLE, $uri . '/assets/widgets/frontend.css', ['aksrt-public'], is_file($css) ? (string) filemtime($css) : null);
wp_register_style('aksrt-pay-box', $uri . '/assets/css/frontend/pay-box.css', ['aksrt-public'], is_file($pay_css) ? (string) filemtime($pay_css) : null);
wp_register_script(self::SCRIPT_HANDLE, $uri . '/assets/widgets/frontend.js', ['aksrt-runtime'], is_file($js) ? (string) filemtime($js) : null, true);
$third_party = $uri . '/assets/widgets/third-party/';
wp_register_script('aksrt-widget-hls', $third_party . 'hls.min.js', [], 'reference-pinned', true);
+2 -2
View File
@@ -23,9 +23,9 @@ final class FrontendRenderer {
}
AssetManager::enqueue_for($definition);
if (in_array($definition->slug(), ['tab_posts', 'slider', 'slider_media_combo', 'icon_cards', 'icon_cover_cards', 'buttons', 'notice'], true)) {
if (in_array($definition->slug(), ['post_pay', 'tab_posts', 'slider', 'slider_media_combo', 'icon_cards', 'icon_cover_cards', 'buttons', 'notice'], true)) {
echo (string) ($args['before_widget'] ?? '');
echo self::reference_title($instance);
if ($definition->slug() !== 'post_pay') echo self::reference_title($instance);
echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo (string) ($args['after_widget'] ?? '');
return;
@@ -145,14 +145,11 @@ final class ContentRenderer {
}
$meta = aksrt_get_pay_meta($post);
if (($meta['pay_type'] ?? 'no') === 'no') {
return RendererHelpers::empty_state(__('当前文章未配置付费内容', 'aksrt'));
return '';
}
if (function_exists('aksrt_has_paid_access') && aksrt_has_paid_access($post)) {
$html = '<div class="aksrt-post-pay is-authorized ' . esc_attr((string) $instance['theme']) . '"><i class="fa fas fa-check-circle" aria-hidden="true"></i><strong>' . esc_html__('内容已解锁', 'aksrt') . '</strong><p>' . esc_html__('你已拥有当前知识内容的访问权限。', 'aksrt') . '</p>';
$html .= function_exists('aksrt_get_pay_attributes_html') ? aksrt_get_pay_attributes_html($post, 'aksrt-post-pay__attrs') : '';
$html .= function_exists('aksrt_get_demo_link_html') ? aksrt_get_demo_link_html($post, 'aksrt-widget-button') : '';
return $html . '</div>';
}
return function_exists('aksrt_get_paywall_html') ? aksrt_get_paywall_html($post, true) : RendererHelpers::empty_state(__('请登录或购买后查看', 'aksrt'));
return aksrt_get_paywall_html($post, [
'layout' => 'widget',
'theme' => (string) $instance['theme'],
]);
}
}
@@ -0,0 +1,53 @@
'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const root = path.resolve(__dirname, '..', '..');
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
test('paid article and sidebar widget use the Zibll purchase-card DOM', () => {
const pay = read('inc/helpers/aksrt-pay.php');
const widget = read('src/WidgetSystem/Renderers/ContentRenderer.php');
const shell = read('src/WidgetSystem/FrontendRenderer.php');
const single = read('inc/helpers/aksrt-single-render.php');
const hooks = read('inc/core-hooks/part-3.php');
assert.match(pay, /zib-widget pay-box pay-widget/);
assert.match(pay, /zib-widget pay-box order-type-/);
assert.match(pay, /flex pay-flexbox/);
assert.match(pay, /hide-sm pay-thumb/);
assert.match(pay, /pay-tag abs-center/);
assert.match(pay, /price-box/);
assert.match(pay, /vip-price-buts but-average inline/);
assert.match(pay, /cashier-link/);
assert.match(widget, /'layout' => 'widget'/);
assert.match(shell, /\['post_pay', 'tab_posts'/);
assert.doesNotMatch(single, /aksrt-panel pay-box pay-type-download/);
assert.doesNotMatch(hooks, /aksrt_paid_content_enhance/);
});
test('the purchase card owns one direct stylesheet and no retired paywall path', () => {
const pay = read('inc/helpers/aksrt-pay.php');
const shortcodes = read('src/Core/Shortcodes.php');
const assets = read('src/Core/ScriptsPart1b.php') + read('src/WidgetSystem/AssetManager.php');
const hidden = read('assets/css/frontend/single-post/hidden-content.css');
const widgets = read('assets/widgets/frontend.css');
const css = read('assets/css/frontend/pay-box.css');
const publicCss = read('assets/css/main.css');
assert.match(assets, /assets\/css\/frontend\/pay-box\.css|\'pay-box\'/);
assert.match(shortcodes, /return aksrt_get_paywall_html\(\$post, \['message' => \$message\]\);/);
assert.match(css, /\.zib-widget\.pay-box/);
assert.doesNotMatch(css, /@media/);
assert.match(publicCss, /\.pay-box\.pay-widget \.vip-price/);
assert.match(publicCss, /\.pay-flexbox\s*\{\s*flex-wrap:\s*wrap;/);
const retired = pay + hidden + widgets + shortcodes;
assert.doesNotMatch(retired, /aksrt-paywall__(?:card|icon|body|title|desc|price|actions|btn|hint|login-link)/);
assert.doesNotMatch(retired, /aksrt-post-pay/);
assert.doesNotMatch(retired, /str_replace\([\s\S]*aksrt-paywall__desc/);
assert.doesNotMatch(pay, /aksrt-paid-(?:gallery|video)__(?:locked|preview|overlay|placeholder|price)/);
});