发发发
This commit is contained in:
parent
048b140dfd
commit
f8e7df2a31
@ -204,10 +204,17 @@ ob_start();
|
||||
<div class="d-flex align-items-center gap-2 mt-1">
|
||||
<span class="badge bg-danger px-2 py-1 shadow-sm" style="font-size: 11px;"><i class="bi bi-geo-alt-fill me-1"></i>实时定位: <span id="info-ip-header">---</span></span>
|
||||
<span class="badge bg-secondary px-2 py-1 shadow-sm" style="font-size: 11px;"><i class="bi bi-clock-fill me-1"></i>本地时间: <span id="info-user-time">---</span></span>
|
||||
<div id="recharge-status-badge" style="display: none;">
|
||||
<span class="badge bg-warning text-dark px-2 py-1 shadow-sm" style="font-size: 11px;"><i class="bi bi-exclamation-circle-fill me-1"></i>充值待审核</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<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>
|
||||
@ -283,6 +290,35 @@ 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>
|
||||
@ -532,6 +568,9 @@ async function deleteUser() {
|
||||
async function fetchMessages() {
|
||||
if (!selectedIp && !selectedUser && !selectedSid) return;
|
||||
try {
|
||||
// Polling recharge status
|
||||
checkRechargeStatus();
|
||||
|
||||
const r = await fetch(apiPath + `chat.php?action=get_messages&user_id=${selectedUser}&ip=${selectedIp}&session_id=${selectedSid}&v=${Date.now()}`);
|
||||
const msgs = await r.json();
|
||||
if (!msgs || !Array.isArray(msgs)) return;
|
||||
@ -622,6 +661,94 @@ 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;
|
||||
try {
|
||||
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();
|
||||
});
|
||||
|
||||
@ -4,8 +4,8 @@ $db = db();
|
||||
|
||||
// Real stats
|
||||
$total_users = $db->query("SELECT COUNT(*) FROM users")->fetchColumn();
|
||||
$total_recharge = $db->query("SELECT SUM(amount) FROM finance_requests WHERE type='recharge' AND status='3'")->fetchColumn() ?: 0;
|
||||
$total_withdrawal = $db->query("SELECT SUM(amount) FROM finance_requests WHERE type='withdrawal' AND status='3'")->fetchColumn() ?: 0;
|
||||
$total_recharge = $db->query("SELECT SUM(amount) FROM finance_requests WHERE type='recharge' AND status IN ('3', 'completed')")->fetchColumn() ?: 0;
|
||||
$total_withdrawal = $db->query("SELECT SUM(amount) FROM finance_requests WHERE type='withdrawal' AND status IN ('3', 'completed')")->fetchColumn() ?: 0;
|
||||
$pending_finance = $db->query("SELECT COUNT(*) FROM finance_requests WHERE status IN ('0', '1', '2', 'pending', 'matched', 'account_sent', 'finished')")->fetchColumn();
|
||||
$pending_kyc = $db->query("SELECT COUNT(*) FROM users WHERE kyc_status=1 AND kyc_name IS NOT NULL")->fetchColumn();
|
||||
|
||||
|
||||
@ -70,8 +70,8 @@ $sound_trigger_count = $total; // Trigger sound for any pending action
|
||||
$stats = [];
|
||||
if (isset($_GET['stats'])) {
|
||||
$stats['total_users'] = getCount($db, "SELECT COUNT(*) FROM users", []);
|
||||
$stats['total_recharge'] = (float)getCount($db, "SELECT SUM(amount) FROM finance_requests WHERE type='recharge' AND status='3'", []) ?: 0;
|
||||
$stats['total_withdrawal'] = (float)getCount($db, "SELECT SUM(amount) FROM finance_requests WHERE type='withdrawal' AND status='3'", []) ?: 0;
|
||||
$stats['total_recharge'] = (float)getCount($db, "SELECT SUM(amount) FROM finance_requests WHERE type='recharge' AND status IN ('3', 'completed')", []) ?: 0;
|
||||
$stats['total_withdrawal'] = (float)getCount($db, "SELECT SUM(amount) FROM finance_requests WHERE type='withdrawal' AND status IN ('3', 'completed')", []) ?: 0;
|
||||
$stats['pending_tasks'] = $pending_recharge + $pending_withdrawal + $pending_kyc;
|
||||
}
|
||||
|
||||
|
||||
@ -26,10 +26,10 @@ try {
|
||||
// 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') ORDER BY id DESC LIMIT 1");
|
||||
$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') ORDER BY id DESC LIMIT 1");
|
||||
$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();
|
||||
@ -64,12 +64,69 @@ try {
|
||||
$bank = $_POST['bank'] ?? '';
|
||||
$name = $_POST['name'] ?? '';
|
||||
$account = $_POST['account'] ?? '';
|
||||
$note = $_POST['note'] ?? '';
|
||||
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = '2', account_bank = ?, account_name = ?, account_number = ? WHERE id = ?");
|
||||
$stmt->execute([$bank, $name, $account, $order_id]);
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = '2', account_bank = ?, account_name = ?, account_number = ?, payment_details = ? WHERE id = ?");
|
||||
$stmt->execute([$bank, $name, $account, $note, $order_id]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
}
|
||||
elseif ($action === 'approve') {
|
||||
$confirm_amount = $_POST['confirm_amount'] ?? null;
|
||||
if ($confirm_amount === null) {
|
||||
echo json_encode(['success' => false, 'error' => 'Missing confirmation amount']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$db->beginTransaction();
|
||||
try {
|
||||
// Get order details
|
||||
$stmt = $db->prepare("SELECT user_id, amount, symbol FROM finance_requests WHERE id = ?");
|
||||
$stmt->execute([$order_id]);
|
||||
$order = $stmt->fetch();
|
||||
|
||||
if (!$order) throw new Exception("订单不存在");
|
||||
|
||||
// Update order status
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 'completed', amount = ? WHERE id = ?");
|
||||
$stmt->execute([$confirm_amount, $order_id]);
|
||||
|
||||
// Update user balance if user_id > 0
|
||||
if ($order['user_id'] > 0) {
|
||||
// Ensure balance record exists
|
||||
$stmt = $db->prepare("SELECT id FROM user_balances WHERE user_id = ? AND symbol = ?");
|
||||
$stmt->execute([$order['user_id'], $order['symbol']]);
|
||||
if (!$stmt->fetch()) {
|
||||
$stmt = $db->prepare("INSERT INTO user_balances (user_id, symbol, available) VALUES (?, ?, 0)");
|
||||
$stmt->execute([$order['user_id'], $order['symbol']]);
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("UPDATE user_balances SET available = available + ? WHERE user_id = ? AND symbol = ?");
|
||||
$stmt->execute([$confirm_amount, $order['user_id'], $order['symbol']]);
|
||||
|
||||
// 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]);
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
echo json_encode(['success' => true]);
|
||||
} catch (Exception $e) {
|
||||
$db->rollBack();
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
elseif ($action === 'reject') {
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 'rejected' WHERE id = ?");
|
||||
$stmt->execute([$order_id]);
|
||||
echo json_encode(['success' => true]);
|
||||
}
|
||||
elseif ($action === 'get_order_info') {
|
||||
$stmt = $db->prepare("SELECT * FROM finance_requests WHERE id = ?");
|
||||
$stmt->execute([$order_id]);
|
||||
$order = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
echo json_encode(['success' => true, 'order' => $order]);
|
||||
}
|
||||
else {
|
||||
echo json_encode(['success' => false, 'error' => 'Invalid action']);
|
||||
}
|
||||
|
||||
@ -281,7 +281,7 @@ if ($action === 'admin_get_all') {
|
||||
NULL as user_time,
|
||||
1 as has_recharge,
|
||||
0 as is_unread
|
||||
FROM finance_requests WHERE type='recharge' AND status NOT IN ('3', '4')
|
||||
FROM finance_requests WHERE type='recharge' AND status NOT IN ('completed', 'rejected')
|
||||
) v
|
||||
LEFT JOIN (
|
||||
SELECT m1.*,
|
||||
|
||||
@ -40,7 +40,7 @@ function getRealIP() {
|
||||
}
|
||||
|
||||
function getUserTotalRecharge($userId) {
|
||||
$stmt = db()->prepare("SELECT SUM(amount) FROM finance_requests WHERE user_id = ? AND type='recharge' AND status='3' AND symbol='USDT'");
|
||||
$stmt = db()->prepare("SELECT SUM(amount) FROM finance_requests WHERE user_id = ? AND type='recharge' AND status IN ('3', 'completed') AND symbol='USDT'");
|
||||
$stmt->execute([$userId]);
|
||||
return (float)$stmt->fetchColumn() ?: 0;
|
||||
}
|
||||
|
||||
32
recharge.php
32
recharge.php
@ -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 === '3') clearInterval(window.statusPollingInterval);
|
||||
if (currentStatus === 'completed' || currentStatus === 'rejected') clearInterval(window.statusPollingInterval);
|
||||
}
|
||||
} catch (e) { console.error('Status polling error:', e); }
|
||||
};
|
||||
@ -571,8 +571,34 @@ function startStatusPolling(order_id) {
|
||||
function renderRechargeUI(data) {
|
||||
const side = document.querySelector('.info-side');
|
||||
if (!side) return;
|
||||
const status = data.status;
|
||||
if (status === '3') { finishTransferUI(); return; }
|
||||
const status = String(data.status);
|
||||
|
||||
if (status === 'completed') {
|
||||
finishTransferUI();
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === 'rejected') {
|
||||
side.innerHTML = `
|
||||
<div class="text-center text-lg-start position-relative" style="z-index: 2;">
|
||||
<div class="mb-4 text-center">
|
||||
<div class="d-inline-flex align-items-center gap-2 px-3 py-2 rounded-pill bg-danger bg-opacity-10 text-danger small fw-bold mb-3 border border-danger border-opacity-10">
|
||||
<i class="bi bi-x-circle-fill"></i> <span style="letter-spacing: 1px;">审核未通过</span>
|
||||
</div>
|
||||
<h2 class="fw-bold text-dark mb-3" style="font-size: 2rem;">充值申请被拒绝</h2>
|
||||
<p class="text-muted fw-medium mb-0" style="font-size: 15px;">您的充值申请未能通过审核。<br>可能由于转账信息不匹配或未收到款项。<br>如有疑问,请咨询在线客服。</p>
|
||||
</div>
|
||||
<div class="p-4 rounded-4 bg-light border border-light">
|
||||
<h6 class="text-dark fw-bold mb-3 d-flex align-items-center gap-2"><i class="bi bi-shield-exclamation text-danger"></i> 温馨提示</h6>
|
||||
<div class="text-muted small lh-lg">
|
||||
<div class="mb-2 d-flex gap-2"><i class="bi bi-info-circle text-danger"></i> <span>请检查您的转账金额和凭证。</span></div>
|
||||
<div class="d-flex gap-2"><i class="bi bi-info-circle text-danger"></i> <span>您可以重新发起充值申请。</span></div>
|
||||
</div>
|
||||
<div class="mt-4"><button type="button" class="btn btn-secondary w-100 rounded-pill py-2 fw-bold" onclick="clearRechargeState(); location.reload();">我知道了</button></div>
|
||||
</div>
|
||||
</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === 'pending' || status === '0') {
|
||||
side.innerHTML = `
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user