<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Demo Hệ Thống Duyệt Nạp Tiền TRON</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
</head>
<body class="bg-gray-100 p-10 font-sans">
<div class="max-w-4xl mx-auto bg-white shadow-lg rounded-lg overflow-hidden">
<div class="bg-blue-600 p-4 text-white flex justify-between items-center">
<h1 class="text-xl font-bold"><i class="fas fa-users-cog mr-2"></i>Danh sách Khách hàng</h1>
<span class="text-sm bg-blue-500 px-2 py-1 rounded">Role: Support</span>
</div>
<table class="w-full text-left border-collapse">
<thead>
<tr class="bg-gray-200 text-gray-700 uppercase text-sm leading-normal">
<th class="py-3 px-6">ID</th>
<th class="py-3 px-6">Tên Khách Hàng</th>
<th class="py-3 px-6">Email</th>
<th class="py-3 px-6 text-right">Số dư (USDT)</th>
<th class="py-3 px-6 text-center">Hành động</th>
</tr>
</thead>
<tbody id="customer-list" class="text-gray-600 text-sm font-light">
</tbody>
</table>
</div>
<div id="topup-modal" class="fixed inset-0 bg-gray-900 bg-opacity-50 hidden flex items-center justify-center z-50">
<div class="bg-white rounded-lg shadow-xl w-full max-w-lg mx-4 overflow-hidden transform transition-all">
<div class="bg-gray-50 px-4 py-3 border-b flex justify-between items-center">
<h3 class="text-lg font-semibold text-gray-800">
<i class="fas fa-wallet text-blue-500 mr-2"></i>Duyệt nạp USDT
</h3>
<button onclick="closeModal()" class="text-gray-400 hover:text-gray-600">×</button>
</div>
<div class="p-6 space-y-4">
<div class="bg-blue-50 text-blue-800 text-xs p-2 rounded border border-blue-200">
<strong>Support chú ý:</strong> Hệ thống sẽ tự động check trên Tronscan.
<br> - Copy mã <b>VALID_123</b> để test trường hợp thành công.
<br> - Copy mã <b>USED_456</b> để test trường hợp trùng lặp.
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Đang nạp cho:</label>
<input type="text" id="modal-customer-name" class="w-full bg-gray-100 border border-gray-300 rounded px-3 py-2 text-gray-500" disabled>
<input type="hidden" id="modal-customer-id">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Mã giao dịch (TXID):</label>
<div class="flex gap-2">
<input type="text" id="tx-input" placeholder="Dán mã giao dịch vào đây..." class="flex-1 border border-gray-300 rounded px-3 py-2 focus:outline-none focus:border-blue-500">
<button onclick="checkTransaction()" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded shadow transition">
<i class="fas fa-search mr-1"></i> Kiểm tra
</button>
</div>
</div>
<div id="result-area" class="hidden border rounded p-3 mt-2">
</div>
</div>
<div class="bg-gray-50 px-4 py-3 flex justify-end gap-2">
<button onclick="closeModal()" class="px-4 py-2 bg-gray-300 text-gray-700 rounded hover:bg-gray-400">Hủy bỏ</button>
<button id="btn-confirm" onclick="confirmTopUp()" disabled class="px-4 py-2 bg-green-600 text-white rounded opacity-50 cursor-not-allowed hover:bg-green-700 transition">
<i class="fas fa-check-circle mr-1"></i> Duyệt Nạp
</button>
</div>
</div>
</div>
<script>
// 1. DỮ LIỆU GIẢ LẬP (MOCK DATA)
const customers = [
{ id: 101, name: "Nguyễn Văn A", email: "a.nguyen@example.com", balance: 0 },
{ id: 102, name: "Trần Thị B", email: "b.tran@gmail.com", balance: 50 },
{ id: 103, name: "Lê Văn C", email: "c.le@yahoo.com", balance: 1200 }
];
// Giả lập Database chứa các mã đã dùng
const usedTransactionsInDB = ["USED_456", "OLD_TX_789"];
// 2. RENDER GIAO DIỆN
function renderCustomers() {
const tbody = document.getElementById('customer-list');
tbody.innerHTML = '';
customers.forEach(cus => {
const tr = document.createElement('tr');
tr.className = "border-b border-gray-200 hover:bg-gray-100";
tr.innerHTML = `
<td class="py-3 px-6 whitespace-nowrap font-medium">${cus.id}</td>
<td class="py-3 px-6">${cus.name}</td>
<td class="py-3 px-6">${cus.email}</td>
<td class="py-3 px-6 text-right font-bold text-green-600">$${cus.balance.toLocaleString()}</td>
<td class="py-3 px-6 text-center">
<button onclick="openModal(${cus.id})" class="bg-blue-500 hover:bg-blue-600 text-white py-1 px-3 rounded text-xs shadow">
<i class="fas fa-plus-circle"></i> Nạp USDT
</button>
</td>
`;
tbody.appendChild(tr);
});
}
// Khởi chạy lần đầu
renderCustomers();
// 3. XỬ LÝ MODAL
let currentCustomerId = null;
function openModal(id) {
const customer = customers.find(c => c.id === id);
if(!customer) return;
currentCustomerId = id;
document.getElementById('modal-customer-name').value = customer.name;
document.getElementById('modal-customer-id').value = customer.id;
// Reset form
document.getElementById('tx-input').value = '';
document.getElementById('result-area').classList.add('hidden');
document.getElementById('btn-confirm').disabled = true;
document.getElementById('btn-confirm').classList.add('opacity-50', 'cursor-not-allowed');
document.getElementById('topup-modal').classList.remove('hidden');
}
function closeModal() {
document.getElementById('topup-modal').classList.add('hidden');
}
// 4. LOGIC CHECK GIAO DỊCH (CORE FEATURE)
function checkTransaction() {
const txInput = document.getElementById('tx-input').value.trim();
const resultArea = document.getElementById('result-area');
const btnConfirm = document.getElementById('btn-confirm');
// Reset trạng thái
resultArea.classList.remove('hidden', 'bg-red-50', 'border-red-200', 'bg-green-50', 'border-green-200', 'bg-yellow-50', 'border-yellow-200');
resultArea.innerHTML = '<div class="text-center text-gray-500"><i class="fas fa-spinner fa-spin"></i> Đang kết nối Tronscan...</div>';
btnConfirm.disabled = true;
btnConfirm.classList.add('opacity-50', 'cursor-not-allowed');
// Giả lập độ trễ mạng (1 giây)
setTimeout(() => {
// --- KỊCH BẢN 1: GIAO DỊCH ĐÃ DÙNG (DUPLICATE) ---
if (usedTransactionsInDB.includes(txInput)) {
showResult('DUPLICATE', {
hash: txInput,
amount: 100,
time: '2023-10-10 15:30:00',
usedBy: 'Khách hàng ID #999'
});
}
// --- KỊCH BẢN 2: GIAO DỊCH HỢP LỆ (SUCCESS) ---
else if (txInput === 'VALID_123') {
showResult('SUCCESS', {
hash: txInput,
amount: 500, // Số tiền giả lập lấy từ API
time: new Date().toLocaleString(),
from: 'T_KHACH_HANG_ABCXYZ'
});
}
// --- KỊCH BẢN 3: KHÔNG TÌM THẤY (NOT FOUND) ---
else {
showResult('NOT_FOUND');
}
}, 800);
}
// Hàm hiển thị kết quả check
let currentTransactionAmount = 0; // Lưu tạm số tiền để nạp
function showResult(type, data) {
const resultArea = document.getElementById('result-area');
const btnConfirm = document.getElementById('btn-confirm');
if (type === 'SUCCESS') {
currentTransactionAmount = data.amount;
resultArea.className = "border rounded p-3 mt-2 bg-green-50 border-green-200 text-green-800";
resultArea.innerHTML = `
<div class="font-bold mb-1"><i class="fas fa-check-circle"></i> Giao dịch Hợp lệ</div>
<ul class="text-sm list-disc pl-5 space-y-1">
<li><strong>Số tiền:</strong> ${data.amount} USDT</li>
<li><strong>Thời gian:</strong> ${data.time}</li>
<li><strong>Từ ví:</strong> ${data.from}</li>
<li><strong>Trạng thái:</strong> Chưa sử dụng</li>
</ul>
`;
// Mở khóa nút nạp
btnConfirm.disabled = false;
btnConfirm.classList.remove('opacity-50', 'cursor-not-allowed');
} else if (type === 'DUPLICATE') {
resultArea.className = "border rounded p-3 mt-2 bg-red-50 border-red-200 text-red-800";
resultArea.innerHTML = `
<div class="font-bold mb-1"><i class="fas fa-exclamation-triangle"></i> CẢNH BÁO: Đã sử dụng</div>
<div class="text-sm">Mã giao dịch này đã được nạp trước đó!</div>
<ul class="text-sm list-disc pl-5 mt-1">
<li><strong>Số tiền:</strong> ${data.amount} USDT</li>
<li><strong>Đã nạp lúc:</strong> ${data.time}</li>
<li><strong>Người nạp:</strong> ${data.usedBy}</li>
</ul>
`;
} else {
resultArea.className = "border rounded p-3 mt-2 bg-yellow-50 border-yellow-200 text-yellow-800";
resultArea.innerHTML = `
<div class="font-bold mb-1"><i class="fas fa-times-circle"></i> Không tìm thấy</div>
<div class="text-sm">Không tìm thấy giao dịch này trên Blockchain hoặc Tronscan chưa cập nhật. Vui lòng kiểm tra lại mã.</div>
`;
}
}
// 5. XÁC NHẬN NẠP TIỀN
function confirmTopUp() {
const customer = customers.find(c => c.id === currentCustomerId);
if (customer) {
// Cộng tiền
customer.balance += currentTransactionAmount;
// Cập nhật giao diện
renderCustomers();
closeModal();
// Thông báo (Alert đơn giản)
alert(`Đã nạp thành công ${currentTransactionAmount} USDT cho khách hàng ${customer.name}`);
// (Trong thực tế: Gọi API lưu vào DB để đánh dấu mã này đã dùng)
usedTransactionsInDB.push(document.getElementById('tx-input').value);
}
}
</script>
</body>
</html>
Số dòng: 241