新消息想
This commit is contained in:
parent
1adae4ff1b
commit
9cc9c493bd
@ -321,7 +321,7 @@ let notifySound = new Audio('https://assets.mixkit.co/active_storage/sfx/2358/23
|
|||||||
const searchInput = document.getElementById('user-search');
|
const searchInput = document.getElementById('user-search');
|
||||||
const search = searchInput ? searchInput.value.toLowerCase() : '';
|
const search = searchInput ? searchInput.value.toLowerCase() : '';
|
||||||
|
|
||||||
const r = await fetch('/api/chat.php?action=admin_get_all');
|
const r = await fetch('../api/chat.php?action=admin_get_all');
|
||||||
if (!r.ok) return;
|
if (!r.ok) return;
|
||||||
|
|
||||||
const users = await r.json();
|
const users = await r.json();
|
||||||
@ -455,14 +455,14 @@ let notifySound = new Audio('https://assets.mixkit.co/active_storage/sfx/2358/23
|
|||||||
fd.append('user_id', userId);
|
fd.append('user_id', userId);
|
||||||
fd.append('ip_address', ip);
|
fd.append('ip_address', ip);
|
||||||
fd.append('session_id', sid);
|
fd.append('session_id', sid);
|
||||||
fetch('/api/chat.php?action=mark_read', { method: 'POST', body: fd }).then(() => refreshUsers());
|
fetch('../api/chat.php?action=mark_read', { method: 'POST', body: fd }).then(() => refreshUsers());
|
||||||
}
|
}
|
||||||
|
|
||||||
async function recallMessage(msgId) {
|
async function recallMessage(msgId) {
|
||||||
if (!confirm('确定撤回该消息吗?')) return;
|
if (!confirm('确定撤回该消息吗?')) return;
|
||||||
const fd = new URLSearchParams();
|
const fd = new URLSearchParams();
|
||||||
fd.append('message_id', msgId);
|
fd.append('message_id', msgId);
|
||||||
const r = await fetch('/api/chat.php?action=admin_recall_message', { method: 'POST', body: fd });
|
const r = await fetch('../api/chat.php?action=admin_recall_message', { method: 'POST', body: fd });
|
||||||
const res = await r.json();
|
const res = await r.json();
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
fetchMessages();
|
fetchMessages();
|
||||||
@ -476,7 +476,7 @@ async function deleteChat(userId, ip, sid, event) {
|
|||||||
fd.append('user_id', userId);
|
fd.append('user_id', userId);
|
||||||
fd.append('ip_address', ip);
|
fd.append('ip_address', ip);
|
||||||
fd.append('session_id', sid);
|
fd.append('session_id', sid);
|
||||||
const r = await fetch('/api/chat.php?action=admin_delete_user', { method: 'POST', body: fd });
|
const r = await fetch('../api/chat.php?action=admin_delete_user', { method: 'POST', body: fd });
|
||||||
const res = await r.json();
|
const res = await r.json();
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
if (selectedSid == sid && selectedIp == ip && selectedUser == userId) {
|
if (selectedSid == sid && selectedIp == ip && selectedUser == userId) {
|
||||||
@ -503,7 +503,7 @@ async function deleteUser() {
|
|||||||
fd.append('user_id', selectedUser);
|
fd.append('user_id', selectedUser);
|
||||||
fd.append('ip_address', selectedIp);
|
fd.append('ip_address', selectedIp);
|
||||||
fd.append('session_id', selectedSid);
|
fd.append('session_id', selectedSid);
|
||||||
const r = await fetch('/api/chat.php?action=admin_delete_user', { method: 'POST', body: fd });
|
const r = await fetch('../api/chat.php?action=admin_delete_user', { method: 'POST', body: fd });
|
||||||
const res = await r.json();
|
const res = await r.json();
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
selectedUser = null;
|
selectedUser = null;
|
||||||
@ -525,7 +525,7 @@ async function deleteUser() {
|
|||||||
async function fetchMessages() {
|
async function fetchMessages() {
|
||||||
if (!selectedIp && !selectedUser && !selectedSid) return;
|
if (!selectedIp && !selectedUser && !selectedSid) return;
|
||||||
try {
|
try {
|
||||||
const r = await fetch(`/api/chat.php?action=get_messages&user_id=${selectedUser}&ip=${selectedIp}&session_id=${selectedSid}`);
|
const r = await fetch(`../api/chat.php?action=get_messages&user_id=${selectedUser}&ip=${selectedIp}&session_id=${selectedSid}`);
|
||||||
const msgs = await r.json();
|
const msgs = await r.json();
|
||||||
if (!msgs || !Array.isArray(msgs)) return;
|
if (!msgs || !Array.isArray(msgs)) return;
|
||||||
|
|
||||||
@ -637,7 +637,7 @@ async function notifyMatchSuccess() {
|
|||||||
fd.append('account', account);
|
fd.append('account', account);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = await fetch('/api/admin_recharge.php?action=match_success', { method: 'POST', body: fd });
|
const r = await fetch('../api/admin_recharge.php?action=match_success', { method: 'POST', body: fd });
|
||||||
const res = await r.json();
|
const res = await r.json();
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
alert('匹配成功!状态已更新。若要向用户显示收款账户,请继续点击“发送账户”按钮。');
|
alert('匹配成功!状态已更新。若要向用户显示收款账户,请继续点击“发送账户”按钮。');
|
||||||
@ -666,7 +666,7 @@ async function sendPaymentInfo() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('Sending account info...', { bank, name, account });
|
console.log('Sending account info...', { bank, name, account });
|
||||||
const r = await fetch('/api/admin_recharge.php?action=send_account', { method: 'POST', body: fd });
|
const r = await fetch('../api/admin_recharge.php?action=send_account', { method: 'POST', body: fd });
|
||||||
const res = await r.json();
|
const res = await r.json();
|
||||||
|
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
@ -712,7 +712,7 @@ document.getElementById('image-input').addEventListener('change', async (e) => {
|
|||||||
formData.append('session_id', selectedSid || '');
|
formData.append('session_id', selectedSid || '');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = await fetch('/api/chat.php?action=upload_image', {
|
const r = await fetch('../api/chat.php?action=upload_image', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
});
|
});
|
||||||
@ -762,7 +762,7 @@ document.getElementById('chat-form').addEventListener('submit', async (e) => {
|
|||||||
fd.append('session_id', selectedSid);
|
fd.append('session_id', selectedSid);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = await fetch('/api/chat.php?action=admin_send', { method: 'POST', body: fd });
|
const r = await fetch('../api/chat.php?action=admin_send', { method: 'POST', body: fd });
|
||||||
const res = await r.json();
|
const res = await r.json();
|
||||||
|
|
||||||
const tempMsg = document.querySelector(`[data-id="${tempId}"]`);
|
const tempMsg = document.querySelector(`[data-id="${tempId}"]`);
|
||||||
@ -784,7 +784,7 @@ document.getElementById('save-remark-btn').addEventListener('click', async () =>
|
|||||||
fd.append('session_id', selectedSid);
|
fd.append('session_id', selectedSid);
|
||||||
fd.append('remark', remark);
|
fd.append('remark', remark);
|
||||||
|
|
||||||
const r = await fetch('/api/chat.php?action=save_remark', { method: 'POST', body: fd });
|
const r = await fetch('../api/chat.php?action=save_remark', { method: 'POST', body: fd });
|
||||||
const res = await r.json();
|
const res = await r.json();
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
alert('备注已保存');
|
alert('备注已保存');
|
||||||
|
|||||||
@ -215,20 +215,22 @@ $requests = $stmt->fetchAll();
|
|||||||
</td>
|
</td>
|
||||||
<td><small class="text-muted"><?= $r['created_at'] ?></small></td>
|
<td><small class="text-muted"><?= $r['created_at'] ?></small></td>
|
||||||
<td>
|
<td>
|
||||||
<?php if ($r['status'] == 0): ?>
|
<?php if ($r['status'] === '0' || $r['status'] === 'pending'): ?>
|
||||||
<span class="badge bg-secondary">待匹配</span>
|
<span class="badge bg-secondary">待匹配</span>
|
||||||
<?php elseif ($r['status'] == 1): ?>
|
<?php elseif ($r['status'] === 'matched' || $r['status'] === '1'): ?>
|
||||||
<span class="badge bg-info">匹配成功</span>
|
<span class="badge bg-info">匹配成功</span>
|
||||||
<?php elseif ($r['status'] == 2): ?>
|
<?php elseif ($r['status'] === 'account_sent' || $r['status'] === '2'): ?>
|
||||||
<span class="badge bg-primary">已发送账户</span>
|
<span class="badge bg-primary">已发送账户</span>
|
||||||
<?php elseif ($r['status'] == 3): ?>
|
<?php elseif ($r['status'] === '3' || $r['status'] === 'finished'): ?>
|
||||||
<span class="badge bg-success">已通过</span>
|
<span class="badge bg-success">已通过</span>
|
||||||
<?php elseif ($r['status'] == 4): ?>
|
<?php elseif ($r['status'] === '4'): ?>
|
||||||
<span class="badge bg-danger">已拒绝</span>
|
<span class="badge bg-danger">已拒绝</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="badge bg-dark"><?= htmlspecialchars($r['status']) ?></span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<?php if (in_array((int)$r['status'], [0, 1, 2])): ?>
|
<?php if (in_array($r['status'], ['0', 'pending', 'matched', '1', 'account_sent', '2'])): ?>
|
||||||
<div class="btn-group btn-group-sm">
|
<div class="btn-group btn-group-sm">
|
||||||
<form method="POST" class="d-inline">
|
<form method="POST" class="d-inline">
|
||||||
<input type="hidden" name="request_id" value="<?= $r['id'] ?>">
|
<input type="hidden" name="request_id" value="<?= $r['id'] ?>">
|
||||||
|
|||||||
@ -283,19 +283,19 @@ function renderAdminPage($content, $title = '后台管理') {
|
|||||||
|
|
||||||
// Clear badges based on current page
|
// Clear badges based on current page
|
||||||
if (currentPage.includes('finance.php')) {
|
if (currentPage.includes('finance.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=finance');
|
fetch('../api/admin_notifications.php?action=clear&type=finance');
|
||||||
} else if (currentPage.includes('kyc.php')) {
|
} else if (currentPage.includes('kyc.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=kyc');
|
fetch('../api/admin_notifications.php?action=clear&type=kyc');
|
||||||
} else if (currentPage.includes('binary.php')) {
|
} else if (currentPage.includes('binary.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=binary');
|
fetch('../api/admin_notifications.php?action=clear&type=binary');
|
||||||
} else if (currentPage.includes('contract.php')) {
|
} else if (currentPage.includes('contract.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=contract');
|
fetch('../api/admin_notifications.php?action=clear&type=contract');
|
||||||
} else if (currentPage.includes('spot.php')) {
|
} else if (currentPage.includes('spot.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=spot');
|
fetch('../api/admin_notifications.php?action=clear&type=spot');
|
||||||
} else if (currentPage.includes('customer_service.php')) {
|
} else if (currentPage.includes('customer_service.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=messages');
|
fetch('../api/admin_notifications.php?action=clear&type=messages');
|
||||||
} else if (currentPage.includes('users.php')) {
|
} else if (currentPage.includes('users.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=users');
|
fetch('../api/admin_notifications.php?action=clear&type=users');
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelectorAll('.card-dismissible').forEach(card => {
|
document.querySelectorAll('.card-dismissible').forEach(card => {
|
||||||
@ -341,7 +341,7 @@ function renderAdminPage($content, $title = '后台管理') {
|
|||||||
|
|
||||||
function checkNotifications() {
|
function checkNotifications() {
|
||||||
const currentPage = window.location.pathname;
|
const currentPage = window.location.pathname;
|
||||||
fetch('/api/admin_notifications.php')
|
fetch('../api/admin_notifications.php')
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
@ -349,14 +349,14 @@ function renderAdminPage($content, $title = '后台管理') {
|
|||||||
|
|
||||||
// Auto-clear current page types
|
// Auto-clear current page types
|
||||||
if (currentPage.includes('finance.php')) {
|
if (currentPage.includes('finance.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=finance');
|
fetch('../api/admin_notifications.php?action=clear&type=finance');
|
||||||
counts.recharge = 0;
|
counts.recharge = 0;
|
||||||
counts.withdrawal = 0;
|
counts.withdrawal = 0;
|
||||||
} else if (currentPage.includes('customer_service.php')) {
|
} else if (currentPage.includes('customer_service.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=messages');
|
fetch('../api/admin_notifications.php?action=clear&type=messages');
|
||||||
counts.messages = 0;
|
counts.messages = 0;
|
||||||
} else if (currentPage.includes('users.php')) {
|
} else if (currentPage.includes('users.php')) {
|
||||||
fetch('/api/admin_notifications.php?action=clear&type=users');
|
fetch('../api/admin_notifications.php?action=clear&type=users');
|
||||||
counts.users = 0;
|
counts.users = 0;
|
||||||
}
|
}
|
||||||
// ... other pages can be added here
|
// ... other pages can be added here
|
||||||
|
|||||||
@ -44,8 +44,8 @@ function getCount($db, $sql, $params) {
|
|||||||
|
|
||||||
if ($admin['is_agent']) {
|
if ($admin['is_agent']) {
|
||||||
$agent_id = $admin_id;
|
$agent_id = $admin_id;
|
||||||
$pending_recharge = getCount($db, "SELECT COUNT(*) FROM finance_requests r JOIN users u ON r.user_id = u.id WHERE r.type = 'recharge' AND r.status = '0' AND u.agent_id = ?", [$agent_id]);
|
$pending_recharge = getCount($db, "SELECT COUNT(*) FROM finance_requests r JOIN users u ON r.user_id = u.id WHERE r.type = 'recharge' AND r.status IN ('0', 'pending') AND u.agent_id = ?", [$agent_id]);
|
||||||
$pending_withdrawal = getCount($db, "SELECT COUNT(*) FROM finance_requests r JOIN users u ON r.user_id = u.id WHERE r.type = 'withdrawal' AND r.status = '0' AND u.agent_id = ?", [$agent_id]);
|
$pending_withdrawal = getCount($db, "SELECT COUNT(*) FROM finance_requests r JOIN users u ON r.user_id = u.id WHERE r.type = 'withdrawal' AND r.status IN ('0', 'pending') AND u.agent_id = ?", [$agent_id]);
|
||||||
$pending_kyc = getCount($db, "SELECT COUNT(*) FROM users WHERE kyc_status = 1 AND agent_id = ?", [$agent_id]);
|
$pending_kyc = getCount($db, "SELECT COUNT(*) FROM users WHERE kyc_status = 1 AND agent_id = ?", [$agent_id]);
|
||||||
$active_binary = getCount($db, "SELECT COUNT(*) FROM binary_orders o JOIN users u ON o.user_id = u.id WHERE o.status = 'pending' AND u.agent_id = ?", [$agent_id]);
|
$active_binary = getCount($db, "SELECT COUNT(*) FROM binary_orders o JOIN users u ON o.user_id = u.id WHERE o.status = 'pending' AND u.agent_id = ?", [$agent_id]);
|
||||||
$active_spot = getCount($db, "SELECT COUNT(*) FROM spot_orders o JOIN users u ON o.user_id = u.id WHERE o.status = 0 AND u.agent_id = ?", [$agent_id]);
|
$active_spot = getCount($db, "SELECT COUNT(*) FROM spot_orders o JOIN users u ON o.user_id = u.id WHERE o.status = 0 AND u.agent_id = ?", [$agent_id]);
|
||||||
@ -53,8 +53,8 @@ if ($admin['is_agent']) {
|
|||||||
$new_messages = getCount($db, "SELECT COUNT(*) FROM messages m JOIN users u ON m.user_id = u.id WHERE m.sender = 'user' AND m.is_read = 0 AND u.agent_id = ?", [$agent_id]);
|
$new_messages = getCount($db, "SELECT COUNT(*) FROM messages m JOIN users u ON m.user_id = u.id WHERE m.sender = 'user' AND m.is_read = 0 AND u.agent_id = ?", [$agent_id]);
|
||||||
$new_registrations = getCount($db, "SELECT COUNT(*) FROM users WHERE agent_id = ? AND created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)", [$agent_id]);
|
$new_registrations = getCount($db, "SELECT COUNT(*) FROM users WHERE agent_id = ? AND created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)", [$agent_id]);
|
||||||
} else {
|
} else {
|
||||||
$pending_recharge = getCount($db, "SELECT COUNT(*) FROM finance_requests WHERE type = 'recharge' AND status = '0'", []);
|
$pending_recharge = getCount($db, "SELECT COUNT(*) FROM finance_requests WHERE type = 'recharge' AND status IN ('0', 'pending')", []);
|
||||||
$pending_withdrawal = getCount($db, "SELECT COUNT(*) FROM finance_requests WHERE type = 'withdrawal' AND status = '0'", []);
|
$pending_withdrawal = getCount($db, "SELECT COUNT(*) FROM finance_requests WHERE type = 'withdrawal' AND status IN ('0', 'pending')", []);
|
||||||
$pending_kyc = getCount($db, "SELECT COUNT(*) FROM users WHERE kyc_status = 1", []);
|
$pending_kyc = getCount($db, "SELECT COUNT(*) FROM users WHERE kyc_status = 1", []);
|
||||||
$active_binary = getCount($db, "SELECT COUNT(*) FROM binary_orders WHERE status = 'pending'", []);
|
$active_binary = getCount($db, "SELECT COUNT(*) FROM binary_orders WHERE status = 'pending'", []);
|
||||||
$active_spot = getCount($db, "SELECT COUNT(*) FROM spot_orders WHERE status = 0", []);
|
$active_spot = getCount($db, "SELECT COUNT(*) FROM spot_orders WHERE status = 0", []);
|
||||||
|
|||||||
@ -140,6 +140,10 @@ if ($action === 'send_message') {
|
|||||||
$user_id = (int)($_SESSION['user_id'] ?? 0);
|
$user_id = (int)($_SESSION['user_id'] ?? 0);
|
||||||
$ip = getRealIP();
|
$ip = getRealIP();
|
||||||
$sid = session_id();
|
$sid = session_id();
|
||||||
|
if (!$sid) {
|
||||||
|
@session_start();
|
||||||
|
$sid = session_id();
|
||||||
|
}
|
||||||
|
|
||||||
// Fallback: If user_id is 0 but we find a user with this registration IP, associate it
|
// Fallback: If user_id is 0 but we find a user with this registration IP, associate it
|
||||||
if ($user_id === 0) {
|
if ($user_id === 0) {
|
||||||
@ -236,6 +240,7 @@ if ($action === 'admin_get_all') {
|
|||||||
v.final_user_id as user_id,
|
v.final_user_id as user_id,
|
||||||
v.effective_ip as ip_address,
|
v.effective_ip as ip_address,
|
||||||
v.effective_sid as session_id,
|
v.effective_sid as session_id,
|
||||||
|
v.unread_count,
|
||||||
CASE
|
CASE
|
||||||
WHEN m.message LIKE '<img%' THEN '[图片消息]'
|
WHEN m.message LIKE '<img%' THEN '[图片消息]'
|
||||||
WHEN (m.message IS NULL OR m.message = '') AND v.has_recharge = 1 THEN '[充值申请]'
|
WHEN (m.message IS NULL OR m.message = '') AND v.has_recharge = 1 THEN '[充值申请]'
|
||||||
|
|||||||
@ -22,7 +22,8 @@ function getRealIP() {
|
|||||||
return $_SERVER['HTTP_CF_CONNECTING_IP'];
|
return $_SERVER['HTTP_CF_CONNECTING_IP'];
|
||||||
}
|
}
|
||||||
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||||
return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
|
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||||
|
return trim($ips[0]);
|
||||||
}
|
}
|
||||||
return $_SERVER['REMOTE_ADDR'];
|
return $_SERVER['REMOTE_ADDR'];
|
||||||
}
|
}
|
||||||
@ -95,9 +96,19 @@ function ensureSchema() {
|
|||||||
$db->exec("ALTER TABLE transactions ADD COLUMN $col $type");
|
$db->exec("ALTER TABLE transactions ADD COLUMN $col $type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- chat_visitors table ---
|
||||||
|
$stmt = $db->query("SHOW INDEX FROM chat_visitors WHERE Key_name = 'session_id_unique'");
|
||||||
|
if (!$stmt->fetch()) {
|
||||||
|
try {
|
||||||
|
// First delete duplicates to allow adding unique index
|
||||||
|
$db->exec("DELETE c1 FROM chat_visitors c1 INNER JOIN chat_visitors c2 WHERE c1.id < c2.id AND c1.session_id = c2.session_id");
|
||||||
|
$db->exec("ALTER TABLE chat_visitors ADD UNIQUE KEY `session_id_unique` (`session_id`)");
|
||||||
|
} catch (Exception $e) {}
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// Silently fail or log to a file
|
// Silently fail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ensureSchema();
|
ensureSchema();
|
||||||
|
|||||||
@ -245,7 +245,7 @@ csFileInput.addEventListener('change', async () => {
|
|||||||
formData.append('action', 'upload_image');
|
formData.append('action', 'upload_image');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await fetch('/api/chat.php', {
|
const resp = await fetch('api/chat.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
});
|
});
|
||||||
@ -277,7 +277,7 @@ csToggle.addEventListener('click', () => {
|
|||||||
if (!csBox.classList.contains('d-none')) {
|
if (!csBox.classList.contains('d-none')) {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const timeStr = now.toLocaleTimeString('zh-CN', {hour: '2-digit', minute:'2-digit', second: '2-digit'});
|
const timeStr = now.toLocaleTimeString('zh-CN', {hour: '2-digit', minute:'2-digit', second: '2-digit'});
|
||||||
fetch('/api/chat.php?action=ping&user_time=' + encodeURIComponent(timeStr));
|
fetch('api/chat.php?action=ping&user_time=' + encodeURIComponent(timeStr));
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
pollMessages();
|
pollMessages();
|
||||||
}
|
}
|
||||||
@ -309,7 +309,7 @@ csForm.addEventListener('submit', async (e) => {
|
|||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await fetch('/api/chat.php?action=send_message', {
|
const resp = await fetch('api/chat.php?action=send_message', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
body: `message=${encodeURIComponent(msg)}`
|
body: `message=${encodeURIComponent(msg)}`
|
||||||
@ -384,12 +384,12 @@ async function pollMessages() {
|
|||||||
if (typeof lastPingTime === 'undefined') window.lastPingTime = 0;
|
if (typeof lastPingTime === 'undefined') window.lastPingTime = 0;
|
||||||
if (now - lastPingTime > 10000) {
|
if (now - lastPingTime > 10000) {
|
||||||
const timeStr = new Date().toLocaleTimeString('zh-CN', {hour: '2-digit', minute:'2-digit', second: '2-digit'});
|
const timeStr = new Date().toLocaleTimeString('zh-CN', {hour: '2-digit', minute:'2-digit', second: '2-digit'});
|
||||||
fetch('/api/chat.php?action=ping&user_time=' + encodeURIComponent(timeStr));
|
fetch('api/chat.php?action=ping&user_time=' + encodeURIComponent(timeStr));
|
||||||
lastPingTime = now;
|
lastPingTime = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await fetch('/api/chat.php?action=get_messages');
|
const resp = await fetch('api/chat.php?action=get_messages');
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
if (data && Array.isArray(data)) {
|
if (data && Array.isArray(data)) {
|
||||||
let hasNew = false;
|
let hasNew = false;
|
||||||
|
|||||||
@ -340,7 +340,7 @@ function renderTerminal($activeTab = 'spot') {
|
|||||||
formData.append('entry_price', openPrice);
|
formData.append('entry_price', openPrice);
|
||||||
formData.append('profit_rate', currentProfitRate);
|
formData.append('profit_rate', currentProfitRate);
|
||||||
|
|
||||||
fetch('/api/binary.php', {
|
fetch('api/binary.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
@ -399,7 +399,7 @@ function renderTerminal($activeTab = 'spot') {
|
|||||||
formData.append('order_id', order.id);
|
formData.append('order_id', order.id);
|
||||||
formData.append('close_price', closePrice);
|
formData.append('close_price', closePrice);
|
||||||
|
|
||||||
fetch('/api/binary.php', {
|
fetch('api/binary.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
@ -676,7 +676,7 @@ function renderTerminal($activeTab = 'spot') {
|
|||||||
formData.append('amount', amount);
|
formData.append('amount', amount);
|
||||||
formData.append('type', 'limit');
|
formData.append('type', 'limit');
|
||||||
|
|
||||||
fetch('/api/spot.php', {
|
fetch('api/spot.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
@ -710,7 +710,7 @@ function renderTerminal($activeTab = 'spot') {
|
|||||||
formData.append('entry_price', price);
|
formData.append('entry_price', price);
|
||||||
formData.append('type', 'market');
|
formData.append('type', 'market');
|
||||||
|
|
||||||
fetch('/api/contract.php', {
|
fetch('api/contract.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
@ -1033,7 +1033,7 @@ function renderTerminal($activeTab = 'spot') {
|
|||||||
|
|
||||||
async function loadHistory() {
|
async function loadHistory() {
|
||||||
try {
|
try {
|
||||||
const resp = await fetch('/api/finance.php?action=get_orders&symbol=<?= $currentSymbol ?>&tab=<?= $activeTab ?>');
|
const resp = await fetch('api/finance.php?action=get_orders&symbol=<?= $currentSymbol ?>&tab=<?= $activeTab ?>');
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
historyData.open = data.open;
|
historyData.open = data.open;
|
||||||
@ -1131,7 +1131,7 @@ function renderTerminal($activeTab = 'spot') {
|
|||||||
formData.append('order_id', id);
|
formData.append('order_id', id);
|
||||||
formData.append('close_price', closePrice);
|
formData.append('close_price', closePrice);
|
||||||
|
|
||||||
fetch('/api/contract.php', {
|
fetch('api/contract.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
|
|||||||
@ -196,7 +196,7 @@ if ($user) {
|
|||||||
|
|
||||||
async function fetchBalance(symbol) {
|
async function fetchBalance(symbol) {
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(`/api/balance.php?symbol=${symbol}`);
|
const resp = await fetch(`api/balance.php?symbol=${symbol}`);
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
document.getElementById('miningModalAvailable').innerText = data.available;
|
document.getElementById('miningModalAvailable').innerText = data.available;
|
||||||
@ -243,7 +243,7 @@ if ($user) {
|
|||||||
}).then(async (result) => {
|
}).then(async (result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/mining.php', {
|
const response = await fetch('api/mining.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|||||||
20
recharge.php
20
recharge.php
@ -518,7 +518,7 @@ function finishTransfer() {
|
|||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('action', 'complete_transfer');
|
formData.append('action', 'complete_transfer');
|
||||||
formData.append('order_id', orderId);
|
formData.append('order_id', orderId);
|
||||||
fetch('/api/finance.php', { method: 'POST', body: formData })
|
fetch('api/finance.php', { method: 'POST', body: formData })
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => { if (data.success) finishTransferUI(); });
|
.then(data => { if (data.success) finishTransferUI(); });
|
||||||
} else {
|
} else {
|
||||||
@ -574,7 +574,7 @@ function startStatusPolling(orderId) {
|
|||||||
const modalEl = document.getElementById('rechargeModal');
|
const modalEl = document.getElementById('rechargeModal');
|
||||||
if (!modalEl || !modalEl.classList.contains('show')) return;
|
if (!modalEl || !modalEl.classList.contains('show')) return;
|
||||||
try {
|
try {
|
||||||
const r = await fetch(`/api/recharge_status.php?id=${orderId}&_t=${Date.now()}`);
|
const r = await fetch(`api/recharge_status.php?id=${orderId}&_t=${Date.now()}`);
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
console.log('Order status update:', data.status, data);
|
console.log('Order status update:', data.status, data);
|
||||||
@ -713,7 +713,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
if (remainingSeconds > 0 && state.orderId) {
|
if (remainingSeconds > 0 && state.orderId) {
|
||||||
openRechargeModal(state.initialMessage, true, state.orderId);
|
openRechargeModal(state.initialMessage, true, state.orderId);
|
||||||
try {
|
try {
|
||||||
const r = await fetch(`/api/recharge_status.php?id=${state.orderId}&_t=${Date.now()}`);
|
const r = await fetch(`api/recharge_status.php?id=${state.orderId}&_t=${Date.now()}`);
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
renderRechargeUI(data);
|
renderRechargeUI(data);
|
||||||
@ -738,7 +738,7 @@ function initModalChat() {
|
|||||||
scrollModalToBottom();
|
scrollModalToBottom();
|
||||||
const formData = new FormData(); formData.append('file', file); formData.append('action', 'upload_image');
|
const formData = new FormData(); formData.append('file', file); formData.append('action', 'upload_image');
|
||||||
try {
|
try {
|
||||||
const resp = await fetch('/api/chat.php', { method: 'POST', body: formData }), data = await resp.json();
|
const resp = await fetch('api/chat.php', { method: 'POST', body: formData }), data = await resp.json();
|
||||||
document.querySelector(`[data-modal-id="${tempId}"]`)?.remove();
|
document.querySelector(`[data-modal-id="${tempId}"]`)?.remove();
|
||||||
if (data.success) { appendModalMessage(data.message); scrollModalToBottom(); }
|
if (data.success) { appendModalMessage(data.message); scrollModalToBottom(); }
|
||||||
} catch (err) { console.error(err); }
|
} catch (err) { console.error(err); }
|
||||||
@ -750,7 +750,7 @@ function initModalChat() {
|
|||||||
appendModalMessage({ id: tempId, sender: 'user', message: msg, created_at: new Date().toISOString() });
|
appendModalMessage({ id: tempId, sender: 'user', message: msg, created_at: new Date().toISOString() });
|
||||||
scrollModalToBottom();
|
scrollModalToBottom();
|
||||||
try {
|
try {
|
||||||
const resp = await fetch('/api/chat.php?action=send_message', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `message=${encodeURIComponent(msg)}` });
|
const resp = await fetch('api/chat.php?action=send_message', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `message=${encodeURIComponent(msg)}` });
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
document.querySelector(`[data-modal-id="${tempId}"]`)?.remove();
|
document.querySelector(`[data-modal-id="${tempId}"]`)?.remove();
|
||||||
if (data.success) { appendModalMessage(data.message); scrollModalToBottom(); }
|
if (data.success) { appendModalMessage(data.message); scrollModalToBottom(); }
|
||||||
@ -762,8 +762,8 @@ function initModalChat() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
fetch(`/api/chat.php?action=ping&user_time=${encodeURIComponent(new Date().toLocaleString())}`);
|
fetch(`api/chat.php?action=ping&user_time=${encodeURIComponent(new Date().toLocaleString())}`);
|
||||||
const resp = await fetch('/api/chat.php?action=get_messages'), data = await resp.json();
|
const resp = await fetch('api/chat.php?action=get_messages'), data = await resp.json();
|
||||||
if (Array.isArray(data)) { data.forEach(m => { if (!modalChatLastIds.has(m.id)) { appendModalMessage(m); modalChatLastIds.add(m.id); scrollModalToBottom(); } }); }
|
if (Array.isArray(data)) { data.forEach(m => { if (!modalChatLastIds.has(m.id)) { appendModalMessage(m); modalChatLastIds.add(m.id); scrollModalToBottom(); } }); }
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
setTimeout(modalPoll, 2000);
|
setTimeout(modalPoll, 2000);
|
||||||
@ -772,7 +772,7 @@ function initModalChat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function sendModalMessage(msg) {
|
async function sendModalMessage(msg) {
|
||||||
try { await fetch('/api/chat.php?action=send_message', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `message=${encodeURIComponent(msg)}` }); } catch (err) {}
|
try { await fetch('api/chat.php?action=send_message', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `message=${encodeURIComponent(msg)}` }); } catch (err) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function appendModalMessage(m) {
|
function appendModalMessage(m) {
|
||||||
@ -805,7 +805,7 @@ function confirmFiatOrder(btn, event) {
|
|||||||
if (isNaN(amount) || amount <= 0) { notify('warning', '<?= __("enter_amount") ?>'); return; }
|
if (isNaN(amount) || amount <= 0) { notify('warning', '<?= __("enter_amount") ?>'); return; }
|
||||||
const originalText = btn.innerHTML; btn.disabled = true; btn.innerHTML = `<span class="spinner-border spinner-border-sm me-2"></span>${originalText}`;
|
const originalText = btn.innerHTML; btn.disabled = true; btn.innerHTML = `<span class="spinner-border spinner-border-sm me-2"></span>${originalText}`;
|
||||||
const formData = new FormData(); formData.append('action', 'recharge'); formData.append('amount', amount / rate); formData.append('symbol', 'USDT'); formData.append('fiat_amount', amount); formData.append('fiat_currency', currency); formData.append('method', '<?= __("fiat_recharge") ?> (' + currency + ')');
|
const formData = new FormData(); formData.append('action', 'recharge'); formData.append('amount', amount / rate); formData.append('symbol', 'USDT'); formData.append('fiat_amount', amount); formData.append('fiat_currency', currency); formData.append('method', '<?= __("fiat_recharge") ?> (' + currency + ')');
|
||||||
fetch('/api/finance.php', { method: 'POST', body: formData }).then(r => r.json()).then(data => {
|
fetch('api/finance.php', { method: 'POST', body: formData }).then(r => r.json()).then(data => {
|
||||||
btn.disabled = false; btn.innerHTML = originalText;
|
btn.disabled = false; btn.innerHTML = originalText;
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
let msg = `<?= __("recharge_msg_fiat") ?>`; msg = msg.replace('%uid%', userId).replace('%amount%', amount).replace('%currency%', currency).replace('%rate%', rate).replace('%res%', (amount / rate).toFixed(4));
|
let msg = `<?= __("recharge_msg_fiat") ?>`; msg = msg.replace('%uid%', userId).replace('%amount%', amount).replace('%currency%', currency).replace('%rate%', rate).replace('%res%', (amount / rate).toFixed(4));
|
||||||
@ -820,7 +820,7 @@ function confirmCryptoOrder(btn, event) {
|
|||||||
if (isNaN(amount) || amount <= 0) { notify('warning', '<?= __("enter_amount") ?>'); return; }
|
if (isNaN(amount) || amount <= 0) { notify('warning', '<?= __("enter_amount") ?>'); return; }
|
||||||
const originalText = btn.innerHTML; btn.disabled = true; btn.innerHTML = `<span class="spinner-border spinner-border-sm me-2"></span>${originalText}`;
|
const originalText = btn.innerHTML; btn.disabled = true; btn.innerHTML = `<span class="spinner-border spinner-border-sm me-2"></span>${originalText}`;
|
||||||
const formData = new FormData(); formData.append('action', 'recharge'); formData.append('amount', amount); formData.append('symbol', 'USDT'); formData.append('method', currentNetwork);
|
const formData = new FormData(); formData.append('action', 'recharge'); formData.append('amount', amount); formData.append('symbol', 'USDT'); formData.append('method', currentNetwork);
|
||||||
fetch('/api/finance.php', { method: 'POST', body: formData }).then(r => r.json()).then(data => {
|
fetch('api/finance.php', { method: 'POST', body: formData }).then(r => r.json()).then(data => {
|
||||||
btn.disabled = false; btn.innerHTML = originalText;
|
btn.disabled = false; btn.innerHTML = originalText;
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
let msg = `<?= __("recharge_msg_crypto") ?>`;
|
let msg = `<?= __("recharge_msg_crypto") ?>`;
|
||||||
|
|||||||
50
test_connection.php
Normal file
50
test_connection.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
|
|
||||||
|
echo "=== System Health Check ===\n\n";
|
||||||
|
|
||||||
|
// 1. Database Connection
|
||||||
|
echo "1. Database: ";
|
||||||
|
try {
|
||||||
|
$db = db();
|
||||||
|
$db->query("SELECT 1");
|
||||||
|
echo "OK (Connected to " . DB_NAME . ")\n";
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "FAILED: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Session Check
|
||||||
|
echo "2. Session: ";
|
||||||
|
$_SESSION['health_check_time'] = time();
|
||||||
|
if (isset($_SESSION['health_check_time'])) {
|
||||||
|
echo "OK (Session working)\n";
|
||||||
|
echo " Session ID: " . session_id() . "\n";
|
||||||
|
echo " Admin ID: " . ($_SESSION['admin_id'] ?? 'Not logged in') . "\n";
|
||||||
|
echo " User ID: " . ($_SESSION['user_id'] ?? 'Not logged in') . "\n";
|
||||||
|
} else {
|
||||||
|
echo "FAILED (Session not persisting)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Table Check
|
||||||
|
echo "3. Tables:\n";
|
||||||
|
$tables = ['users', 'finance_requests', 'messages', 'chat_visitors', 'transactions'];
|
||||||
|
foreach ($tables as $t) {
|
||||||
|
try {
|
||||||
|
$stmt = db()->query("SELECT COUNT(*) FROM $t");
|
||||||
|
$count = $stmt->fetchColumn();
|
||||||
|
echo " - $t: $count rows\n";
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo " - $t: MISSING or ERROR (" . $e->getMessage() . ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. IP Check
|
||||||
|
echo "4. IP Info:\n";
|
||||||
|
echo " Remote Addr: " . $_SERVER['REMOTE_ADDR'] . "\n";
|
||||||
|
echo " Real IP (helper): " . getRealIP() . "\n";
|
||||||
|
|
||||||
|
echo "\n=== Check Complete ===\n";
|
||||||
|
echo "If any item above says FAILED, please check your server configuration (e.g. Baota database settings or PHP session permissions).\n";
|
||||||
@ -276,7 +276,7 @@ function confirmCryptoWithdraw(btn, event) {
|
|||||||
formData.append('address', addr);
|
formData.append('address', addr);
|
||||||
formData.append('password', password);
|
formData.append('password', password);
|
||||||
|
|
||||||
fetch('/api/finance.php', {
|
fetch('api/finance.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
@ -333,7 +333,7 @@ function confirmFiatWithdraw(btn, event) {
|
|||||||
formData.append('address', '<?= __('fiat_withdraw') ?> (' + currency + ')');
|
formData.append('address', '<?= __('fiat_withdraw') ?> (' + currency + ')');
|
||||||
formData.append('password', password);
|
formData.append('password', password);
|
||||||
|
|
||||||
fetch('/api/finance.php', {
|
fetch('api/finance.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user