This commit is contained in:
Flatlogic Bot 2026-02-22 13:11:48 +00:00
parent 3e2db33621
commit 00bab18fd4
3 changed files with 51 additions and 79 deletions

View File

@ -256,23 +256,28 @@ $requests = $stmt->fetchAll();
<span class="badge bg-light text-muted border"><?= $r['status'] == '4' ? '已拒绝' : '已通过' ?></span>
<?php else: ?>
<div class="btn-group btn-group-sm">
<?php if ($r['status'] === '0' || $r['status'] === 'pending'): ?>
<button type="button" class="btn btn-primary" onclick="submitMatchOnly(<?= $r['id'] ?>)">
匹配成功
</button>
<?php elseif ($r['status'] === '1' || $r['status'] === 'matched'): ?>
<button type="button" class="btn btn-info text-white" onclick="showSendModal(<?= $r['id'] ?>, '<?= htmlspecialchars($r['account_bank'] ?? '') ?>', '<?= htmlspecialchars($r['account_name'] ?? '') ?>', '<?= htmlspecialchars($r['account_number'] ?? '') ?>')">
发送账户
</button>
<?php elseif ($r['status'] === '2' || $r['status'] === 'account_sent'): ?>
<span class="badge bg-light text-muted border d-flex align-items-center px-2">等待用户转账...</span>
<?php elseif ($r['status'] === 'finished'): ?>
<?php if ($r['type'] === 'recharge'): ?>
<?php if ($r['type'] === 'recharge'): ?>
<?php if ($r['status'] == '0' || $r['status'] == 'pending'): ?>
<button type="button" class="btn btn-primary" onclick="submitMatchOnly(<?= $r['id'] ?>)">
匹配成功
</button>
<?php elseif ($r['status'] == '1' || $r['status'] == 'matched'): ?>
<button type="button" class="btn btn-info text-white" onclick="showSendModal(<?= $r['id'] ?>, '<?= htmlspecialchars($r['account_bank'] ?? '') ?>', '<?= htmlspecialchars($r['account_name'] ?? '') ?>', '<?= htmlspecialchars($r['account_number'] ?? '') ?>')">
发送账户
</button>
<?php elseif ($r['status'] == '2' || $r['status'] == 'account_sent'): ?>
<span class="badge bg-light text-muted border d-flex align-items-center px-2">等待用户转账...</span>
<?php elseif ($r['status'] == 'finished'): ?>
<button type="button" class="btn btn-outline-success fw-bold"
onclick="showApproveModal(<?= $r['id'] ?>, <?= $r['fiat_amount'] ?: 0 ?>, '<?= $r['fiat_currency'] ?: 'USDT' ?>', <?= $display_amount ?>)">
通过
</button>
<button class="btn btn-outline-danger fw-bold ms-1" onclick="showRejectModal(<?= $r['id'] ?>)">拒绝</button>
<?php else: ?>
<span class="badge bg-light text-muted border"><?= htmlspecialchars($r['status']) ?></span>
<?php endif; ?>
<?php else: /* Withdrawal */ ?>
<?php if ($r['status'] == '0' || $r['status'] == 'pending' || $r['status'] == 'finished'): ?>
<form method="POST" class="d-inline">
<input type="hidden" name="request_id" value="<?= $r['id'] ?>">
<input type="hidden" name="action" value="approve">
@ -280,10 +285,10 @@ $requests = $stmt->fetchAll();
通过
</button>
</form>
<button class="btn btn-outline-danger fw-bold ms-1" onclick="showRejectModal(<?= $r['id'] ?>)">拒绝</button>
<?php else: ?>
<span class="badge bg-light text-muted border"><?= htmlspecialchars($r['status']) ?></span>
<?php endif; ?>
<button class="btn btn-outline-danger fw-bold ms-1" onclick="showRejectModal(<?= $r['id'] ?>)">拒绝</button>
<?php else: ?>
<span class="badge bg-light text-muted border"><?= htmlspecialchars($r['status']) ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
@ -404,36 +409,6 @@ async function submitMatchOnly(id) {
if(data.success) location.reload(); else alert(data.error || '操作失败');
}
function showSendModal(id, bank, name, account) {
document.getElementById('send_id').value = id;
document.getElementById('send_bank').value = bank;
document.getElementById('send_name').value = name;
document.getElementById('send_account').value = account;
new bootstrap.Modal(document.getElementById('sendModal')).show();
}
async function submitSend() {
const id = document.getElementById('send_id').value;
const bank = document.getElementById('send_bank').value;
const name = document.getElementById('send_name').value;
const account = document.getElementById('send_account').value;
const note = document.getElementById('send_note').value;
if(!bank || !name || !account) return alert('请完整填写信息');
const formData = new FormData();
formData.append('id', id);
formData.append('bank', bank);
formData.append('name', name);
formData.append('account', account);
formData.append('note', note);
const resp = await fetch('../api/admin_recharge.php?action=send_account', { method: 'POST', body: formData });
const data = await resp.json();
if(data.success) location.reload(); else alert(data.error || '操作失败');
}
function showSendModal(id, bank, name, account) {
document.getElementById('send_id').value = id;
document.getElementById('send_bank').value = bank;

View File

@ -81,6 +81,11 @@ function ensureSchema() {
foreach ($columns as $c) {
if ($c['Field'] === 'status' && strpos(strtolower($c['Type']), 'int') !== false) {
$db->exec("ALTER TABLE finance_requests MODIFY COLUMN status VARCHAR(50) DEFAULT '0'");
// Fix legacy data
$db->exec("UPDATE finance_requests SET status = '0' WHERE status = '0' OR status = 0");
$db->exec("UPDATE finance_requests SET status = '1' WHERE status = '1' OR status = 1");
$db->exec("UPDATE finance_requests SET status = '2' WHERE status = '2' OR status = 2");
$db->exec("UPDATE finance_requests SET status = '3' WHERE status = '3' OR status = 3");
}
}

View File

@ -405,32 +405,17 @@ $bep20_addr = $settings['usdt_bep20_address'] ?? '0x742d35Cc6634C0532925a3b844Bc
let currentNetwork = 'TRC20';
let currentAddress = '<?= $trc20_addr ?>';
const userId = '<?= $user['uid'] ?? $user['id'] ?>';
const apiPath = (window.location.origin + window.location.pathname).split('/recharge.php')[0] + '/api/';
const apiPath = 'api/';
let rechargeCountdownInterval;
let modalChatLastIds = new Set();
let remainingSeconds = 1800;
let modalChatPolling = false;
window.lastRechargeStatus = null; // Track status to prevent flickering
function notify(icon, title, text = '') {
return Swal.fire({
icon: icon,
title: title,
text: text,
background: '#1e2329',
color: '#fff',
confirmButtonColor: '#0062ff',
confirmButtonText: '<?= __("confirm") ?>'
});
}
let exchangeRates = {};
window.lastRechargeStatus = null;
async function updateRate() {
const select = document.getElementById('fiatCurrency');
const symbol = select.value;
// Try to get fresh rates
try {
const resp = await fetch(apiPath + 'exchange.php?v=' + Date.now());
const data = await resp.json();
@ -446,7 +431,6 @@ async function updateRate() {
document.getElementById('selectedCurrencyLabel').innerText = symbol;
document.getElementById('currentRateText').innerText = `${rate.toFixed(4)} ${symbol}`;
// Update the data-rate attribute so calculateUSDT can use it too
select.options[select.selectedIndex].setAttribute('data-rate', rate);
calculateUSDT();
@ -455,6 +439,7 @@ async function updateRate() {
function calculateUSDT() {
const amount = parseFloat(document.getElementById('fiatAmount').value) || 0;
const select = document.getElementById('fiatCurrency');
if (!select) return;
const rate = parseFloat(select.options[select.selectedIndex].getAttribute('data-rate'));
const est = amount / rate;
document.getElementById('estUsdt').innerText = est.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USDT';
@ -473,8 +458,10 @@ function selectNetwork(net, addr) {
btn.classList.add('btn-outline-secondary');
}
});
document.getElementById('cryptoAddress').value = addr;
document.getElementById('qrCode').src = `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${addr}`;
const addrInput = document.getElementById('cryptoAddress');
if (addrInput) addrInput.value = addr;
const qrImg = document.getElementById('qrCode');
if (qrImg) qrImg.src = `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${addr}`;
}
function saveRechargeState(state) {
@ -489,6 +476,7 @@ function clearRechargeState() {
localStorage.removeItem('recharge_state');
if (rechargeCountdownInterval) clearInterval(rechargeCountdownInterval);
if (window.statusPollingInterval) clearInterval(window.statusPollingInterval);
window.lastRechargeStatus = null;
}
function finishTransfer() {
@ -500,7 +488,12 @@ function finishTransfer() {
formData.append('order_id', orderId);
fetch(apiPath + 'finance.php?v=' + Date.now(), { method: 'POST', body: formData })
.then(r => r.json())
.then(data => { if (data.success) renderRechargeUI({status: 'finished'}); });
.then(data => {
if (data.success) {
window.lastRechargeStatus = 'finished';
renderRechargeUI({status: 'finished'});
}
});
} else {
notify('warning', '订单信息丢失,请刷新页面');
}
@ -509,8 +502,10 @@ function finishTransfer() {
function finishTransferUI() {
clearRechargeState();
const modalEl = document.getElementById('rechargeModal');
const modalInstance = bootstrap.Modal.getInstance(modalEl);
if (modalInstance) modalInstance.hide();
if (modalEl) {
const modalInstance = bootstrap.Modal.getInstance(modalEl);
if (modalInstance) modalInstance.hide();
}
notify('success', '<?= __("recharge_success_title") ?>', '<?= __("recharge_success_text") ?>');
}
@ -525,7 +520,7 @@ function openRechargeModal(initialMessage, isRestore = false, orderId = null) {
if (!isRestore) {
remainingSeconds = 1800;
saveRechargeState({ phase: 'pending', initialMessage, orderId: currentOrderId });
sendModalMessage(initialMessage); // Automatically notify admin about the new recharge request
sendModalMessage(initialMessage);
}
if (currentOrderId) startStatusPolling(currentOrderId);
@ -544,7 +539,7 @@ function openRechargeModal(initialMessage, isRestore = false, orderId = null) {
if (--remainingSeconds < 0) clearInterval(rechargeCountdownInterval);
}, 1000);
if (!isRestore) renderRechargeUI({ status: 'pending' });
if (!isRestore) renderRechargeUI({ status: '0' });
initModalChat();
}
@ -554,14 +549,12 @@ function startStatusPolling(order_id) {
const modalEl = document.getElementById('rechargeModal');
if (!modalEl || !modalEl.classList.contains('show')) return;
try {
// Add cache busting
const r = await fetch(apiPath + `recharge_status.php?id=${order_id}&t=${Date.now()}`);
if (!r.ok) throw new Error('Network response was not ok');
const data = await r.json();
if (data.success) {
// Force status to string
const currentStatus = String(data.status);
// Only re-render if status has changed or UI is empty
const side = document.querySelector('.info-side');
if (window.lastRechargeStatus !== currentStatus || (side && side.innerHTML.trim() === "")) {
window.lastRechargeStatus = currentStatus;
@ -572,7 +565,9 @@ function startStatusPolling(order_id) {
clearInterval(window.statusPollingInterval);
}
}
} catch (e) { console.error('Status polling error:', e); }
} catch (e) {
console.error('Status polling error:', e);
}
};
checkStatus();
window.statusPollingInterval = setInterval(checkStatus, 3000);
@ -582,10 +577,8 @@ function renderRechargeUI(data) {
const side = document.querySelector('.info-side');
if (!side) return;
// Normalize status to string
const status = String(data.status || '0');
// Check if approved or rejected
if (status === 'completed' || status === '3') {
finishTransferUI();
return;
@ -613,7 +606,6 @@ function renderRechargeUI(data) {
return;
}
// Workflow phases
if (status === 'pending' || status === '0') {
side.innerHTML = `
<div class="text-center text-lg-start position-relative" style="z-index: 2;">
@ -744,7 +736,6 @@ function renderRechargeUI(data) {
</div>`;
}
// Sync countdown if exists
if (remainingSeconds > 0) {
let mins = Math.floor(remainingSeconds / 60), secs = remainingSeconds % 60;
const timeStr = `${mins}:${secs < 10 ? '0' : ''}${secs}`;
@ -762,9 +753,10 @@ document.addEventListener('DOMContentLoaded', async () => {
if (remainingSeconds > 0 && state.orderId) {
openRechargeModal(state.initialMessage, true, state.orderId);
try {
const r = await fetch(`api/recharge_status.php?id=${state.orderId}&_t=${Date.now()}`);
const r = await fetch(apiPath + `recharge_status.php?id=${state.orderId}&_t=${Date.now()}`);
const data = await r.json();
if (data.success) {
window.lastRechargeStatus = String(data.status);
renderRechargeUI(data);
}
} catch (e) {}