feat(vip): add default icons and remove download speed
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,11 +21,8 @@ export const vipSchema = {
|
||||
pay_user_vip_desc: '',
|
||||
pay_user_vip_more: '',
|
||||
pay_download_limit: 0,
|
||||
pay_download_speed: 0,
|
||||
pay_download_limit_vip_1: 0,
|
||||
pay_download_speed_vip_1: 0,
|
||||
pay_download_limit_vip_2: 0,
|
||||
pay_download_speed_vip_2: 0,
|
||||
pay_vip_pass_charge_s: false,
|
||||
pay_vip_pass_charge_desc: '',
|
||||
pay_vip_pass_charge_only_password: true,
|
||||
@@ -51,12 +48,12 @@ export const vipSchema = {
|
||||
{ key: 'pay_user_vip_1_name', label: '一级会员名称', type: 'input', default: '一级会员', dependsOn: { key: 'pay_user_vip_1_s', value: true } },
|
||||
{ key: 'pay_user_vip_1_desc', label: '一级会员一句话简介', type: 'input', default: '尊享一级会员特权', dependsOn: { key: 'pay_user_vip_1_s', value: true } },
|
||||
{ key: 'pay_user_vip_1_equity', label: '一级会员权益 HTML', type: 'textarea', default: '<li>免费下载部分资源</li><li>会员专属身份标识</li><li>付费内容会员价</li>', dependsOn: { key: 'pay_user_vip_1_s', value: true }, help: '建议使用 <li> 列表项' },
|
||||
{ key: 'vip_1_img_icon', label: '一级会员图标 URL', type: 'input', default: '', dependsOn: { key: 'pay_user_vip_1_s', value: true } },
|
||||
{ key: 'vip_1_img_icon', label: '一级会员图标 URL', type: 'input', default: '', dependsOn: { key: 'pay_user_vip_1_s', value: true }, help: '留空使用内置 vip-1.svg 图标' },
|
||||
{ key: 'pay_user_vip_2_s', label: '启用二级会员', type: 'switch', default: true },
|
||||
{ key: 'pay_user_vip_2_name', label: '二级会员名称', type: 'input', default: '二级会员', dependsOn: { key: 'pay_user_vip_2_s', value: true } },
|
||||
{ key: 'pay_user_vip_2_desc', label: '二级会员一句话简介', type: 'input', default: '尊享二级会员特权', dependsOn: { key: 'pay_user_vip_2_s', value: true } },
|
||||
{ key: 'pay_user_vip_2_equity', label: '二级会员权益 HTML', type: 'textarea', default: '<li>更高免费下载额度</li><li>更高等级身份标识</li><li>更多付费内容会员价</li>', dependsOn: { key: 'pay_user_vip_2_s', value: true } },
|
||||
{ key: 'vip_2_img_icon', label: '二级会员图标 URL', type: 'input', default: '', dependsOn: { key: 'pay_user_vip_2_s', value: true } },
|
||||
{ key: 'vip_2_img_icon', label: '二级会员图标 URL', type: 'input', default: '', dependsOn: { key: 'pay_user_vip_2_s', value: true }, help: '留空使用内置 vip-2.svg 图标' },
|
||||
{ key: 'pay_user_vip_desc', label: '弹窗顶部会员说明', type: 'textarea', default: '' },
|
||||
{ key: 'pay_user_vip_more', label: '弹窗底部补充说明 HTML', type: 'textarea', default: '' },
|
||||
],
|
||||
@@ -109,11 +106,8 @@ export const vipSchema = {
|
||||
icon: 'fas fa-gift',
|
||||
fields: [
|
||||
{ key: 'pay_download_limit', label: '普通用户下载限制', type: 'number', default: 0, min: 0, max: 9999, help: '0为不限制' },
|
||||
{ key: 'pay_download_speed', label: '普通用户下载速度(KB/s)', type: 'number', default: 0, min: 0, max: 99999, help: '0为不限制' },
|
||||
{ key: 'pay_download_limit_vip_1', label: '一级会员下载限制', type: 'number', default: 0, min: 0, max: 9999, dependsOn: { key: 'pay_user_vip_1_s', value: true } },
|
||||
{ key: 'pay_download_speed_vip_1', label: '一级会员下载速度(KB/s)', type: 'number', default: 0, min: 0, max: 99999, dependsOn: { key: 'pay_user_vip_1_s', value: true } },
|
||||
{ key: 'pay_download_limit_vip_2', label: '二级会员下载限制', type: 'number', default: 0, min: 0, max: 9999, dependsOn: { key: 'pay_user_vip_2_s', value: true } },
|
||||
{ key: 'pay_download_speed_vip_2', label: '二级会员下载速度(KB/s)', type: 'number', default: 0, min: 0, max: 99999, dependsOn: { key: 'pay_user_vip_2_s', value: true } },
|
||||
{ key: 'pay_vip_pass_charge_s', label: '会员卡密兑换', type: 'switch', default: false },
|
||||
{ key: 'pay_vip_pass_charge_desc', label: '卡密兑换说明', type: 'textarea', default: '', dependsOn: { key: 'pay_vip_pass_charge_s', value: true } },
|
||||
{ key: 'pay_vip_pass_charge_only_password', label: '仅密码兑换', type: 'switch', default: true, dependsOn: { key: 'pay_vip_pass_charge_s', value: true }, help: '开启后只需输入卡密;关闭则需卡号+卡密。' },
|
||||
|
||||
@@ -361,6 +361,22 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.aksrt-vip-level-icon {
|
||||
display: inline-block;
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.aksrt-vip-badge__icon {
|
||||
display: inline-block;
|
||||
width: 1.1em;
|
||||
height: 1.1em;
|
||||
object-fit: contain;
|
||||
vertical-align: -.15em;
|
||||
}
|
||||
|
||||
.aksrt-vip-badge i {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
@@ -691,6 +691,19 @@ body.uc-modal-open {
|
||||
padding: 22px;
|
||||
color: #fff;
|
||||
}
|
||||
.aksrt-vip-level-icon {
|
||||
display: inline-block;
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.uc-vip-card__icon .aksrt-vip-level-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.uc-vip-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1024" height="1024"><defs><linearGradient id="a"><stop offset="0" stop-color="#fcdba2"/><stop offset="1" stop-color="#fdf6d8"/></linearGradient><linearGradient id="e"><stop offset="0" stop-color="#f8b446"/><stop offset="1" stop-color="#fdf4cf"/></linearGradient><linearGradient xlink:href="#a" id="j" x1="523.292" x2="521.856" y1="345.301" y2="627.851" gradientTransform="translate(8.2904476 3.9483139) scale(.96795)" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#b" id="f" x1="143.09692" x2="898.33069" y1="164.29646" y2="810.88257" gradientTransform="translate(-.00191063 -.00196486) scale(1.0005)" gradientUnits="userSpaceOnUse"/><linearGradient id="b"><stop offset="0" stop-color="#fbe2c9"/><stop offset="1" stop-color="#eea36b"/></linearGradient><linearGradient xlink:href="#c" id="g" x1="1274.6226" x2="1902.6591" y1="-291.49371" y2="204.04561" gradientTransform="translate(-1063.8611 567.31936) scale(1.0005)" gradientUnits="userSpaceOnUse"/><linearGradient id="c"><stop offset="0" stop-color="#e2a576"/><stop offset="1" stop-color="#f9e7d6"/></linearGradient><linearGradient xlink:href="#d" id="h" x1="-285.41812" x2="285.38971" y1="-257.87775" y2="255.19093" gradientTransform="translate(512.02424 518.02725) scale(1.0005)" gradientUnits="userSpaceOnUse"/><linearGradient id="d"><stop offset="0" stop-color="#facda1"/><stop offset="1" stop-color="#e3814e"/></linearGradient><radialGradient xlink:href="#e" id="i" cx="521.652" cy="617.926" r="257.943" fx="521.652" fy="617.926" gradientTransform="matrix(.9934 .00447 -.0041 .91186 -2.4439201 11.161921)" gradientUnits="userSpaceOnUse"/></defs><circle cx="512" cy="512" r="508" fill="url(#f)"/><circle cx="513.64362" cy="515.61957" r="425.46204" fill="url(#g)"/><circle cx="512.02417" cy="518.02716" r="386.19312" fill="url(#h)"/><path fill="url(#i)" d="M260.93578 362.19446v273.13658c0 31.70185 13.987 57.984 47.47974 57.984h404.12609c23.37369 0 47.64683-21.11456 47.74888-58.93648 0-32.14907-.27014-278.28715-.27014-278.28715l-246.59831 255.5878z"/><path fill="url(#j)" d="M517.23194 291.90631 362.70967 569.71123c-37.86393 67.97299 24.27614 70.95448 24.27614 70.95448h241.41372s66.13307 1.85993 33.10956-68.66634z"/><circle cx="516.09039" cy="286.75574" r="39.223614" fill="#fdf9e1"/></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.0 KiB |
@@ -297,6 +297,14 @@
|
||||
var row = node("div", "pay-vip-form-row");
|
||||
var info = node("div", "pay-vip-info level-" + level);
|
||||
var levelInfo = levels[String(level)] || {};
|
||||
if (levelInfo.img_icon) {
|
||||
var levelIcon = node("img", "aksrt-vip-level-icon");
|
||||
levelIcon.src = text(levelInfo.img_icon);
|
||||
levelIcon.alt = "";
|
||||
levelIcon.loading = "lazy";
|
||||
levelIcon.decoding = "async";
|
||||
append(info, levelIcon);
|
||||
}
|
||||
append(info, node("div", "v-name font-bold", group.name || levelInfo.name || "VIP" + level));
|
||||
if (levelInfo.desc) append(info, node("div", "muted-2-color em09 mb6", levelInfo.desc));
|
||||
renderEquity(info, levelInfo.equity);
|
||||
|
||||
+10
-26
@@ -230,31 +230,6 @@ if (!function_exists('aksrt_get_user_free_download_limit')) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download speed cap in KB/s for a user (0 = unlimited).
|
||||
*/
|
||||
if (!function_exists('aksrt_get_user_download_speed')) {
|
||||
function aksrt_get_user_download_speed(int $user_id = 0): int {
|
||||
if ($user_id <= 0) {
|
||||
$user_id = get_current_user_id();
|
||||
}
|
||||
if ($user_id <= 0 || !class_exists('\AKSRT\Settings\Settings')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$vip = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
||||
$level = function_exists('aksrt_get_user_vip_level') ? aksrt_get_user_vip_level($user_id) : 0;
|
||||
$levels = is_array($vip['levels'] ?? null) ? $vip['levels'] : [];
|
||||
$benefit = is_array($vip['benefit'] ?? null) ? $vip['benefit'] : [];
|
||||
|
||||
if ($level >= 1 && !empty($levels[$level]['enabled'])) {
|
||||
return max(0, (int) ($levels[$level]['download_speed'] ?? 0));
|
||||
}
|
||||
|
||||
return max(0, (int) ($benefit['download_speed'] ?? 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count free downloads used today for a user (zibll pay_down_number).
|
||||
*/
|
||||
@@ -383,7 +358,16 @@ function aksrt_render_vip_badge(int $user_id = 0, string $size = 'sm'): string {
|
||||
$size_class = 'aksrt-vip-badge--' . $size;
|
||||
$level_class = $level >= 2 ? 'aksrt-vip-badge--vip2' : 'aksrt-vip-badge--vip1';
|
||||
|
||||
return '<span class="aksrt-vip-badge aksrt-vip-badge--gold ' . esc_attr($size_class . ' ' . $level_class) . '"><i class="fas fa-crown"></i> ' . esc_html($badge_text) . '</span>';
|
||||
$icon_url = '';
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$vip_settings = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
||||
$icon_url = esc_url((string) ($vip_settings['levels'][$level]['img_icon'] ?? ''));
|
||||
}
|
||||
$icon = $icon_url !== ''
|
||||
? '<img class="aksrt-vip-badge__icon" src="' . $icon_url . '" alt="" loading="lazy" decoding="async" />'
|
||||
: '<i class="fas fa-crown" aria-hidden="true"></i>';
|
||||
|
||||
return '<span class="aksrt-vip-badge aksrt-vip-badge--gold ' . esc_attr($size_class . ' ' . $level_class) . '">' . $icon . ' ' . esc_html($badge_text) . '</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,7 +50,10 @@ if ($vip_level >= 1 && !empty($vip_settings['levels'][$vip_level]['name'])) {
|
||||
$level_name = (string) $vip_settings['levels'][$vip_level]['name'];
|
||||
}
|
||||
|
||||
$cash_symbol = '¥';
|
||||
$level_icon_url = esc_url((string) ($vip_settings['levels'][$vip_level]['img_icon'] ?? ''));
|
||||
$level_icon = $level_icon_url !== ''
|
||||
? '<img class="aksrt-vip-level-icon" src="' . $level_icon_url . '" alt="" loading="lazy" decoding="async">'
|
||||
: '<i class="fas fa-crown" aria-hidden="true"></i>';
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$paid_display = \AKSRT\Settings\Settings::get_paid_content_settings();
|
||||
$cash_symbol = (string) ($paid_display['display']['currency_symbol'] ?? '¥');
|
||||
@@ -79,7 +82,7 @@ if (class_exists('\AKSRT\Payment\ChargeCard')) {
|
||||
<div class="uc-vip-card__content">
|
||||
<div class="uc-vip-card__header">
|
||||
<div class="uc-vip-card__icon">
|
||||
<i class="fas fa-crown" aria-hidden="true"></i>
|
||||
<?php echo $level_icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
<div class="uc-vip-card__info">
|
||||
<span class="uc-vip-card__label"><?php echo esc_html($level_name); ?></span>
|
||||
|
||||
@@ -30,7 +30,7 @@ if ($status === '') {
|
||||
|
||||
if ($vip_level > 0) {
|
||||
$title = (string) ($vip_levels[$vip_level]['name'] ?? ('VIP' . $vip_level));
|
||||
if ($expires <= 0 && $vip_state_source !== 'order') {
|
||||
if ($expires <= 0 && ($vip_state['source'] ?? 'none') !== 'order') {
|
||||
$status = __('永久会员', 'aksrt');
|
||||
} else {
|
||||
$remaining_days = max(1, (int) ceil(($expires - time()) / DAY_IN_SECONDS));
|
||||
@@ -44,9 +44,15 @@ if ($vip_level > 0) {
|
||||
$title = (string) ($vip_levels[$expired_level]['name'] ?? ('VIP' . $expired_level));
|
||||
$status = __('已过期', 'aksrt');
|
||||
}
|
||||
|
||||
$sidebar_level = $vip_level > 0 ? $vip_level : $expired_level;
|
||||
$sidebar_icon_url = esc_url((string) ($vip_levels[$sidebar_level]['img_icon'] ?? ''));
|
||||
$sidebar_icon = $sidebar_icon_url !== ''
|
||||
? '<img class="aksrt-vip-level-icon" src="' . $sidebar_icon_url . '" alt="" loading="lazy" decoding="async">'
|
||||
: '<i class="fas fa-crown" aria-hidden="true"></i>';
|
||||
?>
|
||||
<a class="uc-sidebar-vip" href="<?php echo esc_url($vip_url); ?>">
|
||||
<span class="uc-sidebar-vip__icon"><i class="fas fa-crown" aria-hidden="true"></i></span>
|
||||
<span class="uc-sidebar-vip__icon"><?php echo $sidebar_icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
|
||||
<span class="uc-sidebar-vip__content">
|
||||
<strong><?php echo esc_html($title); ?></strong>
|
||||
<small><?php echo esc_html($status); ?></small>
|
||||
|
||||
@@ -90,13 +90,17 @@ if ($level > 0) {
|
||||
: __('到期时间:已过期', 'aksrt');
|
||||
}
|
||||
|
||||
$status_icon_url = esc_url((string) ($levels[$vip_level_number]['img_icon'] ?? ''));
|
||||
$status_icon = $status_icon_url !== ''
|
||||
? '<img class="aksrt-vip-level-icon" src="' . $status_icon_url . '" alt="" loading="lazy" decoding="async">'
|
||||
: '<i class="fas fa-crown"></i>';
|
||||
$status_html = '<div class="uc-vip-status" role="status">'
|
||||
. '<div class="uc-vip-status__heading">'
|
||||
. '<h2 class="uc-vip-status__label">' . esc_html__('我的会员', 'aksrt') . '</h2>'
|
||||
. '<span class="uc-vip-status__state">' . esc_html($vip_state_label) . '</span>'
|
||||
. '</div>'
|
||||
. '<div class="uc-vip-status__main uc-vip-status__main--level-' . (int) $vip_level_number . '">'
|
||||
. '<span class="uc-vip-status__icon" aria-hidden="true"><i class="fas fa-crown"></i></span>'
|
||||
. '<span class="uc-vip-status__icon" aria-hidden="true">' . $status_icon . '</span>'
|
||||
. '<span class="uc-vip-status__level">' . esc_html($vip_level_name) . '</span>'
|
||||
. '</div>'
|
||||
. '<div class="uc-vip-status__desc">' . esc_html($vip_description) . '</div>'
|
||||
@@ -118,6 +122,10 @@ foreach ([1, 2] as $lv) {
|
||||
: '';
|
||||
$cta = sprintf(__('开通%s', 'aksrt'), $lv_name);
|
||||
$vip_attr = $lv;
|
||||
$lv_icon_url = esc_url((string) ($levels[$lv]['img_icon'] ?? ''));
|
||||
$lv_icon = $lv_icon_url !== ''
|
||||
? '<img class="aksrt-vip-level-icon" src="' . $lv_icon_url . '" alt="" loading="lazy" decoding="async">'
|
||||
: '<i class="fas fa-crown" aria-hidden="true"></i>';
|
||||
if (str_starts_with($btn_type, 'renew_')) {
|
||||
$renew_lv = (int) substr($btn_type, 6);
|
||||
if ($lv === $renew_lv) {
|
||||
@@ -144,7 +152,7 @@ foreach ([1, 2] as $lv) {
|
||||
$cards .= '<div class="vip-baicon" aria-hidden="true"><i class="fas fa-gem"></i></div>';
|
||||
$cards .= '<div class="relative uc-vip-level-card__inner">';
|
||||
$cards .= '<div class="v-iconbox mb10 flex jc ac">';
|
||||
$cards .= '<div class="v-icon flex jc ac"><i class="fas fa-crown" aria-hidden="true"></i></div>';
|
||||
$cards .= '<div class="v-icon flex jc ac">' . $lv_icon . '</div>';
|
||||
$cards .= '<div class="v-info text-left"><div class="v-name font-bold">' . esc_html($lv_name) . '</div>';
|
||||
if ($lv_desc !== '') {
|
||||
$cards .= '<div class="v-desc em09 muted-2-color">' . esc_html($lv_desc) . '</div>';
|
||||
|
||||
@@ -112,12 +112,12 @@ class SchemaPayment {
|
||||
['key' => 'pay_user_vip_1_name', 'label' => '一级会员名称', 'type' => 'input', 'default' => '一级会员', 'dependsOn' => ['key' => 'pay_user_vip_1_s', 'value' => true]],
|
||||
['key' => 'pay_user_vip_1_desc', 'label' => '一级会员一句话简介', 'type' => 'input', 'default' => '尊享一级会员特权', 'dependsOn' => ['key' => 'pay_user_vip_1_s', 'value' => true]],
|
||||
['key' => 'pay_user_vip_1_equity', 'label' => '一级会员权益 HTML', 'type' => 'textarea', 'default' => '<li>免费下载部分资源</li><li>会员专属身份标识</li><li>付费内容会员价</li>', 'dependsOn' => ['key' => 'pay_user_vip_1_s', 'value' => true]],
|
||||
['key' => 'vip_1_img_icon', 'label' => '一级会员图标 URL', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'pay_user_vip_1_s', 'value' => true]],
|
||||
['key' => 'vip_1_img_icon', 'label' => '一级会员图标 URL', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'pay_user_vip_1_s', 'value' => true], 'help' => '留空使用内置 vip-1.svg 图标'],
|
||||
['key' => 'pay_user_vip_2_s', 'label' => '启用二级会员', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'pay_user_vip_2_name', 'label' => '二级会员名称', 'type' => 'input', 'default' => '二级会员', 'dependsOn' => ['key' => 'pay_user_vip_2_s', 'value' => true]],
|
||||
['key' => 'pay_user_vip_2_desc', 'label' => '二级会员一句话简介', 'type' => 'input', 'default' => '尊享二级会员特权', 'dependsOn' => ['key' => 'pay_user_vip_2_s', 'value' => true]],
|
||||
['key' => 'pay_user_vip_2_equity', 'label' => '二级会员权益 HTML', 'type' => 'textarea', 'default' => '<li>更高免费下载额度</li><li>更高等级身份标识</li><li>更多付费内容会员价</li>', 'dependsOn' => ['key' => 'pay_user_vip_2_s', 'value' => true]],
|
||||
['key' => 'vip_2_img_icon', 'label' => '二级会员图标 URL', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'pay_user_vip_2_s', 'value' => true]],
|
||||
['key' => 'vip_2_img_icon', 'label' => '二级会员图标 URL', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'pay_user_vip_2_s', 'value' => true], 'help' => '留空使用内置 vip-2.svg 图标'],
|
||||
['key' => 'pay_user_vip_desc', 'label' => '弹窗顶部会员说明', 'type' => 'textarea', 'default' => ''],
|
||||
['key' => 'pay_user_vip_more', 'label' => '弹窗底部补充说明 HTML', 'type' => 'textarea', 'default' => ''],
|
||||
]],
|
||||
@@ -134,11 +134,8 @@ class SchemaPayment {
|
||||
]],
|
||||
['key' => 'benefit', 'title' => '下载权益', 'fields' => [
|
||||
['key' => 'pay_download_limit', 'label' => '普通用户下载限制', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 9999],
|
||||
['key' => 'pay_download_speed', 'label' => '普通用户下载速度(KB/s)', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 99999],
|
||||
['key' => 'pay_download_limit_vip_1', 'label' => '一级会员下载限制', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 9999, 'dependsOn' => ['key' => 'pay_user_vip_1_s', 'value' => true]],
|
||||
['key' => 'pay_download_speed_vip_1', 'label' => '一级会员下载速度(KB/s)', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 99999, 'dependsOn' => ['key' => 'pay_user_vip_1_s', 'value' => true]],
|
||||
['key' => 'pay_download_limit_vip_2', 'label' => '二级会员下载限制', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 9999, 'dependsOn' => ['key' => 'pay_user_vip_2_s', 'value' => true]],
|
||||
['key' => 'pay_download_speed_vip_2', 'label' => '二级会员下载速度(KB/s)', 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 99999, 'dependsOn' => ['key' => 'pay_user_vip_2_s', 'value' => true]],
|
||||
['key' => 'pay_vip_pass_charge_s', 'label' => '会员卡密兑换', 'type' => 'switch', 'default' => false],
|
||||
['key' => 'pay_vip_pass_charge_desc', 'label' => '卡密兑换说明', 'type' => 'textarea', 'default' => '', 'dependsOn' => ['key' => 'pay_vip_pass_charge_s', 'value' => true]],
|
||||
['key' => 'pay_vip_pass_charge_only_password', 'label' => '仅密码兑换', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'pay_vip_pass_charge_s', 'value' => true]],
|
||||
|
||||
@@ -127,7 +127,6 @@ class SchemaPermissions {
|
||||
['key' => 'download_credits_cost', 'label' => '默认积分价参考', 'type' => 'number', 'default' => 1, 'min' => 0, 'max' => 100, 'help' => '仅运营参考/兼容;实际价格以文章付费设置为准。'],
|
||||
['key' => 'download_daily_limit', 'label' => '每日下载限制', 'type' => 'number', 'default' => 0, 'min' => 0, 'help' => '0为不限制'],
|
||||
['key' => 'download_link_expire', 'label' => '下载链接有效期(分钟)', 'type' => 'number', 'default' => 30, 'min' => 5, 'max' => 1440],
|
||||
['key' => 'download_speed_limit', 'label' => '下载速度限制(KB/s)', 'type' => 'number', 'default' => 0, 'min' => 0, 'help' => '0为不限制'],
|
||||
]],
|
||||
['key' => 'vip', 'title' => 'VIP 特权', 'fields' => [
|
||||
['key' => 'download_vip_free', 'label' => 'VIP 免费下载', 'type' => 'switch', 'default' => false],
|
||||
|
||||
@@ -295,16 +295,11 @@ class Download {
|
||||
}
|
||||
|
||||
$target_url = esc_url_raw((string) $meta['downloads'][$idx]['url']);
|
||||
$speed_kb = 0;
|
||||
$uid_speed = (int) ($row['user_id'] ?? 0);
|
||||
if ($uid_speed > 0 && function_exists('aksrt_get_user_download_speed')) {
|
||||
$speed_kb = aksrt_get_user_download_speed($uid_speed);
|
||||
}
|
||||
|
||||
// Local attachment / uploads file: optional throttled stream (Zibll speed limit).
|
||||
// Local attachment / uploads file: stream without artificial throttling.
|
||||
$local_path = $this->resolve_local_download_path($target_url);
|
||||
if ($local_path !== '' && is_readable($local_path)) {
|
||||
$this->stream_local_file($local_path, $speed_kb);
|
||||
$this->stream_local_file($local_path);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -347,9 +342,9 @@ class Download {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream a local file with optional KB/s throttle.
|
||||
* Stream a local file.
|
||||
*/
|
||||
private function stream_local_file(string $path, int $speed_kb = 0): void {
|
||||
private function stream_local_file(string $path): void {
|
||||
$filename = basename($path);
|
||||
$size = filesize($path);
|
||||
if ($size === false) {
|
||||
@@ -364,21 +359,12 @@ class Download {
|
||||
header('Content-Length: ' . (string) $size);
|
||||
|
||||
$chunk = 1024 * 64; // 64KB
|
||||
$sleep_us = 0;
|
||||
if ($speed_kb > 0) {
|
||||
// Emit ~speed_kb KB per second using fixed 64KB chunks when possible.
|
||||
$bytes_per_sec = max(1024, $speed_kb * 1024);
|
||||
$chunk = min(1024 * 64, $bytes_per_sec);
|
||||
$chunk = max(1024, $chunk);
|
||||
// Sleep so chunk_bytes / second ≈ bytes_per_sec.
|
||||
$sleep_us = (int) max(0, (int) round(($chunk / $bytes_per_sec) * 1000000) - 1000);
|
||||
}
|
||||
|
||||
$fh = fopen($path, 'rb');
|
||||
if (!$fh) {
|
||||
$this->fail_410();
|
||||
}
|
||||
// Disable output compression for accurate Content-Length / throttle.
|
||||
// Disable output compression so Content-Length remains accurate.
|
||||
if (function_exists('apache_setenv')) {
|
||||
@apache_setenv('no-gzip', '1');
|
||||
}
|
||||
@@ -392,9 +378,6 @@ class Download {
|
||||
if (function_exists('flush')) {
|
||||
flush();
|
||||
}
|
||||
if ($sleep_us > 0) {
|
||||
usleep($sleep_us);
|
||||
}
|
||||
}
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ trait VipServiceModal {
|
||||
'name' => (string) ($levels[$level]['name'] ?? ('VIP' . $level)),
|
||||
'desc' => (string) ($levels[$level]['desc'] ?? ''),
|
||||
'equity' => $equity,
|
||||
'img_icon' => esc_url_raw((string) ($levels[$level]['img_icon'] ?? '')),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -161,7 +162,10 @@ trait VipServiceModal {
|
||||
? aksrt_format_vip_equity_html($equity, 'mb10 relative')
|
||||
: '';
|
||||
|
||||
$icon = '<i class="fas fa-gem" aria-hidden="true"></i>';
|
||||
$icon_url = esc_url((string) ($levels[$level]['img_icon'] ?? ''));
|
||||
$icon = $icon_url !== ''
|
||||
? '<img class="aksrt-vip-level-icon" src="' . $icon_url . '" alt="" loading="lazy" decoding="async" />'
|
||||
: '<i class="fas fa-gem" aria-hidden="true"></i>';
|
||||
$html = '<div class="vip-card pointer level-' . $level . ' vip-theme' . $level . $cls . '" vip-level="' . $level . '">';
|
||||
$html .= '<div class="vip-baicon" aria-hidden="true">' . $icon . '</div>';
|
||||
$html .= '<div class="vip-img abs-right">' . $icon . '</div>';
|
||||
|
||||
@@ -122,6 +122,23 @@ class PaymentRuntime {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a configured VIP icon, falling back to the bundled level asset.
|
||||
*/
|
||||
private static function get_vip_icon_url(int $level, string $configured): string {
|
||||
$configured = esc_url_raw($configured);
|
||||
if ($configured !== '') {
|
||||
return $configured;
|
||||
}
|
||||
|
||||
$filename = 'vip-' . $level . '.svg';
|
||||
if (defined('AKSRT_DIR') && is_file(AKSRT_DIR . '/assets/img/user/vip/' . $filename)) {
|
||||
return defined('AKSRT_URI') ? AKSRT_URI . '/assets/img/user/vip/' . $filename : '';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Dual-level VIP settings (Zibll pay_user_vip_1 / pay_user_vip_2).
|
||||
*
|
||||
@@ -190,27 +207,24 @@ class PaymentRuntime {
|
||||
'name' => $name1,
|
||||
'desc' => sanitize_text_field((string) ($settings['pay_user_vip_1_desc'] ?? __('尊享一级会员特权', 'aksrt'))),
|
||||
'equity' => wp_kses((string) (($settings['pay_user_vip_1_equity'] ?? '') !== '' ? $settings['pay_user_vip_1_equity'] : '<li>免费下载部分资源</li><li>会员专属身份标识</li><li>付费内容会员价</li>'), $allowed_equity),
|
||||
'img_icon' => esc_url_raw((string) ($settings['vip_1_img_icon'] ?? '')),
|
||||
'img_icon' => self::get_vip_icon_url(1, (string) ($settings['vip_1_img_icon'] ?? '')),
|
||||
'product_s' => !isset($settings['vip_1_product_s']) || !empty($settings['vip_1_product_s']),
|
||||
'products_raw' => $products_1,
|
||||
'download_limit' => max(0, min(9999, (int) ($settings['pay_download_limit_vip_1'] ?? 0))),
|
||||
'download_speed' => max(0, min(99999, (int) ($settings['pay_download_speed_vip_1'] ?? 0))),
|
||||
],
|
||||
2 => [
|
||||
'enabled' => $vip2_enabled,
|
||||
'name' => $name2,
|
||||
'desc' => sanitize_text_field((string) ($settings['pay_user_vip_2_desc'] ?? __('尊享二级会员特权', 'aksrt'))),
|
||||
'equity' => wp_kses((string) (($settings['pay_user_vip_2_equity'] ?? '') !== '' ? $settings['pay_user_vip_2_equity'] : '<li>更高免费下载额度</li><li>更高等级身份标识</li><li>更多付费内容会员价</li>'), $allowed_equity),
|
||||
'img_icon' => esc_url_raw((string) ($settings['vip_2_img_icon'] ?? '')),
|
||||
'img_icon' => self::get_vip_icon_url(2, (string) ($settings['vip_2_img_icon'] ?? '')),
|
||||
'product_s' => !isset($settings['vip_2_product_s']) || !empty($settings['vip_2_product_s']),
|
||||
'products_raw' => $products_2,
|
||||
'download_limit' => max(0, min(9999, (int) ($settings['pay_download_limit_vip_2'] ?? 0))),
|
||||
'download_speed' => max(0, min(99999, (int) ($settings['pay_download_speed_vip_2'] ?? 0))),
|
||||
],
|
||||
],
|
||||
'benefit' => [
|
||||
'download_limit' => max(0, min(9999, (int) ($settings['pay_download_limit'] ?? 0))),
|
||||
'download_speed' => max(0, min(99999, (int) ($settings['pay_download_speed'] ?? 0))),
|
||||
'pass_charge' => !empty($settings['pay_vip_pass_charge_s']),
|
||||
'pass_charge_desc' => sanitize_textarea_field((string) ($settings['pay_vip_pass_charge_desc'] ?? '')),
|
||||
'pass_charge_only_password' => !isset($settings['pay_vip_pass_charge_only_password']) || !empty($settings['pay_vip_pass_charge_only_password']),
|
||||
|
||||
Reference in New Issue
Block a user