feat(revenue): immediate commission credit with independent withdrawable pool
Aligns affiliate commission with the reference theme: commission is credited to a dedicated COMMISSION asset pool the moment an order is paid, removing the 7-day settlement freeze, the settlement cron, and the settlement_days setting. - Ledger: add AssetType::COMMISSION (isolated from the recharge balance wallet) - CommissionLedger: credit-on-record + opportunistic debt repayment; refunds claw back the full commission from the pool, carrying any shortfall as debt (aksrt_commission_debt) that future commission pays down first - Withdrawal: make asset-aware via a source discriminator (commission vs balance); each pool keeps independent daily limits, pending gate, and reject-refund. Balance withdrawal (recharge + creator income) is unchanged - Fix pay_rebate_self_s: honor self-commission at purchase time - Revenue card: show pool balance + 累计/已提现 (drop 待结算), debt when present - Schema 2.0.0 -> 2.1.0: add commission_debt, drop freeze columns
This commit is contained in:
1 parent
cded20ae02
commit
61667aa03c
22 files changed
+569
-268
No files matched your search
@@ -3,7 +3,6 @@
|
||||
@import url("user-center/vip.css");
|
||||
@import url("user-center/level.css");
|
||||
@import url("user-center/settings.css");
|
||||
@import url("revenue.css");
|
||||
@import url("user-center/revenue.css");
|
||||
@import url("user-center/revenue-earnings.css");
|
||||
@import url("user-center/responsive.css");
|
||||
@@ -27,12 +27,16 @@
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card {
|
||||
position: relative;
|
||||
min-height: 116px;
|
||||
padding: 16px 22px;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 12px 28px rgba(15, 23, 42, .08);
|
||||
@@ -56,7 +60,10 @@
|
||||
|
||||
.uc-content .uc-commission-card__body {
|
||||
display: grid;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
align-content: space-between;
|
||||
gap: 8px;
|
||||
min-height: 84px;
|
||||
}
|
||||
|
||||
@@ -69,29 +76,73 @@
|
||||
|
||||
.uc-content .uc-commission-card__body > span:first-child {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
opacity: .85;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body strong {
|
||||
font-size: 32px;
|
||||
font-size: 34px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body strong small {
|
||||
margin-left: 4px;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card--ratio .uc-commission-card__body strong small {
|
||||
margin-left: 6px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__body > span:last-child,
|
||||
.uc-content .uc-commission-card__body > p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
opacity: .92;
|
||||
font-size: 13px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card--ratio .uc-commission-card__body strong {
|
||||
color: inherit;
|
||||
/* 我的佣金:累计 / 已提现(含欠款)副信息。 */
|
||||
.uc-content .uc-commission-card__meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px 16px;
|
||||
}
|
||||
|
||||
/* 待偿欠款:退款收回不足挂账,副信息里以描边标签弱提示。 */
|
||||
.uc-content .uc-commission-card__debt {
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, .22);
|
||||
}
|
||||
|
||||
/* 立即提现按钮:贴右居中,对齐参考主题 .abs-right。 */
|
||||
.uc-content .uc-commission-card__action {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 16px;
|
||||
z-index: 2;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 7px 14px;
|
||||
transform: translateY(-50%);
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
color: #fff;
|
||||
background: rgba(255, 255, 255, .22);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.uc-content .uc-commission-card__action:hover {
|
||||
background: rgba(255, 255, 255, .32);
|
||||
}
|
||||
|
||||
/* 提现按钮所在卡片:正文右侧预留空间,避免与按钮重叠。 */
|
||||
.uc-content .uc-commission-card--balance:has(.uc-commission-card__action) .uc-commission-card__body {
|
||||
padding-right: 96px;
|
||||
}
|
||||
|
||||
/* 三 Tab 推广收益:佣金详细页采用紧凑的一列信息清单。 */
|
||||
|
||||
@@ -85,6 +85,12 @@
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
/* 三个 Tab 面板首屏全部直出,靠 hidden 属性做本地切换;
|
||||
* display:grid 会覆盖 [hidden] 的 display:none,必须显式复位。 */
|
||||
.uc-reward-pane[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.uc-reward-pane--detail {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
+23
-5
@@ -934,8 +934,24 @@
|
||||
modal.dataset.aksrtWithdrawInitialized = '1';
|
||||
var form = modal.querySelector('[data-aksrt-withdraw-form]');
|
||||
var busy = false;
|
||||
// 提现来源随打开按钮传入:commission 走佣金池,其余走余额钱包。
|
||||
// 每个来源的每日次数/额度不同,按钮上带了各自的 min/remaining,
|
||||
// 打开时覆盖到金额输入框,提交时把 source 一并回传。
|
||||
document.querySelectorAll('[data-aksrt-withdraw-open]').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () { openModal(modal); });
|
||||
btn.addEventListener('click', function () {
|
||||
var src = btn.getAttribute('data-aksrt-withdraw-source') || 'balance';
|
||||
modal.dataset.aksrtWithdrawSource = src === 'commission' ? 'commission' : 'balance';
|
||||
var amountEl = form ? form.querySelector('[data-aksrt-withdraw-amount]') : null;
|
||||
if (amountEl) {
|
||||
var min = btn.getAttribute('data-withdraw-min');
|
||||
var remAmt = btn.getAttribute('data-withdraw-remaining-amount');
|
||||
var remCnt = btn.getAttribute('data-withdraw-remaining-count');
|
||||
if (min !== null) amountEl.setAttribute('data-withdraw-min', min);
|
||||
if (remAmt !== null) amountEl.setAttribute('data-withdraw-remaining-amount', remAmt);
|
||||
if (remCnt !== null) amountEl.setAttribute('data-withdraw-remaining-count', remCnt);
|
||||
}
|
||||
openModal(modal);
|
||||
});
|
||||
});
|
||||
modal.querySelectorAll('[data-aksrt-withdraw-close]').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () { closeModal(modal); });
|
||||
@@ -978,10 +994,11 @@
|
||||
}
|
||||
busy = true;
|
||||
notyf('正在提交提现申请…', 'load', '', 'aksrt-balance-withdraw-toast');
|
||||
var source = modal.dataset.aksrtWithdrawSource === 'commission' ? 'commission' : 'balance';
|
||||
api('/earnings/withdrawals', {
|
||||
method: 'POST',
|
||||
headers: { 'Idempotency-Key': operationKey(form) },
|
||||
body: JSON.stringify({ amount: amount, method: method, account: account })
|
||||
body: JSON.stringify({ amount: amount, method: method, account: account, source: source })
|
||||
}).then(function (r) {
|
||||
busy = false;
|
||||
if (!r.ok || (r.json && r.json.code && !r.json.success)) {
|
||||
@@ -994,11 +1011,12 @@
|
||||
if (data && data.withdrawal_number) successMessage += '(' + data.withdrawal_number + ')';
|
||||
notyf(successMessage, 'success', 5, 'aksrt-balance-withdraw-toast');
|
||||
closeModal(modal);
|
||||
var panel = modal.closest ? modal.closest('.dashboard-panel') : null;
|
||||
panel = panel || document.getElementById('panel-credits');
|
||||
// 佣金提现刷新推广收益面板,余额提现刷新余额面板;各自拉取对应片段。
|
||||
var panelName = source === 'commission' ? 'revenue' : 'credits';
|
||||
var panel = document.getElementById('panel-' + panelName) || (modal.closest ? modal.closest('.dashboard-panel') : null);
|
||||
var rest = (window.aksrtData && (window.aksrtData.restUrl || window.aksrtData.apiUrl)) || (window.aksrtUserCenter && window.aksrtUserCenter.restUrl) || '';
|
||||
if (panel && rest) {
|
||||
fetch(rest.replace(/\/$/, '') + '/user-center/panel/credits', { credentials: 'same-origin', headers: { 'X-WP-Nonce': (window.aksrtData && (window.aksrtData.restNonce || window.aksrtData.nonce)) || '' } })
|
||||
fetch(rest.replace(/\/$/, '') + '/user-center/panel/' + panelName, { credentials: 'same-origin', headers: { 'X-WP-Nonce': (window.aksrtData && (window.aksrtData.restNonce || window.aksrtData.nonce)) || '' } })
|
||||
.then(function (response) { return response.json(); })
|
||||
.then(function (payload) {
|
||||
if (!payload || !payload.success || !payload.data || typeof payload.data.html !== 'string') return;
|
||||
|
||||
@@ -158,6 +158,26 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 推广收益三个 Tab 的内容在首屏已由 PHP 全部直出,切换只需本地切换
|
||||
* 显隐,无需任何网络往返,消除切换阻塞。分页仍走 loadRevenueTab。 */
|
||||
function toggleRevenueTab(tabName) {
|
||||
var target = document.getElementById('panel-revenue');
|
||||
if (!target) return false;
|
||||
var pane = target.querySelector('[data-reward-pane="' + tabName + '"]');
|
||||
if (!pane) return false;
|
||||
target.querySelectorAll('[data-reward-pane]').forEach(function(node) {
|
||||
var active = node === pane;
|
||||
node.hidden = !active;
|
||||
});
|
||||
target.querySelectorAll('.uc-reward-tabs a[data-reward-tab]').forEach(function(link) {
|
||||
var active = link.getAttribute('data-reward-tab') === tabName;
|
||||
link.classList.toggle('is-active', active);
|
||||
if (active) link.setAttribute('aria-current', 'page');
|
||||
else link.removeAttribute('aria-current');
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function loadRevenueTab(queryParams) {
|
||||
var target = document.getElementById('panel-revenue');
|
||||
var restUrl = (window.aksrtData && (window.aksrtData.restUrl || window.aksrtData.apiUrl)) || cfg.restUrl || '';
|
||||
@@ -260,6 +280,13 @@
|
||||
if (link.closest('.uc-reward-tabs, .uc-reward-pagination')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var rewardTab = link.getAttribute('data-reward-tab');
|
||||
/* Tab 切换:内容已全部直出,纯本地切换显隐,零网络往返。 */
|
||||
if (rewardTab && toggleRevenueTab(rewardTab)) {
|
||||
if (window.history.replaceState) window.history.replaceState({}, '', '/user/revenue/');
|
||||
return;
|
||||
}
|
||||
/* 分页:需要新一页数据,仍走 REST 片段加载。 */
|
||||
loadRevenueTab(url.searchParams).then(function() {
|
||||
if (window.history.replaceState) window.history.replaceState({}, '', '/user/revenue/');
|
||||
if (typeof window.AKSRTAffiliateRevenueInit === 'function') window.AKSRTAffiliateRevenueInit();
|
||||
|
||||
Reference in new issue
Block a user