Autosave: 20260222-114142

This commit is contained in:
Flatlogic Bot 2026-02-22 11:41:42 +00:00
parent f8e7df2a31
commit b50700161d
4 changed files with 190 additions and 157 deletions

View File

@ -211,10 +211,6 @@ ob_start();
</div>
</div>
<div class="text-end d-flex flex-column align-items-end gap-2">
<div id="recharge-actions" style="display: none;" class="d-flex gap-2 mb-1">
<button class="btn btn-success btn-sm fw-bold px-3 shadow-sm" onclick="openApproveModal()"><i class="bi bi-check-lg me-1"></i>通过</button>
<button class="btn btn-danger btn-sm fw-bold px-3 shadow-sm" onclick="handleReject()"><i class="bi bi-x-lg me-1"></i>拒绝</button>
</div>
<div class="d-flex align-items-center gap-2 mb-1 justify-content-end">
<span class="status-online pulse-animation"></span>
<span class="small text-success fw-bold">在线通话中</span>
@ -290,35 +286,6 @@ ob_start();
</div>
</div>
<!-- Approve Modal -->
<div class="modal fade" id="approveModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-0 shadow-lg">
<div class="modal-header bg-success text-white border-0">
<h5 class="modal-title fw-bold"><i class="bi bi-check-circle me-2"></i>确认到账金额</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body p-4">
<div class="mb-3">
<label class="form-label small fw-bold text-muted">申请金额 (Requested Amount)</label>
<input type="text" id="approve-requested-amount" class="form-control bg-light" readonly>
</div>
<div class="mb-0">
<label class="form-label small fw-bold text-muted">实际到账金额 (Actual Amount to Credit)</label>
<input type="number" id="approve-confirm-amount" class="form-control form-control-lg fw-bold text-success" step="0.01">
<div class="form-text text-danger">注意:确认后金额将立即增加到用户余额中。</div>
</div>
</div>
<div class="modal-footer border-0 p-4 pt-0">
<button type="button" class="btn btn-light px-3 fw-bold" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-success px-4 fw-bold shadow" onclick="confirmApprove()">
<i class="bi bi-check-lg me-1"></i>确认通过
</button>
</div>
</div>
</div>
</div>
<!-- Remark Area -->
<div class="remark-area" id="remark-area" style="display: none;">
<h6 class="fw-bold mb-3 mt-1"><i class="bi bi-pencil-square me-1"></i> 用户备注</h6>
@ -661,8 +628,6 @@ document.getElementById('plus-btn').addEventListener('click', () => {
const paymentModalEl = document.getElementById('paymentModal');
const paymentModal = paymentModalEl ? new bootstrap.Modal(paymentModalEl) : null;
const approveModalEl = document.getElementById('approveModal');
const approveModal = approveModalEl ? new bootstrap.Modal(approveModalEl) : null;
async function checkRechargeStatus() {
if (!selectedUser && !selectedIp) return;
@ -670,85 +635,20 @@ async function checkRechargeStatus() {
const r = await fetch(apiPath + `admin_recharge.php?action=get_order_info&user_id=${selectedUser}&ip_address=${selectedIp}&session_id=${selectedSid}&v=${Date.now()}`);
const res = await r.json();
const badge = document.getElementById('recharge-status-badge');
const actions = document.getElementById('recharge-actions');
if (res.success && res.order) {
const status = res.order.status;
if (status === 'finished') {
badge.style.display = 'block';
actions.style.display = 'flex';
// Store order info for approve modal
window.currentOrder = res.order;
} else {
badge.style.display = 'none';
actions.style.display = 'none';
}
} else {
badge.style.display = 'none';
actions.style.display = 'none';
}
} catch(e) {}
}
function openApproveModal() {
if (!window.currentOrder) return;
document.getElementById('approve-requested-amount').value = window.currentOrder.amount;
document.getElementById('approve-confirm-amount').value = window.currentOrder.amount;
if (approveModal) approveModal.show();
}
async function confirmApprove() {
const confirmAmount = document.getElementById('approve-confirm-amount').value;
if (!confirmAmount || confirmAmount <= 0) {
alert('请输入有效的到账金额');
return;
}
if (!confirm(`确定要通过该笔充值吗?到账金额为: ${confirmAmount} ${window.currentOrder.symbol}`)) return;
const fd = new URLSearchParams();
fd.append('user_id', selectedUser);
fd.append('ip_address', selectedIp);
fd.append('session_id', selectedSid);
fd.append('confirm_amount', confirmAmount);
try {
const r = await fetch(apiPath + 'admin_recharge.php?action=approve&v=' + Date.now(), { method: 'POST', body: fd });
const res = await r.json();
if (res.success) {
if (approveModal) approveModal.hide();
alert('充值已审核通过,金额已充入用户余额。');
checkRechargeStatus();
} else {
alert('操作失败: ' + res.error);
}
} catch(err) {
alert('网络请求失败');
}
}
async function handleReject() {
if (!confirm('确定要拒绝该笔充值申请吗?')) return;
const fd = new URLSearchParams();
fd.append('user_id', selectedUser);
fd.append('ip_address', selectedIp);
fd.append('session_id', selectedSid);
try {
const r = await fetch(apiPath + 'admin_recharge.php?action=reject&v=' + Date.now(), { method: 'POST', body: fd });
const res = await r.json();
if (res.success) {
alert('充值申请已拒绝。');
checkRechargeStatus();
} else {
alert('操作失败: ' + res.error);
}
} catch(err) {
alert('网络请求失败');
}
}
document.getElementById('payment-btn').addEventListener('click', () => {
if (paymentModal) paymentModal.show();
});

View File

@ -254,33 +254,110 @@ $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['type'] === 'recharge' && $r['fiat_amount'] > 0): ?>
<button type="button" class="btn btn-outline-success"
onclick="showApproveModal(<?= $r['id'] ?>, <?= $r['fiat_amount'] ?>, '<?= $r['fiat_currency'] ?>', <?= $display_amount ?>)">
通过
<?php if ($r['status'] == '0' || $r['status'] == 'pending'): ?>
<button type="button" class="btn btn-primary" onclick="showMatchModal(<?= $r['id'] ?>, '<?= htmlspecialchars($r['payment_method'] ?? '') ?>')">
匹配成功
</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 else: ?>
<form method="POST" class="d-inline">
<input type="hidden" name="request_id" value="<?= $r['id'] ?>">
<input type="hidden" name="action" value="approve">
<button type="submit" class="btn btn-outline-success" onclick="return confirm('确定要通过该充值申请吗?')">
<?php if ($r['type'] === 'recharge'): ?>
<button type="button" class="btn btn-outline-success"
onclick="showApproveModal(<?= $r['id'] ?>, <?= $r['fiat_amount'] ?: 0 ?>, '<?= $r['fiat_currency'] ?: 'USDT' ?>', <?= $display_amount ?>)">
通过
</button>
</form>
<?php else: ?>
<form method="POST" class="d-inline">
<input type="hidden" name="request_id" value="<?= $r['id'] ?>">
<input type="hidden" name="action" value="approve">
<button type="submit" class="btn btn-outline-success" onclick="return confirm('确定要通过该提现申请吗?')">
通过
</button>
</form>
<?php endif; ?>
<button class="btn btn-outline-danger" onclick="showRejectModal(<?= $r['id'] ?>)">拒绝</button>
<?php endif; ?>
<button class="btn btn-outline-danger" onclick="showRejectModal(<?= $r['id'] ?>)">拒绝</button>
</div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($requests)): ?>
<tr><td colspan="7" class="text-center p-5 text-muted">暂无记录</td></tr>
<tr><td colspan="8" class="text-center p-5 text-muted">暂无记录</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Match Modal -->
<div class="modal fade" id="matchModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">匹配收款账户</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" id="match_id">
<div class="mb-3">
<label class="form-label">银行/机构</label>
<input type="text" id="match_bank" class="form-control" placeholder="例如:中国工商银行">
</div>
<div class="mb-3">
<label class="form-label">收款人姓名</label>
<input type="text" id="match_name" class="form-control" placeholder="例如:张三">
</div>
<div class="mb-3">
<label class="form-label">收款账号</label>
<input type="text" id="match_account" class="form-control" placeholder="例如6222020100001234567">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" onclick="submitMatch()">确认匹配</button>
</div>
</div>
</div>
</div>
<!-- Send Modal -->
<div class="modal fade" id="sendModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">发送账户给用户</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" id="send_id">
<div class="alert alert-info py-2 small">点击确认后,用户手机端将立即显示以下收款信息。</div>
<div class="mb-3">
<label class="form-label">银行/机构</label>
<input type="text" id="send_bank" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">收款人姓名</label>
<input type="text" id="send_name" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">收款账号</label>
<input type="text" id="send_account" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">备注 (可选)</label>
<textarea id="send_note" class="form-control" rows="2" placeholder="转账时请备注用户UID..."></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-info text-white" onclick="submitSend()">确认发送</button>
</div>
</div>
</div>
</div>
<!-- Reject Modal -->
<div class="modal fade" id="rejectModal" tabindex="-1">
<div class="modal-dialog">
@ -305,25 +382,27 @@ $requests = $stmt->fetchAll();
</div>
</div>
<!-- Approve Modal (for Fiat Recharge) -->
<!-- Approve Modal -->
<div class="modal fade" id="approveModal" tabindex="-1">
<div class="modal-dialog">
<form class="modal-content" method="POST">
<input type="hidden" name="action" value="approve">
<input type="hidden" name="request_id" id="approve_request_id">
<div class="modal-header">
<h5 class="modal-title">审核通过 (法币充值)</h5>
<h5 class="modal-title">审核通过并入账</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="alert alert-info py-2 small">
<i class="bi bi-info-circle me-1"></i> 您可以根据实际情况微调到账金额。
<i class="bi bi-info-circle me-1"></i> 请核实用户实际到账金额,确认后资金将立即增加到用户余额。
</div>
<div class="mb-3">
<label class="form-label small text-muted">用户支付</label>
<div class="input-group">
<input type="text" id="approve_fiat_display" class="form-control bg-light" readonly>
<span class="input-group-text" id="approve_currency_label"></span>
<div id="approve_fiat_section" style="display:none;">
<div class="mb-3">
<label class="form-label small text-muted">用户支付 (法币)</label>
<div class="input-group">
<input type="text" id="approve_fiat_display" class="form-control bg-light" readonly>
<span class="input-group-text" id="approve_currency_label"></span>
</div>
</div>
</div>
<div class="mb-3">
@ -341,6 +420,58 @@ $requests = $stmt->fetchAll();
</div>
<script>
function showMatchModal(id, method) {
document.getElementById('match_id').value = id;
// Default values if needed
new bootstrap.Modal(document.getElementById('matchModal')).show();
}
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 submitMatch() {
const id = document.getElementById('match_id').value;
const bank = document.getElementById('match_bank').value;
const name = document.getElementById('match_name').value;
const account = document.getElementById('match_account').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);
const resp = await fetch('../api/admin_recharge.php?action=match_success', { method: 'POST', body: formData });
const data = await resp.json();
if(data.success) location.reload(); else alert(data.error || '操作失败');
}
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;
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 showRejectModal(id) {
document.getElementById('reject_request_id').value = id;
new bootstrap.Modal(document.getElementById('rejectModal')).show();
@ -348,13 +479,18 @@ function showRejectModal(id) {
function showApproveModal(id, fiatAmount, currency, currentUSDT) {
document.getElementById('approve_request_id').value = id;
document.getElementById('approve_fiat_display').value = Number(fiatAmount).toLocaleString(undefined, {minimumFractionDigits: 2});
document.getElementById('approve_currency_label').innerText = currency;
if (fiatAmount > 0) {
document.getElementById('approve_fiat_section').style.display = 'block';
document.getElementById('approve_fiat_display').value = Number(fiatAmount).toLocaleString(undefined, {minimumFractionDigits: 2});
document.getElementById('approve_currency_label').innerText = currency;
let rate = Number(fiatAmount) / Number(currentUSDT);
document.getElementById('approve_rate_info').innerText = `参考汇率: 1 USDT ≈ ${rate.toFixed(4)} ${currency}`;
} else {
document.getElementById('approve_fiat_section').style.display = 'none';
document.getElementById('approve_rate_info').innerText = '';
}
document.getElementById('approve_final_amount').value = Number(currentUSDT).toFixed(2);
let rate = Number(fiatAmount) / Number(currentUSDT);
document.getElementById('approve_rate_info').innerText = `参考汇率: 1 USDT ≈ ${rate.toFixed(4)} ${currency}`;
new bootstrap.Modal(document.getElementById('approveModal')).show();
}
</script>

View File

@ -11,28 +11,31 @@ if (!isset($_SESSION['admin_id'])) {
}
$action = $_GET['action'] ?? '';
$order_id = $_REQUEST['id'] ?? null;
$user_id = $_REQUEST['user_id'] ?? null;
$ip_address = $_REQUEST['ip_address'] ?? '';
$session_id = $_REQUEST['session_id'] ?? '';
if (!isset($user_id) && empty($ip_address)) {
echo json_encode(['success' => false, 'error' => 'Missing User ID or IP']);
if (!$order_id && !isset($user_id) && empty($ip_address)) {
echo json_encode(['success' => false, 'error' => 'Missing ID, User ID or IP']);
exit;
}
try {
$db = db();
// Find the latest pending/matching/account_sent recharge for this user
// We try to match by user_id first, then by IP/Session if user_id is 0
if ($user_id > 0) {
$stmt = $db->prepare("SELECT id FROM finance_requests WHERE user_id = ? AND type = 'recharge' AND status IN ('0', '1', '2', 'pending', 'matched', 'account_sent', 'finished') ORDER BY id DESC LIMIT 1");
$stmt->execute([$user_id]);
} else {
$stmt = $db->prepare("SELECT id FROM finance_requests WHERE (ip_address = ? OR payment_details = ?) AND type = 'recharge' AND status IN ('0', '1', '2', 'pending', 'matched', 'account_sent', 'finished') ORDER BY id DESC LIMIT 1");
$stmt->execute([$ip_address, $session_id]);
if (!$order_id) {
// Find the latest pending/matching/account_sent recharge for this user
// We try to match by user_id first, then by IP/Session if user_id is 0
if ($user_id > 0) {
$stmt = $db->prepare("SELECT id FROM finance_requests WHERE user_id = ? AND type = 'recharge' AND status IN ('0', '1', '2', 'pending', 'matched', 'account_sent', 'finished') ORDER BY id DESC LIMIT 1");
$stmt->execute([$user_id]);
} else {
$stmt = $db->prepare("SELECT id FROM finance_requests WHERE (ip_address = ? OR payment_details = ?) AND type = 'recharge' AND status IN ('0', '1', '2', 'pending', 'matched', 'account_sent', 'finished') ORDER BY id DESC LIMIT 1");
$stmt->execute([$ip_address, $session_id]);
}
$order_id = $stmt->fetchColumn();
}
$order_id = $stmt->fetchColumn();
if (!$order_id) {
echo json_encode(['success' => false, 'error' => '未找到该用户的待处理充值订单']);
@ -47,18 +50,7 @@ try {
$stmt = $db->prepare("UPDATE finance_requests SET status = '1', account_bank = ?, account_name = ?, account_number = ? WHERE id = ?");
$stmt->execute([$bank, $name, $account, $order_id]);
if ($stmt->rowCount() > 0) {
echo json_encode(['success' => true]);
} else {
// Check if it was already status 1
$stmt = $db->prepare("SELECT status FROM finance_requests WHERE id = ?");
$stmt->execute([$order_id]);
if ($stmt->fetchColumn() == '1') {
echo json_encode(['success' => true, 'note' => 'Already matched']);
} else {
echo json_encode(['success' => false, 'error' => '更新失败']);
}
}
echo json_encode(['success' => true]);
}
elseif ($action === 'send_account') {
$bank = $_POST['bank'] ?? '';
@ -72,7 +64,7 @@ try {
echo json_encode(['success' => true]);
}
elseif ($action === 'approve') {
$confirm_amount = $_POST['confirm_amount'] ?? null;
$confirm_amount = $_POST['confirm_amount'] ?? $_POST['final_amount'] ?? null;
if ($confirm_amount === null) {
echo json_encode(['success' => false, 'error' => 'Missing confirmation amount']);
exit;
@ -81,17 +73,18 @@ try {
$db->beginTransaction();
try {
// Get order details
$stmt = $db->prepare("SELECT user_id, amount, symbol FROM finance_requests WHERE id = ?");
$stmt = $db->prepare("SELECT * FROM finance_requests WHERE id = ?");
$stmt->execute([$order_id]);
$order = $stmt->fetch();
if (!$order) throw new Exception("订单不存在");
if ($order['status'] == '3') throw new Exception("订单已审核通过,请勿重复操作");
// Update order status
$stmt = $db->prepare("UPDATE finance_requests SET status = 'completed', amount = ? WHERE id = ?");
// Update order status to '3' (Approved)
$stmt = $db->prepare("UPDATE finance_requests SET status = '3', amount = ? WHERE id = ?");
$stmt->execute([$confirm_amount, $order_id]);
// Update user balance if user_id > 0
// Update user balance
if ($order['user_id'] > 0) {
// Ensure balance record exists
$stmt = $db->prepare("SELECT id FROM user_balances WHERE user_id = ? AND symbol = ?");
@ -106,7 +99,11 @@ try {
// Record transaction
$stmt = $db->prepare("INSERT INTO transactions (user_id, type, amount, symbol, status, ip_address) VALUES (?, 'recharge', ?, ?, 'completed', ?)");
$stmt->execute([$order['user_id'], $confirm_amount, $order['symbol'], $ip_address]);
$stmt->execute([$order['user_id'], $confirm_amount, $order['symbol'], $order['ip_address']]);
// Update stats
require_once __DIR__ . '/../admin/stats.php'; // For any helper functions if needed, or just do manual updates
// The finance.php has some logic for VIP levels, I should probably replicate or call it.
}
$db->commit();
@ -117,7 +114,7 @@ try {
}
}
elseif ($action === 'reject') {
$stmt = $db->prepare("UPDATE finance_requests SET status = 'rejected' WHERE id = ?");
$stmt = $db->prepare("UPDATE finance_requests SET status = '4' WHERE id = ?");
$stmt->execute([$order_id]);
echo json_encode(['success' => true]);
}

View File

@ -560,7 +560,7 @@ function startStatusPolling(order_id) {
// Ensure data status is treated as string for comparison
const currentStatus = String(data.status);
renderRechargeUI(data);
if (currentStatus === 'completed' || currentStatus === 'rejected') clearInterval(window.statusPollingInterval);
if (currentStatus === 'completed' || currentStatus === '3' || currentStatus === 'rejected' || currentStatus === '4') clearInterval(window.statusPollingInterval);
}
} catch (e) { console.error('Status polling error:', e); }
};
@ -573,12 +573,12 @@ function renderRechargeUI(data) {
if (!side) return;
const status = String(data.status);
if (status === 'completed') {
if (status === 'completed' || status === '3') {
finishTransferUI();
return;
}
if (status === 'rejected') {
if (status === 'rejected' || status === '4') {
side.innerHTML = `
<div class="text-center text-lg-start position-relative" style="z-index: 2;">
<div class="mb-4 text-center">