From 5c6b422866369289c6bc0672cff571ceeb630ff6 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 1 Nov 2026 15:09:49 +0800 Subject: [PATCH] fix(frontend): route every user-center points label through the custom currency name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后台「积分配置 → 自定义货币名称」改名后,用户中心仍有大量硬编码 「积分」:做任务赚积分 / 购买积分 / 签到领积分、积分记录 / 积分任务、 每日可免费获取 XX 积分、我的积分、积分+1、创作中心积分收益等。 get_currency_name() 早已存在且可用,问题只是这些文案没有走它。 本PR 全部替换,无双路、无迁移: 服务端渲染(用户中心 renderers) - credits-balance.php:购买/做任务赚/签到领 + 整个购买弹窗 - profile-credits.php:积分记录 / 积分任务 页签 - credits-points-tasks.php:每日上限三态与空态 - sidebar-creator.php / profile-creator.php:积分收益 - transfer-modal.php:积分转账提示 - Signin.php:签到详情弹窗(我的积分 / 奖励 tooltip / 积分+N) - VipServiceModal.php:我的积分 / 积分兑换会员 - download-permission-card.php:购买价格 客户端渲染(JS 无法调用 PHP,注入 currencyName 到 aksrtData) - signin.js:签到状态行「已签到 N 天 +1」 - credits.js:转账标题/金额标签 + 购买提示 toast - cms-download.js:积分不足视图、我的积分 入口、余额不足文案 - pay-vip.js:积分兑换会员入口(优先 catalog.currency_name) - order-center.js:订单行单位回退 契约测试同步改为断言模板构造而非死字符串,并新增两例: 改名后跟随、未注入时回退「积分」。 Co-Authored-By: Claude Opus 5 (1M context) --- assets/js/cms-download.js | 24 +++++++++---- assets/js/credits.js | 14 +++++--- assets/js/order-center.js | 10 +++++- assets/js/pay-vip.js | 5 ++- assets/js/signin.js | 12 +++++-- .../user-center-renderers/credits-balance.php | 29 ++++++++++----- .../credits-points-tasks.php | 14 ++++---- .../user-center-renderers/profile-creator.php | 11 ++++-- .../user-center-renderers/profile-credits.php | 8 +++-- .../user-center-renderers/sidebar-creator.php | 6 +++- .../user-center-renderers/transfer-modal.php | 4 ++- src/Content/VipServiceModal.php | 4 +-- src/Core/ScriptsPart1c.php | 3 ++ src/Credits/Signin.php | 22 +++++++----- .../download/download-permission-card.php | 7 ++-- .../card-pass-modal-redeem.test.cjs | 4 ++- tests/widget-system/signin-runtime.test.cjs | 35 ++++++++++++++++--- ...ser-center-sidebar-icons-contract.test.cjs | 7 +++- .../vip-points-exchange-modal.test.cjs | 10 +++--- 19 files changed, 170 insertions(+), 59 deletions(-) diff --git a/assets/js/cms-download.js b/assets/js/cms-download.js index 518b0eaf..eef83e67 100644 --- a/assets/js/cms-download.js +++ b/assets/js/cms-download.js @@ -20,6 +20,12 @@ const REST_BASE = window.aksrtData.siteUrl ? window.aksrtData.siteUrl.replace(/\/$/, '') + '/wp-json/aksrt/v1' : '/wp-json/aksrt/v1'; const PAY_CONTENT_PATH = '/pay/content/'; + // 自定义货币名称(后台「积分配置 → 自定义货币名称」)由服务端注入。 + // 余额不足提示在客户端拼装,必须跟随它。 + function currencyName() { + return (window.aksrtData && window.aksrtData.currencyName) || '积分'; + } + function escapeHtml(value) { return String(value == null ? '' : value) .replace(/&/g, '&') @@ -192,6 +198,8 @@ let viewKey = 'error'; let subtitle = ''; let action = null; + // credits 视图标题跟随自定义货币名称;其余视图沿用静态文案。 + let unit = ''; data = data || {}; msg = msg || ''; @@ -215,8 +223,9 @@ viewKey = 'credits'; const balance = typeof data.balance === 'number' ? data.balance : 0; const cost = typeof data.cost === 'number' ? data.cost : 0; - msg = '当前余额 ' + balance + ' 积分,需要 ' + cost + ' 积分。可通过签到、阅读、邀请好友等方式获取积分。'; - if (data.credits_url) action = { kind: 'link', url: data.credits_url, label: '我的积分', icon: 'fa-coins' }; + unit = currencyName(); + msg = '当前余额 ' + balance + ' ' + unit + ',需要 ' + cost + ' ' + unit + '。可通过签到、阅读、邀请好友等方式获取' + unit + '。'; + if (data.credits_url) action = { kind: 'link', url: data.credits_url, label: '我的' + unit, icon: 'fa-coins' }; } else if (code === 'aksrt_download_limit') { viewKey = 'quota'; msg = msg || '您今日下载免费资源个数已超限,请明日再下载。'; @@ -232,6 +241,7 @@ open( dlView(viewKey, { + title: viewKey === 'credits' && unit ? unit + '不足' : undefined, subtitle: subtitle, body: msg ? '

' + escapeHtml(msg) + '

' : '', actions: action ? [action] : [], @@ -368,7 +378,8 @@ } function formatAssetLabel(preview, value) { - const currency = escapeHtml(preview.currency || (preview.pay_modo === 'points' ? '积分' : '¥')); + // preview.currency 由服务端解析(积分价走自定义货币名称),缺省时回退同一来源。 + const currency = escapeHtml(preview.currency || (preview.pay_modo === 'points' ? currencyName() : '¥')); const amount = escapeHtml(value == null ? '' : value); return preview.pay_modo === 'points' ? amount + currency : currency + amount; } @@ -483,15 +494,16 @@ body += '
' + priceRows + '
'; if (isPoints) { + const unit = currencyName(); body += '
' + '
' + - '我的积分' + + '我的' + unit + '
' + balance + '
'; if (!preview.balance_enough) { - body += '
抱歉,您的积分不足,暂时无法支付
'; + body += '
抱歉,您的' + unit + '不足,暂时无法支付
'; body += ''; openCashierContent(body, returnFocusEl); diff --git a/assets/js/credits.js b/assets/js/credits.js index c0c6830b..1c9b691f 100644 --- a/assets/js/credits.js +++ b/assets/js/credits.js @@ -16,6 +16,12 @@ } var activePoll = null; + // 自定义货币名称(后台「积分配置 → 自定义货币名称」)由服务端注入。 + // 转账标题/金额标签与购买提示都在客户端拼装,必须跟随它。 + function currencyName() { + return (aksrt && aksrt.currencyName) || '积分'; + } + function operationKey(owner) { if (!owner.dataset.aksrtOperationKey) { owner.dataset.aksrtOperationKey = window.AksrtRequest.createIdempotencyKey(); @@ -495,7 +501,7 @@ ? Math.max(1, parseInt(btn.getAttribute('data-aksrt-transfer-min') || '1', 10) || 1) : 1; if (typeInput) typeInput.value = type; - if (title) title.textContent = type === 'points' ? '积分转账' : '余额转账'; + if (title) title.textContent = type === 'points' ? currencyName() + '转账' : '余额转账'; var amountEl = form ? form.querySelector('[data-aksrt-transfer-amount]') : null; if (amountEl) { amountEl.min = type === 'points' ? String(pointsTransferMin) : '0.01'; @@ -503,7 +509,7 @@ amountEl.inputMode = type === 'points' ? 'numeric' : 'decimal'; amountEl.value = ''; } - if (amountLabel) amountLabel.textContent = type === 'points' ? '积分' : '金额'; + if (amountLabel) amountLabel.textContent = type === 'points' ? currencyName() : '金额'; if (balanceInfo) balanceInfo.hidden = type === 'points'; if (pointsInfo) pointsInfo.hidden = type !== 'points'; if (results) results.innerHTML = ''; @@ -744,11 +750,11 @@ selectProduct('custom'); } if ((!pkg || pkg === 'custom') && !validCustom) { - notyf('请选择或输入需购买的积分', 'danger'); + notyf('请选择或输入需购买的' + currencyName(), 'danger'); return; } busy = true; - notyf('正在购买积分…', 'load', '', 'aksrt-balance-points-toast'); + notyf('正在购买' + currencyName() + '…', 'load', '', 'aksrt-balance-points-toast'); api('/pay/balance/points-exchange', { method: 'POST', headers: { 'Idempotency-Key': operationKey(form) }, diff --git a/assets/js/order-center.js b/assets/js/order-center.js index 40ef2a45..675c9a9e 100644 --- a/assets/js/order-center.js +++ b/assets/js/order-center.js @@ -35,13 +35,21 @@ function formatMoney(order) { var raw = String(order && order.amount != null ? order.amount : "0"); if (order && order.is_points) { - return escapeHtml(order.currency_symbol || "积分") + " " + (/^\d+$/.test(raw) ? raw : "0"); + // 单位名由服务端随订单下发(UserOrders::currency_symbol), + // 缺省时回退到自定义货币名称,避免改名后残留「积分」。 + var unit = order.currency_symbol || currencyName(); + return escapeHtml(unit) + " " + (/^\d+$/.test(raw) ? raw : "0"); } var match = /^(0|[1-9]\d*)(?:\.(\d{1,2}))?$/.exec(raw); var amount = match ? match[1] + "." + (match[2] || "").padEnd(2, "0") : "0.00"; return "¥" + amount; } + // 自定义货币名称(后台「积分配置 → 自定义货币名称」)由服务端注入。 + function currencyName() { + return (window.aksrtData && window.aksrtData.currencyName) || "积分"; + } + function orderTag(orderNumber) { return "order:" + String(orderNumber || "").toLowerCase(); } diff --git a/assets/js/pay-vip.js b/assets/js/pay-vip.js index 7a73124e..9cca6aa6 100644 --- a/assets/js/pay-vip.js +++ b/assets/js/pay-vip.js @@ -493,8 +493,11 @@ var pointsLink = node("a", "btn-block but mb10 padding-lg c-green mini-radius"); pointsLink.href = "javascript:;"; pointsLink.setAttribute("data-aksrt-vip-points-open", ""); + // 入口文案跟随自定义货币名称(后台「积分配置 → 自定义货币名称」), + // 与它打开的服务端静态弹窗标题保持同一命名。 + var currencyName = (catalog.currency_name || (window.aksrtData && window.aksrtData.currencyName) || "积分"); pointsLink.innerHTML = '' - + "积分兑换会员" + + currencyName + "兑换会员" + ''; append(products, pointsLink); } diff --git a/assets/js/signin.js b/assets/js/signin.js index bf62d3e0..d09fa1a7 100644 --- a/assets/js/signin.js +++ b/assets/js/signin.js @@ -13,6 +13,12 @@ var signinBusy = false; var refreshSequence = 0; + // 自定义货币名称(后台「积分配置 → 自定义货币名称」)由服务端注入, + // 状态行文案必须跟随它,否则改名后这里仍显示「积分」。 + function currencyName() { + return (window.aksrtData && window.aksrtData.currencyName) || '积分'; + } + function api(path, options) { return window.AksrtRequest.request(path, options || {}).then(function (response) { return { @@ -111,11 +117,11 @@ return; } if (data.signed) { - setStatusHtml('已签到 ' + data.streak + ' 天 +' + data.reward_today); + setStatusHtml('已签到 ' + data.streak + ' 天 +' + data.reward_today + ' ' + currencyName()); swapButtonsToDetailsLink(); return; } - setStatusHtml('连续 ' + data.streak + ' 天,+' + data.reward_if_signin); + setStatusHtml('连续 ' + data.streak + ' 天,+' + data.reward_if_signin + ' ' + currencyName()); }); } @@ -168,7 +174,7 @@ element.textContent = Number(result.json.balance || 0).toLocaleString(); element.title = element.textContent; }); - setStatusHtml('已签到 ' + result.json.streak + ' 天 +' + result.json.reward); + setStatusHtml('已签到 ' + result.json.streak + ' 天 +' + result.json.reward + ' ' + currencyName()); swapButtonsToDetailsLink(); }).catch(function (error) { restoreButton(); diff --git a/inc/helpers/user-center-renderers/credits-balance.php b/inc/helpers/user-center-renderers/credits-balance.php index d91f86f9..0f9f9c68 100644 --- a/inc/helpers/user-center-renderers/credits-balance.php +++ b/inc/helpers/user-center-renderers/credits-balance.php @@ -24,6 +24,10 @@ $points_exchange = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Se $recharge = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_payment_recharge_settings() : []; $points_exchange_on = !empty($points_exchange['enabled']) && !empty($recharge['enabled']); $currency = (string) ($currency_name ?? __('积分', 'aksrt')); +// 文案里的货币名统一走自定义名称(后台「积分配置 → 自定义货币名称」)。 +$points_buy_label = sprintf(__('购买%s', 'aksrt'), $currency); +$points_earn_label = sprintf(__('做任务赚%s', 'aksrt'), $currency); +$points_signin_label = sprintf(__('签到领%s', 'aksrt'), $currency); ?>
@@ -36,7 +40,7 @@ $currency = (string) ($currency_name ?? __('积分', 'aksrt')); ' . esc_html__('已签到', 'aksrt') . ''); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> @@ -52,11 +56,11 @@ $currency = (string) ($currency_name ?? __('积分', 'aksrt')); - +
- + parse_points_packages((string) ($points_exchange['products_raw'] ?? '')) : []; @@ -81,7 +94,7 @@ $currency = (string) ($currency_name ?? __('积分', 'aksrt')); if (function_exists('aksrt_sort_payment_methods')) { $points_methods = aksrt_sort_payment_methods($points_methods); } - $points_custom_limit_html = sprintf(__('最低购买%d积分,最高购买%d积分', 'aksrt'), $pb_min_points, $pb_daily_max_points); + $points_custom_limit_html = $points_limit_html; $points_gateway = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_payment_gateway_settings() : []; $points_mark = (string) ($points_gateway['currency']['mark'] ?? '¥'); $points_default_product = $points_packages ? (string) $points_packages[0]['key'] : 'custom'; @@ -90,11 +103,11 @@ $currency = (string) ($currency_name ?? __('积分', 'aksrt'));