ces
This commit is contained in:
parent
2abf771e6c
commit
582dc33422
18
about.php
18
about.php
@ -6,28 +6,28 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<h1 class="mb-4 fw-bold"><?php echo __('about_us'); ?></h1>
|
||||
<div class="card bg-dark border-secondary p-4">
|
||||
<p class="lead mb-4"><?php echo __('about_content'); ?></p>
|
||||
<h3 class="mt-4 mb-3"><?= __('our_mission') ?></h3>
|
||||
<p class="text-muted">
|
||||
<div class="card bg-surface border-secondary p-4">
|
||||
<p class="lead mb-4 text-white"><?php echo __('about_content'); ?></p>
|
||||
<h3 class="mt-4 mb-3 text-white"><?= __('our_mission') ?></h3>
|
||||
<p class="text-white-50">
|
||||
<?= __('mission_content') ?>
|
||||
</p>
|
||||
<h3 class="mt-4 mb-3"><?= __('global_presence') ?></h3>
|
||||
<p class="text-muted">
|
||||
<h3 class="mt-4 mb-3 text-white"><?= __('global_presence') ?></h3>
|
||||
<p class="text-white-50">
|
||||
<?= __('presence_content') ?>
|
||||
</p>
|
||||
<div class="row mt-5 text-center">
|
||||
<div class="col-4">
|
||||
<h2 class="fw-bold text-primary">5M+</h2>
|
||||
<p class="small text-muted"><?= __('users') ?></p>
|
||||
<p class="small text-white-50"><?= __('users') ?></p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<h2 class="fw-bold text-primary">100+</h2>
|
||||
<p class="small text-muted"><?= __('countries') ?></p>
|
||||
<p class="small text-white-50"><?= __('countries') ?></p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<h2 class="fw-bold text-primary">$10B+</h2>
|
||||
<p class="small text-muted"><?= __('daily_volume') ?></p>
|
||||
<p class="small text-white-50"><?= __('daily_volume') ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -250,86 +250,83 @@ let currentUserContext = '';
|
||||
|
||||
async function refreshUsers() {
|
||||
try {
|
||||
const searchInput = document.getElementById('user-search');
|
||||
const search = searchInput ? searchInput.value.toLowerCase() : '';
|
||||
|
||||
const r = await fetch('/api/chat.php?action=admin_get_all');
|
||||
const users = await r.json();
|
||||
|
||||
const list = document.getElementById('user-list');
|
||||
if (!list) return;
|
||||
|
||||
if (users.error) {
|
||||
console.error('API Error:', users.error);
|
||||
list.innerHTML = `<div class="p-4 text-center text-danger small">接口错误: ${users.error}</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(users)) {
|
||||
console.error('API response is not an array:', users);
|
||||
list.innerHTML = `<div class="p-4 text-center text-danger small">数据格式错误</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (users.length === 0) {
|
||||
list.innerHTML = '<div class="p-4 text-center text-muted small">暂无活跃会话 (720h内)</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const list = document.getElementById('user-list');
|
||||
const searchInput = document.getElementById('user-search');
|
||||
const search = searchInput ? searchInput.value.toLowerCase() : '';
|
||||
|
||||
let html = '';
|
||||
users.forEach(u => {
|
||||
try {
|
||||
const userId = u.user_id;
|
||||
const username = u.username || '匿名用户';
|
||||
const uid = u.uid || '---';
|
||||
const ip = u.ip_address || '---';
|
||||
const rawRemark = u.remark || '';
|
||||
const remark = rawRemark.toString().replace(/\n/g, " ");
|
||||
const userTime = u.user_time || '---';
|
||||
const lastTime = u.created_at ? new Date(u.created_at.replace(/-/g, "/")) : new Date();
|
||||
|
||||
let lastMsgText = u.message || '';
|
||||
if (lastMsgText.startsWith('[PAYMENT_INFO]')) {
|
||||
lastMsgText = '[收款账号信息]';
|
||||
}
|
||||
|
||||
const isActive = (selectedIp === ip && selectedUser == userId);
|
||||
if (isActive) {
|
||||
const infoUserTime = document.getElementById('info-user-time');
|
||||
if (infoUserTime) infoUserTime.innerText = userTime;
|
||||
}
|
||||
|
||||
// Using data attributes to avoid escaping issues in onclick
|
||||
html += `
|
||||
<div class="user-card ${isActive ? 'active' : ''}"
|
||||
data-user-id="${userId}"
|
||||
data-ip="${ip}"
|
||||
data-name="${username.replace(/"/g, '"')}"
|
||||
data-uid="${uid}"
|
||||
data-remark="${remark.replace(/"/g, '"')}"
|
||||
data-user-time="${userTime}">
|
||||
<div class="d-flex justify-content-between mb-1">
|
||||
<span class="fw-bold small text-truncate" style="max-width: 150px;">${username}</span>
|
||||
<span class="text-muted" style="font-size: 10px;">${lastTime.toLocaleTimeString('zh-CN', {hour: '2-digit', minute:'2-digit'})}</span>
|
||||
</div>
|
||||
${rawRemark ? `<div class="small text-danger text-truncate mb-1" style="font-size: 11px;">[备注: ${rawRemark}]</div>` : ''}
|
||||
<div class="small text-truncate text-muted mb-1" style="font-size: 12px;">${lastMsgText}</div>
|
||||
<div class="d-flex justify-content-between align-items-center" style="font-size: 10px;">
|
||||
<span class="text-secondary">UID: ${uid}</span>
|
||||
<span class="text-primary fw-bold">${ip}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} catch (e) {
|
||||
console.error('Error rendering user card:', e, u);
|
||||
const userId = u.user_id || 0;
|
||||
const username = (u.username || '匿名用户').toString();
|
||||
const uid = (u.uid || '---').toString();
|
||||
const ip = (u.ip_address || '---').toString();
|
||||
const rawRemark = (u.remark || '').toString();
|
||||
const userTime = (u.user_time || '---').toString();
|
||||
const lastTimeStr = u.created_at ? u.created_at.replace(/-/g, "/") : new Date().toISOString();
|
||||
const lastTime = new Date(lastTimeStr);
|
||||
|
||||
// Search filter
|
||||
if (search && !username.toLowerCase().includes(search) && !ip.includes(search) && !uid.includes(search)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let lastMsgText = (u.message || '').toString();
|
||||
if (lastMsgText.startsWith('[PAYMENT_INFO]')) {
|
||||
lastMsgText = '[收款账号信息]';
|
||||
}
|
||||
|
||||
const isActive = (selectedIp === ip && selectedUser == userId);
|
||||
|
||||
// Safe strings for onclick
|
||||
const jsName = username.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
||||
const jsRemark = rawRemark.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
||||
|
||||
html += `
|
||||
<div class="user-card ${isActive ? 'active' : ''}"
|
||||
onclick="openChat('${userId}', '${ip}', '${jsName}', '${uid}', '${jsRemark}', '${userTime}')">
|
||||
<div class="d-flex justify-content-between mb-1">
|
||||
<span class="fw-bold small text-truncate" style="max-width: 150px;">${username}</span>
|
||||
<span class="text-muted" style="font-size: 10px;">${isNaN(lastTime.getTime()) ? '---' : lastTime.toLocaleTimeString('zh-CN', {hour: '2-digit', minute:'2-digit'})}</span>
|
||||
</div>
|
||||
${rawRemark ? `<div class="small text-danger text-truncate mb-1" style="font-size: 11px;">[备注: ${rawRemark}]</div>` : ''}
|
||||
<div class="small text-truncate text-muted mb-1" style="font-size: 12px;">${lastMsgText}</div>
|
||||
<div class="d-flex justify-content-between align-items-center" style="font-size: 10px;">
|
||||
<span class="text-secondary">UID: ${uid}</span>
|
||||
<span class="text-primary fw-bold">${ip}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
list.innerHTML = html || '<div class="p-4 text-center text-muted small">暂无活跃会话</div>';
|
||||
list.innerHTML = html || '<div class="p-4 text-center text-muted small">未找到匹配的会话</div>';
|
||||
} catch (err) {
|
||||
console.error('Refresh users failed:', err);
|
||||
const list = document.getElementById('user-list');
|
||||
if (list) {
|
||||
list.innerHTML = `<div class="p-4 text-center text-danger small">脚本运行错误,请刷新页面</div>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle clicks on user cards using event delegation
|
||||
document.getElementById('user-list').addEventListener('click', (e) => {
|
||||
const card = e.target.closest('.user-card');
|
||||
if (card) {
|
||||
const d = card.dataset;
|
||||
openChat(d.userId, d.ip, d.name, d.uid, d.remark, d.userTime);
|
||||
}
|
||||
});
|
||||
|
||||
function openChat(userId, ip, name, uid, remark, userTime) {
|
||||
selectedUser = userId;
|
||||
selectedIp = ip;
|
||||
@ -347,7 +344,7 @@ function openChat(userId, ip, name, uid, remark, userTime) {
|
||||
|
||||
lastMsgId = 0;
|
||||
fetchMessages();
|
||||
refreshUsers(); // Refresh list to update active state
|
||||
refreshUsers();
|
||||
}
|
||||
|
||||
async function recallMessage(msgId) {
|
||||
@ -391,7 +388,6 @@ async function fetchMessages() {
|
||||
const msgs = await r.json();
|
||||
if (!msgs || !Array.isArray(msgs)) return;
|
||||
|
||||
// If user changed, clear everything
|
||||
const context = selectedUser + '_' + selectedIp;
|
||||
if (currentUserContext !== context) {
|
||||
document.getElementById('messages-area').innerHTML = '';
|
||||
@ -427,7 +423,7 @@ async function fetchMessages() {
|
||||
|
||||
function appendMessageHTML(m) {
|
||||
const area = document.getElementById('messages-area');
|
||||
if (!area || area.querySelector(`[data-id="${m.id}"]`)) return;
|
||||
if (!area) return;
|
||||
|
||||
const time = m.created_at || new Date().toISOString();
|
||||
const msgDate = time.includes('-') ? new Date(time.replace(/-/g, "/")) : new Date(time);
|
||||
@ -440,10 +436,10 @@ function appendMessageHTML(m) {
|
||||
div.className = `msg ${m.sender === 'admin' ? 'msg-admin' : 'msg-user'}`;
|
||||
div.setAttribute('data-id', m.id);
|
||||
|
||||
let displayMsg = m.message;
|
||||
let displayMsg = (m.message || '').toString();
|
||||
if (isPaymentInfo) {
|
||||
try {
|
||||
const info = JSON.parse(m.message.replace('[PAYMENT_INFO]', ''));
|
||||
const info = JSON.parse(displayMsg.replace('[PAYMENT_INFO]', ''));
|
||||
displayMsg = `<div class="p-2 border border-white border-opacity-20 rounded bg-white bg-opacity-10 small">
|
||||
<div class="fw-bold"><i class="bi bi-bank me-1"></i>已发送收款账号</div>
|
||||
<div class="mt-1 opacity-75">${info.bank} - ${info.name}</div>
|
||||
@ -469,9 +465,10 @@ document.getElementById('plus-btn').addEventListener('click', () => {
|
||||
document.getElementById('image-input').click();
|
||||
});
|
||||
|
||||
const paymentModal = new bootstrap.Modal(document.getElementById('paymentModal'));
|
||||
const paymentModalEl = document.getElementById('paymentModal');
|
||||
const paymentModal = paymentModalEl ? new bootstrap.Modal(paymentModalEl) : null;
|
||||
document.getElementById('payment-btn').addEventListener('click', () => {
|
||||
paymentModal.show();
|
||||
if (paymentModal) paymentModal.show();
|
||||
});
|
||||
|
||||
async function sendPaymentInfo() {
|
||||
@ -497,8 +494,7 @@ async function sendPaymentInfo() {
|
||||
const r = await fetch('/api/chat.php?action=admin_send', { method: 'POST', body: fd });
|
||||
const res = await r.json();
|
||||
if (res.success) {
|
||||
paymentModal.hide();
|
||||
// Clear inputs
|
||||
if (paymentModal) paymentModal.hide();
|
||||
document.getElementById('pay-bank').value = '';
|
||||
document.getElementById('pay-name').value = '';
|
||||
document.getElementById('pay-account').value = '';
|
||||
@ -512,7 +508,6 @@ document.getElementById('image-input').addEventListener('change', async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
// Local preview for "0 latency"
|
||||
const localUrl = URL.createObjectURL(file);
|
||||
const tempId = 'temp_img_' + Date.now();
|
||||
const localMsgHtml = `<img src="${localUrl}" class="img-fluid rounded" style="max-width: 100%; max-height: 250px; object-fit: contain; margin: 5px 0; opacity: 0.6;">`;
|
||||
@ -524,7 +519,7 @@ document.getElementById('image-input').addEventListener('change', async (e) => {
|
||||
created_at: new Date().toISOString()
|
||||
});
|
||||
const area = document.getElementById('messages-area');
|
||||
area.scrollTop = area.scrollHeight;
|
||||
if (area) area.scrollTop = area.scrollHeight;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
@ -538,13 +533,12 @@ document.getElementById('image-input').addEventListener('change', async (e) => {
|
||||
});
|
||||
const res = await r.json();
|
||||
|
||||
// Remove temp
|
||||
const tempMsg = document.querySelector(`[data-id="${tempId}"]`);
|
||||
if (tempMsg) tempMsg.remove();
|
||||
|
||||
if (res.success && res.message) {
|
||||
appendMessageHTML(res.message);
|
||||
area.scrollTop = area.scrollHeight;
|
||||
if (area) area.scrollTop = area.scrollHeight;
|
||||
fetchMessages();
|
||||
} else {
|
||||
alert('上传失败: ' + res.error);
|
||||
@ -554,7 +548,7 @@ document.getElementById('image-input').addEventListener('change', async (e) => {
|
||||
if (tempMsg) tempMsg.remove();
|
||||
}
|
||||
|
||||
e.target.value = ''; // Reset
|
||||
e.target.value = '';
|
||||
setTimeout(() => URL.revokeObjectURL(localUrl), 5000);
|
||||
});
|
||||
|
||||
@ -566,7 +560,6 @@ document.getElementById('chat-form').addEventListener('submit', async (e) => {
|
||||
|
||||
input.value = '';
|
||||
|
||||
// Optimistic UI
|
||||
const tempId = 'temp_msg_' + Date.now();
|
||||
appendMessageHTML({
|
||||
id: tempId,
|
||||
@ -575,7 +568,7 @@ document.getElementById('chat-form').addEventListener('submit', async (e) => {
|
||||
created_at: new Date().toISOString()
|
||||
});
|
||||
const area = document.getElementById('messages-area');
|
||||
area.scrollTop = area.scrollHeight;
|
||||
if (area) area.scrollTop = area.scrollHeight;
|
||||
|
||||
const fd = new URLSearchParams();
|
||||
fd.append('message', msg);
|
||||
@ -591,7 +584,7 @@ document.getElementById('chat-form').addEventListener('submit', async (e) => {
|
||||
|
||||
if (res.success && res.message) {
|
||||
appendMessageHTML(res.message);
|
||||
area.scrollTop = area.scrollHeight;
|
||||
if (area) area.scrollTop = area.scrollHeight;
|
||||
fetchMessages();
|
||||
}
|
||||
} catch(err) {}
|
||||
|
||||
@ -95,7 +95,7 @@ ob_start();
|
||||
$type = $_GET['type'] ?? 'recharge';
|
||||
$user_id = isset($_GET['user_id']) ? (int)$_GET['user_id'] : null;
|
||||
|
||||
$sql = "SELECT r.*, u.username, u.uid FROM finance_requests r JOIN users u ON r.user_id = u.id WHERE r.type = ?";
|
||||
$sql = "SELECT r.*, u.username, u.uid FROM finance_requests r LEFT JOIN users u ON r.user_id = u.id WHERE r.type = ?";
|
||||
$params = [$type];
|
||||
|
||||
if ($admin['is_agent']) {
|
||||
@ -155,8 +155,8 @@ $requests = $stmt->fetchAll();
|
||||
<tr>
|
||||
<td><?= $r['id'] ?></td>
|
||||
<td>
|
||||
<div><?= htmlspecialchars($r['username']) ?></div>
|
||||
<code class="small"><?= $r['uid'] ?></code>
|
||||
<div><?= htmlspecialchars($r['username'] ?? '未知用户') ?></div>
|
||||
<code class="small"><?= htmlspecialchars($r['uid'] ?? '---') ?></code>
|
||||
</td>
|
||||
<td>
|
||||
<span class="fw-bold <?= $r['type'] === 'recharge' ? 'text-success' : 'text-danger' ?>">
|
||||
|
||||
40
api.php
40
api.php
@ -4,48 +4,48 @@ require_once __DIR__ . '/includes/header.php';
|
||||
?>
|
||||
<main class="container py-5">
|
||||
<h1 class="mb-4 fw-bold"><?php echo __('api_doc'); ?></h1>
|
||||
<div class="card bg-dark border-secondary p-4">
|
||||
<div class="card bg-surface border-secondary p-4 shadow-sm">
|
||||
<div class="row">
|
||||
<div class="col-md-3 border-end border-secondary">
|
||||
<nav class="nav flex-column sticky-top" style="top: 100px;">
|
||||
<a class="nav-link text-white fw-bold mb-2" href="#intro"><?= __('api_intro') ?></a>
|
||||
<a class="nav-link text-muted mb-2" href="#auth"><?= __('api_auth') ?></a>
|
||||
<a class="nav-link text-muted mb-2" href="#market"><?= __('api_market_data') ?></a>
|
||||
<a class="nav-link text-muted mb-2" href="#trade"><?= __('api_trade_endpoints') ?></a>
|
||||
<a class="nav-link text-muted mb-2" href="#errors"><?= __('api_errors') ?></a>
|
||||
<a class="nav-link text-white-50 mb-2" href="#auth"><?= __('api_auth') ?></a>
|
||||
<a class="nav-link text-white-50 mb-2" href="#market"><?= __('api_market_data') ?></a>
|
||||
<a class="nav-link text-white-50 mb-2" href="#trade"><?= __('api_trade_endpoints') ?></a>
|
||||
<a class="nav-link text-white-50 mb-2" href="#errors"><?= __('api_errors') ?></a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="col-md-9 ps-md-4">
|
||||
<section id="intro" class="mb-5">
|
||||
<h2 class="fw-bold"><?= __('api_intro') ?></h2>
|
||||
<p class="text-muted"><?= __('api_intro_desc') ?></p>
|
||||
<h2 class="fw-bold text-white"><?= __('api_intro') ?></h2>
|
||||
<p class="text-white-50"><?= __('api_intro_desc') ?></p>
|
||||
</section>
|
||||
|
||||
<section id="auth" class="mb-5">
|
||||
<h2 class="fw-bold"><?= __('api_auth') ?></h2>
|
||||
<p class="text-muted"><?= __('api_auth_desc') ?></p>
|
||||
<div class="bg-black p-3 rounded mb-3">
|
||||
<h2 class="fw-bold text-white"><?= __('api_auth') ?></h2>
|
||||
<p class="text-white-50"><?= __('api_auth_desc') ?></p>
|
||||
<div class="bg-black p-3 rounded mb-3 border border-secondary">
|
||||
<code class="text-success">Authorization: Bearer YOUR_API_KEY</code>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="market" class="mb-5">
|
||||
<h2 class="fw-bold"><?= __('api_market_data') ?></h2>
|
||||
<h5 class="mt-4"><?= __('api_get_ticker') ?></h5>
|
||||
<div class="bg-black p-3 rounded mb-2">
|
||||
<code>GET /api/v1/market/ticker?symbol=BTCUSDT</code>
|
||||
<h2 class="fw-bold text-white"><?= __('api_market_data') ?></h2>
|
||||
<h5 class="mt-4 text-white"><?= __('api_get_ticker') ?></h5>
|
||||
<div class="bg-black p-3 rounded mb-2 border border-secondary">
|
||||
<code class="text-info">GET /api/v1/market/ticker?symbol=BTCUSDT</code>
|
||||
</div>
|
||||
<p class="small text-muted"><?= __('api_get_ticker_desc') ?></p>
|
||||
<p class="small text-white-50"><?= __('api_get_ticker_desc') ?></p>
|
||||
</section>
|
||||
|
||||
<section id="trade" class="mb-5">
|
||||
<h2 class="fw-bold"><?= __('trade') ?></h2>
|
||||
<h5 class="mt-4"><?= __('api_place_order') ?></h5>
|
||||
<div class="bg-black p-3 rounded mb-2">
|
||||
<h2 class="fw-bold text-white"><?= __('trade') ?></h2>
|
||||
<h5 class="mt-4 text-white"><?= __('api_place_order') ?></h5>
|
||||
<div class="bg-black p-3 rounded mb-2 border border-secondary">
|
||||
<code class="text-info">POST /api/v1/trade/order</code>
|
||||
</div>
|
||||
<p class="small text-muted"><?= __('api_payload_example') ?></p>
|
||||
<pre class="bg-black p-3 rounded text-warning"><code>{
|
||||
<p class="small text-white-50"><?= __('api_payload_example') ?></p>
|
||||
<pre class="bg-black p-3 rounded text-warning border border-secondary"><code>{
|
||||
"symbol": "BTCUSDT",
|
||||
"side": "buy",
|
||||
"type": "limit",
|
||||
|
||||
12
api/chat.php
12
api/chat.php
@ -135,6 +135,7 @@ if ($action === 'ping') {
|
||||
|
||||
if ($action === 'admin_get_all') {
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($_SESSION['admin_id'])) {
|
||||
echo json_encode(['error' => 'Unauthorized']);
|
||||
exit;
|
||||
@ -147,18 +148,18 @@ if ($action === 'admin_get_all') {
|
||||
v.ip_address,
|
||||
CASE
|
||||
WHEN m.message LIKE '<img%' THEN '[图片消息]'
|
||||
WHEN m.message IS NULL AND v.has_recharge = 1 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,
|
||||
CASE WHEN u.email LIKE '%@user.byro' THEN u.username ELSE COALESCE(u.email, u.username) END as username,
|
||||
COALESCE(u.username, u.email, CONCAT('访客 ', v.ip_address)) as username,
|
||||
u.uid,
|
||||
r.remark,
|
||||
v.user_time
|
||||
FROM (
|
||||
SELECT
|
||||
user_id,
|
||||
MAX(ip_address) as ip_address,
|
||||
ip_address,
|
||||
MAX(last_activity) as last_activity,
|
||||
MAX(user_time) as user_time,
|
||||
MAX(has_recharge) as has_recharge
|
||||
@ -169,7 +170,7 @@ if ($action === 'admin_get_all') {
|
||||
UNION ALL
|
||||
SELECT COALESCE(user_id, 0) as user_id, ip_address, created_at as last_activity, NULL as user_time, 1 as has_recharge FROM finance_requests
|
||||
) t1
|
||||
GROUP BY user_id, (CASE WHEN user_id = 0 THEN ip_address ELSE '0' END)
|
||||
GROUP BY (CASE WHEN user_id = 0 THEN 0 ELSE user_id END), (CASE WHEN user_id = 0 THEN ip_address ELSE '0' END)
|
||||
) v
|
||||
LEFT JOIN (
|
||||
SELECT m1.* FROM messages m1
|
||||
@ -179,11 +180,12 @@ if ($action === 'admin_get_all') {
|
||||
) m ON (v.user_id = COALESCE(m.user_id, 0) AND (v.user_id != 0 OR v.ip_address = m.ip_address))
|
||||
LEFT JOIN users u ON (v.user_id = u.id AND v.user_id != 0)
|
||||
LEFT JOIN chat_remarks r ON (v.user_id = COALESCE(r.user_id, 0) AND (v.user_id != 0 OR v.ip_address = r.ip_address))
|
||||
WHERE v.last_activity > DATE_SUB(NOW(), INTERVAL 72 HOUR)
|
||||
WHERE v.last_activity > DATE_SUB(NOW(), INTERVAL 720 HOUR)
|
||||
ORDER BY created_at DESC
|
||||
");
|
||||
echo json_encode($stmt->fetchAll());
|
||||
} catch (Exception $e) {
|
||||
error_log("Chat API Error: " . $e->getMessage());
|
||||
echo json_encode(['error' => $e->getMessage()]);
|
||||
}
|
||||
exit;
|
||||
|
||||
BIN
assets/pasted-20260221-025919-b4305aa6.png
Normal file
BIN
assets/pasted-20260221-025919-b4305aa6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
24
fees.php
24
fees.php
@ -4,14 +4,14 @@ require_once __DIR__ . '/includes/header.php';
|
||||
?>
|
||||
<main class="container py-5">
|
||||
<h1 class="mb-4 fw-bold"><?php echo __('fee_structure'); ?></h1>
|
||||
<div class="card bg-dark border-secondary p-4 mb-5">
|
||||
<p class="text-muted"><?php echo __('fees_content'); ?></p>
|
||||
<div class="card bg-surface border-secondary p-4 mb-5 shadow-sm">
|
||||
<p class="text-white-50"><?php echo __('fees_content'); ?></p>
|
||||
|
||||
<h3 class="mt-4 mb-4"><?= __('spot_fees') ?></h3>
|
||||
<h3 class="mt-4 mb-4 text-white"><?= __('spot_fees') ?></h3>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-dark table-hover border-secondary">
|
||||
<thead>
|
||||
<tr class="text-muted">
|
||||
<tr class="text-white-50">
|
||||
<th><?= __('tier') ?></th>
|
||||
<th><?= __('trading_vol_30d') ?></th>
|
||||
<th><?= __('maker_fee') ?></th>
|
||||
@ -19,25 +19,25 @@ require_once __DIR__ . '/includes/header.php';
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<tr class="text-white">
|
||||
<td><?= __('level') ?> 0 (<?= __('regular') ?>)</td>
|
||||
<td>< $10,000</td>
|
||||
<td>0.100%</td>
|
||||
<td>0.100%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="text-white">
|
||||
<td><?= __('level') ?> 1</td>
|
||||
<td>≥ $10,000</td>
|
||||
<td>0.080%</td>
|
||||
<td>0.090%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="text-white">
|
||||
<td><?= __('level') ?> 2</td>
|
||||
<td>≥ $100,000</td>
|
||||
<td>0.060%</td>
|
||||
<td>0.080%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="text-white">
|
||||
<td><?= __('level') ?> 3</td>
|
||||
<td>≥ $500,000</td>
|
||||
<td>0.040%</td>
|
||||
@ -47,23 +47,23 @@ require_once __DIR__ . '/includes/header.php';
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h3 class="mt-5 mb-4"><?= __('contract_fees') ?></h3>
|
||||
<h3 class="mt-5 mb-4 text-white"><?= __('contract_fees') ?></h3>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-dark table-hover border-secondary">
|
||||
<thead>
|
||||
<tr class="text-muted">
|
||||
<tr class="text-white-50">
|
||||
<th><?= __('tier') ?></th>
|
||||
<th><?= __('maker_fee') ?></th>
|
||||
<th><?= __('taker_fee') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<tr class="text-white">
|
||||
<td><?= __('regular') ?></td>
|
||||
<td>0.020%</td>
|
||||
<td>0.050%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="text-white">
|
||||
<td><?= __('level') ?> 1</td>
|
||||
<td>0.015%</td>
|
||||
<td>0.045%</td>
|
||||
|
||||
38
help.php
38
help.php
@ -5,7 +5,7 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<main class="container py-5">
|
||||
<div class="text-center mb-5">
|
||||
<h1 class="display-5 fw-bold mb-3"><?php echo __('help'); ?></h1>
|
||||
<p class="text-muted"><?= __('help_subtitle') ?></p>
|
||||
<p class="text-white-50"><?= __('help_subtitle') ?></p>
|
||||
<div class="input-group mb-3 mx-auto" style="max-width: 600px;">
|
||||
<input type="text" class="form-control form-control-lg bg-dark text-white border-secondary" placeholder="<?= __('help_search_placeholder') ?>">
|
||||
<button class="btn btn-primary px-4"><i class="bi bi-search"></i></button>
|
||||
@ -14,50 +14,50 @@ require_once __DIR__ . '/includes/header.php';
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-dark border-secondary h-100 p-4 text-center hover-up">
|
||||
<div class="card bg-surface border-secondary h-100 p-4 text-center hover-up shadow-sm">
|
||||
<i class="bi bi-person-plus fs-1 text-primary mb-3"></i>
|
||||
<h4 class="fw-bold"><?= __('getting_started') ?></h4>
|
||||
<p class="text-muted small"><?= __('getting_started_desc') ?></p>
|
||||
<h4 class="fw-bold text-white"><?= __('getting_started') ?></h4>
|
||||
<p class="text-white-50 small"><?= __('getting_started_desc') ?></p>
|
||||
<a href="#" class="stretched-link"></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-dark border-secondary h-100 p-4 text-center hover-up">
|
||||
<div class="card bg-surface border-secondary h-100 p-4 text-center hover-up shadow-sm">
|
||||
<i class="bi bi-wallet2 fs-1 text-success mb-3"></i>
|
||||
<h4 class="fw-bold"><?= __('dep_with_title') ?></h4>
|
||||
<p class="text-muted small"><?= __('dep_with_desc') ?></p>
|
||||
<h4 class="fw-bold text-white"><?= __('dep_with_title') ?></h4>
|
||||
<p class="text-white-50 small"><?= __('dep_with_desc') ?></p>
|
||||
<a href="#" class="stretched-link"></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-dark border-secondary h-100 p-4 text-center hover-up">
|
||||
<div class="card bg-surface border-secondary h-100 p-4 text-center hover-up shadow-sm">
|
||||
<i class="bi bi-graph-up-arrow fs-1 text-info mb-3"></i>
|
||||
<h4 class="fw-bold"><?= __('trading_tutorials') ?></h4>
|
||||
<p class="text-muted small"><?= __('trading_tutorials_desc') ?></p>
|
||||
<h4 class="fw-bold text-white"><?= __('trading_tutorials') ?></h4>
|
||||
<p class="text-white-50 small"><?= __('trading_tutorials_desc') ?></p>
|
||||
<a href="#" class="stretched-link"></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-dark border-secondary h-100 p-4 text-center hover-up">
|
||||
<div class="card bg-surface border-secondary h-100 p-4 text-center hover-up shadow-sm">
|
||||
<i class="bi bi-shield-lock fs-1 text-warning mb-3"></i>
|
||||
<h4 class="fw-bold"><?= __('sec_acc_title') ?></h4>
|
||||
<p class="text-muted small"><?= __('sec_acc_desc') ?></p>
|
||||
<h4 class="fw-bold text-white"><?= __('sec_acc_title') ?></h4>
|
||||
<p class="text-white-50 small"><?= __('sec_acc_desc') ?></p>
|
||||
<a href="#" class="stretched-link"></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-dark border-secondary h-100 p-4 text-center hover-up">
|
||||
<div class="card bg-surface border-secondary h-100 p-4 text-center hover-up shadow-sm">
|
||||
<i class="bi bi-cpu fs-1 text-danger mb-3"></i>
|
||||
<h4 class="fw-bold"><?= __('api_doc_title') ?></h4>
|
||||
<p class="text-muted small"><?= __('api_doc_desc') ?></p>
|
||||
<h4 class="fw-bold text-white"><?= __('api_doc_title') ?></h4>
|
||||
<p class="text-white-50 small"><?= __('api_doc_desc') ?></p>
|
||||
<a href="/api.php" class="stretched-link"></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-dark border-secondary h-100 p-4 text-center hover-up">
|
||||
<div class="card bg-surface border-secondary h-100 p-4 text-center hover-up shadow-sm">
|
||||
<i class="bi bi-chat-dots fs-1 text-light mb-3"></i>
|
||||
<h4 class="fw-bold"><?= __('contact_sup_title') ?></h4>
|
||||
<p class="text-muted small"><?= __('contact_sup_desc') ?></p>
|
||||
<h4 class="fw-bold text-white"><?= __('contact_sup_title') ?></h4>
|
||||
<p class="text-white-50 small"><?= __('contact_sup_desc') ?></p>
|
||||
<a href="/support.php" class="stretched-link"></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -330,11 +330,11 @@ csForm.addEventListener('submit', async (e) => {
|
||||
});
|
||||
|
||||
function appendMessageHTML(m) {
|
||||
if (document.querySelector(`[data-id="${m.id}"]`)) return;
|
||||
if (!m || !m.id || document.querySelector(`[data-id="${m.id}"]`)) return;
|
||||
|
||||
const sender = m.sender;
|
||||
const text = m.message;
|
||||
const time = m.created_at;
|
||||
const text = (m.message || '').toString();
|
||||
const time = m.created_at || new Date().toISOString();
|
||||
const isImage = text.indexOf('<img') !== -1;
|
||||
|
||||
let dateObj;
|
||||
@ -343,7 +343,7 @@ function appendMessageHTML(m) {
|
||||
} else {
|
||||
dateObj = new Date(time);
|
||||
}
|
||||
const timeStr = dateObj.toLocaleTimeString('zh-CN', {hour: '2-digit', minute:'2-digit', second: '2-digit'});
|
||||
const timeStr = isNaN(dateObj.getTime()) ? '---' : dateObj.toLocaleTimeString('zh-CN', {hour: '2-digit', minute:'2-digit', second: '2-digit'});
|
||||
|
||||
const msgHtml = `
|
||||
<div class="mb-3 d-flex flex-column ${sender === 'user' ? 'align-items-end' : 'align-items-start'} message-item" data-id="${m.id}">
|
||||
|
||||
@ -551,6 +551,43 @@ $translations = [
|
||||
'step_4' => '转账完成后在聊天框告知客服或等待系统同步',
|
||||
'recharge_success_title' => '申请已提交',
|
||||
'recharge_success_text' => '您的充值申请已收到,请等待审核通过。',
|
||||
'recharge_instruction_1' => '系统正在为您分配专属收款账户,请耐心等待',
|
||||
'recharge_instruction_2' => '匹配期间请勿刷新页面或重复提交订单',
|
||||
'recharge_instruction_3' => '若超过倒计时仍未匹配成功,请及时联系在线客服',
|
||||
'recharge_instruction_4' => '收到充值账户,完成转账后,请将转账凭证提交给在线客服',
|
||||
'recharge_instruction_5' => '客服将在核实资金后为您确认到账',
|
||||
'finished_transfer' => '完成转账',
|
||||
'matching_instructions' => '匹配说明',
|
||||
'matching_system_active' => '匹配系统已激活',
|
||||
'high_encryption' => '高等级加密',
|
||||
'online' => '在线',
|
||||
'ip' => 'IP:',
|
||||
'news_title_1' => 'BYRO正式上线全新秒合约交易系统',
|
||||
'news_title_2' => '关于新增多种支付方式的公告',
|
||||
'news_title_3' => 'BYRO获得数字货币运营牌照',
|
||||
'news_title_4' => '提升账户安全:启用谷歌身份验证器',
|
||||
'news_title_5' => '2026年市场研究报告:加密货币的未来',
|
||||
'news_desc_1' => '我们很高兴地宣布,BYRO全新的秒合约系统已正式上线,提供更快的结算速度。',
|
||||
'news_desc_2' => '为了方便全球用户,我们新增了包括本地银行转账在内的多种法币充值方式。',
|
||||
'news_desc_3' => 'BYRO致力于合规化运营,近期已成功获得关键市场的运营许可。',
|
||||
'news_desc_4' => '用户的资产安全是我们的首要任务,我们建议所有用户开启谷歌二次验证。',
|
||||
'news_desc_5' => '深入了解2026年加密货币市场的发展趋势和潜在机会。',
|
||||
'news_meta' => '发布于 2026年2月21日 • 公告',
|
||||
'help_subtitle' => '在这里您可以找到有关使用BYRO的所有问题的答案',
|
||||
'help_search_placeholder' => '搜索问题、功能或教程...',
|
||||
'getting_started' => '新手入门',
|
||||
'getting_started_desc' => '了解如何注册账户并开始您的第一笔交易。',
|
||||
'dep_with_title' => '充值与提现',
|
||||
'dep_with_desc' => '关于如何存入资金和提取资产的详细指南。',
|
||||
'trading_tutorials' => '交易教程',
|
||||
'trading_tutorials_desc' => '掌握现货、合约和秒合约的交易技巧。',
|
||||
'sec_acc_title' => '账户安全',
|
||||
'sec_acc_desc' => '保护您的账户免受未经授权的访问。',
|
||||
'api_doc_title' => '接口文档',
|
||||
'api_doc_desc' => '为开发者提供的完整 API 集成文档。',
|
||||
'contact_sup_title' => '联系支持',
|
||||
'contact_sup_desc' => '如果您遇到问题,我们的团队将全天候为您服务。',
|
||||
'fees_content' => 'BYRO采用透明的费率结构,旨在为用户提供最具竞争力的交易成本。',
|
||||
],
|
||||
'en' => [
|
||||
'home' => 'Home',
|
||||
@ -1081,6 +1118,43 @@ $translations = [
|
||||
'step_4' => 'Click "I have paid" in chat or wait for system sync',
|
||||
'recharge_success_title' => 'Request Submitted',
|
||||
'recharge_success_text' => 'Your recharge request has been received. Please wait for approval.',
|
||||
'recharge_instruction_1' => 'System is allocating an exclusive account for you, please wait patiently.',
|
||||
'recharge_instruction_2' => 'Do not refresh the page or resubmit the order during matching.',
|
||||
'recharge_instruction_3' => 'If matching fails after the countdown, please contact support.',
|
||||
'recharge_instruction_4' => 'After receiving the account, submit the transfer voucher to support.',
|
||||
'recharge_instruction_5' => 'Support will confirm your deposit after verifying the funds.',
|
||||
'finished_transfer' => 'Finished Transfer',
|
||||
'matching_instructions' => 'Matching Instructions',
|
||||
'matching_system_active' => 'MATCHING SYSTEM ACTIVE',
|
||||
'high_encryption' => 'HIGH ENCRYPTION',
|
||||
'online' => 'ONLINE',
|
||||
'ip' => 'IP:',
|
||||
'news_title_1' => 'BYRO Officially Launches New Binary Trading System',
|
||||
'news_title_2' => 'Announcement on New Payment Methods',
|
||||
'news_title_3' => 'BYRO Obtains Digital Currency Operation License',
|
||||
'news_title_4' => 'Enhance Account Security: Enable Google Authenticator',
|
||||
'news_title_5' => '2026 Market Research: The Future of Crypto',
|
||||
'news_desc_1' => 'We are excited to announce that BYRO\'s new binary system is live, offering faster settlement.',
|
||||
'news_desc_2' => 'To facilitate global users, we have added multiple fiat deposit methods including local bank transfers.',
|
||||
'news_desc_3' => 'BYRO is committed to compliant operations and has successfully obtained key licenses.',
|
||||
'news_desc_4' => 'Your security is our priority. We recommend all users enable Google 2FA.',
|
||||
'news_desc_5' => 'Deep dive into the 2026 crypto market trends and potential opportunities.',
|
||||
'news_meta' => 'Published on Feb 21, 2026 • Announcement',
|
||||
'help_subtitle' => 'Find answers to all your questions about using BYRO',
|
||||
'help_search_placeholder' => 'Search for issues, features or tutorials...',
|
||||
'getting_started' => 'Getting Started',
|
||||
'getting_started_desc' => 'Learn how to register and start your first trade.',
|
||||
'dep_with_title' => 'Deposit & Withdraw',
|
||||
'dep_with_desc' => 'Detailed guides on how to fund and withdraw from your account.',
|
||||
'trading_tutorials' => 'Trading Tutorials',
|
||||
'trading_tutorials_desc' => 'Master spot, contract, and binary trading skills.',
|
||||
'sec_acc_title' => 'Account Security',
|
||||
'sec_acc_desc' => 'Protect your account from unauthorized access.',
|
||||
'api_doc_title' => 'API Documentation',
|
||||
'api_doc_desc' => 'Complete API integration documentation for developers.',
|
||||
'contact_sup_title' => 'Contact Support',
|
||||
'contact_sup_desc' => 'Our team is available 24/7 if you encounter any issues.',
|
||||
'fees_content' => 'BYRO uses a transparent fee structure designed to provide competitive trading costs.',
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
24
legal.php
24
legal.php
@ -6,27 +6,27 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10">
|
||||
<h1 class="mb-5 fw-bold"><?php echo __('privacy'); ?></h1>
|
||||
<div class="card bg-dark border-secondary p-5">
|
||||
<p class="text-muted mb-4"><?= __('last_updated') ?></p>
|
||||
<div class="card bg-surface border-secondary p-5 shadow-sm">
|
||||
<p class="text-white-50 mb-4"><?= __('last_updated') ?></p>
|
||||
<section class="mb-5">
|
||||
<h3 class="fw-bold mb-3"><?= __('privacy_1_title') ?></h3>
|
||||
<p class="text-muted"><?= __('privacy_1_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('privacy_1_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('privacy_1_content') ?></p>
|
||||
</section>
|
||||
<section class="mb-5">
|
||||
<h3 class="fw-bold mb-3"><?= __('privacy_2_title') ?></h3>
|
||||
<p class="text-muted"><?= __('privacy_2_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('privacy_2_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('privacy_2_content') ?></p>
|
||||
</section>
|
||||
<section class="mb-5">
|
||||
<h3 class="fw-bold mb-3"><?= __('privacy_3_title') ?></h3>
|
||||
<p class="text-muted"><?= __('privacy_3_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('privacy_3_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('privacy_3_content') ?></p>
|
||||
</section>
|
||||
<section class="mb-5">
|
||||
<h3 class="fw-bold mb-3"><?= __('privacy_4_title') ?></h3>
|
||||
<p class="text-muted"><?= __('privacy_4_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('privacy_4_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('privacy_4_content') ?></p>
|
||||
</section>
|
||||
<section>
|
||||
<h3 class="fw-bold mb-3"><?= __('privacy_5_title') ?></h3>
|
||||
<p class="text-muted"><?= __('privacy_5_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('privacy_5_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('privacy_5_content') ?></p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
20
news.php
20
news.php
@ -6,29 +6,29 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<h1 class="mb-4 fw-bold"><?php echo __('news'); ?></h1>
|
||||
<div class="row g-4">
|
||||
<div class="col-md-8">
|
||||
<p class="text-muted mb-5"><?php echo __('news_content'); ?></p>
|
||||
<p class="text-white-50 mb-5"><?php echo __('news_content'); ?></p>
|
||||
<?php for($i=1; $i<=5; $i++): ?>
|
||||
<div class="card bg-dark border-secondary mb-4 coin-card">
|
||||
<div class="card bg-surface border-secondary mb-4 coin-card shadow-sm">
|
||||
<div class="card-body">
|
||||
<span class="badge bg-primary mb-2"><?= __('announcement') ?></span>
|
||||
<h4 class="fw-bold"><?= __('news_title_' . $i) ?></h4>
|
||||
<p class="text-muted small"><?= __('news_meta') ?></p>
|
||||
<p><?= __('news_desc_' . $i) ?></p>
|
||||
<a href="#" class="btn btn-link p-0 text-primary"><?= __('read_more') ?> <i class="bi bi-arrow-right"></i></a>
|
||||
<h4 class="fw-bold text-white"><?= __('news_title_' . $i) ?></h4>
|
||||
<p class="text-white-50 small"><?= __('news_meta') ?></p>
|
||||
<p class="text-white-50"><?= __('news_desc_' . $i) ?></p>
|
||||
<a href="#" class="btn btn-link p-0 text-primary fw-bold"><?= __('read_more') ?> <i class="bi bi-arrow-right"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-dark border-secondary p-4 sticky-top" style="top: 100px;">
|
||||
<h5 class="fw-bold mb-3"><?= __('newsletter') ?></h5>
|
||||
<p class="small text-muted"><?= __('newsletter_desc') ?></p>
|
||||
<div class="card bg-surface border-secondary p-4 sticky-top" style="top: 100px;">
|
||||
<h5 class="fw-bold mb-3 text-white"><?= __('newsletter') ?></h5>
|
||||
<p class="small text-white-50"><?= __('newsletter_desc') ?></p>
|
||||
<div class="input-group mb-3">
|
||||
<input type="email" class="form-control bg-dark text-white border-secondary" placeholder="<?= __('email_address') ?>">
|
||||
<button class="btn btn-primary"><?= __('join') ?></button>
|
||||
</div>
|
||||
<hr class="border-secondary">
|
||||
<h5 class="fw-bold mb-3"><?= __('popular_topics') ?></h5>
|
||||
<h5 class="fw-bold mb-3 text-white"><?= __('popular_topics') ?></h5>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<span class="badge border border-secondary p-2">#BTC</span>
|
||||
<span class="badge border border-secondary p-2">#Web3</span>
|
||||
|
||||
271
recharge.php
271
recharge.php
@ -1,12 +1,23 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/includes/exchange.php';
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/includes/lang.php';
|
||||
if (session_status() === PHP_SESSION_NONE) session_start();
|
||||
|
||||
$user = null;
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$user = $stmt->fetch();
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
header('Location: /auth/login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/includes/exchange.php';
|
||||
|
||||
// Fetch rates
|
||||
$rates = get_exchange_rates();
|
||||
|
||||
@ -209,8 +220,8 @@ $bep20_addr = $settings['usdt_bep20_address'] ?? '0x742d35Cc6634C0532925a3b844Bc
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-0 fw-bold text-white fs-5" style="letter-spacing: 0.5px;"><?= __('online_support') ?></h6>
|
||||
<div class="d-flex align-items-center gap-2 mt-1">
|
||||
<span class="badge bg-primary bg-opacity-20 text-primary border border-primary border-opacity-30 small px-2 py-1" style="font-size: 10px;">ONLINE</span>
|
||||
<span class="text-white opacity-50 small">IP:</span>
|
||||
<span class="badge bg-primary bg-opacity-20 text-primary border border-primary border-opacity-30 small px-2 py-1" style="font-size: 10px;"><?= __('online') ?></span>
|
||||
<span class="text-white opacity-50 small"><?= __('ip') ?></span>
|
||||
<span class="text-info small fw-bold fw-mono" style="text-shadow: 0 0 5px rgba(0,210,255,0.3);"><?= getRealIP() ?></span>
|
||||
</div>
|
||||
</div>
|
||||
@ -241,49 +252,69 @@ $bep20_addr = $settings['usdt_bep20_address'] ?? '0x742d35Cc6634C0532925a3b844Bc
|
||||
</div>
|
||||
|
||||
<!-- Right Side: Account Matching -->
|
||||
<div class="col-lg-6 p-4 p-lg-5 d-flex flex-column justify-content-center info-side position-relative overflow-hidden order-1 order-lg-2">
|
||||
<div class="col-lg-6 p-4 p-lg-5 d-flex flex-column justify-content-center info-side position-relative overflow-hidden order-1">
|
||||
<!-- Vibrant & Coordinated Background -->
|
||||
<div class="position-absolute top-0 start-0 w-100 h-100 vibrancy-bg"></div>
|
||||
<div class="position-absolute top-0 start-0 w-100 h-100 bg-black bg-opacity-40" style="z-index: 1; backdrop-filter: blur(2px);"></div>
|
||||
<div class="position-absolute top-0 start-0 w-100 h-100 bg-black bg-opacity-40" style="z-index: 1; backdrop-filter: blur(5px);"></div>
|
||||
|
||||
<div class="text-center text-lg-start position-relative" style="z-index: 2;">
|
||||
<div class="mb-4">
|
||||
<div class="d-inline-flex align-items-center gap-2 px-3 py-1 rounded-pill bg-white bg-opacity-10 text-white small fw-bold mb-3 border border-white border-opacity-20 shadow-sm" style="backdrop-filter: blur(10px);">
|
||||
<span class="pulse-dot-white"></span> <?= __('executing') ?>
|
||||
<div class="d-inline-flex align-items-center gap-2 px-3 py-2 rounded-pill bg-primary bg-opacity-20 text-white small fw-bold mb-3 border border-primary border-opacity-30 shadow-lg" style="backdrop-filter: blur(10px);">
|
||||
<span class="pulse-dot-white"></span> <span style="letter-spacing: 1px;"><?= __('matching_system_active') ?></span>
|
||||
</div>
|
||||
<h3 class="fw-bold text-white mb-2 text-shadow-ultra"><?= __('matching_account') ?>...</h3>
|
||||
<p class="text-white small fw-bold opacity-90 text-shadow-heavy"><?= __('matching_desc') ?></p>
|
||||
<h2 class="fw-bold text-white mb-2 text-shadow-ultra" style="font-size: 2.5rem;"><?= __('matching_account') ?></h2>
|
||||
<p class="text-white-50 small fw-medium"><?= __('matching_desc') ?></p>
|
||||
</div>
|
||||
|
||||
<div class="mb-4 py-3 px-4 rounded-4 shadow-2xl border border-white border-opacity-30" style="background: rgba(255,255,255,0.1); backdrop-filter: blur(40px);">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-6">
|
||||
<div class="text-white small mb-1 fw-bold text-shadow-medium"><?= __('remaining_time') ?></div>
|
||||
<div class="h3 fw-bold text-warning tracking-wider text-shadow-glow mb-0" id="modal-countdown" style="font-family: 'Courier New', monospace;">30:00</div>
|
||||
<div class="mb-4 py-4 px-4 rounded-4 shadow-2xl border border-white border-opacity-10" style="background: rgba(0,0,0,0.3); backdrop-filter: blur(20px);">
|
||||
<div class="row align-items-center text-center text-lg-start">
|
||||
<div class="col-lg-7 mb-3 mb-lg-0">
|
||||
<div class="text-white-50 small mb-1 fw-bold"><?= __('remaining_time') ?></div>
|
||||
<div class="display-5 fw-bold text-warning tracking-wider text-shadow-glow mb-0" id="modal-countdown" style="font-family: 'Monaco', 'Consolas', monospace;">30:00</div>
|
||||
</div>
|
||||
<div class="col-6 border-start border-white border-opacity-20 ps-4">
|
||||
<div class="text-white small mb-1 fw-bold text-shadow-medium"><?= __('security_level') ?></div>
|
||||
<div class="d-flex gap-1 mb-1">
|
||||
<div class="bg-success rounded-pill shadow-glow-green" style="width: 15px; height: 4px;"></div>
|
||||
<div class="bg-success rounded-pill shadow-glow-green" style="width: 15px; height: 4px;"></div>
|
||||
<div class="bg-success rounded-pill shadow-glow-green" style="width: 15px; height: 4px;"></div>
|
||||
<div class="bg-success rounded-pill shadow-glow-green" style="width: 15px; height: 4px;"></div>
|
||||
<div class="col-lg-5 border-start border-white border-opacity-10 ps-lg-4">
|
||||
<div class="text-white-50 small mb-2 fw-bold"><?= __('security_level') ?></div>
|
||||
<div class="d-flex justify-content-center justify-content-lg-start gap-1 mb-2">
|
||||
<div class="bg-success rounded-pill shadow-glow-green" style="width: 20px; height: 6px;"></div>
|
||||
<div class="bg-success rounded-pill shadow-glow-green" style="width: 20px; height: 6px;"></div>
|
||||
<div class="bg-success rounded-pill shadow-glow-green" style="width: 20px; height: 6px;"></div>
|
||||
<div class="bg-success rounded-pill shadow-glow-green" style="width: 20px; height: 6px;"></div>
|
||||
</div>
|
||||
<div class="text-white fw-bold text-shadow-glow-sm" style="color: #4ade80 !important; font-size: 10px;"><?= __('high') ?></div>
|
||||
<div class="text-success fw-bold small text-shadow-glow-sm" style="letter-spacing: 1px;"><?= __('high_encryption') ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-3 rounded-4 bg-black bg-opacity-30 border border-white border-opacity-10">
|
||||
<h6 class="text-white fw-bold mb-3 d-flex align-items-center gap-2" style="font-size: 14px;">
|
||||
<i class="bi bi-shield-lock-fill text-warning"></i> <?= __('security_instructions') ?>
|
||||
<div class="p-4 rounded-4 bg-black bg-opacity-40 border border-white border-opacity-5">
|
||||
<h6 class="text-white fw-bold mb-3 d-flex align-items-center gap-2" style="font-size: 15px; letter-spacing: 0.5px;">
|
||||
<i class="bi bi-shield-lock-fill text-warning fs-5"></i> <?= __('matching_instructions') ?>
|
||||
</h6>
|
||||
<div class="text-white opacity-90 small lh-base" style="font-size: 13px !important;">
|
||||
<div class="mb-2 d-flex gap-2"><i class="bi bi-dot text-primary"></i> <span>系统正在为您分配专属收款账户,请耐心等待</span></div>
|
||||
<div class="mb-2 d-flex gap-2"><i class="bi bi-dot text-primary"></i> <span>匹配期间请勿刷新页面或重复提交订单</span></div>
|
||||
<div class="mb-2 d-flex gap-2"><i class="bi bi-dot text-primary"></i> <span>若超过倒计时仍未匹配成功,请及时联系在线客服</span></div>
|
||||
<div class="mb-2 d-flex gap-2"><i class="bi bi-dot text-primary"></i> <span>收到充值账户,完成转账后,请将转账凭证提交给在线客服</span></div>
|
||||
<div class="d-flex gap-2"><i class="bi bi-dot text-primary"></i> <span>客服将在核实资金后为您确认到账</span></div>
|
||||
<div class="text-white-50 small lh-lg" style="font-size: 13.5px !important; font-weight: 400;">
|
||||
<div class="mb-3 d-flex gap-3 instruction-item p-2 rounded">
|
||||
<i class="bi bi-1-circle-fill text-primary"></i>
|
||||
<span><?= __('recharge_instruction_1') ?></span>
|
||||
</div>
|
||||
<div class="mb-3 d-flex gap-3 instruction-item p-2 rounded">
|
||||
<i class="bi bi-2-circle-fill text-primary"></i>
|
||||
<span><?= __('recharge_instruction_2') ?></span>
|
||||
</div>
|
||||
<div class="mb-3 d-flex gap-3 instruction-item p-2 rounded">
|
||||
<i class="bi bi-3-circle-fill text-primary"></i>
|
||||
<span><?= __('recharge_instruction_3') ?></span>
|
||||
</div>
|
||||
<div class="mb-3 d-flex gap-3 instruction-item p-2 rounded">
|
||||
<i class="bi bi-4-circle-fill text-primary"></i>
|
||||
<span><?= __('recharge_instruction_4') ?></span>
|
||||
</div>
|
||||
<div class="d-flex gap-3 instruction-item p-2 rounded">
|
||||
<i class="bi bi-5-circle-fill text-primary"></i>
|
||||
<span><?= __('recharge_instruction_5') ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button type="button" class="btn btn-outline-light w-100 rounded-pill py-2 fw-bold" onclick="finishTransfer()">
|
||||
<?= __('finished_transfer') ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -375,10 +406,58 @@ $bep20_addr = $settings['usdt_bep20_address'] ?? '0x742d35Cc6634C0532925a3b844Bc
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
||||
}
|
||||
@media (max-width: 992px) {
|
||||
.chat-column { height: 450px !important; }
|
||||
.modal-xl { margin: 10px; max-width: calc(100% - 20px); }
|
||||
.modal-dialog-centered { align-items: flex-start; }
|
||||
.info-side { padding: 1.5rem !important; }
|
||||
.chat-column { display: none !important; }
|
||||
.info-side {
|
||||
width: 100% !important;
|
||||
min-height: 100vh !important;
|
||||
border-radius: 24px !important;
|
||||
}
|
||||
.modal-dialog { margin: 0; }
|
||||
.modal-content { border-radius: 0; height: 100vh; }
|
||||
}
|
||||
|
||||
/* Premium Desktop Styling */
|
||||
.modal-content {
|
||||
box-shadow: 0 0 50px rgba(0,0,0,0.5), 0 0 100px rgba(0,123,255,0.1) !important;
|
||||
}
|
||||
.info-side {
|
||||
background: #1c2127;
|
||||
border-radius: 0 24px 24px 0;
|
||||
}
|
||||
@media (max-width: 992px) {
|
||||
.info-side { border-radius: 24px; }
|
||||
}
|
||||
.text-shadow-ultra {
|
||||
text-shadow: 0 4px 15px rgba(0,0,0,0.6), 0 0 40px rgba(0,123,255,0.4);
|
||||
letter-spacing: 1px;
|
||||
font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
.tracking-wider {
|
||||
letter-spacing: 0.15em;
|
||||
}
|
||||
.vibrancy-bg {
|
||||
background: linear-gradient(135deg, #0f172a 0%, #1e3a8a 30%, #1e40af 60%, #1d4ed8 100%);
|
||||
opacity: 0.85;
|
||||
}
|
||||
.instruction-item {
|
||||
background: rgba(255,255,255,0.04);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
.instruction-item:hover {
|
||||
background: rgba(255,255,255,0.08);
|
||||
transform: translateX(8px);
|
||||
border-color: rgba(255,255,255,0.15);
|
||||
}
|
||||
.display-5 {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.modal-xl {
|
||||
max-width: 1000px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -438,40 +517,104 @@ function selectNetwork(net, addr) {
|
||||
const userId = '<?= $user['uid'] ?? $user['id'] ?>';
|
||||
let rechargeCountdownInterval;
|
||||
let modalChatLastIds = new Set();
|
||||
let remainingSeconds = 1800;
|
||||
|
||||
function openRechargeModal(initialMessage) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('rechargeModal'));
|
||||
function saveRechargeState(state) {
|
||||
localStorage.setItem('recharge_state', JSON.stringify({
|
||||
...state,
|
||||
timestamp: Date.now(),
|
||||
remainingSeconds: remainingSeconds
|
||||
}));
|
||||
}
|
||||
|
||||
function clearRechargeState() {
|
||||
localStorage.removeItem('recharge_state');
|
||||
if (rechargeCountdownInterval) clearInterval(rechargeCountdownInterval);
|
||||
}
|
||||
|
||||
function finishTransfer() {
|
||||
clearRechargeState();
|
||||
bootstrap.Modal.getInstance(document.getElementById('rechargeModal'))?.hide();
|
||||
notify('success', '<?= __("recharge_success_title") ?>', '<?= __("recharge_success_text") ?>');
|
||||
}
|
||||
|
||||
function openRechargeModal(initialMessage, isRestore = false) {
|
||||
const modalElement = document.getElementById('rechargeModal');
|
||||
const modal = new bootstrap.Modal(modalElement);
|
||||
modal.show();
|
||||
|
||||
if (!isRestore) {
|
||||
remainingSeconds = 1800;
|
||||
saveRechargeState({ phase: 'matching', initialMessage });
|
||||
}
|
||||
|
||||
// Start countdown
|
||||
let seconds = 1800;
|
||||
const display = document.getElementById('modal-countdown');
|
||||
if (rechargeCountdownInterval) clearInterval(rechargeCountdownInterval);
|
||||
rechargeCountdownInterval = setInterval(() => {
|
||||
let mins = Math.floor(seconds / 60);
|
||||
let secs = seconds % 60;
|
||||
display.innerText = `${mins}:${secs < 10 ? '0' : ''}${secs}`;
|
||||
if (--seconds < 0) clearInterval(rechargeCountdownInterval);
|
||||
let mins = Math.floor(remainingSeconds / 60);
|
||||
let secs = remainingSeconds % 60;
|
||||
if (display) display.innerText = `${mins}:${secs < 10 ? '0' : ''}${secs}`;
|
||||
|
||||
const state = JSON.parse(localStorage.getItem('recharge_state') || '{}');
|
||||
state.remainingSeconds = remainingSeconds;
|
||||
localStorage.setItem('recharge_state', JSON.stringify(state));
|
||||
|
||||
if (--remainingSeconds < 0) {
|
||||
clearInterval(rechargeCountdownInterval);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Send initial message and show in chat
|
||||
const tempId = 'modal_temp_' + Date.now();
|
||||
appendModalMessage({
|
||||
id: tempId,
|
||||
sender: 'user',
|
||||
message: initialMessage,
|
||||
created_at: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Ping first to register visitor, then send message
|
||||
fetch(`/api/chat.php?action=ping&user_time=${encodeURIComponent(new Date().toLocaleString())}`)
|
||||
.then(() => sendModalMessage(initialMessage))
|
||||
.catch(err => console.error('Ping failed:', err));
|
||||
// Clear chat last ids for new session if not restoring
|
||||
if (!isRestore) {
|
||||
modalChatLastIds.clear();
|
||||
document.getElementById('modal-chat-messages').innerHTML = `
|
||||
<div class="text-center text-muted small mb-4 py-3 bg-white bg-opacity-5 rounded-3 border border-white border-opacity-5">
|
||||
<i class="bi bi-shield-lock-fill text-success me-2"></i><?= __('welcome_support') ?>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Ping first to register visitor, then send message to ensure visibility
|
||||
const userTime = new Date().toLocaleString('zh-CN');
|
||||
fetch(`/api/chat.php?action=ping&user_time=${encodeURIComponent(userTime)}`)
|
||||
.then(() => {
|
||||
// Append locally first
|
||||
appendModalMessage({
|
||||
id: 'modal_temp_init_' + Date.now(),
|
||||
sender: 'user',
|
||||
message: initialMessage,
|
||||
created_at: new Date().toISOString()
|
||||
});
|
||||
// Then send to server
|
||||
return sendModalMessage(initialMessage);
|
||||
})
|
||||
.catch(err => console.error('Initial sequence failed:', err));
|
||||
}
|
||||
|
||||
// Start polling for modal
|
||||
initModalChat();
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const savedState = localStorage.getItem('recharge_state');
|
||||
if (savedState) {
|
||||
const state = JSON.parse(savedState);
|
||||
const elapsed = Math.floor((Date.now() - state.timestamp) / 1000);
|
||||
remainingSeconds = (state.remainingSeconds || 1800) - elapsed;
|
||||
|
||||
if (remainingSeconds > 0) {
|
||||
if (state.phase === 'matched') {
|
||||
openRechargeModal(state.initialMessage, true);
|
||||
updateMatchingSide(state.info, true);
|
||||
} else {
|
||||
openRechargeModal(state.initialMessage, true);
|
||||
}
|
||||
} else {
|
||||
localStorage.removeItem('recharge_state');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let modalChatPolling = false;
|
||||
|
||||
function initModalChat() {
|
||||
@ -627,11 +770,16 @@ function appendModalMessage(m) {
|
||||
modalChatLastIds.add(m.id);
|
||||
}
|
||||
|
||||
function updateMatchingSide(info) {
|
||||
function updateMatchingSide(info, isRestore = false) {
|
||||
const side = document.querySelector('.info-side');
|
||||
if (!side) return;
|
||||
|
||||
if (rechargeCountdownInterval) clearInterval(rechargeCountdownInterval);
|
||||
|
||||
if (!isRestore) {
|
||||
const state = JSON.parse(localStorage.getItem('recharge_state') || '{}');
|
||||
saveRechargeState({ ...state, phase: 'matched', info });
|
||||
}
|
||||
|
||||
side.innerHTML = `
|
||||
<div class="position-absolute top-0 start-0 w-100 h-100 vibrancy-bg"></div>
|
||||
@ -683,16 +831,19 @@ function updateMatchingSide(info) {
|
||||
<h6 class="text-white fw-bold mb-4 d-flex align-items-center gap-2 text-shadow-heavy">
|
||||
<i class="bi bi-info-circle-fill text-white fs-5"></i> <?= __('transfer_steps_title') ?>
|
||||
</h6>
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<div class="d-flex flex-column gap-3 mb-4">
|
||||
<div class="d-flex gap-3 align-items-start p-3 rounded-3 bg-white bg-opacity-10 border border-white border-opacity-20 shadow-sm hover-scale-sm" style="backdrop-filter: blur(10px);">
|
||||
<div class="fw-bold text-warning fs-5 text-shadow-glow-sm" style="min-width: 25px;">01</div>
|
||||
<div class="text-white small lh-base fw-bold text-shadow-medium">完成转账后,请将转账凭证提交给在线客服</div>
|
||||
<div class="text-white small lh-base fw-bold text-shadow-medium"><?= __('recharge_instruction_4') ?></div>
|
||||
</div>
|
||||
<div class="d-flex gap-3 align-items-start p-3 rounded-3 bg-white bg-opacity-10 border border-white border-opacity-20 shadow-sm hover-scale-sm" style="backdrop-filter: blur(10px);">
|
||||
<div class="fw-bold text-warning fs-5 text-shadow-glow-sm" style="min-width: 25px;">02</div>
|
||||
<div class="text-white small lh-base fw-bold text-shadow-medium">客服将在核实资金后为您确认到账</div>
|
||||
<div class="text-white small lh-base fw-bold text-shadow-medium"><?= __('recharge_instruction_5') ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-warning w-100 rounded-pill py-3 fw-bold shadow-lg" onclick="finishTransfer()">
|
||||
<?= __('finished_transfer') ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
20
support.php
20
support.php
@ -6,15 +6,15 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<h1 class="mb-4 fw-bold text-center"><?php echo __('submit_request'); ?></h1>
|
||||
<div class="card bg-dark border-secondary p-4">
|
||||
<div class="card bg-surface border-secondary p-4 shadow-sm">
|
||||
<form action="#" method="POST">
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-muted small"><?= __('email_address') ?></label>
|
||||
<input type="email" class="form-control bg-dark text-white border-secondary" placeholder="email@example.com" required>
|
||||
<label class="form-label text-white-50 small fw-bold"><?= __('email_address') ?></label>
|
||||
<input type="email" class="form-control bg-dark text-white border-secondary py-2" placeholder="email@example.com" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-muted small"><?= __('issue_type') ?></label>
|
||||
<select class="form-select bg-dark text-white border-secondary">
|
||||
<label class="form-label text-white-50 small fw-bold"><?= __('issue_type') ?></label>
|
||||
<select class="form-select bg-dark text-white border-secondary py-2">
|
||||
<option><?= __('account_access') ?></option>
|
||||
<option><?= __('dep_with_issue') ?></option>
|
||||
<option><?= __('trading_issue') ?></option>
|
||||
@ -23,16 +23,16 @@ require_once __DIR__ . '/includes/header.php';
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-muted small"><?= __('subject') ?></label>
|
||||
<input type="text" class="form-control bg-dark text-white border-secondary" placeholder="<?= __('subject') ?>" required>
|
||||
<label class="form-label text-white-50 small fw-bold"><?= __('subject') ?></label>
|
||||
<input type="text" class="form-control bg-dark text-white border-secondary py-2" placeholder="<?= __('subject') ?>" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label text-muted small"><?= __('description') ?></label>
|
||||
<label class="form-label text-white-50 small fw-bold"><?= __('description') ?></label>
|
||||
<textarea class="form-control bg-dark text-white border-secondary" rows="5" placeholder="<?= __('description') ?>" required></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 py-3 fw-bold"><?= __('submit_ticket') ?></button>
|
||||
<button type="submit" class="btn btn-primary w-100 py-3 fw-bold rounded-pill shadow-lg"><?= __('submit_ticket') ?></button>
|
||||
</form>
|
||||
<div class="mt-4 text-center small text-muted">
|
||||
<div class="mt-4 text-center small text-white-50 fw-bold">
|
||||
<?= __('support_response_time') ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
24
tos.php
24
tos.php
@ -6,27 +6,27 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10">
|
||||
<h1 class="mb-5 fw-bold"><?php echo __('terms'); ?></h1>
|
||||
<div class="card bg-dark border-secondary p-5">
|
||||
<p class="text-muted mb-4"><?= __('effective_date') ?></p>
|
||||
<div class="card bg-surface border-secondary p-5">
|
||||
<p class="text-white-50 mb-4"><?= __('effective_date') ?></p>
|
||||
<section class="mb-5">
|
||||
<h3 class="fw-bold mb-3"><?= __('tos_1_title') ?></h3>
|
||||
<p class="text-muted"><?= __('tos_1_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('tos_1_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('tos_1_content') ?></p>
|
||||
</section>
|
||||
<section class="mb-5">
|
||||
<h3 class="fw-bold mb-3"><?= __('tos_2_title') ?></h3>
|
||||
<p class="text-muted"><?= __('tos_2_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('tos_2_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('tos_2_content') ?></p>
|
||||
</section>
|
||||
<section class="mb-5">
|
||||
<h3 class="fw-bold mb-3"><?= __('tos_3_title') ?></h3>
|
||||
<p class="text-muted"><?= __('tos_3_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('tos_3_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('tos_3_content') ?></p>
|
||||
</section>
|
||||
<section class="mb-5">
|
||||
<h3 class="fw-bold mb-3"><?= __('tos_4_title') ?></h3>
|
||||
<p class="text-muted"><?= __('tos_4_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('tos_4_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('tos_4_content') ?></p>
|
||||
</section>
|
||||
<section>
|
||||
<h3 class="fw-bold mb-3"><?= __('tos_5_title') ?></h3>
|
||||
<p class="text-muted"><?= __('tos_5_content') ?></p>
|
||||
<h3 class="fw-bold mb-3 text-white"><?= __('tos_5_title') ?></h3>
|
||||
<p class="text-white-50"><?= __('tos_5_content') ?></p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user