From 18da39788f48839436613a2628a3afdb7ae1d5a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Aug 2026 17:48:10 +0800 Subject: [PATCH] feat(vip): add default icons and remove download speed Co-Authored-By: Claude Fable 5 --- .../admin/src/schema/sections/payment/vip.js | 10 ++---- assets/css/frontend/credits.css | 16 +++++++++ assets/css/routes/user-center/credits.css | 13 +++++++ assets/img/user/vip/vip-1.svg | 1 + assets/img/user/vip/vip-2.svg | 1 + assets/js/pay-vip.js | 8 +++++ inc/helpers/aksrt-vip.php | 36 ++++++------------- .../user-center-renderers/credits-vip.php | 7 ++-- .../user-center-renderers/sidebar-vip.php | 10 ++++-- inc/helpers/user-center-renderers/vip-tab.php | 12 +++++-- src/Admin/Schema/SchemaPayment.php | 7 ++-- src/Admin/Schema/SchemaPermissions.php | 1 - src/Content/Download.php | 27 +++----------- src/Content/VipServiceModal.php | 6 +++- src/Settings/PaymentRuntime.php | 24 ++++++++++--- 15 files changed, 105 insertions(+), 74 deletions(-) create mode 100644 assets/img/user/vip/vip-1.svg create mode 100644 assets/img/user/vip/vip-2.svg diff --git a/assets/admin/src/schema/sections/payment/vip.js b/assets/admin/src/schema/sections/payment/vip.js index 6a8ef4a4..10d8c43e 100644 --- a/assets/admin/src/schema/sections/payment/vip.js +++ b/assets/admin/src/schema/sections/payment/vip.js @@ -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: '
  • 免费下载部分资源
  • 会员专属身份标识
  • 付费内容会员价
  • ', dependsOn: { key: 'pay_user_vip_1_s', value: true }, help: '建议使用
  • 列表项' }, - { 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: '
  • 更高免费下载额度
  • 更高等级身份标识
  • 更多付费内容会员价
  • ', 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: '开启后只需输入卡密;关闭则需卡号+卡密。' }, diff --git a/assets/css/frontend/credits.css b/assets/css/frontend/credits.css index 68c8ae29..d9b39852 100644 --- a/assets/css/frontend/credits.css +++ b/assets/css/frontend/credits.css @@ -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; } diff --git a/assets/css/routes/user-center/credits.css b/assets/css/routes/user-center/credits.css index e382f941..c48c9a41 100644 --- a/assets/css/routes/user-center/credits.css +++ b/assets/css/routes/user-center/credits.css @@ -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; diff --git a/assets/img/user/vip/vip-1.svg b/assets/img/user/vip/vip-1.svg new file mode 100644 index 00000000..a1d2934c --- /dev/null +++ b/assets/img/user/vip/vip-1.svg @@ -0,0 +1 @@ + diff --git a/assets/img/user/vip/vip-2.svg b/assets/img/user/vip/vip-2.svg new file mode 100644 index 00000000..b700f4ff --- /dev/null +++ b/assets/img/user/vip/vip-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/js/pay-vip.js b/assets/js/pay-vip.js index 23801c86..c37d993a 100644 --- a/assets/js/pay-vip.js +++ b/assets/js/pay-vip.js @@ -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); diff --git a/inc/helpers/aksrt-vip.php b/inc/helpers/aksrt-vip.php index f5ea4c8a..a00790f3 100644 --- a/inc/helpers/aksrt-vip.php +++ b/inc/helpers/aksrt-vip.php @@ -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 ' ' . esc_html($badge_text) . ''; + $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 !== '' + ? '' + : ''; + + return '' . $icon . ' ' . esc_html($badge_text) . ''; } /** diff --git a/inc/helpers/user-center-renderers/credits-vip.php b/inc/helpers/user-center-renderers/credits-vip.php index 374d555e..f274bd4e 100644 --- a/inc/helpers/user-center-renderers/credits-vip.php +++ b/inc/helpers/user-center-renderers/credits-vip.php @@ -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 !== '' + ? '' + : ''; 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')) {
    - +
    diff --git a/inc/helpers/user-center-renderers/sidebar-vip.php b/inc/helpers/user-center-renderers/sidebar-vip.php index 4b15329a..7f08b2d5 100644 --- a/inc/helpers/user-center-renderers/sidebar-vip.php +++ b/inc/helpers/user-center-renderers/sidebar-vip.php @@ -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 !== '' + ? '' + : ''; ?> - + diff --git a/inc/helpers/user-center-renderers/vip-tab.php b/inc/helpers/user-center-renderers/vip-tab.php index b93fa589..fdb7d46a 100644 --- a/inc/helpers/user-center-renderers/vip-tab.php +++ b/inc/helpers/user-center-renderers/vip-tab.php @@ -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 !== '' + ? '' + : ''; $status_html = '
    ' . '
    ' . '

    ' . esc_html__('我的会员', 'aksrt') . '

    ' . '' . esc_html($vip_state_label) . '' . '
    ' . '
    ' - . '' + . '' . '' . esc_html($vip_level_name) . '' . '
    ' . '
    ' . esc_html($vip_description) . '
    ' @@ -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 !== '' + ? '' + : ''; 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 .= ''; $cards .= '
    '; $cards .= '
    '; - $cards .= '
    '; + $cards .= '
    ' . $lv_icon . '
    '; $cards .= '
    ' . esc_html($lv_name) . '
    '; if ($lv_desc !== '') { $cards .= '
    ' . esc_html($lv_desc) . '
    '; diff --git a/src/Admin/Schema/SchemaPayment.php b/src/Admin/Schema/SchemaPayment.php index b88e04f2..742cb65d 100644 --- a/src/Admin/Schema/SchemaPayment.php +++ b/src/Admin/Schema/SchemaPayment.php @@ -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' => '
  • 免费下载部分资源
  • 会员专属身份标识
  • 付费内容会员价
  • ', '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' => '
  • 更高免费下载额度
  • 更高等级身份标识
  • 更多付费内容会员价
  • ', '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]], diff --git a/src/Admin/Schema/SchemaPermissions.php b/src/Admin/Schema/SchemaPermissions.php index 0d0de2ef..b33360fd 100644 --- a/src/Admin/Schema/SchemaPermissions.php +++ b/src/Admin/Schema/SchemaPermissions.php @@ -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], diff --git a/src/Content/Download.php b/src/Content/Download.php index 855a43ed..5fd70714 100644 --- a/src/Content/Download.php +++ b/src/Content/Download.php @@ -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); } diff --git a/src/Content/VipServiceModal.php b/src/Content/VipServiceModal.php index decbc881..2f992942 100644 --- a/src/Content/VipServiceModal.php +++ b/src/Content/VipServiceModal.php @@ -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 = ''; + $icon_url = esc_url((string) ($levels[$level]['img_icon'] ?? '')); + $icon = $icon_url !== '' + ? '' + : ''; $html = '
    '; $html .= ''; $html .= '
    ' . $icon . '
    '; diff --git a/src/Settings/PaymentRuntime.php b/src/Settings/PaymentRuntime.php index 447dcf15..b6ab4943 100644 --- a/src/Settings/PaymentRuntime.php +++ b/src/Settings/PaymentRuntime.php @@ -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'] : '
  • 免费下载部分资源
  • 会员专属身份标识
  • 付费内容会员价
  • '), $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'] : '
  • 更高免费下载额度
  • 更高等级身份标识
  • 更多付费内容会员价
  • '), $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']),