From ea16f9c2fe42fe316f42952a8ca14f1b74d91582 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Sep 2026 23:17:32 +0800 Subject: [PATCH] perf(revenue): server-render the promotion link and stop settling on reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Opening the 推广收益 tab was slow because every read path ran settlement and two COUNT aggregates before the browser could show the link. - profile-revenue.php: the link input now carries a server-rendered value from ReferralAttribution::create_link(), so 复制链接 works on first paint instead of after a REST round trip - CommissionLedger::overview() no longer calls lazy_settle_due(); the lazy-settlement hook and its static flag are gone. Settlement runs only on the existing hourly aksrt_affiliate_settle_due cron, which uses a larger batch (100 vs 20) and would otherwise re-run up to 20 locked SELECT..FOR UPDATE + write cycles inside a GET request - ReferralAttribution::rest_me() drops the lazy_settle_due() call and the stats() result; stats() itself is deleted — its two COUNTs (one of them COUNT(DISTINCT source_user_id)) had no consumer left once the 推广人数 row was removed - credits.js: reads the link from the already-rendered input and only fetches /revenue/me for poster config and commission ratio. A failed fetch no longer blocks copying — it silently skips the poster enhancement - tests: the lazy-settlement contract is inverted to assert the read path stays read-only and cron stays wired; new assertions pin the server-rendered value and the no-COUNT REST payload Co-Authored-By: Claude Fable 5 --- assets/js/credits.js | 14 ++++++------- .../user-center-renderers/profile-revenue.php | 7 ++++++- src/Payment/CommissionLedger.php | 9 -------- src/Payment/ReferralAttribution.php | 21 ------------------- .../referral-policy-contract.test.cjs | 20 +++++++++--------- .../referral-qr-contract.test.cjs | 17 ++++++++++++++- 6 files changed, 39 insertions(+), 49 deletions(-) diff --git a/assets/js/credits.js b/assets/js/credits.js index 87320e98..9572507f 100644 --- a/assets/js/credits.js +++ b/assets/js/credits.js @@ -115,6 +115,8 @@ } // ===== Forward-only affiliate revenue center ===== + /* 推广链接由 PHP 直出,首屏即可见、可复制;这里只补异步才拿得到的 + * 海报配置与佣金比例,取失败也不影响复制。 */ function initAffiliateRevenue() { var root = document.querySelector('[data-aksrt-revenue-page]'); if (!root || root.dataset.affiliateBound) return; @@ -123,16 +125,14 @@ var copy = root.querySelector('[data-affiliate-copy]'); var feedback = root.querySelector('[data-affiliate-feedback]'); function setFeedback(text, error) { if (feedback) { feedback.textContent = text; feedback.classList.toggle('is-error', !!error); } } + var url = input ? input.value : ''; + if (copy) copy.disabled = !url; api('/revenue/me').then(function (r) { - if (!r.ok) { setFeedback((r.json && r.json.message) || '推广数据加载失败。', true); return; } + if (!r.ok) return; var j = r.json || {}; - if (input) { - input.value = j.url || ''; - } - if (copy) copy.disabled = !j.url; var ratio = root.querySelector('[data-affiliate-ratio]'); if (ratio) ratio.textContent = String(j.current_ratio || 0) + '%'; - initAffiliatePoster(root, j.url || '', j.poster || {}, j.site_name || document.title); - }).catch(function () { setFeedback('推广数据加载失败。', true); }); + initAffiliatePoster(root, url || j.url || '', j.poster || {}, j.site_name || document.title); + }).catch(function () { /* 海报与比例为增强项,静默失败即可。 */ }); if (copy) copy.addEventListener('click', function () { if (!input || !input.value) return; var done = function () { setFeedback('推广链接已复制。'); }; diff --git a/inc/helpers/user-center-renderers/profile-revenue.php b/inc/helpers/user-center-renderers/profile-revenue.php index 175f9a62..a990627b 100644 --- a/inc/helpers/user-center-renderers/profile-revenue.php +++ b/inc/helpers/user-center-renderers/profile-revenue.php @@ -56,6 +56,11 @@ $details_title = trim((string) ($affiliate['details_title'] ?? '')); if ($details_title === '') { $details_title = __('返佣详解', 'aksrt'); } +/* 推广链接服务端直出:避免为了一个本地拼接的 URL 多绕一次 REST 往返。 */ +$affiliate_link_url = ''; +if (class_exists('\AKSRT\Payment\ReferralAttribution')) { + $affiliate_link_url = (string) (\AKSRT\Payment\ReferralAttribution::get_instance()->create_link($user_id)['url'] ?? ''); +} $revenue_request = is_array($context['revenue_request'] ?? null) ? $context['revenue_request'] : []; $active_reward_tab = sanitize_key((string) ($revenue_request['reward_tab'] ?? ($_GET['reward_tab'] ?? 'detail'))); @@ -144,7 +149,7 @@ $status_labels = [