Files
jiapu/public/js/earning-pages.js
T
2026-08-29 19:06:07 +08:00

186 lines
8.4 KiB
JavaScript

(function (root, factory) {
if (typeof module === 'object' && module.exports) {
module.exports = factory(root);
return;
}
root.EarningPages = factory(root);
if (root.document) root.document.addEventListener('DOMContentLoaded', root.EarningPages.init);
})(typeof globalThis !== 'undefined' ? globalThis : window, function (root) {
'use strict';
function confirmAction(message) {
if (root.ProfileUI && typeof root.ProfileUI.confirmAction === 'function') {
return root.ProfileUI.confirmAction(message);
}
return Promise.resolve(!root['confirm'] || root['confirm'](message));
}
var WITHDRAWAL_STATUS = {
PENDING: '待审核', APPROVED: '已通过', PAYING: '打款中', PAID: '已到账',
REJECTED: '已驳回', FAILED: '打款失败', CANCELLED: '已取消'
};
var ENTRY_TYPE = {
PAYMENT_REWARD: '推广奖励', PAYMENT_REFUND_REVERSAL: '退款冲销', WITHDRAWAL_FREEZE: '提现冻结',
WITHDRAWAL_CANCEL: '取消提现', WITHDRAWAL_REJECT: '提现驳回', WITHDRAWAL_PAID: '提现到账',
WITHDRAWAL_FAILED: '提现失败'
};
function escapeHtml(value) {
return String(value === undefined || value === null ? '' : value)
.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}
function normalizeMoney(value) {
var text = String(value === undefined || value === null ? '' : value).trim();
return /^(?:0|[1-9][0-9]*)(?:\.[0-9]{1,2})?$/.test(text) ? text : '';
}
function createRequestId() {
if (root.crypto && typeof root.crypto.randomUUID === 'function') return root.crypto.randomUUID();
return 'pc-' + Date.now() + '-' + Math.random().toString(16).slice(2);
}
function moneyToCents(value) {
var text = normalizeMoney(value);
var parts;
if (!text) return null;
parts = text.split('.');
return BigInt(parts[0]) * 100n + BigInt((parts[1] || '').padEnd(2, '0'));
}
function buildWithdrawalBody(values, requestId) {
var source = values || {};
return {
requestId: String(requestId || '').trim(),
amount: normalizeMoney(source.amount),
payoutQrOssId: String(source.payoutQrOssId || '').trim(),
payoutAccountName: String(source.payoutAccountName || '').trim()
};
}
function validateWithdrawalBody(body, availableAmount) {
if (!body.requestId) return '提现请求号生成失败,请刷新页面重试';
if (!body.amount || Number(body.amount) <= 0) return '请输入有效提现金额,最多两位小数';
if (moneyToCents(availableAmount) !== null && moneyToCents(body.amount) > moneyToCents(availableAmount)) {
return '提现金额不能超过可用余额';
}
if (!/^[1-9][0-9]*$/.test(body.payoutQrOssId)) return '请上传收款码';
if (!body.payoutAccountName) return '请填写收款人姓名';
if (body.payoutAccountName.length > 64) return '收款人姓名不能超过 64 个字符';
return '';
}
function renderSummary(value) {
var source = value || {};
return '<div class="module-grid three"><div class="module-card"><h3>可用收益</h3><strong>¥' +
escapeHtml(source.availableAmount || '0.00') + '</strong></div><div class="module-card"><h3>冻结金额</h3><strong>¥' +
escapeHtml(source.frozenAmount || '0.00') + '</strong></div><div class="module-card"><h3>最低提现</h3><strong>' +
escapeHtml(source.minimumWithdrawal ? '¥' + source.minimumWithdrawal : '以提交校验为准') + '</strong></div></div>';
}
function renderLedger(page) {
var rows = page && Array.isArray(page.rows) ? page.rows : [];
if (!rows.length) return '<div class="api-empty">当前没有收益流水</div>';
return rows.map(function (item) {
return '<article class="module-row"><div><h3>' + escapeHtml(ENTRY_TYPE[item.entryType] || item.entryType || '收益变动') +
'</h3><p>' + escapeHtml([item.createTime, item.remark].filter(Boolean).join(' · ')) +
'</p></div><strong>' + escapeHtml(String(item.availableDelta || '0.00')) + '</strong></article>';
}).join('');
}
function renderWithdrawals(page) {
var rows = page && Array.isArray(page.rows) ? page.rows : [];
if (!rows.length) return '<div class="api-empty">当前没有提现记录</div>';
return rows.map(function (item) {
var id = String(item.withdrawalId || '').trim();
return '<article class="module-row"><div><h3>提现 ¥' + escapeHtml(item.amount || '0.00') +
'</h3><p>' + escapeHtml([item.withdrawalNo, item.payoutAccountName, item.createTime, item.auditRemark, item.failureReason].filter(Boolean).join(' · ')) +
'</p></div><span class="pill">' + escapeHtml(WITHDRAWAL_STATUS[item.withdrawalStatus] || item.withdrawalStatus || '未知') + '</span>' +
(item.withdrawalStatus === 'PENDING' && /^[1-9][0-9]*$/.test(id) ? '<button class="btn outline" type="button" data-withdrawal-cancel="' + escapeHtml(id) + '">取消</button>' : '') + '</article>';
}).join('');
}
async function init() {
var page = root.document && root.document.querySelector('[data-earning-page]');
var api = root.GenealogyApi && root.GenealogyApi.defaultClient;
var summaryBox = page && page.querySelector('[data-earning-summary]');
var ledgerBox = page && page.querySelector('[data-earning-ledger]');
var withdrawalBox = page && page.querySelector('[data-earning-withdrawals]');
var form = page && page.querySelector('[data-withdrawal-form]');
var status = page && page.querySelector('[data-earning-status]');
var availableAmount = '';
var requestId = createRequestId();
var pending = false;
if (!page) return;
if (!api || !api.getToken || !api.getToken()) {
if (root.location) root.location.href = 'login.html';
return;
}
function setStatus(type, message) {
if (type) root.ProfileUI.setApiState(status, type, message);
else status.textContent = message || '';
}
async function loadAll() {
var values = await Promise.all([
api.earningSummary(), api.earningLedger({ pageNum: 1, pageSize: 20 }),
api.earningWithdrawals({ pageNum: 1, pageSize: 20 })
]);
availableAmount = String(values[0] && values[0].availableAmount || '');
summaryBox.innerHTML = renderSummary(values[0]);
ledgerBox.innerHTML = renderLedger(values[1]);
withdrawalBox.innerHTML = renderWithdrawals(values[2]);
form.querySelector('[data-withdrawal-submit]').disabled = values[0] && values[0].withdrawalEnabled === false;
return values;
}
try { await loadAll(); setStatus('', '收益数据已加载'); }
catch (error) { setStatus('error', error.message || '收益数据读取失败'); return; }
form.addEventListener('submit', async function (event) {
var body;
var validation;
event.preventDefault();
if (pending) return;
body = buildWithdrawalBody({
amount: form.elements.amount.value,
payoutAccountName: form.elements.payoutAccountName.value,
payoutQrOssId: form.elements.payoutQrOssId.value
}, requestId);
validation = validateWithdrawalBody(body, availableAmount);
if (validation) return setStatus('error', validation);
pending = true; setStatus('loading', '正在提交提现申请…');
try {
await api.createEarningWithdrawal(body);
requestId = createRequestId(); form.reset(); form.elements.payoutQrOssId.value = '';
await loadAll(); setStatus('', '提现申请已提交');
} catch (error) { setStatus('error', error.message || '提现申请失败'); }
finally { pending = false; }
});
withdrawalBox.addEventListener('click', async function (event) {
var button = event.target.closest('[data-withdrawal-cancel]');
if (!button || pending || !await confirmAction('确认取消这笔待审核提现吗?')) return;
pending = true; setStatus('loading', '正在取消提现…');
try { await api.cancelEarningWithdrawal(button.getAttribute('data-withdrawal-cancel')); await loadAll(); setStatus('', '提现已取消'); }
catch (error) { setStatus('error', error.message || '取消提现失败'); }
finally { pending = false; }
});
}
return {
normalizeMoney: normalizeMoney,
createRequestId: createRequestId,
buildWithdrawalBody: buildWithdrawalBody,
validateWithdrawalBody: validateWithdrawalBody,
renderSummary: renderSummary,
renderLedger: renderLedger,
renderWithdrawals: renderWithdrawals,
init: init
};
});