186 lines
8.4 KiB
JavaScript
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, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
.replace(/"/g, '"').replace(/'/g, ''');
|
|
}
|
|
|
|
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
|
|
};
|
|
});
|