392 lines
19 KiB
PHP
392 lines
19 KiB
PHP
<?php
|
|
session_start();
|
|
require_once __DIR__ . '/../db/config.php';
|
|
ini_set('display_errors', 0);
|
|
error_reporting(E_ALL);
|
|
|
|
$action = $_GET['action'] ?? '';
|
|
|
|
if ($action === 'upload_image' || (isset($_POST['action']) && $_POST['action'] === 'upload_image')) {
|
|
if (!isset($_FILES['file'])) {
|
|
echo json_encode(['success' => false, 'error' => 'No file uploaded']);
|
|
exit;
|
|
}
|
|
|
|
$file = $_FILES['file'];
|
|
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
|
|
$allowed = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
|
|
|
if (!in_array(strtolower($ext), $allowed)) {
|
|
echo json_encode(['success' => false, 'error' => 'Invalid file type']);
|
|
exit;
|
|
}
|
|
|
|
$filename = time() . '_' . uniqid() . '.' . $ext;
|
|
$targetDir = __DIR__ . '/../assets/images/chat/';
|
|
if (!is_dir($targetDir)) {
|
|
mkdir($targetDir, 0777, true);
|
|
}
|
|
|
|
$targetPath = $targetDir . $filename;
|
|
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
|
|
$imageUrl = '/assets/images/chat/' . $filename;
|
|
$message = '<img src="' . $imageUrl . '" class="img-fluid rounded chat-img-preview" style="max-width: 100%; max-height: 250px; object-fit: contain; margin: 5px 0; display: block; cursor: pointer;" onclick="if(window.showLightbox) window.showLightbox(this.src); else window.open(this.src);">';
|
|
|
|
if (isset($_SESSION['admin_id'])) {
|
|
$user_id = (int)($_POST['user_id'] ?? 0);
|
|
$ip = $_POST['ip_address'] ?? '';
|
|
$sid = $_POST['session_id'] ?? '';
|
|
if ($ip === '---') $ip = '';
|
|
// If IP is missing, try to get it from messages or fallback to current IP
|
|
if (empty($ip) && empty($sid)) {
|
|
if ($user_id != 0) {
|
|
$stmt = db()->prepare("SELECT ip_address, session_id FROM messages WHERE user_id = ? AND ip_address != '' AND ip_address != '---' ORDER BY id DESC LIMIT 1");
|
|
$stmt->execute([$user_id]);
|
|
$row = $stmt->fetch();
|
|
$ip = $row['ip_address'] ?? '';
|
|
$sid = $row['session_id'] ?? '';
|
|
}
|
|
if (empty($ip)) {
|
|
$ip = getRealIP();
|
|
}
|
|
}
|
|
$sender = 'admin';
|
|
$admin_id = $_SESSION['admin_id'];
|
|
$stmt = db()->prepare("INSERT INTO messages (user_id, admin_id, sender, message, ip_address, session_id) VALUES (?, ?, ?, ?, ?, ?)");
|
|
$stmt->execute([$user_id, $admin_id, $sender, $message, $ip, $sid]);
|
|
} else {
|
|
$user_id = (int)($_SESSION['user_id'] ?? 0);
|
|
$ip = getRealIP();
|
|
$sid = session_id();
|
|
|
|
// Fallback: If user_id is 0 but we find a user with this registration IP, associate it
|
|
if ($user_id === 0) {
|
|
$stmt = db()->prepare("SELECT id FROM users WHERE registration_ip = ? OR last_login_ip = ? ORDER BY id DESC LIMIT 1");
|
|
$stmt->execute([$ip, $ip]);
|
|
$user_id = (int)($stmt->fetchColumn() ?: 0);
|
|
}
|
|
|
|
$sender = 'user';
|
|
$stmt = db()->prepare("INSERT INTO messages (user_id, sender, message, ip_address, session_id) VALUES (?, ?, ?, ?, ?)");
|
|
$stmt->execute([$user_id, $sender, $message, $ip, $sid]);
|
|
}
|
|
|
|
$newId = db()->lastInsertId();
|
|
$createdAt = date('Y-m-d H:i:s');
|
|
|
|
// Update visitors table to ensure immediate visibility for both users and admins
|
|
if ($sender === 'user') {
|
|
$user_time = date('H:i:s');
|
|
$stmt = db()->prepare("INSERT INTO chat_visitors (user_id, ip_address, session_id, user_time) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE last_ping = CURRENT_TIMESTAMP, session_id = VALUES(session_id)");
|
|
$stmt->execute([$user_id, $ip, $sid, $user_time]);
|
|
}
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'url' => $imageUrl,
|
|
'message' => [
|
|
'id' => $newId,
|
|
'sender' => $sender,
|
|
'message' => $message,
|
|
'created_at' => $createdAt
|
|
]
|
|
]);
|
|
} else {
|
|
echo json_encode(['success' => false, 'error' => 'Failed to move uploaded file']);
|
|
}
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'get_messages') {
|
|
$user_id = $_SESSION['user_id'] ?? 0;
|
|
$target_user_id = $_GET['user_id'] ?? $user_id;
|
|
$target_ip = $_GET['ip'] ?? getRealIP();
|
|
$target_sid = $_GET['session_id'] ?? '';
|
|
|
|
// If admin is requesting, we use the provided user_id and ip/session
|
|
if (isset($_SESSION['admin_id'])) {
|
|
$stmt = db()->prepare("SELECT * FROM messages WHERE (user_id = ? AND user_id != 0) OR (session_id = ? AND session_id != '') OR (ip_address = ? AND ip_address != '' AND session_id = '') ORDER BY created_at ASC");
|
|
$stmt->execute([$target_user_id, $target_sid, $target_ip]);
|
|
|
|
// Mark as read
|
|
$stmt_read = db()->prepare("UPDATE messages SET is_read = 1 WHERE sender = 'user' AND ((user_id = ? AND user_id != 0) OR (session_id = ? AND session_id != '') OR (ip_address = ? AND ip_address != '' AND session_id = ''))");
|
|
$stmt_read->execute([$target_user_id, $target_sid, $target_ip]);
|
|
} else {
|
|
// User requesting their own messages
|
|
$user_id = (int)($_SESSION['user_id'] ?? 0);
|
|
$ip = getRealIP();
|
|
$sid = session_id();
|
|
|
|
// Fallback: If user_id is 0 but we find a user with this IP, associate it
|
|
if ($user_id === 0) {
|
|
$stmt = db()->prepare("SELECT id FROM users WHERE registration_ip = ? OR last_login_ip = ? ORDER BY id DESC LIMIT 1");
|
|
$stmt->execute([$ip, $ip]);
|
|
$user_id = (int)($stmt->fetchColumn() ?: 0);
|
|
}
|
|
|
|
$stmt = db()->prepare("SELECT * FROM messages WHERE (user_id = ? AND user_id != 0) OR (session_id = ?) OR (ip_address = ? AND ip_address != '' AND session_id = '') ORDER BY created_at ASC");
|
|
$stmt->execute([$user_id, $sid, $ip]);
|
|
}
|
|
|
|
$messages = $stmt->fetchAll();
|
|
echo json_encode($messages);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'send_message') {
|
|
$message = $_POST['message'] ?? '';
|
|
if (!$message) exit(json_encode(['success' => false, 'error' => 'Empty message']));
|
|
|
|
$user_id = (int)($_SESSION['user_id'] ?? 0);
|
|
$ip = getRealIP();
|
|
$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
|
|
if ($user_id === 0) {
|
|
$stmt = db()->prepare("SELECT id FROM users WHERE registration_ip = ? OR last_login_ip = ? ORDER BY id DESC LIMIT 1");
|
|
$stmt->execute([$ip, $ip]);
|
|
$user_id = (int)($stmt->fetchColumn() ?: 0);
|
|
}
|
|
|
|
$stmt = db()->prepare("INSERT INTO messages (user_id, sender, message, ip_address, session_id) VALUES (?, ?, ?, ?, ?)");
|
|
$stmt->execute([$user_id, 'user', $message, $ip, $sid]);
|
|
$newId = db()->lastInsertId();
|
|
|
|
// Also update visitors table to ensure immediate visibility
|
|
$user_time = date('H:i:s');
|
|
$stmt = db()->prepare("INSERT INTO chat_visitors (user_id, ip_address, session_id, user_time) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE last_ping = CURRENT_TIMESTAMP, session_id = VALUES(session_id)");
|
|
$stmt->execute([$user_id, $ip, $sid, $user_time]);
|
|
|
|
echo json_encode(['success' => true, 'id' => $newId, 'message' => ['id' => $newId, 'sender' => 'user', 'message' => $message, 'created_at' => date('Y-m-d H:i:s')]]);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'mark_read') {
|
|
if (!isset($_SESSION['admin_id'])) exit(json_encode(['success' => false, 'error' => 'Unauthorized']));
|
|
$user_id = (int)($_POST['user_id'] ?? 0);
|
|
$ip = $_POST['ip_address'] ?? '';
|
|
$sid = $_POST['session_id'] ?? '';
|
|
if ($ip === '---') $ip = '';
|
|
|
|
$stmt = db()->prepare("UPDATE messages SET is_read = 1 WHERE sender = 'user' AND is_read = 0 AND ((user_id = ? AND user_id != 0) OR (session_id = ? AND session_id != '') OR (ip_address = ? AND ip_address != '' AND session_id = ''))");
|
|
$stmt->execute([$user_id, $sid, $ip]);
|
|
echo json_encode(['success' => true]);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'admin_send') {
|
|
if (!isset($_SESSION['admin_id'])) exit(json_encode(['success' => false, 'error' => 'Unauthorized']));
|
|
|
|
$message = $_POST['message'] ?? '';
|
|
$user_id = (int)($_POST['user_id'] ?? 0);
|
|
$target_ip = $_POST['ip_address'] ?? '';
|
|
$target_sid = $_POST['session_id'] ?? '';
|
|
if ($target_ip === '---') $target_ip = '';
|
|
|
|
if (!$message) exit(json_encode(['success' => false, 'error' => 'Empty message']));
|
|
|
|
// Robust IP/Session matching: if target is empty but user_id is set, try to find their last known details
|
|
if (empty($target_ip) && empty($target_sid)) {
|
|
if ($user_id != 0) {
|
|
$stmt = db()->prepare("SELECT ip_address, session_id FROM messages WHERE user_id = ? AND ip_address != '' AND ip_address != '---' ORDER BY id DESC LIMIT 1");
|
|
$stmt->execute([$user_id]);
|
|
$row = $stmt->fetch();
|
|
$target_ip = $row['ip_address'] ?? '';
|
|
$target_sid = $row['session_id'] ?? '';
|
|
}
|
|
if (empty($target_ip)) {
|
|
$target_ip = getRealIP();
|
|
}
|
|
}
|
|
|
|
$admin_id = $_SESSION['admin_id'] ?? 1;
|
|
$sender = 'admin';
|
|
|
|
$stmt = db()->prepare("INSERT INTO messages (user_id, admin_id, sender, message, ip_address, session_id) VALUES (?, ?, ?, ?, ?, ?)");
|
|
$stmt->execute([$user_id, $admin_id, $sender, $message, $target_ip, $target_sid]);
|
|
$newId = db()->lastInsertId();
|
|
echo json_encode(['success' => true, 'id' => $newId, 'message' => ['id' => $newId, 'sender' => $sender, 'message' => $message, 'created_at' => date('Y-m-d H:i:s')]]);
|
|
exit;
|
|
}
|
|
|
|
|
|
if ($action === 'ping') {
|
|
$user_id = $_SESSION['user_id'] ?? 0;
|
|
$ip = getRealIP();
|
|
$sid = session_id();
|
|
$user_time = $_GET['user_time'] ?? '';
|
|
$stmt = db()->prepare("INSERT INTO chat_visitors (user_id, ip_address, session_id, user_time) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE last_ping = CURRENT_TIMESTAMP, user_time = ?, session_id = VALUES(session_id)");
|
|
$stmt->execute([$user_id, $ip, $sid, $user_time, $user_time]);
|
|
echo json_encode(['success' => true]);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'admin_get_all') {
|
|
header('Content-Type: application/json');
|
|
|
|
if (!isset($_SESSION['admin_id'])) {
|
|
echo json_encode(['error' => 'Unauthorized']);
|
|
exit;
|
|
}
|
|
try {
|
|
// Robust query to get all active chat sessions, merging guest sessions into user sessions if IP or Session matches
|
|
// Grouping by (final_user_id, effective_sid, effective_ip) to ensure "One ID, One Conversation"
|
|
$stmt = db()->query("
|
|
SELECT
|
|
v.final_user_id as user_id,
|
|
v.effective_ip as ip_address,
|
|
v.effective_sid as session_id,
|
|
v.unread_count,
|
|
CASE
|
|
WHEN m.message LIKE '<img%' THEN '[图片消息]'
|
|
WHEN (m.message IS NULL OR m.message = '') AND v.has_recharge = 1 THEN '[充值申请]'
|
|
ELSE COALESCE(m.message, '新会话')
|
|
END as message,
|
|
COALESCE(m.created_at, v.last_activity) as created_at,
|
|
COALESCE(u.username, u.email, CONCAT('访客 ', COALESCE(NULLIF(v.effective_ip, ''), '0.0.0.0'))) as username,
|
|
IFNULL(u.uid, '---') as uid,
|
|
IFNULL(u.registration_ip, '---') as registration_ip,
|
|
IFNULL(r.remark, '') as remark,
|
|
IFNULL(v.user_time, '---') as user_time
|
|
FROM (
|
|
SELECT
|
|
final_user_id,
|
|
SUBSTRING_INDEX(GROUP_CONCAT(effective_ip ORDER BY last_activity DESC SEPARATOR '|'), '|', 1) as effective_ip,
|
|
SUBSTRING_INDEX(GROUP_CONCAT(effective_sid ORDER BY last_activity DESC SEPARATOR '|'), '|', 1) as effective_sid,
|
|
MAX(last_activity) as last_activity,
|
|
MAX(user_time) as user_time,
|
|
MAX(has_recharge) as has_recharge,
|
|
SUM(is_unread) as unread_count
|
|
FROM (
|
|
SELECT
|
|
COALESCE(NULLIF(user_id, 0), (SELECT id FROM users WHERE registration_ip = m.ip_address AND m.ip_address != '---' AND m.ip_address != '' LIMIT 1), 0) as final_user_id,
|
|
CASE WHEN ip_address = '---' THEN '' ELSE IFNULL(ip_address, '') END as effective_ip,
|
|
IFNULL(session_id, '') as effective_sid,
|
|
created_at as last_activity,
|
|
NULL as user_time,
|
|
0 as has_recharge,
|
|
CASE WHEN sender = 'user' AND is_read = 0 THEN 1 ELSE 0 END as is_unread
|
|
FROM messages m
|
|
UNION ALL
|
|
SELECT
|
|
COALESCE(NULLIF(user_id, 0), (SELECT id FROM users WHERE registration_ip = cv.ip_address AND cv.ip_address != '---' AND cv.ip_address != '' LIMIT 1), 0) as final_user_id,
|
|
CASE WHEN ip_address = '---' THEN '' ELSE IFNULL(ip_address, '') END as effective_ip,
|
|
IFNULL(session_id, '') as effective_sid,
|
|
last_ping as last_activity,
|
|
user_time,
|
|
0 as has_recharge,
|
|
0 as is_unread
|
|
FROM chat_visitors cv
|
|
UNION ALL
|
|
SELECT
|
|
COALESCE(NULLIF(user_id, 0), (SELECT id FROM users WHERE registration_ip = fr.ip_address AND fr.ip_address != '---' AND fr.ip_address != '' LIMIT 1), 0) as final_user_id,
|
|
CASE WHEN ip_address = '---' THEN '' ELSE IFNULL(ip_address, '') END as effective_ip,
|
|
'' as effective_sid,
|
|
created_at as last_activity,
|
|
NULL as user_time,
|
|
1 as has_recharge,
|
|
0 as is_unread
|
|
FROM finance_requests fr
|
|
) t1
|
|
GROUP BY final_user_id, (CASE WHEN final_user_id = 0 THEN effective_sid ELSE '' END), (CASE WHEN final_user_id = 0 AND effective_sid = '' THEN effective_ip ELSE '' END)
|
|
) v
|
|
LEFT JOIN (
|
|
SELECT m1.*, m2.final_user_id as m_final_user_id, m2.effective_ip as m_effective_ip, m2.effective_sid as m_effective_sid FROM messages m1
|
|
INNER JOIN (
|
|
SELECT MAX(id) as max_id, final_user_id, effective_ip, effective_sid FROM (
|
|
SELECT id,
|
|
COALESCE(NULLIF(user_id, 0), (SELECT id FROM users WHERE registration_ip = messages.ip_address AND messages.ip_address != '---' AND messages.ip_address != '' LIMIT 1), 0) as final_user_id,
|
|
CASE WHEN ip_address = '---' THEN '' ELSE IFNULL(ip_address, '') END as effective_ip,
|
|
IFNULL(session_id, '') as effective_sid
|
|
FROM messages
|
|
) t2 GROUP BY final_user_id, (CASE WHEN final_user_id = 0 THEN effective_sid ELSE '' END), (CASE WHEN final_user_id = 0 AND effective_sid = '' THEN effective_ip ELSE '' END)
|
|
) m2 ON m1.id = m2.max_id
|
|
) m ON (v.final_user_id = m.m_final_user_id AND (v.final_user_id != 0 OR (v.effective_sid != '' AND v.effective_sid = m.m_effective_sid) OR (v.effective_sid = '' AND v.effective_ip = m.m_effective_ip)))
|
|
LEFT JOIN users u ON (v.final_user_id = u.id AND v.final_user_id != 0)
|
|
LEFT JOIN chat_remarks r ON (v.final_user_id = r.user_id AND (v.final_user_id != 0 OR (v.effective_sid != '' AND v.effective_sid = r.session_id) OR (v.effective_sid = '' AND v.effective_ip = r.ip_address)))
|
|
ORDER BY created_at DESC
|
|
");
|
|
$results = $stmt->fetchAll();
|
|
// Convert unread_count to int
|
|
foreach ($results as &$row) {
|
|
$row['unread_count'] = (int)$row['unread_count'];
|
|
}
|
|
echo json_encode($results);
|
|
} catch (Exception $e) {
|
|
error_log("Chat API Error: " . $e->getMessage());
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
}
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'save_remark') {
|
|
if (!isset($_SESSION['admin_id'])) exit(json_encode(['success' => false, 'error' => 'Unauthorized']));
|
|
|
|
$user_id = $_POST['user_id'] ?? 0;
|
|
$ip = $_POST['ip_address'] ?? '';
|
|
$sid = $_POST['session_id'] ?? '';
|
|
if ($ip === '---') $ip = '';
|
|
$remark = $_POST['remark'] ?? '';
|
|
|
|
$stmt = db()->prepare("INSERT INTO chat_remarks (user_id, ip_address, session_id, remark) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE remark = ?, session_id = VALUES(session_id)");
|
|
$stmt->execute([$user_id, $ip, $sid, $remark, $remark]);
|
|
|
|
echo json_encode(['success' => true]);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'get_remark') {
|
|
if (!isset($_SESSION['admin_id'])) exit(json_encode(['success' => false, 'error' => 'Unauthorized']));
|
|
|
|
$user_id = $_GET['user_id'] ?? 0;
|
|
$ip = $_GET['ip'] ?? '';
|
|
$sid = $_GET['session_id'] ?? '';
|
|
if ($ip === '---') $ip = '';
|
|
|
|
$stmt = db()->prepare("SELECT remark FROM chat_remarks WHERE user_id = ? AND (session_id = ? AND session_id != '') OR (user_id != 0 AND user_id = ?) OR (ip_address = ? AND ip_address != '' AND session_id = '')");
|
|
$stmt->execute([$user_id, $sid, $user_id, $ip]);
|
|
$remark = $stmt->fetchColumn() ?: '';
|
|
|
|
echo json_encode(['success' => true, 'remark' => $remark]);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'admin_delete_user') {
|
|
if (!isset($_SESSION['admin_id'])) exit(json_encode(['success' => false, 'error' => 'Unauthorized']));
|
|
$user_id = $_POST['user_id'] ?? 0;
|
|
$ip = $_POST['ip_address'] ?? '';
|
|
$sid = $_POST['session_id'] ?? '';
|
|
if ($ip === '---') $ip = '';
|
|
|
|
if ($user_id != 0) {
|
|
$stmt = db()->prepare("DELETE FROM messages WHERE user_id = ?");
|
|
$stmt->execute([$user_id]);
|
|
$stmt = db()->prepare("DELETE FROM chat_visitors WHERE user_id = ?");
|
|
$stmt->execute([$user_id]);
|
|
$stmt = db()->prepare("DELETE FROM chat_remarks WHERE user_id = ?");
|
|
$stmt->execute([$user_id]);
|
|
} else {
|
|
$stmt = db()->prepare("DELETE FROM messages WHERE user_id = 0 AND (session_id = ? OR ip_address = ?)");
|
|
$stmt->execute([$sid, $ip]);
|
|
$stmt = db()->prepare("DELETE FROM chat_visitors WHERE user_id = 0 AND (session_id = ? OR ip_address = ?)");
|
|
$stmt->execute([$sid, $ip]);
|
|
$stmt = db()->prepare("DELETE FROM chat_remarks WHERE user_id = 0 AND (session_id = ? OR ip_address = ?)");
|
|
$stmt->execute([$sid, $ip]);
|
|
}
|
|
echo json_encode(['success' => true]);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'admin_recall_message') {
|
|
if (!isset($_SESSION['admin_id'])) exit(json_encode(['success' => false, 'error' => 'Unauthorized']));
|
|
$message_id = $_POST['message_id'] ?? 0;
|
|
$stmt = db()->prepare("DELETE FROM messages WHERE id = ? AND sender = 'admin'");
|
|
$stmt->execute([$message_id]);
|
|
echo json_encode(['success' => true]);
|
|
exit;
|
|
}
|