38451-vm/admin/customer_service.php
2026-02-18 09:17:22 +00:00

171 lines
7.1 KiB
PHP

<?php
session_start();
require_once __DIR__ . '/../db/config.php';
// Check if admin
if (!isset($_SESSION['admin_id'])) {
header("Location: /admin/login.php");
exit;
}
// In a real app, check for admin role here
?>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Byro Admin | 客服系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet">
<style>
body { background-color: #f0f2f5; font-family: 'Noto Sans SC', sans-serif; height: 100vh; margin: 0; }
.sidebar { width: 350px; background: #fff; border-right: 1px solid #ddd; display: flex; flex-direction: column; }
.main-chat { flex: 1; display: flex; flex-direction: column; background: #fff; }
.user-list { flex: 1; overflow-y: auto; }
.user-card { padding: 15px; border-bottom: 1px solid #f0f0f0; cursor: pointer; transition: all 0.2s; }
.user-card:hover { background: #f8f9fa; }
.user-card.active { background: #e7f3ff; border-left: 5px solid #007bff; }
.chat-header { padding: 15px 25px; border-bottom: 1px solid #ddd; background: #fff; z-index: 10; }
.messages-area { flex: 1; padding: 25px; background: #f9f9f9; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
.msg { max-width: 75%; padding: 10px 15px; border-radius: 18px; font-size: 14px; line-height: 1.5; }
.msg-admin { align-self: flex-end; background: #007bff; color: #fff; border-bottom-right-radius: 2px; }
.msg-user { align-self: flex-start; background: #fff; color: #333; border: 1px solid #eee; border-bottom-left-radius: 2px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); }
.chat-input-area { padding: 20px; border-top: 1px solid #ddd; background: #fff; }
.status-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; margin-right: 5px; }
.status-online { background: #28a745; }
</style>
</head>
<body class="d-flex">
<div class="sidebar">
<div class="p-3 bg-primary text-white d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center gap-2">
<a href="/admin/index.php" class="text-white"><i class="bi bi-arrow-left"></i></a>
<h5 class="m-0 fw-bold">客服中心</h5>
</div>
<span class="badge bg-light text-primary">Live</span>
</div>
<div class="p-2">
<input type="text" class="form-control form-control-sm" placeholder="搜索用户 UID / IP">
</div>
<div class="user-list" id="user-list">
<!-- User cards -->
</div>
</div>
<div class="main-chat">
<div class="chat-header" id="chat-header" style="display: none;">
<div class="d-flex justify-content-between align-items-center">
<div>
<h5 class="m-0 fw-bold" id="header-name">用户名称</h5>
<div class="small text-muted" id="header-meta">UID: --- | IP: ---</div>
</div>
<div class="text-end">
<span class="status-dot status-online"></span>
<span class="small text-success fw-bold">正在对话</span>
</div>
</div>
</div>
<div class="messages-area" id="messages-area">
<div class="m-auto text-center text-muted">
<i class="bi bi-chat-left-dots fs-1 d-block mb-3"></i>
<p>从左侧选择一个会话开始实时对话</p>
</div>
</div>
<div class="chat-input-area" id="input-area" style="display: none;">
<form id="chat-form" class="d-flex gap-2">
<input type="text" id="msg-input" class="form-control" placeholder="输入消息回复用户..." autocomplete="off">
<button type="submit" class="btn btn-primary px-4 fw-bold">发送回复</button>
</form>
</div>
</div>
<script>
let selectedUser = null;
let selectedIp = null;
let lastMsgId = 0;
async function refreshUsers() {
const r = await fetch('/api/chat.php?action=admin_get_all');
const users = await r.json();
const list = document.getElementById('user-list');
let html = '';
users.forEach(u => {
const isActive = (selectedIp === u.ip_address && selectedUser == u.user_id);
html += `
<div class="user-card ${isActive ? 'active' : ''}" onclick="openChat('${u.user_id}', '${u.ip_address}', '${u.username || '匿名用户'}', '${u.uid || '---'}')">
<div class="d-flex justify-content-between mb-1">
<span class="fw-bold">${u.username || '匿名用户'}</span>
<span class="small text-muted">${new Date(u.created_at).toLocaleTimeString()}</span>
</div>
<div class="small text-truncate text-muted mb-1">${u.message}</div>
<div class="d-flex justify-content-between align-items-center">
<span class="badge bg-light text-dark border" style="font-size: 10px;">UID: ${u.uid || '---'}</span>
<span class="text-primary" style="font-size: 10px;">${u.ip_address}</span>
</div>
</div>
`;
});
list.innerHTML = html;
}
function openChat(userId, ip, name, uid) {
selectedUser = userId;
selectedIp = ip;
document.getElementById('header-name').innerText = name;
document.getElementById('header-meta').innerText = `UID: ${uid} | IP: ${ip}`;
document.getElementById('chat-header').style.display = 'block';
document.getElementById('input-area').style.display = 'block';
lastMsgId = 0;
fetchMessages();
}
async function fetchMessages() {
if (!selectedIp) return;
const r = await fetch(`/api/chat.php?action=get_messages&user_id=${selectedUser}&ip=${selectedIp}`);
const msgs = await r.json();
const area = document.getElementById('messages-area');
// Simple filter for the specific conversation
const filtered = msgs.filter(m => m.ip_address === selectedIp && (m.user_id == selectedUser || m.user_id == 0));
if (filtered.length > lastMsgId) {
area.innerHTML = '';
filtered.forEach(m => {
const div = document.createElement('div');
div.className = `msg ${m.sender === 'admin' ? 'msg-admin' : 'msg-user'}`;
div.innerText = m.message;
area.appendChild(div);
});
area.scrollTop = area.scrollHeight;
lastMsgId = filtered.length;
}
}
document.getElementById('chat-form').addEventListener('submit', async (e) => {
e.preventDefault();
const input = document.getElementById('msg-input');
const msg = input.value.trim();
if (!msg) return;
const fd = new URLSearchParams();
fd.append('message', msg);
fd.append('user_id', selectedUser);
fd.append('ip_address', selectedIp);
await fetch('/api/chat.php?action=admin_send', { method: 'POST', body: fd });
input.value = '';
fetchMessages();
});
setInterval(refreshUsers, 3000);
setInterval(fetchMessages, 1000);
refreshUsers();
</script>
</body>
</html>