fix(widgets): align mini paid badges with reference
This commit is contained in:
1 parent
fd034ff055
commit
985f18c750
8 files changed
+249
-31
No files matched your search
@@ -220,13 +220,6 @@
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.item-meta .meta-pay img {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
object-fit: contain;
|
||||
vertical-align: -0.15em;
|
||||
}
|
||||
|
||||
.posts-item .item-meta a,
|
||||
.posts-mini .item-meta a {
|
||||
color: inherit;
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
.posts-row{margin-right:-8px;margin-bottom:15px;margin-left:-8px}.posts-row>*:not(.post_ajax_loader){margin-right:8px!important;margin-left:8px!important}.posts-row>.post_ajax_loader .posts-item,.posts-row>.post_ajax_loader .posts-mini{margin-right:8px;margin-left:8px}.posts-item{margin:15px 0;padding:20px;overflow:hidden;background:var(--main-bg-color, #fff);border-radius:var(--main-radius, 8px);box-shadow:0 0 10px var(--main-shadow, rgba(116, 116, 116, .08));transition:.2s}.posts-item.flex,.posts-item .flex,.posts-mini .flex{display:flex}.posts-item .flex.xx,.posts-mini .flex.xx{flex-direction:column}.posts-item .flex.ac,.posts-mini .flex.ac{align-items:center}.posts-item .flex.jsb,.posts-mini .flex.jsb{justify-content:space-between}.posts-item .flex1,.posts-mini .flex1{flex:1;overflow:hidden}.posts-item .post-graphic:not(.order1){margin-right:20px}.posts-item .order1.post-graphic{margin-right:0;margin-left:20px}.posts-item .item-thumbnail{position:relative;display:block;width:190px;height:0;padding-bottom:var(--posts-list-scale, 70%);overflow:hidden;border-radius:var(--main-radius, 8px)}.item-thumbnail.contain img{object-fit:contain}.swiper-slide.gradient-bg .dplayer-poster img,.swiper-slide.gradient-bg>*>img{object-fit:contain!important;border-radius:0!important}.item-thumbnail .swiper-wrapper{height:100%!important}.list .item-thumbnail .aksrt-slider,.list .item-thumbnail.new-swiper{position:absolute;width:100%;height:100%;margin:0!important}.item-thumbnail .dplayer.dplayer-thumb{position:absolute;inset:0;z-index:1;padding-bottom:var(--posts-list-scale, 70%);background:#000;opacity:0;transition:opacity .3s}.card .item-thumbnail .dplayer.dplayer-thumb{padding-bottom:var(--posts-card-scale, 70%)}.item-thumbnail .dplayer-thumb video,.item-thumbnail .swiper-wrapper,.item-thumbnail img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.item-thumbnail .swiper-pagination{right:0!important;bottom:0!important;left:0!important;padding:0 2px!important;text-align:center!important}.posts-item.thumb-dplayer-playing .dplayer-thumb{opacity:1}.posts-item.thumb-dplayer-playing .abs-center{opacity:0}.posts-item .item-heading{display:-webkit-box;max-height:2.8em;margin-top:0;margin-bottom:5px;overflow:hidden;font-size:18px;line-height:1.4em;white-space:normal;-webkit-box-orient:vertical;-webkit-line-clamp:2}.font-bold{font-weight:700}.list.style2 .item-thumbnail{width:130px}.list.style2 .item-heading{display:unset;max-height:1.4em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.posts-item .item-heading>a{color:var(--key-color, #333)}.posts-item .item-heading>a:hover{color:var(--focus-color, #f04494)}.posts-item .item-excerpt{margin:0 0 6px;overflow:hidden;color:var(--muted-color, #777);text-overflow:ellipsis;white-space:nowrap}.posts-item .item-meta item{margin-right:8px;font-size:13px}.posts-item .item-meta svg.icon,.posts-mini .item-meta svg.icon{display:inline-block;width:1em;height:1em;margin-right:2px;fill:currentColor;overflow:hidden;vertical-align:-.15em}.posts-item .meta-right item:last-child{margin-right:0}.item-meta .avatar-mini{width:20px;height:20px;border-radius:50%;transform:translateY(-1px)}.item-meta .meta-pay{padding:0 4px}.item-meta .meta-pay img{width:1em;height:1em;object-fit:contain;vertical-align:-.15em}.posts-item .item-meta a,.posts-mini .item-meta a{color:inherit}.posts-item .item-tags a{margin-right:5px;padding:2px 5px;font-size:11px}.posts-item .item-tags a .fa{font-size:1em}.posts-item.card{display:inline-block;width:calc(33.333% - 16px);margin:8px;padding:10px;vertical-align:top;transition:.3s}.posts-item.card:last-child{margin-bottom:20px}.posts-item.card .item-body{width:100%;margin:10px 0 0;padding:0}.posts-item.card .item-meta item{font-size:12px}.posts-mini-con .item-heading,.posts-item.card .item-heading{font-size:14px}.posts-item.card .item-heading{min-height:2.8em}.posts-item.card .item-tags{min-height:23px}.posts-item.card .item-thumbnail{width:100%;padding-bottom:var(--posts-card-scale, 70%)}.posts-item.card.style2{background:transparent;box-shadow:none}.posts-item.card.style2:hover{background:var(--main-bg-color, #fff);box-shadow:0 0 10px var(--main-shadow, rgba(116, 116, 116, .08))}.posts-item.card.style3{padding:0}.posts-item.card.style3 .item-thumbnail,.posts-item.card.style3 .item-thumbnail img{border-radius:var(--main-radius, 8px) var(--main-radius, 8px) 0 0}.posts-item.card.style3 .item-body{margin:0;padding:10px}.posts-item.mult-thumb .thumb-items{margin:0 -3px 6px}.posts-item.mult-thumb .thumb-items>span{position:relative;display:inline-block;width:calc(25% - 6px);height:0;margin:0 3px;padding-bottom:calc(var(--posts-list-scale, 70%) / 4)}.posts-item.mult-thumb .thumb-items>span>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.posts-item.mult-thumb .thumb-items.contain>span{overflow:hidden;background:var(--main-border-color, rgba(50, 50, 50, .06));border-radius:var(--main-radius, 8px)}.posts-item.mult-thumb .thumb-items.contaiLine truncated
|
||||
.posts-row{margin-right:-8px;margin-bottom:15px;margin-left:-8px}.posts-row>*:not(.post_ajax_loader){margin-right:8px!important;margin-left:8px!important}.posts-row>.post_ajax_loader .posts-item,.posts-row>.post_ajax_loader .posts-mini{margin-right:8px;margin-left:8px}.posts-item{margin:15px 0;padding:20px;overflow:hidden;background:var(--main-bg-color, #fff);border-radius:var(--main-radius, 8px);box-shadow:0 0 10px var(--main-shadow, rgba(116, 116, 116, .08));transition:.2s}.posts-item.flex,.posts-item .flex,.posts-mini .flex{display:flex}.posts-item .flex.xx,.posts-mini .flex.xx{flex-direction:column}.posts-item .flex.ac,.posts-mini .flex.ac{align-items:center}.posts-item .flex.jsb,.posts-mini .flex.jsb{justify-content:space-between}.posts-item .flex1,.posts-mini .flex1{flex:1;overflow:hidden}.posts-item .post-graphic:not(.order1){margin-right:20px}.posts-item .order1.post-graphic{margin-right:0;margin-left:20px}.posts-item .item-thumbnail{position:relative;display:block;width:190px;height:0;padding-bottom:var(--posts-list-scale, 70%);overflow:hidden;border-radius:var(--main-radius, 8px)}.item-thumbnail.contain img{object-fit:contain}.swiper-slide.gradient-bg .dplayer-poster img,.swiper-slide.gradient-bg>*>img{object-fit:contain!important;border-radius:0!important}.item-thumbnail .swiper-wrapper{height:100%!important}.list .item-thumbnail .aksrt-slider,.list .item-thumbnail.new-swiper{position:absolute;width:100%;height:100%;margin:0!important}.item-thumbnail .dplayer.dplayer-thumb{position:absolute;inset:0;z-index:1;padding-bottom:var(--posts-list-scale, 70%);background:#000;opacity:0;transition:opacity .3s}.card .item-thumbnail .dplayer.dplayer-thumb{padding-bottom:var(--posts-card-scale, 70%)}.item-thumbnail .dplayer-thumb video,.item-thumbnail .swiper-wrapper,.item-thumbnail img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.item-thumbnail .swiper-pagination{right:0!important;bottom:0!important;left:0!important;padding:0 2px!important;text-align:center!important}.posts-item.thumb-dplayer-playing .dplayer-thumb{opacity:1}.posts-item.thumb-dplayer-playing .abs-center{opacity:0}.posts-item .item-heading{display:-webkit-box;max-height:2.8em;margin-top:0;margin-bottom:5px;overflow:hidden;font-size:18px;line-height:1.4em;white-space:normal;-webkit-box-orient:vertical;-webkit-line-clamp:2}.font-bold{font-weight:700}.list.style2 .item-thumbnail{width:130px}.list.style2 .item-heading{display:unset;max-height:1.4em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.posts-item .item-heading>a{color:var(--key-color, #333)}.posts-item .item-heading>a:hover{color:var(--focus-color, #f04494)}.posts-item .item-excerpt{margin:0 0 6px;overflow:hidden;color:var(--muted-color, #777);text-overflow:ellipsis;white-space:nowrap}.posts-item .item-meta item{margin-right:8px;font-size:13px}.posts-item .item-meta svg.icon,.posts-mini .item-meta svg.icon{display:inline-block;width:1em;height:1em;margin-right:2px;fill:currentColor;overflow:hidden;vertical-align:-.15em}.posts-item .meta-right item:last-child{margin-right:0}.item-meta .avatar-mini{width:20px;height:20px;border-radius:50%;transform:translateY(-1px)}.item-meta .meta-pay{padding:0 4px}.posts-item .item-meta a,.posts-mini .item-meta a{color:inherit}.posts-item .item-tags a{margin-right:5px;padding:2px 5px;font-size:11px}.posts-item .item-tags a .fa{font-size:1em}.posts-item.card{display:inline-block;width:calc(33.333% - 16px);margin:8px;padding:10px;vertical-align:top;transition:.3s}.posts-item.card:last-child{margin-bottom:20px}.posts-item.card .item-body{width:100%;margin:10px 0 0;padding:0}.posts-item.card .item-meta item{font-size:12px}.posts-mini-con .item-heading,.posts-item.card .item-heading{font-size:14px}.posts-item.card .item-heading{min-height:2.8em}.posts-item.card .item-tags{min-height:23px}.posts-item.card .item-thumbnail{width:100%;padding-bottom:var(--posts-card-scale, 70%)}.posts-item.card.style2{background:transparent;box-shadow:none}.posts-item.card.style2:hover{background:var(--main-bg-color, #fff);box-shadow:0 0 10px var(--main-shadow, rgba(116, 116, 116, .08))}.posts-item.card.style3{padding:0}.posts-item.card.style3 .item-thumbnail,.posts-item.card.style3 .item-thumbnail img{border-radius:var(--main-radius, 8px) var(--main-radius, 8px) 0 0}.posts-item.card.style3 .item-body{margin:0;padding:10px}.posts-item.mult-thumb .thumb-items{margin:0 -3px 6px}.posts-item.mult-thumb .thumb-items>span{position:relative;display:inline-block;width:calc(25% - 6px);height:0;margin:0 3px;padding-bottom:calc(var(--posts-list-scale, 70%) / 4)}.posts-item.mult-thumb .thumb-items>span>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.posts-item.mult-thumb .thumb-items.contain>span{overflow:hidden;background:var(--main-border-color, rgba(50, 50, 50, .06));border-radius:var(--main-radius, 8px)}.posts-item.mult-thumb .thumb-items.contain>span>img{object-fit:contain;border-radius:0}.posts-item.no_margin{margin:0;border-radLine truncated
|
||||
@@ -219,13 +219,6 @@
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.item-meta .meta-pay img {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
object-fit: contain;
|
||||
vertical-align: -0.15em;
|
||||
}
|
||||
|
||||
.posts-item .item-meta a,
|
||||
.posts-mini .item-meta a {
|
||||
color: inherit;
|
||||
|
||||
@@ -164,6 +164,7 @@
|
||||
.widget-tab-post .item-heading.font-bold { font-weight:700; }
|
||||
.widget-tab-post .posts-mini { vertical-align:baseline; }
|
||||
.widget-tab-post .posts-mini-con { flex:auto; }
|
||||
.widget-tab-post .item-meta .meta-pay { padding:0 4px; cursor:auto; }
|
||||
.widget-tab-post .post_ajax_loader { min-height: 40px; }
|
||||
/* Keep the reference's compact pagination after public pagination.css. */
|
||||
.widget-tab-post .pagenav {
|
||||
|
||||
@@ -97,6 +97,7 @@ if (!function_exists('aksrt_renderer_collect_post_data')) {
|
||||
'post_type' => (string) get_post_type($post_id),
|
||||
'is_sticky' => is_sticky($post_id),
|
||||
'resource_badge' => (string) aksrt_resource_card_badge_text($post_id),
|
||||
'pay_meta' => $pay_meta,
|
||||
'pay_type' => sanitize_key((string) ($pay_meta['pay_type'] ?? 'no')),
|
||||
'pay_limit' => (int) ($pay_meta['pay_limit'] ?? 0),
|
||||
];
|
||||
@@ -175,6 +176,9 @@ if (!function_exists('aksrt_renderer_mult_thumb')) {
|
||||
|
||||
if (!function_exists('aksrt_renderer_pay_badge')) {
|
||||
function aksrt_renderer_pay_badge(array $data, bool $compact = false): string {
|
||||
if ($compact) {
|
||||
return aksrt_renderer_compact_pay_badge((array) ($data['pay_meta'] ?? []));
|
||||
}
|
||||
if ((string) $data['resource_badge'] === '') {
|
||||
return '';
|
||||
}
|
||||
@@ -184,24 +188,58 @@ if (!function_exists('aksrt_renderer_pay_badge')) {
|
||||
$type_labels = function_exists('aksrt_get_pay_types') ? aksrt_get_pay_types() : [];
|
||||
$title = (string) ($type_labels[(string) ($data['pay_type'] ?? '')] ?? __('付费内容', 'aksrt'));
|
||||
$icon = $is_vip ? aksrt_renderer_vip_icon($vip_level) : '';
|
||||
if ($compact) {
|
||||
return '<item class="meta-pay badg badg-sm mr6 ' . esc_attr($class) . '" data-toggle="tooltip" title="' . esc_attr($title) . '">' . $icon . esc_html((string) $data['resource_badge']) . '</item>';
|
||||
}
|
||||
$tooltip = $is_vip ? ' data-toggle="tooltip" title="' . esc_attr($title) . '"' : '';
|
||||
return '<a rel="nofollow" href="' . esc_url((string) $data['permalink']) . '#posts-pay"' . $tooltip . ' class="meta-pay but ' . esc_attr($is_vip ? $class : 'jb-yellow') . '">' . $icon . esc_html((string) $data['resource_badge']) . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_compact_pay_badge')) {
|
||||
/** Compact article meta uses the published price and a type icon, not the large tag's text. */
|
||||
function aksrt_renderer_compact_pay_badge(array $meta): string {
|
||||
$types = [
|
||||
'reading' => [__('付费阅读', 'aksrt'), 'fa fas fa-book'],
|
||||
'download' => [__('付费资源', 'aksrt'), 'fa fas fa-download'],
|
||||
'gallery' => [__('付费图片', 'aksrt'), 'fa far fa-file-image'],
|
||||
'video' => [__('付费视频', 'aksrt'), 'fa fas fa-play-circle'],
|
||||
];
|
||||
$type = (string) ($meta['pay_type'] ?? 'no');
|
||||
if (!isset($types[$type])) {
|
||||
return '';
|
||||
}
|
||||
[$title, $type_icon] = $types[$type];
|
||||
$points = ($meta['pay_modo'] ?? '0') === 'points';
|
||||
$price = $points ? (string) max(0, (int) ($meta['points_price'] ?? 0)) : aksrt_format_price((string) ($meta['price'] ?? '0.00'));
|
||||
$icon = aksrt_icon_markup($type_icon, 'mr3');
|
||||
$class = 'c-yellow';
|
||||
if ($price === '0') {
|
||||
$title = str_replace(__('付费', 'aksrt'), __('免费', 'aksrt'), $title);
|
||||
$label = esc_html__('免费', 'aksrt');
|
||||
} else {
|
||||
$level = max(0, min(2, (int) ($meta['pay_limit'] ?? 0)));
|
||||
$vip = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
||||
if ($level > 0 && !empty($vip['enabled'])) {
|
||||
$class = 'jb-vip' . $level;
|
||||
$icon = aksrt_renderer_vip_icon($level);
|
||||
$label = esc_html__('会员专属', 'aksrt');
|
||||
} else {
|
||||
$display = \AKSRT\Settings\Settings::get_paid_content_settings()['display'];
|
||||
$mark = $points ? aksrt_icon_markup('zibsvg-points', 'points-mark') : esc_html((string) ($display['currency_symbol'] ?? '¥'));
|
||||
$label = '<span class="em09">' . $mark . '</span>' . esc_html($price);
|
||||
}
|
||||
}
|
||||
return '<item class="meta-pay badg badg-sm mr6 ' . esc_attr($class) . '" data-toggle="tooltip" title="' . esc_attr($title) . '">' . $icon . $label . '</item>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_vip_icon')) {
|
||||
function aksrt_renderer_vip_icon(int $level): string {
|
||||
if (!class_exists('\AKSRT\Settings\Settings')) {
|
||||
return '<i class="fa fas fa-certificate mr3" aria-hidden="true"></i>';
|
||||
}
|
||||
$settings = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
||||
$url = esc_url((string) ($settings['levels'][$level]['img_icon'] ?? ''));
|
||||
return $url !== ''
|
||||
? '<img class="mr3" src="' . $url . '" alt="" aria-hidden="true">'
|
||||
: '<i class="fa fas fa-certificate mr3" aria-hidden="true"></i>';
|
||||
$url = (string) ($settings['levels'][$level]['img_icon'] ?? '');
|
||||
if ($url === '') {
|
||||
$url = get_template_directory_uri() . '/assets/img/user/vip/vip-' . $level . '.svg';
|
||||
}
|
||||
$name = (string) ($settings['levels'][$level]['name'] ?? 'VIP');
|
||||
return '<img' . aksrt_get_lazy_attr('lazy_other', $url, 'img-icon mr3') . ' data-toggle="tooltip" title="' . esc_attr($name) . '" alt="' . esc_attr($name) . '">';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,4 +30,16 @@
|
||||
- `tab-posts-style-contract.test.cjs` 检查覆盖公共排版/分页样式所需的局部选择器及桌面、移动端样式契约。
|
||||
- 验证范围为源码、渲染输出、脚本行为和构建检查;不将这些检查描述为像素级视觉验收。
|
||||
|
||||
结果:仓库全部 Node 测试 785/785 通过(包含本次新增 24 项);小工具 PHP 测试 139 条断言通过;修改的 7 个 PHP 文件语法检查、前端 JS 语法检查、CSS 解析、后台 SPA 构建及差异空白检查通过。
|
||||
上一轮结果:仓库全部 Node 测试 785/785 通过(包含本次新增 24 项);小工具 PHP 测试 139 条断言通过;修改的 7 个 PHP 文件语法检查、前端 JS 语法检查、CSS 解析、后台 SPA 构建及差异空白检查通过。
|
||||
|
||||
## mini 付费标签补充复核
|
||||
|
||||
对照 `zib_get_posts_list_pay_badge()`、`zibpay_get_pay_type_icon()`、`zibpay_get_points_mark()`、`zibpay_get_vip_icon()` 及对应 CSS,修正以下差异:
|
||||
|
||||
- compact 标签直接从标准付费元数据读取公开价格,独立渲染类型图标、`em09` 货币/积分符号和金额;不复用大列表的整段价格文案或当前用户折扣价。
|
||||
- 免费内容先于购买等级限制判断,显示类型图标与“免费”,提示文字使用对应免费类型;会员专属只在会员功能启用时使用相应等级的 VIP 标签。
|
||||
- VIP 图片恢复 `img-icon mr3`、通用图片懒加载及会员名称提示,删除证书字形替代与强制 1em 正方形图片规则,保持图文同行和图片原有比例。
|
||||
- 在小工具样式中固定付费标签的 4px 水平内边距,消除公共按钮样式在不同页面覆盖造成的差别;非链接标签恢复普通光标。
|
||||
- `mini-pay-badge-reference.test.cjs` 检查真实 mini 渲染输出的四种付费类型、现金、积分、免费、两级 VIP、会员开关、标签位置和样式规则。
|
||||
|
||||
补充验证结果:新增 6 项付费标签测试通过,仓库全部 Node 测试 791/791 通过;139 条 PHP 断言、修改文件的 PHP 语法检查、CSS 解析、公共资源构建、后台 SPA 构建和差异空白检查通过。未进行真实视觉效果验收。
|
||||
@@ -0,0 +1,95 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const { execFileSync } = require('node:child_process');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const root = path.resolve(__dirname, '../..');
|
||||
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
|
||||
const cases = JSON.parse(execFileSync('php', [path.join(__dirname, 'tab-posts-render-harness.php')], { encoding: 'utf8' })).cases;
|
||||
|
||||
function row(html, id) {
|
||||
const result = html.split('<div class="posts-mini ajax-item">').slice(1)
|
||||
.find((item) => item.includes(`href="https://example.test/post/${id}"`));
|
||||
assert.ok(result, `the actual mini renderer emitted post ${id}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
function badge(html, id) {
|
||||
const result = row(html, id).match(/<item class="meta-pay\b[\s\S]*?<\/item>/g) || [];
|
||||
assert.equal(result.length, 1, 'each article has exactly one compact paid badge');
|
||||
return result[0];
|
||||
}
|
||||
|
||||
test('cash mini badges show type icons, a smaller currency mark and the published amount', () => {
|
||||
const expected = [
|
||||
[70, 'fa fas fa-book', '付费阅读', '12.5'],
|
||||
[69, 'fa fas fa-download', '付费资源', '12'],
|
||||
[68, 'fa far fa-file-image', '付费图片', '8.6'],
|
||||
[67, 'fa fas fa-play-circle', '付费视频', '5'],
|
||||
];
|
||||
for (const [id, icon, title, amount] of expected) {
|
||||
assert.equal(badge(cases.pay_meta_right, id),
|
||||
`<item class="meta-pay badg badg-sm mr6 c-yellow" data-toggle="tooltip" title="${title}"><i class="${icon} mr3" aria-hidden="true"></i><span class="em09">¥</span>${amount}</item>`);
|
||||
}
|
||||
assert.doesNotMatch(cases.pay_meta_right, /旧版资源标签/);
|
||||
assert.match(badge(cases.pay_meta_custom_currency, 70), /<span class="em09">€<\/span>12\.5<\/item>/);
|
||||
assert.match(badge(cases.pay_meta_right, 55), /<span class="em09">¥<\/span>0\.5<\/item>/);
|
||||
});
|
||||
|
||||
test('points mini badges use the existing SVG mark inside em09 without the long currency name', () => {
|
||||
for (const [id, amount] of [[62, 125], [61, 60], [60, 500], [59, 12]]) {
|
||||
const html = badge(cases.pay_meta_right, id);
|
||||
assert.ok(html.includes(`<span class="em09"><svg class="points-mark" aria-hidden="true"><use xlink:href="#icon-points"></use></svg></span>${amount}</item>`));
|
||||
assert.doesNotMatch(html, /积分|¥|€|class="icon"/);
|
||||
}
|
||||
});
|
||||
|
||||
test('zero prices render the short free badge and take priority over VIP purchase limits', () => {
|
||||
for (const [id, title] of [[66, '免费阅读'], [65, '免费资源'], [64, '免费图片'], [63, '免费视频']]) {
|
||||
const html = badge(cases.pay_meta_right, id);
|
||||
assert.ok(html.includes(`title="${title}"`));
|
||||
assert.match(html, /<\/i>免费<\/item>$/);
|
||||
assert.doesNotMatch(html, /会员专属|jb-vip|em09|免费资源<\/item>/);
|
||||
}
|
||||
});
|
||||
|
||||
test('VIP badges use the selected level image inline and keep the reference membership-switch rule', () => {
|
||||
for (const html of [cases.pay_meta_right, cases.pay_vip1_only, cases.pay_vip2_only]) {
|
||||
for (const [id, level, name] of [[58, 1, '黄金会员'], [57, 2, '钻石会员']]) {
|
||||
const current = badge(html, id);
|
||||
assert.ok(current.includes(`mr6 jb-vip${level}"`));
|
||||
assert.ok(current.includes(`<img class="img-icon mr3" src="https://example.test/vip-${level}.svg" data-toggle="tooltip" title="${name}" alt="${name}">会员专属`));
|
||||
assert.doesNotMatch(current, /fa-certificate|class="em09"/);
|
||||
}
|
||||
}
|
||||
for (const id of [58, 57]) {
|
||||
const html = badge(cases.pay_vip_disabled, id);
|
||||
assert.match(html, /mr6 c-yellow/);
|
||||
assert.match(html, /<span class="em09">¥<\/span>12\.5/);
|
||||
assert.doesNotMatch(html, /会员专属|img-icon|jb-vip/);
|
||||
}
|
||||
});
|
||||
|
||||
test('mini badges stay on the correct meta side, disappear with meta and ignore non-paid posts', () => {
|
||||
const right = row(cases.pay_meta_right, 70);
|
||||
const left = row(cases.pay_meta_left, 70);
|
||||
assert.ok(right.indexOf('class="meta-right"') < right.indexOf('class="meta-pay '));
|
||||
assert.ok(left.indexOf('class="meta-pay ') < left.indexOf('class="meta-right"'));
|
||||
badge(cases.pay_meta_right, 70);
|
||||
badge(cases.pay_meta_left, 70);
|
||||
assert.doesNotMatch(cases.pay_meta_hidden, /meta-pay|item-meta/);
|
||||
assert.doesNotMatch(row(cases.pay_meta_right, 51), /meta-pay/);
|
||||
assert.equal(cases.pay_empty, '');
|
||||
});
|
||||
|
||||
test('mini badge styles preserve reference padding and VIP aspect ratio across page bundles', () => {
|
||||
const widgetCss = read('assets/widgets/frontend.css');
|
||||
const rule = widgetCss.match(/\.widget-tab-post \.item-meta \.meta-pay\s*\{([^}]+)\}/)[1];
|
||||
assert.match(rule, /padding:\s*0 4px/);
|
||||
assert.match(rule, /cursor:\s*auto/);
|
||||
for (const file of ['assets/css/frontend/post-card.css', 'assets/css/build/homepage.css']) {
|
||||
assert.doesNotMatch(read(file), /\.item-meta \.meta-pay img\s*\{/);
|
||||
}
|
||||
assert.match(read('assets/css/main.css'), /\.img-icon\s*\{[^}]*height:\s*1\.1em;[^}]*display:\s*inline-block/s);
|
||||
});
|
||||
@@ -63,18 +63,30 @@ namespace AKSRT\Settings {
|
||||
public static function get_post_thumb_settings(): array { return ['thumb_catimg_s' => false]; }
|
||||
public static function get_post_page_settings(): array { return ['like_enabled' => true]; }
|
||||
public static function get_comment_display_settings(): array { return ['close_comments' => false]; }
|
||||
public static function get_paid_content_settings(): array { return $GLOBALS['tab_fixture_paid_settings'] ?? ['display' => ['currency_symbol' => '¥']]; }
|
||||
public static function get_payment_vip_settings(): array { return $GLOBALS['tab_fixture_vip_settings'] ?? ['levels' => []]; }
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
$GLOBALS['tab_fixture_posts'] = [];
|
||||
foreach (range(1, 48) as $id) {
|
||||
$GLOBALS['tab_fixture_posts'][] = ['id' => $id, 'cat' => $id <= 36 ? 7 : 8, 'date' => 1000 + $id, 'modified' => 2000 + $id, 'views' => 49 - $id];
|
||||
foreach (range(1, 70) as $id) {
|
||||
$category = $id <= 36 ? 7 : ($id <= 48 ? 8 : 9);
|
||||
$GLOBALS['tab_fixture_posts'][] = ['id' => $id, 'cat' => $category, 'date' => 1000 + $id, 'modified' => 2000 + $id, 'views' => 71 - $id];
|
||||
}
|
||||
$GLOBALS['tab_fixture_current_post'] = null;
|
||||
$GLOBALS['tab_fixture_global_style'] = [];
|
||||
$GLOBALS['tab_fixture_mobile'] = false;
|
||||
$GLOBALS['tab_fixture_avatar_calls'] = [];
|
||||
$GLOBALS['tab_fixture_pay_meta'] = [];
|
||||
$GLOBALS['tab_fixture_paid_settings'] = ['display' => ['currency_symbol' => '¥']];
|
||||
$GLOBALS['tab_fixture_vip_settings'] = [
|
||||
'enabled' => true,
|
||||
'levels' => [
|
||||
1 => ['enabled' => true, 'name' => '黄金会员', 'img_icon' => 'https://example.test/vip-1.svg'],
|
||||
2 => ['enabled' => true, 'name' => '钻石会员', 'img_icon' => 'https://example.test/vip-2.svg'],
|
||||
],
|
||||
];
|
||||
|
||||
function __($text, $domain = null): string { return (string) $text; }
|
||||
function esc_html__($text, $domain = null): string { return esc_html((string) $text); }
|
||||
@@ -137,14 +149,21 @@ namespace {
|
||||
function get_comments_link(int $id = 0): string { return 'https://example.test/post/' . $id . '#comments'; }
|
||||
function get_post_type(int $id = 0): string { unset($id); return 'post'; }
|
||||
function is_sticky(int $id = 0): bool { unset($id); return false; }
|
||||
function aksrt_resource_card_badge_text(int $id): string { unset($id); return ''; }
|
||||
function aksrt_get_pay_meta($post = null): array { unset($post); return ['pay_type' => 'no']; }
|
||||
function aksrt_resource_card_badge_text(int $id): string { return isset($GLOBALS['tab_fixture_pay_meta'][$id]) ? '旧版资源标签' : ''; }
|
||||
function aksrt_get_pay_meta($post = null): array {
|
||||
$post_id = $post instanceof WP_Post ? $post->ID : (int) $post;
|
||||
return $GLOBALS['tab_fixture_pay_meta'][$post_id] ?? ['pay_type' => 'no'];
|
||||
}
|
||||
function aksrt_get_pay_types(): array { return ['reading' => '付费阅读', 'download' => '付费下载', 'gallery' => '付费图片', 'video' => '付费视频']; }
|
||||
function aksrt_format_price($price): string {
|
||||
$value = number_format((float) $price, 2, '.', '');
|
||||
return rtrim(rtrim($value, '0'), '.') ?: '0';
|
||||
}
|
||||
function aksrt_get_post_views(int $id): int { return $id * 10; }
|
||||
function aksrt_get_post_likes(int $id): int { return $id * 2; }
|
||||
function aksrt_format_number(int $number): string { return (string) $number; }
|
||||
function aksrt_get_lazy_thumb(string $size = ''): string { unset($size); return 'https://example.test/placeholder.jpg'; }
|
||||
function aksrt_get_lazy_attr(string $key, string $url, string $class = '', string $lazy = ''): string { unset($key, $lazy); return ' class="' . esc_attr($class) . '" src="' . esc_url($url) . '"'; }
|
||||
function aksrt_icon_markup(string $key): string { return '<svg class="' . esc_attr($key) . '"></svg>'; }
|
||||
function wp_reset_postdata(): void { $GLOBALS['tab_fixture_current_post'] = null; $GLOBALS['post'] = null; }
|
||||
function aksrt_widget_ajax_null(string $message = ''): string { return '<div class="aksrt-widget__empty">' . esc_html($message) . '</div>'; }
|
||||
function aksrt_render_placeholder(string $style, int $count): string { return '<div data-placeholder="' . esc_attr($style) . ':' . $count . '"></div>'; }
|
||||
@@ -159,11 +178,34 @@ namespace {
|
||||
function wp_json_encode($value): string { return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR); }
|
||||
|
||||
require dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
require dirname(__DIR__, 2) . '/inc/helpers/aksrt-icons.php';
|
||||
require dirname(__DIR__, 2) . '/inc/helpers/posts-renderer/config.php';
|
||||
require dirname(__DIR__, 2) . '/inc/helpers/posts-renderer/post-data.php';
|
||||
require dirname(__DIR__, 2) . '/inc/helpers/posts-renderer/markup.php';
|
||||
|
||||
$GLOBALS['tab_fixture_global_style'] = ['list_type' => 'card', 'list_show_type' => 'no_margin', 'list_list_option' => ['style' => 'style2'], 'list_card_option' => ['style' => 'style3'], 'list_orderby' => 'date', 'post_time_source' => 'modified', 'post_list_author' => true, 'post_list_time' => true];
|
||||
$GLOBALS['tab_fixture_pay_meta'] = [
|
||||
70 => ['pay_type' => 'reading', 'pay_modo' => '0', 'price' => '12.50', 'points_price' => 0, 'pay_limit' => 0],
|
||||
69 => ['pay_type' => 'download', 'pay_modo' => '0', 'price' => '12.00', 'points_price' => 0, 'pay_limit' => 0],
|
||||
68 => ['pay_type' => 'gallery', 'pay_modo' => '0', 'price' => '8.60', 'points_price' => 0, 'pay_limit' => 0],
|
||||
67 => ['pay_type' => 'video', 'pay_modo' => '0', 'price' => '5.00', 'points_price' => 0, 'pay_limit' => 0],
|
||||
66 => ['pay_type' => 'reading', 'pay_modo' => '0', 'price' => '0.00', 'points_price' => 0, 'pay_limit' => 0],
|
||||
65 => ['pay_type' => 'download', 'pay_modo' => '0', 'price' => '0.00', 'points_price' => 0, 'pay_limit' => 0],
|
||||
64 => ['pay_type' => 'gallery', 'pay_modo' => 'points', 'price' => '0.00', 'points_price' => 0, 'pay_limit' => 0],
|
||||
63 => ['pay_type' => 'video', 'pay_modo' => '0', 'price' => '0.00', 'points_price' => 0, 'pay_limit' => 1],
|
||||
62 => ['pay_type' => 'reading', 'pay_modo' => 'points', 'price' => '0.00', 'points_price' => 125, 'pay_limit' => 0],
|
||||
61 => ['pay_type' => 'download', 'pay_modo' => 'points', 'price' => '0.00', 'points_price' => 60, 'pay_limit' => 0],
|
||||
60 => ['pay_type' => 'gallery', 'pay_modo' => 'points', 'price' => '0.00', 'points_price' => 500, 'pay_limit' => 0],
|
||||
59 => ['pay_type' => 'video', 'pay_modo' => 'points', 'price' => '0.00', 'points_price' => 12, 'pay_limit' => 0],
|
||||
58 => ['pay_type' => 'reading', 'pay_modo' => '0', 'price' => '12.50', 'points_price' => 0, 'pay_limit' => 1],
|
||||
57 => ['pay_type' => 'download', 'pay_modo' => '0', 'price' => '12.50', 'points_price' => 0, 'pay_limit' => 2],
|
||||
56 => ['pay_type' => 'gallery', 'pay_modo' => '0', 'price' => '8.75', 'points_price' => 0, 'pay_limit' => 1],
|
||||
55 => ['pay_type' => 'reading', 'pay_modo' => '0', 'price' => '0.50', 'points_price' => 0, 'pay_limit' => 0],
|
||||
54 => ['pay_type' => 'download', 'pay_modo' => '0', 'price' => '0.50', 'points_price' => 0, 'pay_limit' => 0],
|
||||
53 => ['pay_type' => 'gallery', 'pay_modo' => '0', 'price' => '0.50', 'points_price' => 0, 'pay_limit' => 0],
|
||||
52 => ['pay_type' => 'video', 'pay_modo' => '0', 'price' => '0.50', 'points_price' => 0, 'pay_limit' => 0],
|
||||
51 => ['pay_type' => 'no', 'pay_modo' => '0', 'price' => '0.00', 'points_price' => 0, 'pay_limit' => 0],
|
||||
];
|
||||
$tabs = [
|
||||
['title' => '热门', 'cat' => '7', 'orderby' => 'date'],
|
||||
['title' => '', 'cat' => '7'],
|
||||
@@ -246,5 +288,49 @@ namespace {
|
||||
ob_start();
|
||||
\AKSRT\WidgetSystem\FrontendRenderer::render($definition, ['before_widget' => '<aside>', 'after_widget' => '</aside>'], $wrapper_instance, $widget);
|
||||
$cases['frontend_wrapper'] = (string) ob_get_clean();
|
||||
$paid_instance = \AKSRT\WidgetSystem\FieldSchema::normalize(\AKSRT\WidgetSystem\WidgetSchemas::for('tab_posts'), [
|
||||
'style' => 'mini', 'mini_opt' => ['show_meta'], 'count' => 20, 'paginate' => '',
|
||||
'tabs' => [['title' => '付费徽标用例', 'cat' => '9']],
|
||||
]);
|
||||
$cases['pay_meta_right'] = \AKSRT\WidgetSystem\PostRenderer::payload($paid_instance, 'tab_posts', 1, '0')['html'];
|
||||
$paid_instance['mini_opt'] = [];
|
||||
$cases['pay_meta_hidden'] = \AKSRT\WidgetSystem\PostRenderer::payload($paid_instance, 'tab_posts', 1, '0')['html'];
|
||||
$paid_instance['mini_opt'] = ['show_meta'];
|
||||
|
||||
$GLOBALS['tab_fixture_global_style']['post_list_author'] = false;
|
||||
$GLOBALS['tab_fixture_global_style']['post_list_time'] = false;
|
||||
$cases['pay_meta_left'] = \AKSRT\WidgetSystem\PostRenderer::payload($paid_instance, 'tab_posts', 1, '0')['html'];
|
||||
$GLOBALS['tab_fixture_global_style']['post_list_author'] = true;
|
||||
$GLOBALS['tab_fixture_global_style']['post_list_time'] = true;
|
||||
|
||||
$GLOBALS['tab_fixture_paid_settings']['display']['currency_symbol'] = '€';
|
||||
$cases['pay_meta_custom_currency'] = \AKSRT\WidgetSystem\PostRenderer::payload($paid_instance, 'tab_posts', 1, '0')['html'];
|
||||
$GLOBALS['tab_fixture_paid_settings']['display']['currency_symbol'] = '¥';
|
||||
|
||||
$GLOBALS['tab_fixture_vip_settings'] = [
|
||||
'enabled' => true,
|
||||
'levels' => [
|
||||
1 => ['enabled' => true, 'name' => '黄金会员', 'img_icon' => 'https://example.test/vip-1.svg'],
|
||||
2 => ['enabled' => false, 'name' => '钻石会员', 'img_icon' => 'https://example.test/vip-2.svg'],
|
||||
],
|
||||
];
|
||||
$cases['pay_vip1_only'] = \AKSRT\WidgetSystem\PostRenderer::payload($paid_instance, 'tab_posts', 1, '0')['html'];
|
||||
$GLOBALS['tab_fixture_vip_settings'] = [
|
||||
'enabled' => true,
|
||||
'levels' => [
|
||||
1 => ['enabled' => false, 'name' => '黄金会员', 'img_icon' => 'https://example.test/vip-1.svg'],
|
||||
2 => ['enabled' => true, 'name' => '钻石会员', 'img_icon' => 'https://example.test/vip-2.svg'],
|
||||
],
|
||||
];
|
||||
$cases['pay_vip2_only'] = \AKSRT\WidgetSystem\PostRenderer::payload($paid_instance, 'tab_posts', 1, '0')['html'];
|
||||
$GLOBALS['tab_fixture_vip_settings'] = [
|
||||
'enabled' => false,
|
||||
'levels' => [
|
||||
1 => ['enabled' => false, 'name' => '黄金会员', 'img_icon' => 'https://example.test/vip-1.svg'],
|
||||
2 => ['enabled' => false, 'name' => '钻石会员', 'img_icon' => 'https://example.test/vip-2.svg'],
|
||||
],
|
||||
];
|
||||
$cases['pay_vip_disabled'] = \AKSRT\WidgetSystem\PostRenderer::payload($paid_instance, 'tab_posts', 1, '0')['html'];
|
||||
$cases['pay_empty'] = aksrt_renderer_compact_pay_badge([]);
|
||||
echo json_encode(['cases' => $cases], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
|
||||
}
|
||||
Reference in new issue
Block a user