Compare commits

..

24 Commits

Author SHA1 Message Date
Flatlogic Bot
f322e98994 最后修改好 2026-02-14 05:49:34 +00:00
Flatlogic Bot
23ce9c4446 最新完美 2026-02-14 05:11:30 +00:00
Flatlogic Bot
868df18001 Autosave: 20260214-023012 2026-02-14 02:30:12 +00:00
Flatlogic Bot
1fcaec3d09 2026-213 2026-02-13 15:48:44 +00:00
Flatlogic Bot
d6a987a3fc Autosave: 20260213-144007 2026-02-13 14:40:07 +00:00
Flatlogic Bot
18dcb64063 Autosave: 20260213-130144 2026-02-13 13:01:44 +00:00
Flatlogic Bot
451acfd26a Autosave: 20260213-122446 2026-02-13 12:24:46 +00:00
Flatlogic Bot
01edcfe23d Autosave: 20260213-120315 2026-02-13 12:03:16 +00:00
Flatlogic Bot
32423d4989 Autosave: 20260213-074324 2026-02-13 07:43:24 +00:00
Flatlogic Bot
f9a6e8e38c 新新新新新新 2026-02-12 14:37:41 +00:00
Flatlogic Bot
75bce5aa09 最新的修复 2026-02-12 14:26:48 +00:00
Flatlogic Bot
116b830b18 最新 2026-02-12 11:06:42 +00:00
Flatlogic Bot
231218bd5e 以修复 2026-02-12 09:10:15 +00:00
Flatlogic Bot
238c9e0d22 Autosave: 20260212-080055 2026-02-12 08:00:55 +00:00
Flatlogic Bot
c93c7ad3ca Autosave: 20260212-050303 2026-02-12 05:03:03 +00:00
Flatlogic Bot
b61cbbc19a Revert to version 5464b9a 2026-02-12 02:24:15 +00:00
Flatlogic Bot
f5c7fa12cc Revert to version 5e2fe8c 2026-02-12 02:23:53 +00:00
Flatlogic Bot
5464b9a32d Revert to version 79b0724 2026-02-12 02:23:13 +00:00
Flatlogic Bot
a22438663d Autosave: 20260212-020231 2026-02-12 02:02:32 +00:00
Flatlogic Bot
5e2fe8c059 LOGO更改 2026-02-11 15:49:10 +00:00
Flatlogic Bot
79b07243ce 交易所 2026-02-11 15:18:19 +00:00
Flatlogic Bot
7c4904baad Autosave: 20260211-133533 2026-02-11 13:35:33 +00:00
Flatlogic Bot
cc38735373 Autosave: 20260211-115218 2026-02-11 11:52:19 +00:00
Flatlogic Bot
396b0e8f02 Autosave: 20260211-081917 2026-02-11 08:19:17 +00:00
97 changed files with 9818 additions and 451 deletions

67
about.php Normal file
View File

@ -0,0 +1,67 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 1000px; margin: 0 auto;">
<h1 style="font-size: 3.5rem; font-weight: 800; margin-bottom: 30px; background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">
About NovaEx
</h1>
<p style="font-size: 1.4rem; color: var(--text-muted); line-height: 1.8; margin-bottom: 60px;">
Founded in 2017, NovaEx has grown from a visionary startup to a global leader in the cryptocurrency exchange industry. Our mission is to accelerate the world's transition to a more open, efficient, and inclusive financial system through blockchain technology.
</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-bottom: 80px;">
<div style="background: #161a1e; padding: 40px; border-radius: 24px; border: 1px solid #2b3139;">
<i class="fas fa-rocket" style="font-size: 2rem; color: #4facfe; margin-bottom: 20px;"></i>
<h3 style="font-size: 1.8rem; margin-bottom: 15px;">Our Mission</h3>
<p style="color: var(--text-muted); line-height: 1.6;">To empower individuals and institutions with secure, intuitive, and high-performance tools for trading and managing digital assets.</p>
</div>
<div style="background: #161a1e; padding: 40px; border-radius: 24px; border: 1px solid #2b3139;">
<i class="fas fa-eye" style="font-size: 2rem; color: #00f2fe; margin-bottom: 20px;"></i>
<h3 style="font-size: 1.8rem; margin-bottom: 15px;">Our Vision</h3>
<p style="color: var(--text-muted); line-height: 1.6;">A world where decentralized finance is accessible to everyone, creating a borderless economy based on transparency and trust.</p>
</div>
</div>
<section style="margin-bottom: 80px;">
<h2 style="font-size: 2.2rem; margin-bottom: 30px;">Our Journey</h2>
<div style="display: flex; flex-direction: column; gap: 30px;">
<div style="display: flex; gap: 20px;">
<div style="width: 80px; font-weight: bold; color: #4facfe;">2017</div>
<div style="flex: 1; border-left: 2px solid #2b3139; padding-left: 20px;">
<h4 style="font-size: 1.2rem; margin-bottom: 10px;">The Beginning</h4>
<p style="color: var(--text-muted);">NovaEx was founded by a team of veteran financiers and blockchain experts with a focus on security and transparency.</p>
</div>
</div>
<div style="display: flex; gap: 20px;">
<div style="width: 80px; font-weight: bold; color: #4facfe;">2019</div>
<div style="flex: 1; border-left: 2px solid #2b3139; padding-left: 20px;">
<h4 style="font-size: 1.2rem; margin-bottom: 10px;">Global Expansion</h4>
<p style="color: var(--text-muted);">Achieved 1 million registered users and launched professional trading tools and mobile applications.</p>
</div>
</div>
<div style="display: flex; gap: 20px;">
<div style="width: 80px; font-weight: bold; color: #4facfe;">2021</div>
<div style="flex: 1; border-left: 2px solid #2b3139; padding-left: 20px;">
<h4 style="font-size: 1.2rem; margin-bottom: 10px;">Institutional Grade</h4>
<p style="color: var(--text-muted);">Integrated advanced security features and custodial solutions for institutional investors worldwide.</p>
</div>
</div>
<div style="display: flex; gap: 20px;">
<div style="width: 80px; font-weight: bold; color: #4facfe;">Today</div>
<div style="flex: 1; border-left: 2px solid #2b3139; padding-left: 20px;">
<h4 style="font-size: 1.2rem; margin-bottom: 10px;">Market Leader</h4>
<p style="color: var(--text-muted);">Processing billions in daily volume with users across 180+ countries, leading the way in crypto innovation.</p>
</div>
</div>
</div>
</section>
<section style="text-align: center; background: linear-gradient(135deg, #161a1e 0%, #0b0e11 100%); padding: 60px; border-radius: 32px; border: 1px solid #2b3139;">
<h2 style="font-size: 2rem; margin-bottom: 20px;">Security is Our DNA</h2>
<p style="color: var(--text-muted); margin-bottom: 30px; max-width: 600px; margin-left: auto; margin-right: auto;">We utilize state-of-the-art encryption, multi-signature cold storage, and 24/7 monitoring to ensure your assets are always safe.</p>
<a href="register.php" class="btn-primary" style="padding: 15px 40px; font-size: 1.1rem; border-radius: 12px;">Join the Revolution</a>
</section>
</div>
</main>
<?php include 'footer.php'; ?>

256
admin/agents.php Normal file
View File

@ -0,0 +1,256 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
// Handle Actions
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) {
$action = $_POST['action'];
if ($action == 'add_agent') {
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$role = 'agent';
$remark = $_POST['remark'] ?? '';
$permissions = isset($_POST['perms']) ? json_encode($_POST['perms']) : '[]';
$stmt = $pdo->prepare("INSERT INTO admins (username, password, role, permissions, remark) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$username, $password, $role, $permissions, $remark]);
} elseif ($action == 'update_agent') {
$id = $_POST['id'];
$username = $_POST['username'];
$remark = $_POST['remark'] ?? '';
$permissions = isset($_POST['perms']) ? json_encode($_POST['perms']) : '[]';
$sql = "UPDATE admins SET username = ?, permissions = ?, remark = ? WHERE id = ?";
$params = [$username, $permissions, $remark, $id];
if (!empty($_POST['password'])) {
$sql = "UPDATE admins SET username = ?, permissions = ?, remark = ?, password = ? WHERE id = ?";
$params = [$username, $permissions, $remark, password_hash($_POST['password'], PASSWORD_DEFAULT), $id];
}
$pdo->prepare($sql)->execute($params);
} elseif ($action == 'delete_agent') {
$id = $_POST['id'];
$pdo->prepare("DELETE FROM admins WHERE id = ? AND role = 'agent'")->execute([$id]);
}
header("Location: agents.php");
exit;
}
$agents = $pdo->query("SELECT * FROM admins WHERE role = 'agent' ORDER BY id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>代理管理 - NovaEx 管理后台</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.card { background: white; border-radius: 12px; border: 1px solid var(--border); padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
.table { width: 100%; border-collapse: collapse; margin-top: 1.5rem; }
.table th, .table td { padding: 15px; text-align: left; border-bottom: 1px solid var(--border); font-size: 0.9rem; }
.table th { background: #f9fafb; color: #707a8a; font-weight: 600; text-transform: uppercase; font-size: 0.75rem; }
.btn { padding: 8px 16px; border-radius: 6px; font-size: 0.85rem; border: none; cursor: pointer; font-weight: 500; transition: 0.2s; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
.btn-primary { background: var(--primary); color: black; }
.btn-danger { background: #f6465d; color: white; }
.modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-content { background: white; width: 600px; padding: 30px; border-radius: 16px; box-shadow: 0 20px 40px rgba(0,0,0,0.2); max-height: 90vh; overflow-y: auto; }
.form-group { margin-bottom: 20px; }
.form-group label { display: block; margin-bottom: 8px; font-weight: 600; color: #474d57; }
.form-group input, .form-group select, .form-group textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 1rem; outline: none; box-sizing: border-box; }
.perms-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px; border: 1px solid var(--border); padding: 15px; border-radius: 8px; }
.perm-item { display: flex; align-items: center; gap: 8px; font-size: 0.85rem; }
</style>
</head>
<body>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item active"><i class="fas fa-user-shield"></i> 代理管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
<a href="chat.php" class="menu-item">
<i class="fas fa-comments"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px;">
<h1>代理管理</h1>
<button class="btn btn-primary" onclick="showModal('addAgentModal')"><i class="fas fa-plus"></i> 添加子管理员/代理</button>
</div>
<div class="card">
<table class="table">
<thead>
<tr>
<th>ID / 账号</th>
<th>角色</th>
<th>备注</th>
<th>权限范围</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($agents as $agent): ?>
<tr>
<td>
<div style="font-weight: bold;"><?php echo $agent['id']; ?></div>
<div style="font-size: 0.9rem; color: #474d57;"><?php echo htmlspecialchars($agent['username']); ?></div>
</td>
<td><span style="background: #eef2f7; padding: 4px 8px; border-radius: 4px; font-size: 0.8rem;">分管理代理</span></td>
<td style="color: #707a8a; font-size: 0.85rem;"><?php echo htmlspecialchars($agent['remark'] ?: '-'); ?></td>
<td>
<?php
$perms = json_decode($agent['permissions'] ?: '[]', true);
if(empty($perms)) echo '<span style="color: #ccc;">无权限</span>';
else echo '<span style="font-size: 0.75rem; color: #00c087;">' . count($perms) . ' 项权限</span>';
?>
</td>
<td style="font-size: 0.8rem; color: #848e9c;"><?php echo $agent['created_at']; ?></td>
<td>
<div style="display: flex; gap: 8px;">
<button class="btn btn-primary btn-sm" onclick='editAgent(<?php echo json_encode($agent); ?>)'><i class="fas fa-edit"></i></button>
<form method="POST" style="display: inline;" onsubmit="return confirm('确定要删除此代理吗?')">
<input type="hidden" name="id" value="<?php echo $agent['id']; ?>">
<input type="hidden" name="action" value="delete_agent">
<button type="submit" class="btn btn-danger btn-sm"><i class="fas fa-trash"></i></button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Agent Modal -->
<div id="addAgentModal" class="modal">
<div class="modal-content">
<div class="modal-header" style="display: flex; justify-content: space-between; margin-bottom: 20px;">
<h3>添加代理管理员</h3>
<i class="fas fa-times" onclick="hideModal('addAgentModal')" style="cursor: pointer;"></i>
</div>
<form method="POST">
<input type="hidden" name="action" value="add_agent">
<div class="form-group">
<label>登录账号</label>
<input type="text" name="username" required placeholder="输入代理登录用户名">
</div>
<div class="form-group">
<label>登录密码</label>
<input type="password" name="password" required placeholder="输入登录密码">
</div>
<div class="form-group">
<label>代理备注</label>
<textarea name="remark" rows="2" placeholder="备注该代理的线下明确信息..."></textarea>
</div>
<div class="form-group">
<label>设置权限</label>
<div class="perms-grid">
<div class="perm-item"><input type="checkbox" name="perms[]" value="users"> 用户管理</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="kyc"> KYC 审核</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="chat"> 客服管理</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="options"> 秒合约订单</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="spot"> 现货订单</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="futures"> 合约订单</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="orders"> 充值记录</div>
</div>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="hideModal('addAgentModal')">取消</button>
<button type="submit" class="btn btn-primary">确认添加</button>
</div>
</form>
</div>
</div>
<!-- Edit Agent Modal -->
<div id="editAgentModal" class="modal">
<div class="modal-content">
<div class="modal-header" style="display: flex; justify-content: space-between; margin-bottom: 20px;">
<h3>编辑代理权限</h3>
<i class="fas fa-times" onclick="hideModal('editAgentModal')" style="cursor: pointer;"></i>
</div>
<form method="POST">
<input type="hidden" name="action" value="update_agent">
<input type="hidden" name="id" id="edit_agent_id">
<div class="form-group">
<label>登录账号</label>
<input type="text" name="username" id="edit_agent_username" required>
</div>
<div class="form-group">
<label>修改密码 (不填则不修改)</label>
<input type="password" name="password" placeholder="留空保持原密码">
</div>
<div class="form-group">
<label>代理备注</label>
<textarea name="remark" id="edit_agent_remark" rows="2"></textarea>
</div>
<div class="form-group">
<label>权限设置</label>
<div class="perms-grid" id="edit_perms_grid">
<div class="perm-item"><input type="checkbox" name="perms[]" value="users"> 用户管理</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="kyc"> KYC 审核</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="chat"> 客服管理</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="options"> 秒合约订单</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="spot"> 现货订单</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="futures"> 合约订单</div>
<div class="perm-item"><input type="checkbox" name="perms[]" value="orders"> 充值记录</div>
</div>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="hideModal('editAgentModal')">取消</button>
<button type="submit" class="btn btn-primary">保存修改</button>
</div>
</form>
</div>
</div>
<script>
function showModal(id) { document.getElementById(id).style.display = 'flex'; }
function hideModal(id) { document.getElementById(id).style.display = 'none'; }
function editAgent(agent) {
document.getElementById('edit_agent_id').value = agent.id;
document.getElementById('edit_agent_username').value = agent.username;
document.getElementById('edit_agent_remark').value = agent.remark || '';
const perms = JSON.parse(agent.permissions || '[]');
const checkboxes = document.querySelectorAll('#edit_perms_grid input[type="checkbox"]');
checkboxes.forEach(cb => {
cb.checked = perms.includes(cb.value);
});
showModal('editAgentModal');
}
</script>
</body>
</html>

9
admin/auth.php Normal file
View File

@ -0,0 +1,9 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if (!isset($_SESSION['admin_id'])) {
header("Location: login.php");
exit;
}

168
admin/chat.php Normal file
View File

@ -0,0 +1,168 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
// Handle deletion of chat
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['delete_user_id'])) {
$del_id = $_GET['delete_user_id'];
$pdo->prepare("DELETE FROM messages WHERE user_id = ?")->execute([$del_id]);
$pdo->prepare("UPDATE fiat_orders SET status = 'rejected' WHERE user_id = ? AND status IN ('matching', 'submitting')")->execute([$del_id]);
header("Location: chat.php");
exit;
}
$user_id = $_GET['user_id'] ?? null;
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
// Fetch users with messages or active recharge orders
$chat_users = $pdo->query("
SELECT DISTINCT u.id, u.username, u.uid,
(SELECT message FROM messages WHERE user_id = u.id ORDER BY id DESC LIMIT 1) as last_msg,
(SELECT created_at FROM messages WHERE user_id = u.id ORDER BY id DESC LIMIT 1) as last_time,
(SELECT COUNT(*) FROM messages WHERE user_id = u.id AND sender = 'user' AND is_read = 0) as unread_count,
(SELECT status FROM fiat_orders WHERE user_id = u.id AND status IN ('matching', 'submitting') LIMIT 1) as recharge_status
FROM users u
JOIN messages m ON u.id = m.user_id
UNION
SELECT DISTINCT u.id, u.username, u.uid,
'发起充值申请' as last_msg,
o.created_at as last_time,
0 as unread_count,
o.status as recharge_status
FROM users u
JOIN fiat_orders o ON u.id = o.user_id
WHERE o.status IN ('matching', 'submitting')
ORDER BY last_time DESC
")->fetchAll();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>客服管理 - NovaEx 管理后台</title>
<link rel="stylesheet" href="../assets/css/custom.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #1E2329; border-right: 1px solid #2B3139; padding: 1rem; }
.chat-container { flex: 1; display: flex; background: #0B0E11; height: 100vh; overflow: hidden; }
.user-list { width: 300px; border-right: 1px solid #2B3139; background: #1E2329; overflow-y: auto; }
.chat-main { flex: 1; display: flex; flex-direction: column; }
.menu-item { padding: 12px; color: #848E9C; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
.menu-item:hover, .menu-item.active { background: #2B3139; color: white; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.user-item { padding: 15px; border-bottom: 1px solid #2B3139; cursor: pointer; position: relative; display: flex; flex-direction: column; }
.user-item:hover, .user-item.active { background: #2B3139; }
.user-info-row { display: flex; justify-content: space-between; align-items: center; width: 100%; }
.user-name { font-weight: bold; color: white; font-size: 0.9rem; flex: 1; }
.delete-btn { color: #848E9C; font-size: 0.9rem; padding: 5px; cursor: pointer; z-index: 10; }
.delete-btn:hover { color: #f6465d; }
.last-msg { color: #848E9C; font-size: 0.75rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 5px; width: 90%; }
.dot { width: 10px; height: 10px; background: #f6465d; border-radius: 50%; }
.recharge-label { font-size: 0.7rem; background: rgba(240, 185, 11, 0.2); color: #f0b90b; padding: 2px 5px; border-radius: 3px; margin-left: 5px; }
.back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; padding: 15px; border-bottom: 1px solid #2B3139; display: block; }
.back-btn:hover { color: white; background: #2B3139; }
#custom-alert { display: none; position: fixed; top: 20px; right: 20px; background: #f0b90b; color: black; padding: 20px; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); z-index: 10000; animation: slideIn 0.5s; width: 300px; }
@keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
</style>
</head>
<body>
<div id="custom-alert">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 10px;">
<i class="fas fa-bell fa-lg"></i>
<strong style="font-size: 1.1rem;">新通知 / NEW NOTIFICATION</strong>
</div>
<div id="alert-msg">您有新的充值申请或用户消息。</div>
<button onclick="location.reload()" style="margin-top: 15px; width: 100%; padding: 8px; background: black; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold;">立即刷新列表</button>
</div>
<div class="admin-layout">
<div class="sidebar">
<h3 style="color: white; margin-bottom: 2rem;">NovaEx 管理员</h3>
<a href="index.php" class="menu-item"><i class="fas fa-chart-pie"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
<a href="chat.php" class="menu-item active">
<i class="fas fa-headset"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge" id="total-badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="chat-container">
<div class="user-list">
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
<div style="padding: 15px; color: #848E9C; font-size: 0.8rem; border-bottom: 1px solid #2B3139;">最近联系人 / 充值申请</div>
<div id="user-items-container">
<?php foreach($chat_users as $u): ?>
<div class="user-item <?php echo $user_id == $u['id'] ? 'active' : ''; ?>" onclick="if(event.target.closest('.delete-btn')) return; location.href='chat.php?user_id=<?php echo $u['id']; ?>'">
<div class="user-info-row">
<div class="user-name">
<?php echo htmlspecialchars($u['username']); ?>
<?php if($u['recharge_status']): ?><span class="recharge-label">充值申请</span><?php endif; ?>
</div>
<div style="display: flex; align-items: center; gap: 10px;">
<?php if($u['unread_count'] > 0 || $u['recharge_status'] == 'matching'): ?><div class="dot"></div><?php endif; ?>
<i class="fas fa-trash delete-btn" title="删除记录" onclick="if(confirm('确定要删除与该用户的聊天及充值申请吗?')) window.location.href='chat.php?action=delete&delete_user_id=<?php echo $u['id']; ?>'"></i>
</div>
</div>
<div class="last-msg"><?php echo htmlspecialchars($u['last_msg']); ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="chat-main">
<?php if($user_id): ?>
<iframe src="chat_iframe.php?user_id=<?php echo $user_id; ?>" style="width: 100%; height: 100%; border: none;"></iframe>
<?php else: ?>
<div style="flex: 1; display: flex; align-items: center; justify-content: center; color: #5e6673; flex-direction: column;">
<i class="fas fa-comments" style="font-size: 4rem; margin-bottom: 20px;"></i>
<p>请在左侧选择一个用户或处理中的充值申请</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
<audio id="notif-sound" src="https://assets.mixkit.co/active_storage/sfx/2869/2869-preview.mp3" preload="auto"></audio>
<script>
let lastTotal = <?php echo ($unread_msgs + $pending_orders); ?>;
function checkNotifications() {
fetch('../api/get_messages.php?action=count_unread')
.then(res => res.json())
.then(data => {
if (data.total > lastTotal) {
document.getElementById('notif-sound').play().catch(e => {});
document.getElementById('custom-alert').style.display = 'block';
document.getElementById('alert-msg').innerText = "您有新的充值申请或用户消息 (当前未读: " + data.total + ")";
const badge = document.getElementById('total-badge');
if (badge) badge.innerText = data.total;
} else if (data.total < lastTotal) {
const badge = document.getElementById('total-badge');
if (badge) {
if (data.total === 0) badge.remove();
else badge.innerText = data.total;
}
}
lastTotal = data.total;
});
}
setInterval(checkNotifications, 2000);
</script>
</body>
</html>

330
admin/chat_iframe.php Normal file
View File

@ -0,0 +1,330 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
require_once '../includes/currency_helper.php';
$pdo = db();
$user_id = $_GET['user_id'] ?? null;
if (!$user_id) die("需要用户 ID");
// Initial mark as read
$pdo->prepare("UPDATE messages SET is_read = 1 WHERE user_id = ? AND sender = 'user'")->execute([$user_id]);
// 处理消息发送
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['message'])) {
$msg = $_POST['message'];
$pdo->prepare("INSERT INTO messages (user_id, sender, message, type) VALUES (?, 'admin', ?, 'text')")->execute([$user_id, $msg]);
exit;
}
// 处理充值/提现操作
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) {
$oid = $_POST['order_id'];
if ($_POST['action'] == 'match_deposit') {
$bank = $_POST['bank_name'] ?? '';
$name = $_POST['account_name'] ?? '';
$number = $_POST['account_number'] ?? '';
$remarks = $_POST['remarks'] ?? '';
$info = "Bank$bank\nAccount Name$name\nBank Acc$number\nRemarks$remarks";
$pdo->prepare("UPDATE fiat_orders SET status = 'matched', bank_account_info = ? WHERE id = ?")->execute([$info, $oid]);
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $info]);
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, "✅ 匹配成功收款账户已下发请在转账后上传凭证。clearly"]);
echo "<script>parent.location.reload();</script>";
exit;
} elseif ($_POST['action'] == 'send_withdraw_format') {
$format = "Bank\nBank Acc\nAccount Name";
$pdo->prepare("UPDATE fiat_orders SET status = 'matched', bank_account_info = ? WHERE id = ?")->execute([$format, $oid]);
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $format]);
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, "✅ 请按上述格式回复您的收款详情。"]);
echo "<script>parent.location.reload();</script>";
exit;
} elseif ($_POST['action'] == 'complete') {
$stmt = $pdo->prepare("SELECT order_type, usdt_amount, currency FROM fiat_orders WHERE id = ?");
$stmt->execute([$oid]);
$order = $stmt->fetch();
$pdo->beginTransaction();
try {
if ($order['order_type'] === 'deposit') {
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['usdt_amount'], $user_id]);
$msg = "🎉 您的充值已确认到账!";
} else {
$msg = "🎉 您的提现申请已处理完成,请查收!";
}
$pdo->prepare("UPDATE fiat_orders SET status = 'completed' WHERE id = ?")->execute([$oid]);
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $msg]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
die($e->getMessage());
}
echo "<script>parent.location.reload();</script>";
exit;
} elseif ($_POST['action'] == 'reject') {
$stmt = $pdo->prepare("SELECT order_type, usdt_amount FROM fiat_orders WHERE id = ?");
$stmt->execute([$oid]);
$order = $stmt->fetch();
$pdo->beginTransaction();
try {
if ($order['order_type'] === 'withdrawal') {
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['usdt_amount'], $user_id]);
}
$pdo->prepare("UPDATE fiat_orders SET status = 'rejected' WHERE id = ?")->execute([$oid]);
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, "❌ 您的申请已被拒绝,如有疑问请咨询客服。"]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
die($e->getMessage());
}
echo "<script>parent.location.reload();</script>";
exit;
}
}
$user = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$user->execute([$user_id]);
$userData = $user->fetch();
$orders = $pdo->prepare("SELECT * FROM fiat_orders WHERE user_id = ? AND status IN ('matching', 'matched', 'paid') ORDER BY id DESC");
$orders->execute([$user_id]);
$pending_orders = $orders->fetchAll();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
body { margin: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #0B0E11; color: white; display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
.chat-header { padding: 12px 20px; background: #1E2329; border-bottom: 1px solid #2B3139; display: flex; flex-direction: column; gap: 5px; font-size: 13px; }
.header-top { display: flex; justify-content: space-between; align-items: center; }
.header-bottom { display: flex; justify-content: space-between; font-size: 12px; color: #848E9C; }
#chat-box { flex: 1; padding: 20px; display: flex; flex-direction: column; gap: 15px; overflow-y: auto; scroll-behavior: smooth; background: #0b0e11; }
.msg { max-width: 80%; padding: 12px 16px; border-radius: 16px; font-size: 13.5px; line-height: 1.6; position: relative; }
.msg.admin { align-self: flex-end; background: #f0b90b; color: black; border-bottom-right-radius: 4px; }
.msg.user { align-self: flex-start; background: #2B3139; color: #EAECEF; border-bottom-left-radius: 4px; border: 1px solid #3b424d; }
.msg-time { font-size: 10px; opacity: 0.5; margin-top: 5px; display: block; text-align: right; }
.input-area { padding: 15px 20px; background: #1E2329; border-top: 1px solid #2B3139; display: flex; gap: 12px; align-items: center; }
input[type="text"] { flex: 1; background: #0B0E11; border: 1px solid #2B3139; color: white; padding: 12px 15px; border-radius: 10px; outline: none; transition: 0.3s; }
input[type="text"]:focus { border-color: #f0b90b; }
button { background: #f0b90b; border: none; color: black; padding: 10px 20px; border-radius: 10px; cursor: pointer; font-weight: bold; transition: 0.3s; }
button:hover { background: #fcd535; }
.order-panel { background: #1E2329; border-bottom: 1px solid #2B3139; padding: 15px; max-height: 250px; overflow-y: auto; }
.order-card { background: #2B3139; border: 1px solid #3b424d; padding: 15px; border-radius: 12px; margin-bottom: 10px; }
.order-card input { background: #0B0E11; border: 1px solid #3b424d; color: white; padding: 8px; border-radius: 6px; font-size: 12px; margin-bottom: 5px; width: 100%; box-sizing: border-box; }
.status-tag { padding: 2px 8px; border-radius: 4px; font-size: 10px; font-weight: bold; text-transform: uppercase; }
.status-matching { background: rgba(240, 185, 11, 0.2); color: #f0b90b; }
.status-matched { background: rgba(0, 192, 135, 0.2); color: #00c087; }
.status-paid { background: rgba(14, 203, 129, 0.2); color: #0ecb81; }
.sending { opacity: 0.7; }
.sending::after { content: '...'; position: absolute; right: 5px; bottom: 5px; font-size: 10px; }
.icon-btn { background: #2b3139; border: 1px solid #3b424d; width: 40px; height: 40px; border-radius: 8px; color: #f0b90b; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; }
.icon-btn:hover { background: #3b424d; }
</style>
</head>
<body>
<div class="chat-header">
<div class="header-top">
<span><i class="fas fa-user-circle"></i> <b><?php echo htmlspecialchars($userData['username'] ?? ''); ?></b> (UID: <?php echo $userData['uid'] ?? ''; ?>)</span>
<span style="color: #00c087; font-weight: bold;">余额: <?php echo number_format($userData['balance'] ?? 0, 2); ?> USDT</span>
</div>
<div class="header-bottom">
<span><i class="fas fa-network-wired"></i> 实时 IP: <?php echo htmlspecialchars($userData['last_ip'] ?? '未知'); ?></span>
<span><i class="fas fa-clock"></i> 当前时间: <?php echo date('Y-m-d H:i:s'); ?></span>
</div>
</div>
<div style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
<?php if ($pending_orders): ?>
<div class="order-panel">
<div style="font-size: 11px; color: #848E9C; margin-bottom: 10px; font-weight: bold;">待处理申请 (ACTIVE REQUESTS)</div>
<?php foreach($pending_orders as $o):
$orderTypeDisplay = $o['order_type'] === 'deposit' ? '充值' : '提现';
$statusDisplay = '';
if ($o['status'] === 'matching') $statusDisplay = '待受理';
elseif ($o['status'] === 'matched') $statusDisplay = '已下发';
elseif ($o['status'] === 'paid') $statusDisplay = '待审核';
?>
<div class="order-card">
<div style="display:flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
<div>
<span style="font-weight: 800; color: #f0b90b; font-size: 14px;"><?php echo $orderTypeDisplay; ?>: <?php echo $o['amount']; ?> <?php echo $o['currency']; ?></span>
<span style="color: #848E9C; font-size: 12px; margin-left: 10px;"> <?php echo number_format($o['usdt_amount'], 2); ?> USDT</span>
</div>
<span class="status-tag status-<?php echo $o['status']; ?>"><?php echo $statusDisplay; ?></span>
</div>
<?php if($o['status'] == 'matching'): ?>
<?php if($o['order_type'] == 'deposit'): ?>
<form method="POST">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="match_deposit">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px;">
<input type="text" name="bank_name" placeholder="银行名称" required>
<input type="text" name="account_name" placeholder="收款姓名" required>
<input type="text" name="account_number" placeholder="收款账号 / IBAN" required style="grid-column: span 2;">
<input type="text" name="remarks" placeholder="备注说明 (可选)" style="grid-column: span 2;">
<button type="submit" style="grid-column: span 2; background: #00c087; color: white;">下发收款账户</button>
</div>
</form>
<?php else: ?>
<form method="POST">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="send_withdraw_format">
<button type="submit" style="width: 100%; background: #4facfe; color: white;">发送提现信息格式模板</button>
</form>
<?php endif; ?>
<?php else: ?>
<div style="display: flex; gap: 10px;">
<form method="POST" style="flex: 1;">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="complete">
<button type="submit" style="width: 100%; background: #00c087; color: white;">同意 (Approve)</button>
</form>
<form method="POST" style="flex: 1;">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="reject">
<button type="submit" style="width: 100%; background: #f6465d; color: white;">拒绝 (Reject)</button>
</form>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<div id="chat-box"></div>
</div>
<form class="input-area" id="msg-form">
<button type="button" class="icon-btn" id="upload-btn" onclick="document.getElementById('image-input').click()">
<i class="fas fa-plus"></i>
</button>
<input type="file" id="image-input" accept="image/*" style="display: none;" onchange="uploadImage(this)">
<input type="text" id="msg-input" placeholder="输入消息..." autocomplete="off">
<button type="submit"><i class="fas fa-paper-plane"></i></button>
</form>
<audio id="notif-sound" src="https://assets.mixkit.co/active_storage/sfx/2869/2869-preview.mp3" preload="auto"></audio>
<script>
const chatBox = document.getElementById('chat-box');
const msgInput = document.getElementById('msg-input');
const uploadBtn = document.getElementById('upload-btn');
const notifSound = document.getElementById('notif-sound');
let lastMsgId = 0;
let lastMessagesHtml = '';
let isSending = false;
async function loadMessages() {
if (isSending) return;
try {
const resp = await fetch('../api/get_messages.php?user_id=<?php echo $user_id; ?>');
const res = await resp.json();
if (res.success) {
let html = '';
let hasNewUserMsg = false;
res.data.forEach(m => {
if (m.id > lastMsgId) {
if (m.sender === 'user' && lastMsgId > 0) hasNewUserMsg = true;
lastMsgId = m.id;
}
html += `
<div class="msg ${m.sender}">
${m.type === 'image' ? `<img src="../${m.message}" style="max-width:100%; border-radius:8px; cursor:pointer;" onclick="window.open(this.src)">` : m.message.replace(/\n/g, '<br>')}
<span class="msg-time">${new Date(m.created_at).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span>
</div>
`;
});
if (hasNewUserMsg) {
try { notifSound.play(); } catch(e) {}
}
if (html !== lastMessagesHtml) {
const isAtBottom = chatBox.scrollHeight - chatBox.scrollTop <= chatBox.clientHeight + 100;
chatBox.innerHTML = html;
lastMessagesHtml = html;
if (isAtBottom) chatBox.scrollTop = chatBox.scrollHeight;
// Mark as read
fetch('../api/get_messages.php?action=mark_read&user_id=<?php echo $user_id; ?>&reader=admin');
}
}
} catch (e) {}
}
document.getElementById('msg-form').onsubmit = async (e) => {
e.preventDefault();
const msg = msgInput.value.trim();
if (!msg || isSending) return;
msgInput.value = '';
isSending = true;
// Optimistic UI
const tempMsg = document.createElement('div');
tempMsg.className = 'msg admin sending';
tempMsg.innerHTML = `${msg.replace(/\n/g, '<br>')}<span class="msg-time">${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span>`;
chatBox.appendChild(tempMsg);
chatBox.scrollTop = chatBox.scrollHeight;
const formData = new FormData();
formData.append('message', msg);
try {
await fetch(window.location.href, { method: 'POST', body: formData });
isSending = false;
await loadMessages();
} catch (e) {
isSending = false;
tempMsg.style.background = '#f6465d';
tempMsg.innerHTML += ' (发送失败)';
}
};
function uploadImage(input) {
if (!input.files || !input.files[0]) return;
const formData = new FormData();
formData.append('image', input.files[0]);
formData.append('is_admin', '1'); // Optional, to distinguish sender if needed
uploadBtn.disabled = true;
uploadBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
// We need a separate API or same API for admin image upload
// api/upload_chat_image.php already handles sending message as 'user'
// I should probably create a separate one or modify it.
// Let's modify api/upload_chat_image.php to support admin sender.
fetch('../api/upload_chat_image.php?sender=admin&user_id=<?php echo $user_id; ?>', { method: 'POST', body: formData })
.then(res => res.json())
.then(res => {
if (res.success) {
loadMessages();
} else {
alert(res.error || '上传失败');
}
})
.finally(() => {
uploadBtn.disabled = false;
uploadBtn.innerHTML = '<i class="fas fa-plus"></i>';
input.value = '';
});
}
loadMessages();
setInterval(loadMessages, 1000);
</script>
</body>
</html>

166
admin/futures_orders.php Normal file
View File

@ -0,0 +1,166 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
$faceValue = 10;
if (isset($_POST['action']) && isset($_POST['order_id'])) {
$oid = $_POST['order_id'];
$action = $_POST['action'];
$orderStmt = $pdo->prepare("SELECT o.*, u.balance FROM trading_orders o JOIN users u ON o.user_id = u.id WHERE o.id = ?");
$orderStmt->execute([$oid]);
$order = $orderStmt->fetch();
if ($order && $order['status'] == 'open') {
$user_id = $order['user_id'];
$margin = $order['total'] / $order['leverage'];
if ($action == 'approve') {
// "WIN": Approve and settle at TP price (if set) or current manual price
$exit_price = (float)($order['tp_price'] ?: $order['price']);
$entry_price = (float)$order['price'];
$nominal = (float)$order['amount'] * $faceValue;
$profit = 0;
if ($order['side'] == 'buy') {
$profit = ($exit_price / $entry_price - 1) * $nominal;
} else {
$profit = (1 - $exit_price / $entry_price) * $nominal;
}
$payout = $margin + $profit;
if ($payout < 0) $payout = 0;
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$payout, $user_id]);
$pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved', win_loss = 'win' WHERE id = ?")->execute([$oid]);
} elseif ($action == 'reject') {
// "LOSS": Reject. Margin is already deducted and not returned.
$pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected', win_loss = 'loss' WHERE id = ?")->execute([$oid]);
}
}
}
$orders = $pdo->query("SELECT o.*, u.username, u.uid FROM trading_orders o JOIN users u ON o.user_id = u.id WHERE o.type = 'futures' ORDER BY o.id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>合约交易管理 - NovaEx 管理后台</title>
<link rel="stylesheet" href="../assets/css/custom.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #FFFFFF; border-right: 1px solid #EAECEF; padding: 1rem; }
.main-content { flex: 1; padding: 2rem; background: #FFFFFF; color: #1E2329; }
.menu-item { padding: 12px; color: #474D57; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
.menu-item:hover, .menu-item.active { background: #F5F5F5; color: #F0B90B; }
.badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #EAECEF; font-size: 0.8rem; color: #1E2329; }
.btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; margin-right: 5px; }
.btn-approve { background: #00c087; color: white; }
.btn-reject { background: #f6465d; color: white; }
.back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
.status-badge { padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; }
.status-open { background: #fff3cd; color: #856404; }
.status-closed { background: #d4edda; color: #155724; }
.status-cancelled { background: #f8d7da; color: #721c24; }
</style>
</head>
<body style="background: white;">
<div class="admin-layout">
<div class="sidebar">
<h3 style="color: #1E2329; margin-bottom: 2rem;">NovaEx 管理员</h3>
<a href="index.php" class="menu-item"><i class="fas fa-chart-pie"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
<a href="chat.php" class="menu-item">
<i class="fas fa-headset"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item active"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
<h2 style="color: #1E2329;">合约交易管理 (后台控赢/)</h2>
<p style="color: #707A8A; font-size: 0.9rem;">提示:同意结算将按用户设置的“止盈价”计算盈利并返还保证金;拒绝(亏损)将扣除全部保证金。</p>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>用户</th>
<th>币对</th>
<th>方向</th>
<th>杠杆</th>
<th>开仓价</th>
<th>张数</th>
<th>保证金</th>
<th>止盈价</th>
<th>止损价</th>
<th>状态</th>
<th>结果</th>
<th>下单时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach($orders as $o): ?>
<tr>
<td><?php echo $o['id']; ?></td>
<td><?php echo htmlspecialchars($o['username']); ?> (<?php echo $o['uid']; ?>)</td>
<td><?php echo $o['symbol']; ?></td>
<td style="color: <?php echo $o['side'] == 'buy' ? '#00c087' : '#f6465d'; ?>">
<?php echo $o['side'] == 'buy' ? '做多' : '做空'; ?>
</td>
<td><?php echo $o['leverage']; ?>x</td>
<td><?php echo number_format($o['price'], 2); ?></td>
<td><?php echo $o['amount']; ?></td>
<td><?php echo number_format($o['total'] / $o['leverage'], 2); ?> USDT</td>
<td style="color: #00c087;"><?php echo $o['tp_price'] ?: '--'; ?></td>
<td style="color: #f6465d;"><?php echo $o['sl_price'] ?: '--'; ?></td>
<td>
<span class="status-badge status-<?php echo $o['status']; ?>">
<?php echo $o['status'] == 'open' ? '持仓中' : ($o['status'] == 'closed' ? '已平仓' : '已撤单'); ?>
</span>
</td>
<td>
<?php if($o['win_loss'] == 'win'): ?>
<span style="color: #00c087;">控赢</span>
<?php elseif($o['win_loss'] == 'loss'): ?>
<span style="color: #f6465d;">控亏</span>
<?php else: ?>
--
<?php endif; ?>
</td>
<td><?php echo $o['created_at']; ?></td>
<td>
<?php if($o['status'] == 'open'): ?>
<form method="POST" style="display: inline;">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<button type="submit" name="action" value="approve" class="btn-sm btn-approve">控赢</button>
<button type="submit" name="action" value="reject" class="btn-sm btn-reject">控亏</button>
</form>
<?php else: ?>
--
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</body>
</html>

101
admin/index.php Normal file
View File

@ -0,0 +1,101 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$db = db();
$total_users = $db->query("SELECT COUNT(*) FROM users")->fetchColumn();
$pending_kyc = $db->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->fetchColumn();
$pending_orders = $db->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
$unread_msgs = $db->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>管理后台 - NovaEx</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.stat-card { background: white; padding: 25px; border-radius: 12px; border: 1px solid var(--border); box-shadow: 0 2px 10px rgba(0,0,0,0.03); }
.stat-label { color: #707a8a; font-size: 0.85rem; margin-bottom: 10px; font-weight: 600; text-transform: uppercase; }
.stat-value { font-size: 2.2rem; font-weight: 800; color: #1e2329; }
</style>
</head>
<body>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item active"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item"><i class="fas fa-user-shield"></i> 代理管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核
<?php if($pending_kyc > 0): ?><span class="badge"><?php echo $pending_kyc; ?></span><?php endif; ?>
</a>
<a href="chat.php" class="menu-item"><i class="fas fa-comments"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
<a href="../index.php" class="menu-item" style="margin-top: 2rem; color: #f0b90b;"><i class="fas fa-external-link-alt"></i> 前端首页</a>
</div>
<div class="main-content">
<h1 style="margin-bottom: 2rem;">系统概览</h1>
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem;">
<div class="stat-card">
<div class="stat-label">总注册用户</div>
<div class="stat-value"><?php echo $total_users; ?></div>
</div>
<div class="stat-card">
<div class="stat-label">待审核 KYC</div>
<div class="stat-value" style="color: #f0b90b;"><?php echo $pending_kyc; ?></div>
</div>
<div class="stat-card">
<div class="stat-label">待匹配充值</div>
<div class="stat-value" style="color: #f6465d;"><?php echo $pending_orders; ?></div>
</div>
<div class="stat-card">
<div class="stat-label">待回复消息</div>
<div class="stat-value" style="color: #00c087;"><?php echo $unread_msgs; ?></div>
</div>
</div>
<div style="margin-top: 3rem; background: #f9fafb; padding: 30px; border-radius: 16px; border: 1px solid var(--border);">
<h2 style="margin-bottom: 20px;">控制中心</h2>
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
<div style="background: white; padding: 25px; border-radius: 12px; border: 1px solid var(--border);">
<h3>充值与客服</h3>
<p style="color: #707a8a; font-size: 0.9rem;">实时处理充值申请并与用户在线沟通。</p>
<a href="chat.php" style="background: var(--primary); color: black; padding: 10px 20px; border-radius: 8px; text-decoration: none; display: inline-block; margin-top: 15px; font-weight: bold;">进入客服中心</a>
</div>
<div style="background: white; padding: 25px; border-radius: 12px; border: 1px solid var(--border);">
<h3>交易订单</h3>
<p style="color: #707a8a; font-size: 0.9rem;">监控秒合约、现货及合约交易流水。</p>
<div style="margin-top: 15px; display: flex; gap: 10px;">
<a href="options_orders.php" style="background: #f4f6f9; color: #474d57; padding: 8px 15px; border-radius: 6px; text-decoration: none; font-size: 0.85rem;">秒合约</a>
<a href="futures_orders.php" style="background: #f4f6f9; color: #474d57; padding: 8px 15px; border-radius: 6px; text-decoration: none; font-size: 0.85rem;">合约交易</a>
</div>
</div>
<div style="background: white; padding: 25px; border-radius: 12px; border: 1px solid var(--border);">
<h3>全局设置</h3>
<p style="color: #707a8a; font-size: 0.9rem;">修改系统参数、胜率及站点 LOGO。</p>
<a href="settings.php" style="color: var(--primary); text-decoration: none; display: block; margin-top: 15px; font-weight: bold;">立即配置 <i class="fas fa-arrow-right"></i></a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

206
admin/kyc.php Normal file
View File

@ -0,0 +1,206 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
if (isset($_POST['action']) && isset($_POST['user_id'])) {
$uid = $_POST['user_id'];
$status = $_POST['action'] == 'approve' ? 2 : 0;
$pdo->prepare("UPDATE users SET kyc_status = ? WHERE id = ?")->execute([$status, $uid]);
}
$pending_kyc_list = $pdo->query("SELECT * FROM users WHERE kyc_status = 1 ORDER BY id DESC")->fetchAll();
$approved_kyc_list = $pdo->query("SELECT * FROM users WHERE kyc_status = 2 ORDER BY id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
$pending_kyc_count = count($pending_kyc_list);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>KYC 审核 - NovaEx 管理后台</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.kyc-card { background: white; border: 1px solid var(--border); padding: 25px; border-radius: 12px; margin-bottom: 25px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
.kyc-img { width: 180px; height: 110px; object-fit: cover; border-radius: 8px; cursor: pointer; border: 1px solid var(--border); transition: 0.2s; }
.kyc-img:hover { transform: scale(1.05); box-shadow: 0 5px 15px rgba(0,0,0,0.1); }
.btn { padding: 10px 20px; border-radius: 6px; border: none; cursor: pointer; color: white; font-weight: bold; font-size: 0.9rem; }
.tabs { display: flex; gap: 20px; border-bottom: 1px solid var(--border); margin-bottom: 30px; }
.tab { padding: 12px 20px; cursor: pointer; font-weight: 600; color: #707a8a; position: relative; }
.tab.active { color: var(--primary); }
.tab.active::after { content: ''; position: absolute; bottom: -1px; left: 0; right: 0; height: 3px; background: var(--primary); border-radius: 3px 3px 0 0; }
#detail-modal { position: fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.8); display:none; align-items:center; justify-content:center; z-index:9999; }
.modal-content { background:white; padding:30px; border-radius:12px; max-width:600px; width:90%; }
</style>
</head>
<body>
<div id="detail-modal">
<div class="modal-content">
<h2 id="modal-title">用户认证详情</h2>
<div id="modal-body" style="display:flex; gap:20px; flex-wrap:wrap; margin-top:20px;"></div>
<button onclick="document.getElementById('detail-modal').style.display='none'" class="btn" style="background:var(--text); width:100%; margin-top:20px;">关闭</button>
</div>
</div>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item"><i class="fas fa-user-shield"></i> 代理管理</a>
<a href="kyc.php" class="menu-item active"><i class="fas fa-id-card"></i> KYC 审核
<?php if($pending_kyc_count > 0): ?><span class="badge"><?php echo $pending_kyc_count; ?></span><?php endif; ?>
</a>
<a href="chat.php" class="menu-item"><i class="fas fa-comments"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<h1>实名认证管理 (KYC)</h1>
<div class="tabs">
<div class="tab active" onclick="switchTab('pending')">待审核 (<?php echo count($pending_kyc_list); ?>)</div>
<div class="tab" onclick="switchTab('approved')">已通过 (<?php echo count($approved_kyc_list); ?>)</div>
</div>
<div id="pending-section">
<?php if(empty($pending_kyc_list)): ?>
<div style="text-align: center; padding: 100px; color: #707a8a; background: #f9fafb; border-radius: 12px; border: 1px dashed var(--border);">
<i class="fas fa-check-circle" style="font-size: 3rem; margin-bottom: 15px; opacity: 0.3;"></i>
<p>目前没有待处理的认证申请</p>
</div>
<?php endif; ?>
<?php foreach($pending_kyc_list as $k): ?>
<div class="kyc-card">
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
<div>
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 5px;">
<span style="font-size: 1.2rem; font-weight: 800;"><?php echo htmlspecialchars($k['kyc_name']); ?></span>
<span style="background: #fff9e6; color: #f0b90b; padding: 2px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: bold;">待审核</span>
</div>
<p style="color: #474d57; font-size: 1rem; margin-bottom: 8px;">证件号码: <span style="font-family: monospace; font-weight: bold;"><?php echo htmlspecialchars($k['kyc_id_number']); ?></span></p>
<p style="color: #707a8a; font-size: 0.85rem;">关联账号: <?php echo htmlspecialchars($k['username']); ?> (UID: <?php echo $k['uid']; ?>)</p>
</div>
<div style="display: flex; gap: 10px;">
<form method="POST">
<input type="hidden" name="user_id" value="<?php echo $k['id']; ?>">
<input type="hidden" name="action" value="approve">
<button type="submit" class="btn" style="background: #00c087;"><i class="fas fa-check"></i> 通过审核</button>
</form>
<form method="POST">
<input type="hidden" name="user_id" value="<?php echo $k['id']; ?>">
<input type="hidden" name="action" value="reject">
<button type="submit" class="btn" style="background: #f6465d;"><i class="fas fa-times"></i> 驳回</button>
</form>
</div>
</div>
<div style="display: flex; gap: 20px; margin-top: 25px; flex-wrap: wrap;">
<div style="text-align: center;">
<img src="../<?php echo $k['kyc_id_front']; ?>" class="kyc-img" onclick="window.open(this.src)">
<div style="font-size: 0.75rem; color: #707a8a; margin-top: 8px;">正面照</div>
</div>
<div style="text-align: center;">
<img src="../<?php echo $k['kyc_id_back']; ?>" class="kyc-img" onclick="window.open(this.src)">
<div style="font-size: 0.75rem; color: #707a8a; margin-top: 8px;">反面照</div>
</div>
<div style="text-align: center;">
<img src="../<?php echo $k['kyc_id_handheld']; ?>" class="kyc-img" onclick="window.open(this.src)">
<div style="font-size: 0.75rem; color: #707a8a; margin-top: 8px;">手持照</div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<div id="approved-section" style="display: none;">
<?php if(empty($approved_kyc_list)): ?>
<p style="color: #707A8A; text-align: center; padding: 50px;">暂无已通过认证的用户。</p>
<?php endif; ?>
<div style="background: white; border-radius: 12px; border: 1px solid var(--border); overflow: hidden;">
<table style="width: 100%; border-collapse: collapse;">
<thead style="background: #f9fafb;">
<tr>
<th style="padding: 15px; text-align: left; color: #707a8a; font-size: 0.8rem;">姓名</th>
<th style="padding: 15px; text-align: left; color: #707a8a; font-size: 0.8rem;">证件号码</th>
<th style="padding: 15px; text-align: left; color: #707a8a; font-size: 0.8rem;">关联账号</th>
<th style="padding: 15px; text-align: left; color: #707a8a; font-size: 0.8rem;">认证时间</th>
<th style="padding: 15px; text-align: right; color: #707a8a; font-size: 0.8rem;">操作</th>
</tr>
</thead>
<tbody>
<?php foreach($approved_kyc_list as $k): ?>
<tr style="border-top: 1px solid var(--border);">
<td style="padding: 15px; font-weight: bold;"><?php echo htmlspecialchars($k['kyc_name']); ?></td>
<td style="padding: 15px; font-family: monospace;"><?php echo htmlspecialchars($k['kyc_id_number']); ?></td>
<td style="padding: 15px;"><?php echo htmlspecialchars($k['username']); ?> (<?php echo $k['uid']; ?>)</td>
<td style="padding: 15px; font-size: 0.85rem; color: #707a8a;"><?php echo $k['created_at']; ?></td>
<td style="padding: 15px; text-align: right; display: flex; gap: 10px; justify-content: flex-end;">
<button onclick="showDetails('<?php echo htmlspecialchars($k['kyc_name']); ?>', '<?php echo $k['kyc_id_front']; ?>', '<?php echo $k['kyc_id_back']; ?>', '<?php echo $k['kyc_id_handheld']; ?>')" style="background: none; border: none; color: var(--primary); cursor: pointer; font-size: 0.85rem; font-weight: bold;">查看照片</button>
<form method="POST" onsubmit="return confirm('确定要取消该用户的认证状态吗?')">
<input type="hidden" name="user_id" value="<?php echo $k['id']; ?>">
<input type="hidden" name="action" value="reject">
<button type="submit" style="background: none; border: none; color: #f6465d; cursor: pointer; font-size: 0.85rem; font-weight: bold;">撤销认证</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
function switchTab(tab) {
const tabs = document.querySelectorAll('.tab');
const pending = document.getElementById('pending-section');
const approved = document.getElementById('approved-section');
tabs.forEach(t => t.classList.remove('active'));
if (tab === 'pending') {
tabs[0].classList.add('active');
pending.style.display = 'block';
approved.style.display = 'none';
} else {
tabs[1].classList.add('active');
pending.style.display = 'none';
approved.style.display = 'block';
}
}
function showDetails(name, front, back, handheld) {
document.getElementById('modal-title').innerText = name + ' 的证件照片';
document.getElementById('modal-body').innerHTML = `
<div style="text-align:center;"><img src="../${front}" style="width:150px; height:100px; object-fit:cover; border-radius:8px; border:1px solid #eee;"><div style="font-size:12px; margin-top:5px;">正面</div></div>
<div style="text-align:center;"><img src="../${back}" style="width:150px; height:100px; object-fit:cover; border-radius:8px; border:1px solid #eee;"><div style="font-size:12px; margin-top:5px;">反面</div></div>
<div style="text-align:center;"><img src="../${handheld}" style="width:150px; height:100px; object-fit:cover; border-radius:8px; border:1px solid #eee;"><div style="font-size:12px; margin-top:5px;">手持</div></div>
`;
document.getElementById('detail-modal').style.display = 'flex';
}
</script>
</body>
</html>

68
admin/login.php Normal file
View File

@ -0,0 +1,68 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once '../db/config.php';
require_once '../includes/i18n.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM admins WHERE username = ?");
$stmt->execute([$username]);
$admin = $stmt->fetch();
if ($admin && password_verify($password, $admin['password'])) {
$_SESSION['admin_id'] = $admin['id'];
$_SESSION['admin_username'] = $admin['username'];
$_SESSION['admin_role'] = $admin['role'];
header("Location: index.php");
exit;
} else {
$error = "用户名或密码错误。";
}
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理员登录 - NovaEx</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
body { background: #f4f6f9; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; height: 100vh; display: flex; align-items: center; justify-content: center; margin: 0; }
.login-card { background: white; padding: 40px; border-radius: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.05); width: 100%; max-width: 400px; border: 1px solid #eaecef; }
.logo { color: #f0b90b; font-size: 2rem; font-weight: 800; text-align: center; margin-bottom: 30px; }
.form-group { margin-bottom: 20px; }
.form-group label { display: block; margin-bottom: 8px; font-weight: 600; color: #474d57; font-size: 0.9rem; }
.form-group input { width: 100%; padding: 12px; border: 1px solid #eaecef; border-radius: 8px; font-size: 1rem; outline: none; box-sizing: border-box; }
.btn-login { width: 100%; padding: 14px; background: #f0b90b; border: none; border-radius: 8px; color: black; font-weight: bold; font-size: 1rem; cursor: pointer; transition: 0.2s; margin-top: 10px; }
.btn-login:hover { background: #d9a60a; }
.error { background: #fff5f5; color: #f6465d; padding: 10px; border-radius: 6px; font-size: 0.85rem; margin-bottom: 20px; text-align: center; border: 1px solid #ffe3e3; }
</style>
</head>
<body>
<div class="login-card">
<div class="logo">NovaEx Admin</div>
<?php if($error): ?>
<div class="error"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label>管理员账号</label>
<input type="text" name="username" required placeholder="请输入账号">
</div>
<div class="form-group">
<label>登录密码</label>
<input type="password" name="password" required placeholder="请输入密码">
</div>
<button type="submit" class="btn-login">立即登录</button>
</form>
</div>
</body>
</html>

7
admin/logout.php Normal file
View File

@ -0,0 +1,7 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
session_destroy();
header("Location: login.php");
exit;

137
admin/options_orders.php Normal file
View File

@ -0,0 +1,137 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) {
$id = $_POST['id'];
$control = $_POST['control']; // 'none', 'win', 'loss'
$stmt = $pdo->prepare("UPDATE option_orders SET control = ? WHERE id = ? AND status = 'pending'");
$stmt->execute([$control, $id]);
header("Location: options_orders.php");
exit;
}
$orders = $pdo->query("SELECT o.*, u.username, u.win_loss_control as user_control FROM option_orders o JOIN users u ON o.user_id = u.id ORDER BY o.id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
$pending_kyc = $pdo->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>秒合约订单 - NovaEx 管理后台</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.card { background: white; border-radius: 12px; border: 1px solid var(--border); padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
.table { width: 100%; border-collapse: collapse; margin-top: 1.5rem; font-size: 0.85rem; }
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid var(--border); }
.table th { background: #f9fafb; color: #707a8a; font-weight: 600; text-transform: uppercase; }
.btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; border: 1px solid transparent; cursor: pointer; }
.control-active { border: 2px solid #000 !important; font-weight: bold; }
</style>
</head>
<body>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item"><i class="fas fa-user-shield"></i> 代理管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核
<?php if($pending_kyc > 0): ?><span class="badge"><?php echo $pending_kyc; ?></span><?php endif; ?>
</a>
<a href="chat.php" class="menu-item"><i class="fas fa-comments"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item active"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<h1>秒合约订单管理</h1>
<div class="card" style="margin-top: 20px;">
<table class="table">
<thead>
<tr>
<th>ID / 用户</th>
<th>交易对</th>
<th>方向</th>
<th>金额</th>
<th>周期</th>
<th>开仓价</th>
<th>状态</th>
<th>当前控制</th>
<th>时间</th>
<th>输赢干预</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $o): ?>
<tr>
<td>
<div style="font-weight: bold;"><?php echo $o['id']; ?></div>
<div style="font-size: 0.75rem; color: #707a8a;"><?php echo htmlspecialchars($o['username']); ?></div>
</td>
<td><?php echo $o['symbol']; ?></td>
<td><span style="color: <?php echo $o['direction'] == 'up' ? '#00c087' : '#f6465d'; ?>; font-weight: bold;"><?php echo $o['direction'] == 'up' ? '买涨 ↑' : '买跌 ↓'; ?></span></td>
<td style="font-weight: bold;"><?php echo number_format($o['amount'], 2); ?></td>
<td><?php echo $o['duration']; ?>s</td>
<td><?php echo number_format($o['opening_price'], 2); ?></td>
<td>
<span style="background: #eef2f7; padding: 3px 8px; border-radius: 4px; font-size: 0.75rem;">
<?php echo $o['status'] == 'pending' ? '进行中' : '已结算'; ?>
</span>
</td>
<td>
<?php
$ctrl = $o['control'];
if ($o['status'] == 'pending') {
if ($ctrl != 'none') {
echo "<span style='color: ".($ctrl == 'win' ? '#00c087' : '#f6465d')."; font-weight: bold;'>单控: ".($ctrl == 'win' ? '赢' : '亏')."</span>";
} else {
$uc = $o['user_control'];
echo "<span style='color: #848e9c;'>".($uc == 'none' ? '默认' : ($uc == 'win' ? '全控赢' : '全控亏'))."</span>";
}
} else {
echo "<span style='color: ".($o['result'] == 'win' ? '#00c087' : '#f6465d')."; font-weight: bold;'>".($o['result'] == 'win' ? '盈利' : '亏损')."</span>";
}
?>
</td>
<td style="font-size: 0.75rem; color: #848e9c;"><?php echo $o['created_at']; ?></td>
<td>
<?php if($o['status'] == 'pending'): ?>
<form method="POST" style="display: flex; gap: 5px;">
<input type="hidden" name="id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="control">
<button type="submit" name="control" value="win" class="btn-sm <?php echo $ctrl == 'win' ? 'control-active' : ''; ?>" style="background: #00c087; color: white;">控赢</button>
<button type="submit" name="control" value="loss" class="btn-sm <?php echo $ctrl == 'loss' ? 'control-active' : ''; ?>" style="background: #f6465d; color: white;">控亏</button>
<button type="submit" name="control" value="none" class="btn-sm <?php echo $ctrl == 'none' ? 'control-active' : ''; ?>" style="background: #eee; color: #333;">取消</button>
</form>
<?php else: ?>
<span style="color: #ccc;">已结单</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

181
admin/orders.php Normal file
View File

@ -0,0 +1,181 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
// Handle Actions
if (isset($_POST['action'])) {
$id = $_POST['order_id'];
$table = 'fiat_orders';
if ($_POST['action'] == 'match') {
$info = $_POST['account_info'];
$pdo->prepare("UPDATE $table SET status = 'matched', bank_account_info = ? WHERE id = ?")->execute([$info, $id]);
$orderStmt = $pdo->prepare("SELECT user_id FROM $table WHERE id = ?");
$orderStmt->execute([$id]);
$order = $orderStmt->fetch();
if ($order) {
$msg = "📢 您的充值订单 #$id 匹配成功.\n收款账户信息:\n$info\n请按要求完成转账并上传凭证。";
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
}
} elseif ($_POST['action'] == 'complete') {
$orderStmt = $pdo->prepare("SELECT user_id, amount, currency, usdt_amount FROM $table WHERE id = ?");
$orderStmt->execute([$id]);
$order = $orderStmt->fetch();
if ($order) {
$credit_amount = $order['usdt_amount'];
$pdo->beginTransaction();
try {
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$credit_amount, $order['user_id']]);
$pdo->prepare("UPDATE $table SET status = 'completed' WHERE id = ?")->execute([$id]);
// Update transaction status
$pdo->prepare("UPDATE transactions SET status = 'completed' WHERE user_id = ? AND type = 'deposit' AND description LIKE ?")->execute([$order['user_id'], "%#$id%"]);
$msg = "🎉 您的充值 " . $credit_amount . " USDT 已确认到账。";
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
}
}
} elseif ($_POST['action'] == 'reject') {
$pdo->prepare("UPDATE $table SET status = 'rejected' WHERE id = ?")->execute([$id]);
$orderStmt = $pdo->prepare("SELECT user_id FROM $table WHERE id = ?");
$orderStmt->execute([$id]);
$order = $orderStmt->fetch();
if ($order) {
// Update transaction status
$pdo->prepare("UPDATE transactions SET status = 'rejected' WHERE user_id = ? AND type = 'deposit' AND description LIKE ?")->execute([$order['user_id'], "%#$id%"]);
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], "❌ 您的充值申请 #$id 已被拒绝,请咨询客服。"]);
}
}
}
$all_deposits = $pdo->query("SELECT o.*, u.username, u.uid FROM fiat_orders o JOIN users u ON o.user_id = u.id WHERE o.order_type = 'deposit' ORDER BY o.id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders_count = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'paid')")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>充值管理 - NovaEx 管理后台</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid var(--border); font-size: 0.85rem; }
.status-badge { padding: 3px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: bold; }
.matching { background: rgba(255, 60, 0, 0.2); color: #ff3c00; border: 1px solid #ff3c00; }
.paid { background: rgba(0, 192, 135, 0.2); color: #00c087; border: 1px solid #00c087; }
.matched { background: rgba(55, 122, 255, 0.1); color: #377aff; }
.completed { background: rgba(0, 192, 135, 0.1); color: #00c087; opacity: 0.6; }
.rejected { background: rgba(246, 70, 93, 0.1); color: #f6465d; }
.btn-primary { background: var(--primary); color: black; border: none; padding: 8px 15px; border-radius: 6px; font-weight: bold; cursor: pointer; }
</style>
</head>
<body>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item"><i class="fas fa-user-shield"></i> 代理管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
<a href="chat.php" class="menu-item"><i class="fas fa-comments"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders_count > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders_count); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item active"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<h1>充值申请管理</h1>
<table class="table">
<thead>
<tr>
<th>ID</th><th>用户</th><th>币种</th><th>充值金额</th><th>换算 USDT</th><th>凭证</th><th>状态</th><th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach($all_deposits as $o):
?>
<tr>
<td>#<?php echo $o['id']; ?></td>
<td><?php echo htmlspecialchars($o['username']); ?> (UID: <?php echo $o['uid']; ?>)</td>
<td><span style="color: #007bff"><?php echo strtoupper($o['currency']); ?></span></td>
<td><b><?php echo number_format($o['amount'], 2); ?></b></td>
<td><b style="color: #00c087"><?php echo number_format($o['usdt_amount'], 2); ?></b></td>
<td>
<?php if($o['proof_image']):
?>
<a href="../<?php echo $o['proof_image']; ?>" target="_blank" style="color: #00c087; font-weight: bold;"><i class="fas fa-image"></i> 查看凭证</a>
<?php else:
?>
<span style="color: #555;">未上传</span>
<?php endif;
?>
</td>
<td><span class="status-badge <?php echo $o['status']; ?>">
<?php
if ($o['status'] === 'matching') echo '待受理';
elseif ($o['status'] === 'matched') echo '已分配账户';
elseif ($o['status'] === 'paid') echo '待审核凭证';
elseif ($o['status'] === 'completed') echo '已完成';
elseif ($o['status'] === 'rejected') echo '已拒绝';
else echo strtoupper($o['status']);
?>
</span></td>
<td>
<?php if($o['status'] == 'matching'):
?>
<form method="POST" style="display: flex; gap: 5px;">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="match">
<input type="text" name="account_info" placeholder="收款账户信息" required style="padding: 8px; border: 1px solid var(--border); border-radius: 4px;">
<button type="submit" class="btn-primary" style="background: #ff3c00; color: white;">分配账户</button>
</form>
<?php elseif($o['status'] == 'paid' || $o['status'] == 'matched'):
?>
<div style="display: flex; gap: 5px;">
<form method="POST">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="complete">
<button type="submit" class="btn-primary" style="background: #00c087; color: white;">确认入金</button>
</form>
<form method="POST">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="reject">
<button type="submit" class="btn-primary" style="background: #f6465d; color: white;">驳回</button>
</form>
</div>
<?php endif;
?>
</td>
</tr>
<?php endforeach;
?>
</tbody>
</table>
</div>
</div>
</body>
</html>

215
admin/settings.php Normal file
View File

@ -0,0 +1,215 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$db = db();
$admin_id = $_SESSION['admin_id'] ?? 1; // Fallback to 1 if not set, but auth.php should ensure it's set
$message = "";
$error = "";
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['settings'])) {
foreach ($_POST['settings'] as $name => $value) {
$stmt = $db->prepare("INSERT INTO settings (name, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?");
$stmt->execute([$name, $value, $value]);
}
$message = "系统设置已成功更新。";
}
if (isset($_POST['change_password'])) {
$old_pass = $_POST['old_password'];
$new_pass = $_POST['new_password'];
$confirm_pass = $_POST['confirm_password'];
$stmt = $db->prepare("SELECT password FROM admins WHERE id = ?");
$stmt->execute([$admin_id]);
$admin = $stmt->fetch();
if ($new_pass !== $confirm_pass) {
$error = "两次输入的新密码不一致。";
} elseif (!password_verify($old_pass, $admin['password'])) {
$error = "旧密码错误。";
} else {
$hashed = password_hash($new_pass, PASSWORD_DEFAULT);
$stmt = $db->prepare("UPDATE admins SET password = ? WHERE id = ?");
$stmt->execute([$hashed, $admin_id]);
$message = "管理密码已成功修改。";
}
}
if (isset($_FILES['logo']) && $_FILES['logo']['error'] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES['logo']['name'], PATHINFO_EXTENSION);
$filename = 'logo_' . time() . '.' . $ext;
$target = '../assets/images/' . $filename;
if (!is_dir('../assets/images')) {
mkdir('../assets/images', 0775, true);
}
if (move_uploaded_file($_FILES['logo']['tmp_name'], $target)) {
$logo_url = 'assets/images/' . $filename;
$stmt = $db->prepare("INSERT INTO settings (name, value) VALUES ('site_logo', ?) ON DUPLICATE KEY UPDATE value = ?");
$stmt->execute([$logo_url, $logo_url]);
$message = "LOGO 已成功上传。";
} else {
$error = "LOGO 上传失败。";
}
}
}
$settings_res = $db->query("SELECT * FROM settings")->fetchAll();
$settings = [];
foreach($settings_res as $s) $settings[$s['name']] = $s['value'];
$unread_msgs = $db->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $db->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>系统设置 - 管理后台</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; --card-bg: #f9fafb; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.card { background: white; border-radius: 12px; border: 1px solid var(--border); padding: 25px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); margin-bottom: 2rem; }
.form-group { margin-bottom: 20px; }
.form-group label { display: block; margin-bottom: 8px; font-weight: 600; color: #474d57; }
input[type="text"], input[type="number"], input[type="password"], select, textarea { width: 100%; padding: 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 1rem; outline: none; box-sizing: border-box; }
input:focus, textarea:focus { border-color: var(--primary); }
.btn { padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer; border: none; transition: 0.2s; }
.btn-primary { background: var(--primary); color: #000; }
.btn-primary:hover { opacity: 0.9; }
.logo-preview { max-width: 200px; max-height: 100px; margin-bottom: 15px; border: 1px solid var(--border); padding: 10px; border-radius: 8px; background: #f0f0f0; }
</style>
</head>
<body>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item"><i class="fas fa-user-shield"></i> 代理管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
<a href="chat.php" class="menu-item">
<i class="fas fa-comments"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item active"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<h1 style="margin-bottom: 30px;">系统设置</h1>
<?php if($message): ?>
<div style="background: #e6fcf5; color: #00c087; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 1px solid #00c087;"><i class="fas fa-check-circle"></i> <?php echo $message; ?></div>
<?php endif; ?>
<?php if($error): ?>
<div style="background: #fff5f5; color: #f6465d; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 1px solid #f6465d;"><i class="fas fa-exclamation-circle"></i> <?php echo $error; ?></div>
<?php endif; ?>
<div class="card">
<h3>修改登录密码</h3>
<form method="POST">
<input type="hidden" name="change_password" value="1">
<div class="form-group">
<label>当前密码</label>
<input type="password" name="old_password" required placeholder="请输入当前管理员密码">
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div class="form-group">
<label>新密码</label>
<input type="password" name="new_password" required placeholder="请输入新密码">
</div>
<div class="form-group">
<label>确认新密码</label>
<input type="password" name="confirm_password" required placeholder="请再次输入新密码">
</div>
</div>
<button type="submit" class="btn btn-primary">更新管理密码</button>
</form>
</div>
<div class="card">
<h3>站点配置 (LOGO / 图标)</h3>
<form method="POST" enctype="multipart/form-data">
<div class="form-group">
<label>当前 LOGO</label>
<?php if(isset($settings['site_logo'])): ?>
<img src="../<?php echo $settings['site_logo']; ?>" class="logo-preview" alt="Logo">
<?php else: ?>
<div class="logo-preview" style="display: flex; align-items: center; justify-content: center; color: #ccc;">未设置 LOGO</div>
<?php endif; ?>
<input type="file" name="logo" accept="image/*">
<p style="font-size: 0.8rem; color: #707a8a; margin-top: 5px;">建议尺寸: 200x60 像素。上传后将同步更新前端 LOGO 和网站图标。</p>
</div>
<button type="submit" class="btn btn-primary">上传并更新 LOGO</button>
</form>
</div>
<form method="POST">
<div class="card">
<h3>1. 交易与胜率控制</h3>
<div class="form-group">
<label>全局胜率控制 (%)</label>
<input type="number" name="settings[win_rate]" value="<?php echo $settings['win_rate'] ?? 70; ?>" min="0" max="100">
</div>
</div>
<div class="card">
<h3>2. 价格操纵控制</h3>
<div class="form-group">
<label>价格控制模式</label>
<select name="settings[price_control]">
<option value="0" <?php echo ($settings['price_control'] ?? '0') == '0' ? 'selected' : ''; ?>>实时行情 (API 自动同步)</option>
<option value="1" <?php echo ($settings['price_control'] ?? '0') == '1' ? 'selected' : ''; ?>>强制控价 (所有用户看到指定价格)</option>
</select>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div class="form-group">
<label>BTC 指定价格 ($)</label>
<input type="number" name="settings[manual_btc_price]" value="<?php echo $settings['manual_btc_price'] ?? 0; ?>" step="0.01">
</div>
<div class="form-group">
<label>BTC 插针价格 ($)</label>
<input type="number" name="settings[pin_btc_price]" value="<?php echo $settings['pin_btc_price'] ?? 0; ?>" step="0.01">
</div>
</div>
</div>
<div class="card">
<h3>3. 客服与公告</h3>
<div class="form-group">
<label>客服自动问候语</label>
<textarea name="settings[chat_greeting]" rows="3"><?php echo $settings['chat_greeting'] ?? '您好!欢迎咨询 NovaEx 官方客服。'; ?></textarea>
</div>
<div class="form-group">
<label>系统公告内容 (简体中文)</label>
<input type="text" name="settings[announcement_zh]" value="<?php echo $settings['announcement_zh'] ?? ''; ?>" placeholder="首页顶部公告...">
</div>
</div>
<div style="text-align: right;">
<button type="submit" class="btn btn-primary" style="font-size: 1.1rem; padding: 15px 60px;">保存所有系统设置</button>
</div>
</form>
</div>
</div>
</body>
</html>

152
admin/spot_orders.php Normal file
View File

@ -0,0 +1,152 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
if (isset($_POST['action']) && isset($_POST['order_id'])) {
$oid = $_POST['order_id'];
$action = $_POST['action'];
$orderStmt = $pdo->prepare("SELECT * FROM trading_orders WHERE id = ?");
$orderStmt->execute([$oid]);
$order = $orderStmt->fetch();
if ($order && $order['status'] == 'open') {
$user_id = $order['user_id'];
$symbol = $order['symbol'];
$coin_symbol = str_replace('USDT', '', $symbol);
if ($action == 'approve') {
// "WIN": Approve and settle
if ($order['side'] == 'buy') {
$stmt = $pdo->prepare("INSERT INTO user_assets (user_id, symbol, amount) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE amount = amount + ?");
$stmt->execute([$user_id, $coin_symbol, $order['amount'], $order['amount']]);
} else {
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['total'], $user_id]);
}
$pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved', win_loss = 'win' WHERE id = ?")->execute([$oid]);
} elseif ($action == 'reject') {
// "LOSS": Reject. No assets returned.
$pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected', win_loss = 'loss' WHERE id = ?")->execute([$oid]);
}
}
}
$orders = $pdo->query("SELECT o.*, u.username, u.uid FROM trading_orders o JOIN users u ON o.user_id = u.id WHERE o.type = 'spot' ORDER BY o.id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>现货交易管理 - NovaEx 管理后台</title>
<link rel="stylesheet" href="../assets/css/custom.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #FFFFFF; border-right: 1px solid #EAECEF; padding: 1rem; }
.main-content { flex: 1; padding: 2rem; background: #FFFFFF; color: #1E2329; }
.menu-item { padding: 12px; color: #474D57; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
.menu-item:hover, .menu-item.active { background: #F5F5F5; color: #F0B90B; }
.badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #EAECEF; font-size: 0.85rem; color: #1E2329; }
.btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; margin-right: 5px; }
.btn-approve { background: #00c087; color: white; }
.btn-reject { background: #f6465d; color: white; }
.back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
.status-badge { padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; }
.status-open { background: #fff3cd; color: #856404; }
.status-closed { background: #d4edda; color: #155724; }
.status-cancelled { background: #f8d7da; color: #721c24; }
</style>
</head>
<body style="background: white;">
<div class="admin-layout">
<div class="sidebar">
<h3 style="color: #1E2329; margin-bottom: 2rem;">NovaEx 管理员</h3>
<a href="index.php" class="menu-item"><i class="fas fa-chart-pie"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
<a href="chat.php" class="menu-item">
<i class="fas fa-headset"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item active"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
<h2 style="color: #1E2329;">现货交易管理 (后台控赢/)</h2>
<p style="color: #707A8A; font-size: 0.9rem;">提示:同意即为用户盈(得币/得USDT拒绝即为用户亏资产不退</p>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>用户</th>
<th>币对</th>
<th>方向</th>
<th>类型</th>
<th>价格</th>
<th>数量</th>
<th>总额</th>
<th>状态</th>
<th>结果</th>
<th>时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach($orders as $o): ?>
<tr>
<td><?php echo $o['id']; ?></td>
<td><?php echo htmlspecialchars($o['username']); ?> (<?php echo $o['uid']; ?>)</td>
<td><?php echo $o['symbol']; ?></td>
<td style="color: <?php echo $o['side'] == 'buy' ? '#00c087' : '#f6465d'; ?>">
<?php echo $o['side'] == 'buy' ? '买入' : '卖出'; ?>
</td>
<td><?php echo $o['order_type'] == 'market' ? '市价' : '限价'; ?></td>
<td><?php echo number_format($o['price'], 4); ?></td>
<td><?php echo number_format($o['amount'], 4); ?></td>
<td><?php echo number_format($o['total'], 4); ?> USDT</td>
<td>
<span class="status-badge status-<?php echo $o['status']; ?>">
<?php echo $o['status'] == 'open' ? '进行中' : ($o['status'] == 'closed' ? '已完成' : '已取消'); ?>
</span>
</td>
<td>
<?php if($o['win_loss'] == 'win'): ?>
<span style="color: #00c087;">盈利</span>
<?php elseif($o['win_loss'] == 'loss'): ?>
<span style="color: #f6465d;">亏损</span>
<?php else: ?>
--
<?php endif; ?>
</td>
<td><?php echo $o['created_at']; ?></td>
<td>
<?php if($o['status'] == 'open'): ?>
<form method="POST" style="display: inline;">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<button type="submit" name="action" value="approve" class="btn-sm btn-approve">控赢</button>
<button type="submit" name="action" value="reject" class="btn-sm btn-reject">控亏</button>
</form>
<?php else: ?>
--
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</body>
</html>

320
admin/users.php Normal file
View File

@ -0,0 +1,320 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
// Handle Actions
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) {
$action = $_POST['action'];
if ($action == 'add_user') {
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$uid = 618120 + $pdo->query("SELECT COUNT(*) FROM users")->fetchColumn() + mt_rand(1, 9);
$balance = $_POST['balance'] ?? 0;
$credit_score = $_POST['credit_score'] ?? 80;
$stmt = $pdo->prepare("INSERT INTO users (uid, username, password, balance, credit_score, status) VALUES (?, ?, ?, ?, ?, 'active')");
$stmt->execute([$uid, $username, $password, $balance, $credit_score]);
} elseif ($action == 'update_user') {
$id = $_POST['id'];
$username = $_POST['username'];
$new_balance = (float)$_POST['balance'];
$credit_score = $_POST['credit_score'];
$win_loss = $_POST['win_loss_control'];
$status = $_POST['status'];
// Fetch old balance to log if changed
$old_user = $pdo->prepare("SELECT balance FROM users WHERE id = ?");
$old_user->execute([$id]);
$old_balance = (float)$old_user->fetchColumn();
$sql = "UPDATE users SET username = ?, balance = ?, credit_score = ?, win_loss_control = ?, status = ? WHERE id = ?";
$params = [$username, $new_balance, $credit_score, $win_loss, $status, $id];
if (!empty($_POST['password'])) {
$sql = "UPDATE users SET username = ?, balance = ?, credit_score = ?, win_loss_control = ?, status = ?, password = ? WHERE id = ?";
$params = [$username, $new_balance, $credit_score, $win_loss, $status, password_hash($_POST['password'], PASSWORD_DEFAULT), $id];
}
$pdo->prepare($sql)->execute($params);
if ($new_balance != $old_balance) {
$diff = $new_balance - $old_balance;
$pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'admin_adjust', ?, 'USDT', 'completed', ?)")->execute([
$id, $diff, "管理员手动修改余额 (Balance adjusted by admin)"
]);
}
} elseif ($action == 'adjust_balance') {
$id = $_POST['id'];
$type = $_POST['adjustment_type'];
$amount = (float)$_POST['amount'];
if ($type == 'up') {
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$amount, $id]);
$pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'admin_adjust', ?, 'USDT', 'completed', ?)")->execute([
$id, $amount, "管理员增加余额 (Credit by admin)"
]);
} else {
$pdo->prepare("UPDATE users SET balance = balance - ? WHERE id = ?")->execute([$amount, $id]);
$pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'admin_adjust', ?, 'USDT', 'completed', ?)")->execute([
$id, -$amount, "管理员扣除余额 (Debit by admin)"
]);
}
} elseif ($action == 'toggle_status') {
$id = $_POST['id'];
$user = $pdo->prepare("SELECT status FROM users WHERE id = ?");
$user->execute([$id]);
$new_status = ($user->fetchColumn() == 'active' ? 'disabled' : 'active');
$pdo->prepare("UPDATE users SET status = ? WHERE id = ?")->execute([$new_status, $id]);
}
header("Location: users.php");
exit;
}
$users = $pdo->query("SELECT * FROM users ORDER BY id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
$pending_kyc = $pdo->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>用户管理 - NovaEx 管理后台</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.card { background: white; border-radius: 12px; border: 1px solid var(--border); padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
.table { width: 100%; border-collapse: collapse; margin-top: 1.5rem; }
.table th, .table td { padding: 15px; text-align: left; border-bottom: 1px solid var(--border); font-size: 0.9rem; }
.table th { background: #f9fafb; color: #707a8a; font-weight: 600; text-transform: uppercase; font-size: 0.75rem; }
.btn { padding: 8px 16px; border-radius: 6px; font-size: 0.85rem; border: none; cursor: pointer; font-weight: 500; transition: 0.2s; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
.btn-primary { background: var(--primary); color: black; }
.btn-danger { background: #f6465d; color: white; }
.btn-info { background: #2f80ed; color: white; }
.btn-success { background: #00c087; color: white; }
.status-badge { padding: 4px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: bold; }
.status-active { background: #e6fcf5; color: #00c087; }
.status-disabled { background: #fff5f5; color: #f6465d; }
.modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-content { background: white; width: 550px; padding: 30px; border-radius: 16px; box-shadow: 0 20px 40px rgba(0,0,0,0.2); }
.form-group { margin-bottom: 20px; }
.form-group label { display: block; margin-bottom: 8px; font-weight: 600; color: #474d57; }
.form-group input, .form-group select { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 1rem; outline: none; box-sizing: border-box; }
</style>
</head>
<body>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item active"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item"><i class="fas fa-user-shield"></i> 代理管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核
<?php if($pending_kyc > 0): ?><span class="badge"><?php echo $pending_kyc; ?></span><?php endif; ?>
</a>
<a href="chat.php" class="menu-item"><i class="fas fa-comments"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px;">
<h1>用户管理</h1>
<button class="btn btn-primary" onclick="showModal('addModal')"><i class="fas fa-user-plus"></i> 添加新用户</button>
</div>
<div class="card">
<table class="table">
<thead>
<tr>
<th>UID / 用户名</th>
<th>余额 (USDT)</th>
<th>信用分</th>
<th>输赢控制</th>
<th>状态</th>
<th>注册时间 / IP</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td>
<div style="font-weight: bold;"><?php echo $user['uid']; ?></div>
<div style="font-size: 0.8rem; color: #707a8a;"><?php echo htmlspecialchars($user['username']); ?></div>
</td>
<td><div style="color: #00c087; font-weight: bold;"><?php echo number_format($user['balance'], 2); ?></div></td>
<td><?php echo $user['credit_score']; ?></td>
<td>
<?php
$wc = $user['win_loss_control'];
$labels = ['none' => '正常', 'win' => '起盈', 'loss' => '起亏'];
$colors = ['none' => '#474d57', 'win' => '#00c087', 'loss' => '#f6465d'];
echo "<span style='color: {$colors[$wc]}; font-weight: bold;'>{$labels[$wc]}</span>";
?>
</td>
<td>
<span class="status-badge <?php echo $user['status'] == 'active' ? 'status-active' : 'status-disabled'; ?>">
<?php echo $user['status'] == 'active' ? '正常' : '已冻结'; ?>
</span>
</td>
<td>
<div style="font-size: 0.8rem;"><?php echo $user['created_at']; ?></div>
<div style="font-size: 0.75rem; color: #848e9c;"><?php echo $user['last_ip'] ?: '127.0.0.1'; ?></div>
</td>
<td>
<div style="display: flex; gap: 5px;">
<button class="btn btn-info btn-sm" onclick='editUser(<?php echo json_encode($user); ?>)'><i class="fas fa-edit"></i></button>
<button class="btn btn-success btn-sm" onclick="adjustBalance(<?php echo $user['id']; ?>, '<?php echo $user['username']; ?>')"><i class="fas fa-wallet"></i></button>
<form method="POST" style="display: inline;" onsubmit="return confirm('确定要执行此操作吗?')">
<input type="hidden" name="id" value="<?php echo $user['id']; ?>">
<input type="hidden" name="action" value="toggle_status">
<button type="submit" class="btn btn-info btn-sm" title="锁定/解锁"><i class="fas fa-ban"></i></button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add User Modal -->
<div id="addModal" class="modal">
<div class="modal-content">
<h2>添加新用户</h2>
<form method="POST">
<input type="hidden" name="action" value="add_user">
<div class="form-group">
<label>用户名</label>
<input type="text" name="username" required>
</div>
<div class="form-group">
<label>密码</label>
<input type="password" name="password" required>
</div>
<div class="form-group">
<label>初始余额</label>
<input type="number" name="balance" step="0.01" value="0.00">
</div>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px;">
<button type="button" class="btn" onclick="hideModal('addModal')" style="background: #eee;">取消</button>
<button type="submit" class="btn btn-primary">确定添加</button>
</div>
</form>
</div>
</div>
<!-- Edit User Modal -->
<div id="editModal" class="modal">
<div class="modal-content">
<h2>编辑用户信息</h2>
<form method="POST">
<input type="hidden" name="action" value="update_user">
<input type="hidden" name="id" id="edit-id">
<div class="form-group">
<label>用户名</label>
<input type="text" name="username" id="edit-username" required>
</div>
<div class="form-group">
<label>修改密码 (留空则不修改)</label>
<input type="password" name="password" placeholder="******">
</div>
<div class="form-row" style="display: flex; gap: 15px;">
<div class="form-group" style="flex: 1;">
<label>余额</label>
<input type="number" name="balance" id="edit-balance" step="0.01">
</div>
<div class="form-group" style="flex: 1;">
<label>信用分</label>
<input type="number" name="credit_score" id="edit-credit">
</div>
</div>
<div class="form-row" style="display: flex; gap: 15px;">
<div class="form-group" style="flex: 1;">
<label>输赢控制</label>
<select name="win_loss_control" id="edit-win-loss">
<option value="none">正常</option>
<option value="win">起盈</option>
<option value="loss">起亏</option>
</select>
</div>
<div class="form-group" style="flex: 1;">
<label>状态</label>
<select name="status" id="edit-status">
<option value="active">正常</option>
<option value="disabled">冻结</option>
</select>
</div>
</div>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px;">
<button type="button" class="btn" onclick="hideModal('editModal')" style="background: #eee;">取消</button>
<button type="submit" class="btn btn-primary">保存修改</button>
</div>
</form>
</div>
</div>
<!-- Adjust Balance Modal -->
<div id="balanceModal" class="modal">
<div class="modal-content">
<h2>资金调整 - <span id="adj-name"></span></h2>
<form method="POST">
<input type="hidden" name="action" value="adjust_balance">
<input type="hidden" name="id" id="adj-id">
<div class="form-group">
<label>调整类型</label>
<select name="adjustment_type">
<option value="up">增加余额 (+)</option>
<option value="down">减少余额 (-)</option>
</select>
</div>
<div class="form-group">
<label>调整金额 (USDT)</label>
<input type="number" name="amount" step="0.01" required placeholder="0.00">
</div>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px;">
<button type="button" class="btn" onclick="hideModal('balanceModal')" style="background: #eee;">取消</button>
<button type="submit" class="btn btn-success">确认调整</button>
</div>
</form>
</div>
</div>
<script>
function showModal(id) { document.getElementById(id).style.display = 'flex'; }
function hideModal(id) { document.getElementById(id).style.display = 'none'; }
function editUser(user) {
document.getElementById('edit-id').value = user.id;
document.getElementById('edit-username').value = user.username;
document.getElementById('edit-balance').value = user.balance;
document.getElementById('edit-credit').value = user.credit_score;
document.getElementById('edit-win-loss').value = user.win_loss_control;
document.getElementById('edit-status').value = user.status;
showModal('editModal');
}
function adjustBalance(id, name) {
document.getElementById('adj-id').value = id;
document.getElementById('adj-name').innerText = name;
showModal('balanceModal');
}
window.onclick = function(event) { if (event.target.className === 'modal') { event.target.style.display = "none"; } }
</script>
</body>
</html>

195
admin/withdrawals.php Normal file
View File

@ -0,0 +1,195 @@
<?php
require_once "auth.php";
require_once '../db/config.php';
$pdo = db();
$success_msg = "";
$error_msg = "";
// Handle Actions
if (isset($_POST['action'])) {
$id = $_POST['order_id'];
$table = 'fiat_orders';
if ($_POST['action'] == 'complete') {
$pdo->prepare("UPDATE $table SET status = 'completed' WHERE id = ?")->execute([$id]);
$orderStmt = $pdo->prepare("SELECT user_id, usdt_amount FROM $table WHERE id = ?");
$orderStmt->execute([$id]);
$order = $orderStmt->fetch();
if ($order) {
// Update transaction status
$pdo->prepare("UPDATE transactions SET status = 'completed' WHERE user_id = ? AND type = 'withdrawal' AND description LIKE ?")->execute([$order['user_id'], "%#$id%"]);
$msg = "🎉 您的提现 " . $order['usdt_amount'] . " USDT 已汇出,请查收。";
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
}
$success_msg = "确认成功,提现已处理。";
} elseif ($_POST['action'] == 'reject') {
$remark = !empty($_POST['remark']) ? $_POST['remark'] : '审核不通过';
$orderStmt = $pdo->prepare("SELECT user_id, usdt_amount FROM $table WHERE id = ?");
$orderStmt->execute([$id]);
$order = $orderStmt->fetch();
if ($order) {
$pdo->beginTransaction();
try {
// 退还余额
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['usdt_amount'], $order['user_id']]);
$pdo->prepare("UPDATE $table SET status = 'rejected' WHERE id = ?")->execute([$id]);
// 记录退还到交易记录
$pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'withdraw_return', ?, 'USDT', 'completed', ?)")->execute([
$order['user_id'], $order['usdt_amount'], "提现申请 #$id 被拒绝退回: $remark"
]);
// 更新原交易状态
$pdo->prepare("UPDATE transactions SET status = 'rejected' WHERE user_id = ? AND type = 'withdrawal' AND description LIKE ?")->execute([$order['user_id'], "%#$id%"]);
$msg = "❌ 您的提现申请 #$id 已被拒绝,资金已退回。原因: " . $remark;
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
$pdo->commit();
$success_msg = "已成功驳回提现申请。";
} catch (Exception $e) {
$pdo->rollBack();
$error_msg = "操作失败: " . $e->getMessage();
}
}
}
}
$withdrawals = $pdo->query("SELECT o.*, u.username, u.uid FROM fiat_orders o JOIN users u ON o.user_id = u.id WHERE o.order_type = 'withdrawal' ORDER BY o.id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders_count = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'paid')")->fetchColumn();
$pending_kyc = $pdo->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>提现管理 - NovaEx 管理员</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
.table th, .table td { padding: 15px; text-align: left; border-bottom: 1px solid var(--border); font-size: 0.9rem; }
.table th { background: #fafafa; color: #707a8a; font-weight: 600; }
.status-badge { padding: 4px 10px; border-radius: 6px; font-size: 0.75rem; font-weight: bold; }
.matching { background: rgba(255, 60, 0, 0.2); color: #ff3c00; border: 1px solid #ff3c00; }
.paid { background: rgba(0, 192, 135, 0.2); color: #00c087; border: 1px solid #00c087; }
.completed { background: #e6fff1; color: #03ad5d; }
.rejected { background: #fff1f0; color: #f6465d; }
.alert { padding: 15px; border-radius: 8px; margin-bottom: 20px; font-weight: bold; }
.alert-success { background: #e6fff1; color: #03ad5d; border: 1px solid #03ad5d; }
.alert-error { background: #fff1f0; color: #f6465d; border: 1px solid #f6465d; }
.btn { padding: 8px 15px; border: none; border-radius: 6px; cursor: pointer; font-size: 0.85rem; font-weight: 600; transition: 0.2s; }
.btn-success { background: #03ad5d; color: white; }
.btn-danger { background: #f6465d; color: white; }
.btn:hover { opacity: 0.9; }
input[type="text"] { padding: 8px; border: 1px solid var(--border); border-radius: 6px; font-size: 0.85rem; outline: none; width: 120px; }
</style>
</head>
<body>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item"><i class="fas fa-user-shield"></i> 代理管理</a>
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核
<?php if($pending_kyc > 0): ?><span class="badge"><?php echo $pending_kyc; ?></span><?php endif; ?>
</a>
<a href="chat.php" class="menu-item"><i class="fas fa-comments"></i> 客服管理
<?php if($unread_msgs > 0 || $pending_orders_count > 0): ?><span class="badge"><?php echo ($unread_msgs + $pending_orders_count); ?></span><?php endif; ?>
</a>
<a href="options_orders.php" class="menu-item"><i class="fas fa-clock"></i> 秒合约</a>
<a href="spot_orders.php" class="menu-item"><i class="fas fa-exchange-alt"></i> 现货交易</a>
<a href="futures_orders.php" class="menu-item"><i class="fas fa-file-contract"></i> 合约交易</a>
<a href="orders.php" class="menu-item"><i class="fas fa-wallet"></i> 充值记录</a>
<a href="withdrawals.php" class="menu-item active"><i class="fas fa-hand-holding-usd"></i> 提现记录</a>
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<h1>提现申请管理</h1>
<?php if($success_msg): ?>
<div class="alert alert-success"><i class="fas fa-check-circle"></i> <?php echo $success_msg; ?></div>
<?php endif; ?>
<?php if($error_msg): ?>
<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> <?php echo $error_msg; ?></div>
<?php endif; ?>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>用户</th>
<th>提现币种</th>
<th>金额</th>
<th>折算 USDT</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach($withdrawals as $o): ?>
<tr>
<td>#<?php echo $o['id']; ?></td>
<td><b><?php echo htmlspecialchars($o['username']); ?></b> (UID: <?php echo $o['uid']; ?>)</td>
<td><span style="color: #007bff; font-weight: bold;"><?php echo strtoupper($o['currency']); ?></span></td>
<td><?php echo number_format($o['amount'], 2); ?></td>
<td><b style="color: #00c087"><?php echo number_format($o['usdt_amount'], 2); ?></b></td>
<td><span class="status-badge <?php echo $o['status']; ?>">
<?php
if ($o['status'] === 'matching') echo '待受理';
elseif ($o['status'] === 'matched') echo '已下发模板';
elseif ($o['status'] === 'paid') echo '待处理出款';
elseif ($o['status'] === 'completed') echo '已完成';
elseif ($o['status'] === 'rejected') echo '已拒绝';
else echo strtoupper($o['status']);
?>
</span></td>
<td>
<?php if($o['status'] == 'paid' || $o['status'] == 'matched'): ?>
<div style="display: flex; gap: 8px;">
<form method="POST" style="margin: 0;">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="complete">
<button type="submit" class="btn btn-success" onclick="return confirm('确认已完成出款?')">确认完成</button>
</form>
<form method="POST" style="margin: 0; display: flex; gap: 3px;">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="reject">
<input type="text" name="remark" placeholder="驳回原因" required>
<button type="submit" class="btn btn-danger">驳回</button>
</form>
</div>
<?php else: ?>
--
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</body>
</html>

59
api-docs.php Normal file
View File

@ -0,0 +1,59 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 1200px; margin: 0 auto; display: grid; grid-template-columns: 280px 1fr; gap: 60px;">
<aside style="position: sticky; top: 100px; height: fit-content;">
<h4 style="margin-bottom: 25px; color: var(--primary-color);">API Documentation</h4>
<nav style="display: flex; flex-direction: column; gap: 15px; font-size: 0.95rem;">
<a href="#intro" style="color: white; text-decoration: none;">Introduction</a>
<a href="#auth" style="color: #848e9c; text-decoration: none;">Authentication</a>
<a href="#market" style="color: #848e9c; text-decoration: none;">Market Data</a>
<a href="#trading" style="color: #848e9c; text-decoration: none;">Trading Endpoints</a>
<a href="#account" style="color: #848e9c; text-decoration: none;">Account & Balance</a>
<a href="#errors" style="color: #848e9c; text-decoration: none;">Error Codes</a>
</nav>
</aside>
<section style="background: #161a1e; padding: 60px; border-radius: 32px; border: 1px solid #2b3139;">
<h1 id="intro" style="font-size: 2.5rem; margin-bottom: 30px;">NovaEx API v1</h1>
<p style="color: var(--text-muted); line-height: 1.8; margin-bottom: 40px;">Welcome to the NovaEx API. Our RESTful API allows you to access market data, manage your account, and execute trades programmatically. All responses are returned in JSON format.</p>
<div id="auth" style="margin-top: 60px;">
<h2 style="font-size: 1.8rem; margin-bottom: 20px;">Authentication</h2>
<p style="color: var(--text-muted); line-height: 1.8;">To access private endpoints, you must use your API Key and Secret. These are passed in the request headers:</p>
<div style="background: #0b0e11; padding: 20px; border-radius: 12px; font-family: 'Roboto Mono', monospace; font-size: 0.9rem; color: #00f2fe; margin: 20px 0; border: 1px solid #2b3139;">
X-NOVA-APIKEY: &lt;your_api_key&gt;<br>
X-NOVA-SIGNATURE: &lt;hmac_sha256_signature&gt;
</div>
</div>
<div id="market" style="margin-top: 60px;">
<h2 style="font-size: 1.8rem; margin-bottom: 20px;">Get Ticker</h2>
<p style="color: var(--text-muted); margin-bottom: 20px;">Returns 24h ticker price change statistics.</p>
<div style="background: #0b0e11; padding: 20px; border-radius: 12px; font-family: 'Roboto Mono', monospace; font-size: 0.9rem; margin: 20px 0; border: 1px solid #2b3139;">
<span style="color: #00c087;">GET</span> /api/v1/ticker/24hr?symbol=BTCUSDT
</div>
<h4 style="margin: 30px 0 15px;">Response Example</h4>
<div style="background: #0b0e11; padding: 20px; border-radius: 12px; font-family: 'Roboto Mono', monospace; font-size: 0.85rem; color: #848e9c; border: 1px solid #2b3139;">
{<br>
&nbsp;&nbsp;"symbol": "BTCUSDT",<br>
&nbsp;&nbsp;"priceChange": "105.15",<br>
&nbsp;&nbsp;"priceChangePercent": "0.162",<br>
&nbsp;&nbsp;"lastPrice": "65120.50",<br>
&nbsp;&nbsp;"volume": "12540.25"<br>
}
</div>
</div>
<div id="trading" style="margin-top: 60px;">
<h2 style="font-size: 1.8rem; margin-bottom: 20px;">New Order</h2>
<p style="color: var(--text-muted); margin-bottom: 20px;">Executes a new limit or market order.</p>
<div style="background: #0b0e11; padding: 20px; border-radius: 12px; font-family: 'Roboto Mono', monospace; font-size: 0.9rem; margin: 20px 0; border: 1px solid #2b3139;">
<span style="color: #f0b90b;">POST</span> /api/v1/order
</div>
</div>
</section>
</div>
</main>
<?php include 'footer.php'; ?>

64
api/cancel_order.php Normal file
View File

@ -0,0 +1,64 @@
<?php
session_start();
require_once '../db/config.php';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id'])) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
$user_id = $_SESSION['user_id'];
$data = json_decode(file_get_contents('php://input'), true);
$order_id = $data['order_id'] ?? null;
if (!$order_id) {
echo json_encode(['success' => false, 'error' => 'Invalid order ID']);
exit;
}
try {
$db = db();
$db->beginTransaction();
// Check if order exists and belongs to user and is open
$stmt = $db->prepare("SELECT * FROM trading_orders WHERE id = ? AND user_id = ? AND status = 'open' FOR UPDATE");
$stmt->execute([$order_id, $user_id]);
$order = $stmt->fetch();
if (!$order) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => '订单未找到或已处理']);
exit;
}
// Update status
$stmt = $db->prepare("UPDATE trading_orders SET status = 'cancelled' WHERE id = ?");
$stmt->execute([$order_id]);
if ($order['type'] === 'spot') {
if ($order['side'] === 'buy') {
// Refund USDT
$stmt = $db->prepare("UPDATE users SET balance = balance + ? WHERE id = ?");
$stmt->execute([$order['total'], $user_id]);
} else {
// Refund coins
$coin_symbol = str_replace('USDT', '', $order['symbol']);
$stmt = $db->prepare("INSERT INTO user_assets (user_id, symbol, amount) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE amount = amount + ?");
$stmt->execute([$user_id, $coin_symbol, $order['amount'], $order['amount']]);
}
} else {
// Futures: Refund margin
$margin = $order['total'] / $order['leverage'];
$stmt = $db->prepare("UPDATE users SET balance = balance + ? WHERE id = ?");
$stmt->execute([$margin, $user_id]);
}
$db->commit();
echo json_encode(['success' => true]);
} catch (Exception $e) {
if (isset($db)) $db->rollBack();
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}

22
api/check_order.php Normal file
View File

@ -0,0 +1,22 @@
<?php
require_once '../db/config.php';
session_start();
header('Content-Type: application/json');
if (!isset($_SESSION['user_id']) || !isset($_GET['id'])) {
echo json_encode(['error' => 'Unauthorized']);
exit;
}
$order_id = $_GET['id'];
$pdo = db();
$stmt = $pdo->prepare("SELECT status FROM orders WHERE id = ? AND user_id = ?");
$stmt->execute([$order_id, $_SESSION['user_id']]);
$order = $stmt->fetch();
if ($order) {
echo json_encode(['status' => $order['status']]);
} else {
echo json_encode(['error' => 'Not found']);
}

View File

@ -0,0 +1,24 @@
<?php
session_start();
require_once '../db/config.php';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id'])) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
$user_id = $_SESSION['user_id'];
$pdo = db();
// Check for active orders (including 'paid' which means waiting for admin approval)
$stmt = $pdo->prepare("SELECT id, order_type, status, bank_account_info FROM fiat_orders WHERE user_id = ? AND status IN ('matching', 'matched', 'paid') ORDER BY id DESC LIMIT 1");
$stmt->execute([$user_id]);
$order = $stmt->fetch();
if ($order) {
echo json_encode(['success' => true, 'order' => $order]);
} else {
echo json_encode(['success' => true, 'order' => null]);
}

39
api/get_assets.php Normal file
View File

@ -0,0 +1,39 @@
<?php
session_start();
require_once '../db/config.php';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id'])) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
$user_id = $_SESSION['user_id'];
try {
$db = db();
// Get USDT balance
$stmt = $db->prepare("SELECT balance FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$usdt = $stmt->fetchColumn();
// Get other assets
$stmt = $db->prepare("SELECT symbol, amount FROM user_assets WHERE user_id = ? AND amount > 0");
$stmt->execute([$user_id]);
$other_assets = $stmt->fetchAll(PDO::FETCH_ASSOC);
$assets = [['symbol' => 'USDT', 'amount' => (float)$usdt]];
foreach ($other_assets as $asset) {
$assets[] = [
'symbol' => $asset['symbol'],
'amount' => (float)$asset['amount']
];
}
echo json_encode(['success' => true, 'data' => $assets]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}

47
api/get_messages.php Normal file
View File

@ -0,0 +1,47 @@
<?php
session_start();
require_once '../db/config.php';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id']) && !isset($_GET['admin_key'])) {
// Basic protection, though admin usually has session
// For this project, admin session is also set in $_SESSION['user_id'] or checked by auth.php
}
$pdo = db();
// Action for admin notification count
if (isset($_GET['action']) && $_GET['action'] === 'count_unread') {
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'paid')")->fetchColumn();
echo json_encode(['total' => (int)($unread_msgs + $pending_orders)]);
exit;
}
// Mark messages as read
if (isset($_GET['action']) && $_GET['action'] === 'mark_read' && isset($_GET['user_id'])) {
$u_id = $_GET['user_id'];
$sender_type = isset($_GET['reader']) && $_GET['reader'] === 'admin' ? 'user' : 'admin';
$pdo->prepare("UPDATE messages SET is_read = 1 WHERE user_id = ? AND sender = ?")->execute([$u_id, $sender_type]);
echo json_encode(['success' => true]);
exit;
}
// Support both regular user and admin polling for specific user
$user_id = isset($_GET['user_id']) ? $_GET['user_id'] : ($_SESSION['user_id'] ?? null);
if (!$user_id) {
echo json_encode(['success' => false, 'error' => 'No user_id']);
exit;
}
// Default action: return last 50 messages in ASC order
$stmt = $pdo->prepare("SELECT * FROM (SELECT * FROM messages WHERE user_id = ? ORDER BY id DESC LIMIT 50) AS sub ORDER BY id ASC");
$stmt->execute([$user_id]);
$msgs = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode([
'success' => true,
'data' => $msgs
]);

86
api/get_option_orders.php Normal file
View File

@ -0,0 +1,86 @@
<?php
header('Content-Type: application/json');
require_once '../db/config.php';
session_start();
if (!isset($_SESSION['user_id'])) {
echo json_encode([]); // Return empty array if not logged in
exit;
}
$user_id = $_SESSION['user_id'];
$status_filter = $_GET['status'] ?? 'pending';
if (!in_array($status_filter, ['pending', 'completed'])) {
$status_filter = 'pending';
}
$pdo = db();
// --- Settlement Logic for Due Orders ---
try {
$now = date('Y-m-d H:i:s');
// Fetch orders that are pending and due for settlement
$stmt = $pdo->prepare(
"SELECT o.*, u.win_loss_control FROM option_orders o " .
"JOIN users u ON o.user_id = u.id " .
"WHERE o.status = 'pending' AND o.settle_at <= ?"
);
$stmt->execute([$now]);
$due_orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (count($due_orders) > 0) {
$pdo->beginTransaction();
foreach ($due_orders as $order) {
$result = 'loss';
$final_control = $order['win_loss_control'];
if ($final_control == 'win') {
$result = 'win';
} elseif ($final_control == 'loss') {
$result = 'loss';
} else {
$result = (rand(0, 100) < 51) ? 'loss' : 'win';
}
$profit = 0;
if ($result === 'win') {
$profit = $order['amount'] * $order['profit_rate'];
$total_return = $order['amount'] + $profit;
$bal_stmt = $pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?");
$bal_stmt->execute([$total_return, $order['user_id']]);
} else {
$profit = -$order['amount'];
}
$price_variation = (float)($order['opening_price'] * 0.0001 * rand(1, 5));
if (($order['direction'] === 'up' && $result === 'win') || ($order['direction'] === 'down' && $result === 'loss')) {
$closing_price = $order['opening_price'] + $price_variation;
} else {
$closing_price = $order['opening_price'] - $price_variation;
}
$update_stmt = $pdo->prepare(
"UPDATE option_orders SET status = 'completed', result = ?, profit = ?, closing_price = ? WHERE id = ?"
);
$update_stmt->execute([$result, $profit, $closing_price, $order['id']]);
}
$pdo->commit();
}
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
error_log("Option settlement failed: " . $e->getMessage());
}
// --- Fetch and Return Orders for Frontend ---
$stmt = $pdo->prepare("SELECT * FROM option_orders WHERE user_id = ? AND status = ? ORDER BY created_at DESC LIMIT 50");
$stmt->execute([$user_id, $status_filter]);
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($orders);
?>

38
api/get_orders.php Normal file
View File

@ -0,0 +1,38 @@
<?php
session_start();
require_once '../db/config.php';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id'])) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
$user_id = $_SESSION['user_id'];
$type = $_GET['type'] ?? 'spot';
$status = $_GET['status'] ?? 'open'; // open, positions, history, trades, tpsl
try {
$db = db();
if ($status === 'open' || $status === 'positions') {
$stmt = $db->prepare("SELECT * FROM trading_orders WHERE user_id = ? AND type = ? AND status = 'open' ORDER BY created_at DESC");
$stmt->execute([$user_id, $type]);
} elseif ($status === 'tpsl') {
$stmt = $db->prepare("SELECT * FROM trading_orders WHERE user_id = ? AND type = ? AND status = 'open' AND (tp_price IS NOT NULL OR sl_price IS NOT NULL) ORDER BY created_at DESC");
$stmt->execute([$user_id, $type]);
} elseif ($status === 'history') {
$stmt = $db->prepare("SELECT * FROM trading_orders WHERE user_id = ? AND type = ? AND status IN ('closed', 'cancelled', 'completed') ORDER BY created_at DESC");
$stmt->execute([$user_id, $type]);
} else { // trades
$stmt = $db->prepare("SELECT * FROM trading_orders WHERE user_id = ? AND type = ? AND status IN ('closed', 'completed') ORDER BY created_at DESC");
$stmt->execute([$user_id, $type]);
}
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'data' => $orders]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}

30
api/get_transactions.php Normal file
View File

@ -0,0 +1,30 @@
<?php
session_start();
require_once '../db/config.php';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id'])) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
$user_id = $_SESSION['user_id'];
try {
$db = db();
// Fetch from transactions table
$stmt = $db->prepare("SELECT * FROM transactions WHERE user_id = ? ORDER BY created_at DESC");
$stmt->execute([$user_id]);
$transactions = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Also fetch from orders (withdrawals/deposits) if they are not yet in transactions (for compatibility)
// Actually, I just added transactions logging to withdraw, so new ones will be there.
// For deposits, I should check if they are logged.
echo json_encode(['success' => true, 'data' => $transactions]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}

127
api/place_option_order.php Normal file
View File

@ -0,0 +1,127 @@
<?php
header('Content-Type: application/json');
require_once '../db/config.php';
session_start();
if (!isset($_SESSION['user_id'])) {
echo json_encode(['success' => false, 'error' => 'User not logged in']);
exit;
}
$user_id = $_SESSION['user_id'];
$data = json_decode(file_get_contents('php://input'), true);
// --- Input Validation ---
$pair = $data['pair'] ?? null;
$amount = (float)($data['amount'] ?? 0);
$direction = $data['direction'] ?? null;
$duration = (int)($data['duration'] ?? 0);
$rate = (float)($data['rate'] ?? 0); // Profit rate in percentage
$frontend_price = isset($data['price']) ? (float)$data['price'] : null;
if (empty($pair) || empty($direction) || $amount <= 0 || $duration <= 0 || $rate <= 0) {
echo json_encode(['success' => false, 'error' => 'Invalid order parameters.']);
exit;
}
// --- Server-Side Rules Validation ---
$valid_options = [
60 => ['rate' => 8, 'min' => 100],
90 => ['rate' => 12, 'min' => 5000],
120 => ['rate' => 15, 'min' => 30000],
180 => ['rate' => 20, 'min' => 100000],
300 => ['rate' => 32, 'min' => 300000],
];
if (!isset($valid_options[$duration]) || $valid_options[$duration]['rate'] != $rate) {
echo json_encode(['success' => false, 'error' => 'Invalid duration or profit rate selected.']);
exit;
}
$min_amount = $valid_options[$duration]['min'];
if ($amount < $min_amount) {
echo json_encode(['success' => false, 'error' => "Minimum amount for {$duration}s is {$min_amount} USDT."]);
exit;
}
// --- Securely Fetch Current Price from Binance API ---
function get_current_price($symbol) {
$url = "https://api.binance.com/api/v3/ticker/price?symbol=" . urlencode($symbol);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$response = curl_exec($ch);
curl_close($ch);
if ($response) {
$data = json_decode($response, true);
if (isset($data['price'])) {
return (float)$data['price'];
}
}
return null;
}
$open_price = get_current_price($pair);
// Fallback to frontend price if server fetch fails
if ($open_price === null) {
if ($frontend_price !== null && $frontend_price > 0) {
$open_price = $frontend_price;
} else {
echo json_encode(['success' => false, 'error' => 'Could not fetch current price for the pair. Please try again.']);
exit;
}
}
// --- Database Transaction ---
$pdo = db();
$pdo->beginTransaction();
try {
// 1. Lock user row and check balance
$stmt = $pdo->prepare("SELECT balance FROM users WHERE id = ? FOR UPDATE");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
if (!$user || $user['balance'] < $amount) {
$pdo->rollBack();
echo json_encode(['success' => false, 'error' => 'Insufficient balance.']);
exit;
}
// 2. Deduct balance
$new_balance = $user['balance'] - $amount;
$stmt = $pdo->prepare("UPDATE users SET balance = ? WHERE id = ?");
$stmt->execute([$new_balance, $user_id]);
// 3. Insert the new option order
$start_time = date('Y-m-d H:i:s');
$settle_at = date('Y-m-d H:i:s', time() + $duration);
$profit_rate_decimal = $rate / 100;
$stmt = $pdo->prepare(
"INSERT INTO option_orders (user_id, symbol, amount, direction, duration, profit_rate, opening_price, status, created_at, settle_at) " .
"VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?)"
);
$stmt->execute([$user_id, $pair, $amount, $direction, $duration, $profit_rate_decimal, $open_price, $start_time, $settle_at]);
$order_id = $pdo->lastInsertId();
// 4. Commit the transaction
$pdo->commit();
// 5. Fetch the created order to return to the frontend
$stmt = $pdo->prepare("SELECT * FROM option_orders WHERE id = ?");
$stmt->execute([$order_id]);
$new_order = $stmt->fetch(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'order' => $new_order]);
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
error_log("Option order failed: " . $e->getMessage());
echo json_encode(['success' => false, 'error' => 'An internal error occurred.']);
}
?>

95
api/place_order.php Normal file
View File

@ -0,0 +1,95 @@
<?php
session_start();
require_once '../db/config.php';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id'])) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
$user_id = $_SESSION['user_id'];
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) {
echo json_encode(['success' => false, 'error' => 'Invalid data']);
exit;
}
$symbol = $data['symbol']; // e.g., BTCUSDT
$type = $data['type']; // spot or futures
$side = $data['side']; // buy or sell
$order_type = $data['order_type']; // limit or market
$price = (float)$data['price'];
$amount = (float)$data['amount'];
$total = (float)$data['total'];
$leverage = (int)($data['leverage'] ?? 1);
$tp_price = isset($data['tp_price']) ? (float)$data['tp_price'] : null;
$sl_price = isset($data['sl_price']) ? (float)$data['sl_price'] : null;
try {
$db = db();
$db->beginTransaction();
if ($type === 'spot') {
if ($side === 'buy') {
// Check USDT balance
$stmt = $db->prepare("SELECT balance FROM users WHERE id = ? FOR UPDATE");
$stmt->execute([$user_id]);
$balance = (float)$stmt->fetchColumn();
if ($balance < $total) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => '余额不足 (USDT)']);
exit;
}
// Deduct USDT
$stmt = $db->prepare("UPDATE users SET balance = balance - ? WHERE id = ?");
$stmt->execute([$total, $user_id]);
} else {
// Spot Sell: Check coin balance
$coin_symbol = str_replace('USDT', '', $symbol);
$stmt = $db->prepare("SELECT amount FROM user_assets WHERE user_id = ? AND symbol = ? FOR UPDATE");
$stmt->execute([$user_id, $coin_symbol]);
$asset_amount = (float)$stmt->fetchColumn();
if ($asset_amount < $amount) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => '资产余额不足 (' . $coin_symbol . ')']);
exit;
}
// Deduct coin
$stmt = $db->prepare("UPDATE user_assets SET amount = amount - ? WHERE user_id = ? AND symbol = ?");
$stmt->execute([$amount, $user_id, $coin_symbol]);
}
} else {
// Futures: Deduct margin (USDT)
$margin = $total / $leverage;
$stmt = $db->prepare("SELECT balance FROM users WHERE id = ? FOR UPDATE");
$stmt->execute([$user_id]);
$balance = (float)$stmt->fetchColumn();
if ($balance < $margin) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => '余额不足 (USDT)']);
exit;
}
$stmt = $db->prepare("UPDATE users SET balance = balance - ? WHERE id = ?");
$stmt->execute([$margin, $user_id]);
}
// Insert order
$stmt = $db->prepare("INSERT INTO trading_orders (user_id, symbol, type, side, order_type, price, amount, total, leverage, tp_price, sl_price, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'open')");
$stmt->execute([$user_id, $symbol, $type, $side, $order_type, $price, $amount, $total, $leverage, $tp_price, $sl_price]);
$db->commit();
echo json_encode(['success' => true]);
} catch (Exception $e) {
if (isset($db)) $db->rollBack();
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}

80
api/upload_chat_image.php Normal file
View File

@ -0,0 +1,80 @@
<?php
require_once '../db/config.php';
session_start();
header('Content-Type: application/json');
// Check authorization - either user session or admin session
// For simplicity in this environment, we assume if it's called from admin it might have different session or we check params
// But usually admin also has session_start() and auth.php
$pdo = db();
$sender = isset($_GET['sender']) && $_GET['sender'] === 'admin' ? 'admin' : 'user';
$user_id = isset($_GET['user_id']) ? $_GET['user_id'] : ($_SESSION['user_id'] ?? null);
if (!$user_id) {
echo json_encode(['success' => false, 'error' => 'Unauthorized or missing User ID']);
exit;
}
// Handle Confirm Payment action (User only)
if (isset($_GET['action']) && $_GET['action'] === 'confirm_payment' && $sender === 'user') {
$stmt = $pdo->prepare("SELECT id FROM fiat_orders WHERE user_id = ? AND status = 'matched' ORDER BY id DESC LIMIT 1");
$stmt->execute([$user_id]);
$order = $stmt->fetch();
if (!$order) {
echo json_encode(['success' => false, 'error' => '没有待确认的订单']);
exit;
}
$stmt = $pdo->prepare("UPDATE fiat_orders SET status = 'submitting' WHERE id = ?");
$stmt->execute([$order['id']]);
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', '我已完成支付,请查收凭证。')")->execute([$user_id]);
echo json_encode(['success' => true]);
exit;
}
if (!isset($_FILES['image'])) {
echo json_encode(['success' => false, 'error' => 'No image uploaded']);
exit;
}
$file = $_FILES['image'];
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$allowed = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($ext, $allowed)) {
echo json_encode(['success' => false, 'error' => 'Invalid file type']);
exit;
}
$filename = 'chat_' . ($sender === 'admin' ? 'admin_' : '') . $user_id . '_' . time() . '_' . mt_rand(1000, 9999) . '.' . $ext;
$dir = '../assets/images/chat/';
if (!is_dir($dir)) mkdir($dir, 0775, true);
$target = $dir . $filename;
if (move_uploaded_file($file['tmp_name'], $target)) {
$path = 'assets/images/chat/' . $filename;
$stmt = $pdo->prepare("INSERT INTO messages (user_id, sender, type, message) VALUES (?, ?, 'image', ?)");
$stmt->execute([$user_id, $sender, $path]);
// If it's a user uploading, also update active order proof
if ($sender === 'user') {
$stmt = $pdo->prepare("SELECT id FROM fiat_orders WHERE user_id = ? AND status IN ('matched', 'matching', 'submitting') ORDER BY id DESC LIMIT 1");
$stmt->execute([$user_id]);
$order = $stmt->fetch();
if ($order) {
$stmt = $pdo->prepare("UPDATE fiat_orders SET proof_image = ? WHERE id = ?");
$stmt->execute([$path, $order['id']]);
}
}
echo json_encode(['success' => true, 'path' => $path]);
} else {
echo json_encode(['success' => false, 'error' => 'Failed to save image']);
}

366
app.php Normal file
View File

@ -0,0 +1,366 @@
<?php
require_once 'header.php';
?>
<div class="app-page-container">
<div class="app-hero">
<div class="app-hero-content">
<h1 class="app-title"><?php echo __('app_hero_title', 'NovaEx App'); ?></h1>
<p class="app-subtitle"><?php echo __('app_hero_subtitle', 'Trade anywhere, anytime. The world\'s leading crypto exchange is in your pocket.'); ?></p>
<!-- Mobile Buttons (Visible only on mobile) -->
<div class="mobile-download-buttons">
<a href="#" class="btn-app-download">
<i class="fab fa-apple"></i>
<span>App Store</span>
</a>
<a href="#" class="btn-app-download">
<i class="fab fa-google-play"></i>
<span>Google Play</span>
</a>
<a href="#" class="btn-app-download">
<i class="fas fa-android"></i>
<span>Android APK</span>
</a>
</div>
<!-- Desktop QR Section (Visible only on desktop) -->
<div class="desktop-qr-section">
<div class="qr-container">
<img src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=https://novaex.com/app" alt="QR Code">
</div>
<div class="qr-text">
<p style="font-weight: bold; font-size: 1.1rem; margin-bottom: 5px;"><?php echo __('scan_to_download', 'Scan to Download'); ?></p>
<p style="color: var(--text-muted); font-size: 0.9rem;"><?php echo __('ios_android_support', 'iOS & Android support'); ?></p>
</div>
</div>
</div>
<div class="app-hero-image">
<!-- Mockup image of a phone -->
<div class="phone-mockup">
<div class="phone-screen">
<div class="app-mockup-content">
<div class="app-mockup-header">
<div class="logo-text" style="font-size: 1.2rem;">NovaEx</div>
<i class="fas fa-user-circle"></i>
</div>
<div class="app-mockup-balance">
<p style="color: #848e9c; font-size: 0.8rem;">Total Balance</p>
<h3>$ 48,250.42</h3>
</div>
<div class="app-mockup-actions">
<div class="action-item"><i class="fas fa-plus-circle"></i><span>Deposit</span></div>
<div class="action-item"><i class="fas fa-arrow-circle-up"></i><span>Withdraw</span></div>
<div class="action-item"><i class="fas fa-exchange-alt"></i><span>Transfer</span></div>
</div>
<div class="app-mockup-list">
<div class="list-item">
<div style="display:flex; align-items:center; gap:10px;">
<div class="coin-icon" style="background: #f3ba2f;">B</div>
<div>BTC</div>
</div>
<div style="text-align:right;">
<div>$ 43,251.20</div>
<div style="color: #00c087;">+2.45%</div>
</div>
</div>
<div class="list-item">
<div style="display:flex; align-items:center; gap:10px;">
<div class="coin-icon" style="background: #627eea;">E</div>
<div>ETH</div>
</div>
<div style="text-align:right;">
<div>$ 2,541.10</div>
<div style="color: #f6465d;">-0.15%</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="app-features">
<div class="feature-card">
<i class="fas fa-bolt"></i>
<h4><?php echo __('feature_fast', 'Fast & Reliable'); ?></h4>
<p><?php echo __('feature_fast_desc', 'High-speed matching engine for lightning-fast trades.'); ?></p>
</div>
<div class="feature-card">
<i class="fas fa-shield-alt"></i>
<h4><?php echo __('feature_secure', 'Bank-Grade Security'); ?></h4>
<p><?php echo __('feature_secure_desc', 'Advanced encryption and multi-sig wallets to protect your funds.'); ?></p>
</div>
<div class="feature-card">
<i class="fas fa-headset"></i>
<h4><?php echo __('feature_support', '24/7 Support'); ?></h4>
<p><?php echo __('feature_support_desc', 'Our dedicated support team is always here to help you.'); ?></p>
</div>
</div>
</div>
<style>
.app-page-container {
min-height: 100vh;
background: radial-gradient(circle at top right, #1e2329 0%, #0b0e11 100%);
color: white;
padding: 100px 5% 50px;
}
.app-hero {
display: flex;
align-items: center;
justify-content: space-between;
max-width: 1200px;
margin: 0 auto;
gap: 50px;
}
.app-hero-content {
flex: 1;
}
.app-title {
font-size: 4rem;
font-weight: 800;
margin-bottom: 20px;
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.app-subtitle {
font-size: 1.5rem;
color: #848e9c;
margin-bottom: 40px;
line-height: 1.4;
}
/* Mobile buttons */
.mobile-download-buttons {
display: none;
flex-direction: column;
gap: 15px;
}
.btn-app-download {
background: #2b3139;
color: white;
padding: 15px 25px;
border-radius: 12px;
text-decoration: none;
display: flex;
align-items: center;
gap: 15px;
font-size: 1.1rem;
font-weight: 600;
transition: all 0.3s ease;
border: 1px solid transparent;
}
.btn-app-download:hover {
background: #1e2329;
border-color: #4facfe;
transform: translateY(-2px);
}
.btn-app-download i {
font-size: 1.5rem;
color: #4facfe;
}
/* Desktop QR */
.desktop-qr-section {
display: flex;
align-items: center;
gap: 20px;
background: rgba(255,255,255,0.05);
padding: 20px;
border-radius: 16px;
border: 1px solid rgba(255,255,255,0.1);
width: fit-content;
}
.qr-container {
background: white;
padding: 10px;
border-radius: 10px;
}
.qr-container img {
display: block;
}
/* Phone Mockup */
.app-hero-image {
flex: 1;
display: flex;
justify-content: center;
}
.phone-mockup {
width: 320px;
height: 640px;
background: #000;
border-radius: 40px;
border: 12px solid #2b3139;
position: relative;
box-shadow: 0 50px 100px rgba(0,0,0,0.5);
}
.phone-mockup::before {
content: '';
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 150px;
height: 25px;
background: #2b3139;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
z-index: 2;
}
.phone-screen {
width: 100%;
height: 100%;
background: #0b0e11;
border-radius: 28px;
overflow: hidden;
padding: 40px 15px 20px;
}
.app-mockup-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
}
.app-mockup-balance {
margin-bottom: 30px;
}
.app-mockup-actions {
display: flex;
justify-content: space-around;
margin-bottom: 40px;
}
.action-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
font-size: 0.7rem;
color: #848e9c;
}
.action-item i {
font-size: 1.2rem;
color: #4facfe;
}
.app-mockup-list {
display: flex;
flex-direction: column;
gap: 20px;
}
.list-item {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.85rem;
}
.coin-icon {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
}
/* Features */
.app-features {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
max-width: 1200px;
margin: 100px auto 0;
}
.feature-card {
background: rgba(255,255,255,0.03);
padding: 40px;
border-radius: 24px;
text-align: center;
transition: all 0.3s ease;
border: 1px solid rgba(255,255,255,0.05);
}
.feature-card:hover {
background: rgba(255,255,255,0.05);
transform: translateY(-10px);
border-color: rgba(79, 172, 254, 0.3);
}
.feature-card i {
font-size: 2.5rem;
color: #4facfe;
margin-bottom: 20px;
}
.feature-card h4 {
font-size: 1.3rem;
margin-bottom: 15px;
}
.feature-card p {
color: #848e9c;
font-size: 0.95rem;
line-height: 1.5;
}
/* Responsive */
@media (max-width: 992px) {
.app-hero {
flex-direction: column;
text-align: center;
}
.app-hero-content {
display: flex;
flex-direction: column;
align-items: center;
}
.desktop-qr-section {
display: none;
}
.mobile-download-buttons {
display: flex;
width: 100%;
max-width: 300px;
}
.app-title {
font-size: 3rem;
}
.app-features {
grid-template-columns: 1fr;
}
}
</style>
<?php
require_once 'footer.php';
?>

View File

@ -1,346 +1,270 @@
* { box-sizing: border-box; }
:root {
--color-bg: #ffffff;
--color-text: #1a1a1a;
--color-primary: #2563EB; /* Vibrant Blue */
--color-secondary: #000000;
--color-accent: #A3E635; /* Lime Green */
--color-surface: #f8f9fa;
--font-heading: 'Space Grotesk', sans-serif;
--font-body: 'Inter', sans-serif;
--border-width: 2px;
--shadow-hard: 5px 5px 0px #000;
--shadow-hover: 8px 8px 0px #000;
--radius-pill: 50rem;
--radius-card: 1rem;
--bg-color: #0B0E11;
--nav-bg: #0B0E11;
--primary-color: #0052FF;
--text-color: #FFFFFF;
--text-muted: #848E9C;
--border-color: #2B3139;
--card-bg: #1E2329;
--danger-color: #F6465D;
--success-color: #0ECB81;
--gold-color: #F0B90B;
}
body {
font-family: var(--font-body);
background-color: var(--color-bg);
color: var(--color-text);
margin: 0;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
line-height: 1.5;
padding-bottom: 0;
overflow-x: hidden;
}
h1, h2, h3, h4, h5, h6, .navbar-brand {
font-family: var(--font-heading);
letter-spacing: -0.03em;
}
/* Scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--bg-color); }
::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
::-webkit-scrollbar-thumb:hover { background: #3b4149; }
/* Utilities */
.text-primary { color: var(--color-primary) !important; }
.bg-black { background-color: #000 !important; }
.text-white { color: #fff !important; }
.shadow-hard { box-shadow: var(--shadow-hard); }
.border-2-black { border: var(--border-width) solid #000; }
.py-section { padding-top: 5rem; padding-bottom: 5rem; }
/* Navbar */
.navbar {
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
border-bottom: var(--border-width) solid transparent;
transition: all 0.3s;
padding-top: 1rem;
padding-bottom: 1rem;
background-color: var(--nav-bg);
padding: 0 1.5rem;
height: 64px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border-color);
position: sticky;
top: 0;
z-index: 1000;
}
.navbar.scrolled {
border-bottom-color: #000;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
.nav-links {
display: flex;
gap: 1.5rem;
align-items: center;
}
.brand-text {
font-size: 1.5rem;
font-weight: 800;
.nav-links a {
color: var(--text-color);
text-decoration: none;
font-size: 14px;
font-weight: 600;
transition: color 0.2s;
display: flex;
align-items: center;
}
.nav-link {
font-weight: 500;
color: var(--color-text);
margin-left: 1rem;
.nav-links a:hover {
color: var(--primary-color);
}
/* Utility Classes */
.d-none { display: none !important; }
.d-flex { display: flex !important; }
.d-block { display: block !important; }
@media (max-width: 767px) {
.d-sm-none { display: none !important; }
}
@media (max-width: 991px) {
.d-md-none { display: none !important; }
}
@media (min-width: 768px) {
.d-md-block { display: block !important; }
.d-md-flex { display: flex !important; }
}
@media (min-width: 992px) {
.d-lg-block { display: block !important; }
.d-lg-flex { display: flex !important; }
}
@media (min-width: 1200px) {
.d-xl-flex { display: flex !important; }
}
/* Colorful Icons */
.fa-home { color: #5d5dff; }
.fa-chart-line { color: #00e676; }
.fa-coins { color: #ffd600; }
.fa-file-contract { color: #ff3d00; }
.fa-bolt { color: #fbc02d; }
.fa-hammer { color: #8e24aa !important; }
.fa-wallet { color: #03a9f4; }
.fa-clock { color: #fbc02d; }
.fa-mobile-alt { color: #4facfe; }
.fa-exchange-alt { color: #00e676; }
.dropdown {
position: relative;
display: inline-block;
}
.nav-link:hover, .nav-link.active {
color: var(--color-primary);
.dropdown-content {
display: none;
position: absolute;
background-color: #1E2329;
min-width: 180px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.5);
z-index: 1002;
border: 1px solid var(--border-color);
border-radius: 8px;
top: 100%;
}
/* Buttons */
.btn {
font-weight: 700;
font-family: var(--font-heading);
padding: 0.8rem 2rem;
border-radius: var(--radius-pill);
border: var(--border-width) solid #000;
transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1);
box-shadow: var(--shadow-hard);
.dropdown:hover .dropdown-content {
display: block;
}
.btn:hover {
transform: translate(-2px, -2px);
box-shadow: var(--shadow-hover);
.dropdown-content a {
color: white;
padding: 12px 16px;
text-decoration: none;
display: block;
font-size: 14px;
}
.btn:active {
transform: translate(2px, 2px);
box-shadow: 0 0 0 #000;
.dropdown-content a:hover {
background-color: #2B3139;
}
.btn-primary {
background-color: var(--color-primary);
border-color: #000;
color: #fff;
}
.btn-primary:hover {
background-color: #1d4ed8;
border-color: #000;
color: #fff;
}
.btn-outline-dark {
background-color: #fff;
color: #000;
}
.btn-cta {
background-color: var(--color-accent);
color: #000;
}
.btn-cta:hover {
background-color: #8cc629;
color: #000;
}
/* Hero Section */
.hero-section {
min-height: 100vh;
padding-top: 80px;
}
.background-blob {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.6;
z-index: 1;
}
.blob-1 {
top: -10%;
right: -10%;
width: 600px;
height: 600px;
background: radial-gradient(circle, var(--color-accent), transparent);
}
.blob-2 {
bottom: 10%;
left: -10%;
width: 500px;
height: 500px;
background: radial-gradient(circle, var(--color-primary), transparent);
}
.highlight-text {
background: linear-gradient(120deg, transparent 0%, transparent 40%, var(--color-accent) 40%, var(--color-accent) 100%);
background-repeat: no-repeat;
background-size: 100% 40%;
background-position: 0 88%;
padding: 0 5px;
}
.dot { color: var(--color-primary); }
.badge-pill {
display: inline-block;
padding: 0.5rem 1rem;
border: 2px solid #000;
border-radius: 50px;
font-weight: 700;
background: #fff;
box-shadow: 4px 4px 0 #000;
font-family: var(--font-heading);
font-size: 0.9rem;
}
/* Marquee */
.marquee-container {
overflow: hidden;
white-space: nowrap;
border-top: 2px solid #000;
border-bottom: 2px solid #000;
}
.rotate-divider {
transform: rotate(-2deg) scale(1.05);
z-index: 10;
position: relative;
margin-top: -50px;
margin-bottom: 30px;
}
.marquee-content {
display: inline-block;
animation: marquee 20s linear infinite;
font-family: var(--font-heading);
font-weight: 700;
font-size: 1.5rem;
letter-spacing: 2px;
}
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
}
/* Portfolio Cards */
.project-card {
border: 2px solid #000;
border-radius: var(--radius-card);
overflow: hidden;
background: #fff;
transition: transform 0.3s ease;
box-shadow: var(--shadow-hard);
height: 100%;
display: flex;
flex-direction: column;
}
.project-card:hover {
transform: translateY(-10px);
box-shadow: 8px 8px 0 #000;
}
.card-img-holder {
height: 250px;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 2px solid #000;
position: relative;
font-size: 4rem;
}
.placeholder-art {
transition: transform 0.3s ease;
}
.project-card:hover .placeholder-art {
transform: scale(1.2) rotate(10deg);
}
.bg-soft-blue { background-color: #e0f2fe; }
.bg-soft-green { background-color: #dcfce7; }
.bg-soft-purple { background-color: #f3e8ff; }
.bg-soft-yellow { background-color: #fef9c3; }
.category-tag {
position: absolute;
top: 15px;
right: 15px;
background: #000;
color: #fff;
padding: 5px 12px;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 700;
}
.card-body { padding: 1.5rem; }
.link-arrow {
background-color: var(--primary-color);
color: white;
border: none;
padding: 8px 20px;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
text-decoration: none;
color: #000;
font-weight: 700;
display: inline-flex;
align-items: center;
margin-top: auto;
justify-content: center;
transition: 0.2s;
}
.link-arrow i { transition: transform 0.2s; margin-left: 5px; }
.link-arrow:hover i { transform: translateX(5px); }
.btn-primary:hover { opacity: 0.9; transform: translateY(-1px); }
/* About */
.about-image-stack {
position: relative;
height: 400px;
width: 100%;
/* Mobile Bottom Nav */
.mobile-bottom-nav {
display: none;
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 65px;
background: #161a1e;
border-top: 1px solid var(--border-color);
z-index: 1000;
justify-content: space-around;
align-items: center;
padding: 5px 0 10px;
backdrop-filter: blur(10px);
}
.stack-card {
position: absolute;
width: 80%;
.mobile-nav-item {
display: flex;
flex-direction: column;
align-items: center;
text-decoration: none;
color: var(--text-muted);
font-size: 11px;
gap: 4px;
}
.mobile-nav-item i { font-size: 22px; }
.mobile-nav-item.active { color: var(--primary-color); }
.mobile-nav-item.active i { color: var(--primary-color); }
/* Sidebar Drawer */
.mobile-sidebar {
position: fixed;
top: 0;
left: -100%;
width: 280px;
height: 100%;
border-radius: var(--radius-card);
border: 2px solid #000;
box-shadow: var(--shadow-hard);
left: 10%;
transform: rotate(-3deg);
background-size: cover;
background: #0B0E11;
z-index: 2000;
transition: 0.3s;
box-shadow: 10px 0 30px rgba(0,0,0,0.5);
padding: 20px;
overflow-y: auto;
}
/* Forms */
.form-control {
border: 2px solid #000;
border-radius: 0.5rem;
padding: 1rem;
font-weight: 500;
background: #f8f9fa;
.mobile-sidebar.open { left: 0; }
.sidebar-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.7);
z-index: 1999;
}
.sidebar-overlay.open { display: block; }
/* Responsive Grid Helper */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.form-control:focus {
box-shadow: 4px 4px 0 var(--color-primary);
border-color: #000;
background: #fff;
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 30px; }
.responsive-grid {
display: grid;
grid-template-columns: 1fr 380px;
gap: 30px;
}
/* Animations */
.animate-up {
opacity: 0;
transform: translateY(30px);
animation: fadeUp 0.8s ease forwards;
/* Mobile Optimizations */
@media (max-width: 992px) {
.navbar { padding: 0 1rem; }
.nav-links { display: none; }
.hero-section { flex-direction: column; text-align: center; padding: 40px 5%; }
.grid-3, .grid-2, .responsive-grid { grid-template-columns: 1fr; }
.mobile-bottom-nav { display: flex; }
body { padding-bottom: 70px; }
.section-title { font-size: 1.8rem; }
/* Market Table Mobile */
.market-table-container {
width: 100%;
overflow-x: auto;
}
.market-table th:nth-child(4),
.market-table td:nth-child(4) { display: none; }
}
.delay-100 { animation-delay: 0.1s; }
.delay-200 { animation-delay: 0.2s; }
@media (max-width: 576px) {
.container { padding: 0 15px; }
.logo-text { font-size: 1.2rem !important; }
.logo-svg { width: 24px !important; height: 24px !important; }
@keyframes fadeUp {
to {
opacity: 1;
transform: translateY(0);
}
.btn-login-hide { display: none; }
.market-table th, .market-table td { padding: 10px 12px !important; }
.market-table td div { font-size: 0.85rem !important; }
.deposit-card, .withdraw-card { padding: 25px 20px !important; }
}
/* Social */
.social-links a {
transition: transform 0.2s;
/* User Profile Dropdown Adjustments */
.user-info-header {
padding: 15px;
border-bottom: 1px solid var(--border-color);
}
.uid-badge {
display: inline-block;
}
.social-links a:hover {
transform: scale(1.2) rotate(10deg);
color: var(--color-accent) !important;
}
/* Responsive */
@media (max-width: 991px) {
.rotate-divider {
transform: rotate(0);
margin-top: 0;
margin-bottom: 2rem;
}
.hero-section {
padding-top: 120px;
text-align: center;
min-height: auto;
padding-bottom: 100px;
}
.display-1 { font-size: 3.5rem; }
.blob-1 { width: 300px; height: 300px; right: -20%; }
.blob-2 { width: 300px; height: 300px; left: -20%; }
background: rgba(79, 172, 254, 0.1);
color: var(--primary-color);
font-size: 11px;
padding: 2px 8px;
border-radius: 4px;
margin-top: 5px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

55
careers.php Normal file
View File

@ -0,0 +1,55 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 1200px; margin: 0 auto;">
<div style="text-align: center; margin-bottom: 80px;">
<h1 style="font-size: 3.5rem; font-weight: 800; margin-bottom: 20px;">Build the Future of Finance</h1>
<p style="font-size: 1.2rem; color: var(--text-muted); max-width: 700px; margin: 0 auto;">Join a global team of innovators working to redefine how the world interacts with money.</p>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px; margin-bottom: 100px;">
<div style="background: #161a1e; padding: 40px; border-radius: 24px; border: 1px solid #2b3139;">
<h3 style="font-size: 1.5rem; margin-bottom: 15px;">Remote-First</h3>
<p style="color: var(--text-muted);">We believe in freedom and flexibility. Work from anywhere in the world and manage your own schedule.</p>
</div>
<div style="background: #161a1e; padding: 40px; border-radius: 24px; border: 1px solid #2b3139;">
<h3 style="font-size: 1.5rem; margin-bottom: 15px;">Global Impact</h3>
<p style="color: var(--text-muted);">Your work directly affects millions of users and helps build a more inclusive financial system.</p>
</div>
<div style="background: #161a1e; padding: 40px; border-radius: 24px; border: 1px solid #2b3139;">
<h3 style="font-size: 1.5rem; margin-bottom: 15px;">Ownership</h3>
<p style="color: var(--text-muted);">We value initiative and drive. At NovaEx, you own your projects and have the autonomy to make decisions.</p>
</div>
</div>
<h2 style="font-size: 2.2rem; margin-bottom: 40px; text-align: center;">Open Roles</h2>
<div style="display: flex; flex-direction: column; gap: 20px; margin-bottom: 100px;">
<?php
$jobs = [
['title' => 'Senior Blockchain Engineer', 'dept' => 'Engineering', 'location' => 'Remote / Global'],
['title' => 'Product Designer (UI/UX)', 'dept' => 'Product', 'location' => 'Remote / Europe'],
['title' => 'Customer Success Manager', 'dept' => 'Support', 'location' => 'Remote / Asia'],
['title' => 'Quantitative Trader', 'dept' => 'Trading', 'location' => 'Remote / North America'],
['title' => 'Security Architect', 'dept' => 'Security', 'location' => 'Remote / Global'],
];
foreach ($jobs as $job):
?>
<div style="background: #161a1e; padding: 30px; border-radius: 16px; border: 1px solid #2b3139; display: flex; justify-content: space-between; align-items: center; transition: 0.3s; cursor: pointer;" onmouseover="this.style.borderColor='var(--primary-color)'" onmouseout="this.style.borderColor='#2b3139'">
<div>
<h4 style="font-size: 1.3rem; margin-bottom: 5px;"><?php echo $job['title']; ?></h4>
<span style="font-size: 0.9rem; color: var(--text-muted);"><?php echo $job['dept']; ?> • <?php echo $job['location']; ?></span>
</div>
<a href="#" class="btn-primary" style="padding: 10px 25px; border-radius: 8px;">Apply Now</a>
</div>
<?php endforeach; ?>
</div>
<div style="text-align: center;">
<p style="color: var(--text-muted); margin-bottom: 20px;">Don't see a perfect fit? We're always looking for talented individuals.</p>
<a href="mailto:careers@novaex.com" style="color: var(--primary-color); font-weight: bold; text-decoration: none;">Send us your CV <i class="fas fa-arrow-right"></i></a>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

323
chat.php Normal file
View File

@ -0,0 +1,323 @@
<?php
include 'header.php';
if (!isset($_SESSION['user_id'])) {
echo "<script>location.href='login.php';</script>";
exit;
}
$user_id = $_SESSION['user_id'];
$pdo = db();
// Fetch user info
$stmt = $pdo->prepare("SELECT uid, username, last_ip FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
// Check if there's an active deposit/withdrawal process
$stmt = $pdo->prepare("SELECT * FROM fiat_orders WHERE user_id = ? AND status IN ('matching', 'matched', 'paid') ORDER BY id DESC LIMIT 1");
$stmt->execute([$user_id]);
$active_order = $stmt->fetch();
$is_locked = (bool)$active_order;
// Action to complete transfer/submission
if (isset($_GET['action']) && $_GET['action'] === 'complete_order' && $active_order) {
$stmt = $pdo->prepare("UPDATE fiat_orders SET status = 'paid' WHERE id = ?");
$stmt->execute([$active_order['id']]);
$type_text = ($active_order['order_type'] === 'deposit') ? __('nav_deposit') : __('nav_withdraw');
$msg = "" . __('confirm_transfer') . ", $type_text " . __('paid_waiting_tip');
$stmt = $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
$stmt->execute([$user_id, $msg]);
header("Location: chat.php");
exit;
}
// Fetch greeting message
$stmt = $pdo->prepare("SELECT value FROM settings WHERE name = 'chat_greeting'");
$stmt->execute();
$greeting = $stmt->fetchColumn();
if (!$greeting) {
$greeting = ($lang == 'zh') ? '您好!欢迎咨询 NovaEx 官方客服,请问有什么可以帮您?如果是充值咨询,请提供您的充值金额和币种。' : 'Hello! Welcome to NovaEx official customer service. How can we help you today? For deposit inquiries, please provide your amount and currency.';
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['message'])) {
$msg = trim($_POST['message']);
if ($msg !== '') {
$stmt = $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
$stmt->execute([$user_id, $msg]);
echo json_encode(['success' => true]);
}
exit;
}
?>
<style>
#chat-box::-webkit-scrollbar { width: 6px; }
#chat-box::-webkit-scrollbar-track { background: transparent; }
#chat-box::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
#chat-box { flex: 1; overflow-y: auto; padding: 25px; display: flex; flex-direction: column; gap: 20px; background: #161a1e; scroll-behavior: smooth; }
.msg-container { display: flex; flex-direction: column; transition: all 0.3s ease; }
.msg-content { max-width: 75%; padding: 12px 18px; border-radius: 18px; font-size: 14px; line-height: 1.6; position: relative; }
.account-modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 450px; background: #1e2329; border-radius: 24px; border: 1px solid var(--primary-color); z-index: 10001; padding: 30px; box-shadow: 0 20px 50px rgba(0,0,0,0.8); display: none; }
.modal-backdrop { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 10000; display: none; }
.status-bar { background: rgba(240,185,11,0.1); border: 1px solid var(--primary-color); padding: 15px 25px; border-radius: 12px; margin-bottom: 15px; display: flex; align-items: center; justify-content: space-between; color: var(--primary-color); }
#image-upload-btn:hover { background: #3b424d !important; color: #fcd535 !important; }
#image-upload-btn:disabled { opacity: 0.5; cursor: not-allowed; }
</style>
<!-- Account Details Modal -->
<div id="acc-backdrop" class="modal-backdrop"></div>
<div id="acc-modal" class="account-modal">
<div style="text-align: center; margin-bottom: 25px;">
<div style="width: 60px; height: 60px; background: rgba(240,185,11,0.1); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: var(--primary-color); margin: 0 auto 15px; font-size: 24px;">
<i class="fas fa-university"></i>
</div>
<h3 style="margin: 0; color: white;" id="modal-title"><?php echo __('matched_status'); ?></h3>
<p style="color: var(--text-muted); font-size: 14px; margin-top: 5px;" id="modal-tip"><?php echo __('matched_info_tip'); ?></p>
</div>
<div id="acc-info" style="background: #161a1e; padding: 20px; border-radius: 16px; color: white; font-size: 14px; line-height: 2; border: 1px solid #2b3139; margin-bottom: 25px;">
<!-- Filled by JS -->
</div>
<button onclick="closeAccModal()" class="btn-primary" style="width: 100%; padding: 15px; border-radius: 12px; font-weight: 800;"><?php echo __('confirm'); ?></button>
</div>
<div id="chat-container" class="container" style="max-width: 850px; margin: 30px auto; padding: 0; height: calc(100vh - 200px); min-height: 500px;">
<?php if ($is_locked): ?>
<div class="status-bar">
<div style="display: flex; align-items: center; gap: 15px;">
<i class="fas fa-lock"></i>
<div>
<div style="font-size: 14px; font-weight: 800;"><?php echo ($active_order['order_type'] === 'deposit') ? __('nav_deposit') : __('nav_withdraw'); ?></div>
<div style="font-size: 12px; opacity: 0.8;"><?php
if ($active_order['status'] === 'matching') echo __('matching_status') . '...';
elseif ($active_order['status'] === 'matched') echo ($active_order['order_type'] === 'deposit') ? __('matched_info_tip') : __('withdraw_info_tip');
elseif ($active_order['status'] === 'paid') echo __('paid_waiting_tip');
?></div>
</div>
</div>
<div style="display: flex; gap: 10px;">
<?php if ($active_order['status'] === 'matched'): ?>
<button onclick="showCurrentAccInfo()" class="btn-primary" style="padding: 8px 15px; font-size: 12px; border-radius: 8px; background: #2b3139; color: white; border: 1px solid #3b424d;">
<?php echo ($active_order['order_type'] === 'deposit') ? __('view_account') : __('view_withdraw_format'); ?>
</button>
<?php endif; ?>
<?php if ($active_order['status'] === 'matched'): ?>
<button onclick="window.location.href='?action=complete_order'" class="btn-primary" style="padding: 8px 15px; font-size: 12px; border-radius: 8px;">
<?php echo ($active_order['order_type'] === 'deposit') ? __('complete_transfer_btn') : __('confirm'); ?>
</button>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<div id="chat-card" class="card" style="background: #1e2329; border: 1px solid #2b3139; border-radius: 20px; display: flex; flex-direction: column; height: 100%; box-shadow: 0 10px 30px rgba(0,0,0,0.3); overflow: hidden;">
<!-- Header -->
<div style="padding: 20px 25px; border-bottom: 1px solid #2b3139; display: flex; align-items: center; justify-content: space-between; background: #1e2329;">
<div style="display: flex; align-items: center; gap: 15px;">
<div style="width: 45px; height: 45px; background: #f0b90b; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: black;">
<i class="fas fa-headset fa-lg"></i>
</div>
<div>
<h3 style="margin: 0; font-size: 18px; color: white;"><?php echo __('support_online'); ?></h3>
<div style="display: flex; align-items: center; gap: 5px; font-size: 12px; color: #00c087;">
<span style="width: 8px; height: 8px; background: #00c087; border-radius: 50%; display: inline-block;"></span> 24/7 <?php echo ($lang == 'zh' ? '全天候在线' : 'Always Online'); ?>
</div>
</div>
</div>
<div style="text-align: right; font-size: 12px; color: #848e9c;">
<div>UID: <?php echo htmlspecialchars($user['uid']); ?></div>
<div style="font-size: 10px; opacity: 0.7;">IP: <?php echo htmlspecialchars($user['last_ip']); ?></div>
<a href="index.php" style="color: var(--primary-color); text-decoration: none; display: <?php echo $is_locked ? 'none' : 'block'; ?>; margin-top: 5px;"><i class="fas fa-times"></i> <?php echo __('cancel'); ?></a>
</div>
</div>
<!-- Chat Body -->
<div id="chat-box">
<div style="text-align: center; color: #848e9c; padding: 20px;">Connecting...</div>
</div>
<!-- Input Area -->
<div style="padding: 20px; background: #1e2329; border-top: 1px solid #2b3139;">
<form id="chat-form" style="display: flex; gap: 12px; align-items: center;">
<button type="button" id="image-upload-btn" onclick="document.getElementById('image-input').click()" style="background: #2b3139; border: 1px solid #3b424d; color: #f0b90b; width: 45px; height: 45px; border-radius: 12px; cursor: pointer; flex-shrink: 0; display: flex; align-items: center; justify-content: center; transition: all 0.2s;">
<i class="fas fa-plus"></i>
</button>
<input type="file" id="image-input" accept="image/*" style="display: none;" onchange="uploadImage(this)">
<input type="text" id="chat-input" placeholder="<?php echo __('type_message'); ?>"
style="flex: 1; background: #161a1e; border: 1px solid #2b3139; border-radius: 12px; padding: 14px 20px; color: white; outline: none; font-size: 14px;" autocomplete="off">
<button type="submit" style="background: #f0b90b; border: none; color: black; width: 50px; height: 50px; border-radius: 12px; cursor: pointer; display: flex; align-items: center; justify-content: center; flex-shrink: 0;">
<i class="fas fa-paper-plane fa-lg"></i>
</button>
</form>
</div>
</div>
</div>
<?php if ($is_locked): ?>
<script>
window.onbeforeunload = function() {
return "<?php echo ($lang == 'zh' ? '您的业务流程尚未完成,请勿离开此页面。' : 'Your transaction is not complete. Please stay on this page.'); ?>";
};
document.querySelector('nav')?.style.display = 'none';
document.querySelector('footer')?.style.display = 'none';
history.pushState(null, null, location.href);
window.onpopstate = function() {
history.pushState(null, null, location.href);
};
</script>
<?php endif; ?>
<script>
const chatBox = document.getElementById('chat-box');
const chatForm = document.getElementById('chat-form');
const chatInput = document.getElementById('chat-input');
const uploadBtn = document.getElementById('image-upload-btn');
let lastStatus = '<?php echo $active_order['status'] ?? ''; ?>';
let currentBankAccountInfo = `<?php echo addslashes($active_order['bank_account_info'] ?? ''); ?>`;
const greeting = `<?php echo addslashes($greeting); ?>`;
async function loadMessages() {
try {
const resp = await fetch('api/get_messages.php');
const res = await resp.json();
if (res.success) {
const newMessages = res.data;
if (newMessages.length === 0) {
chatBox.innerHTML = `
<div style="display: flex; flex-direction: column; align-items: flex-start;">
<div class="msg-content" style="background: #2b3139; color: white; border-bottom-left-radius: 4px; border: 1px solid #3b424d;">
${greeting.replace(/\n/g, '<br>')}
</div>
<span style="font-size: 10px; color: #5e6673; margin-top: 6px;">Support</span>
</div>
`;
} else {
let html = '';
newMessages.forEach(m => {
const isUser = m.sender === 'user';
html += `
<div class="msg-container" style="align-items: ${isUser ? 'flex-end' : 'flex-start'};">
<div class="msg-content" style="${isUser ? 'background: #f0b90b; color: black; border-bottom-right-radius: 4px;' : 'background: #2b3139; color: white; border-bottom-left-radius: 4px; border: 1px solid #3b424d;'} ">
${m.type === 'image' ? `<img src="${m.message}" style="max-width:100%; border-radius:8px; cursor:pointer;" onclick="window.open(this.src)">` : m.message.replace(/\n/g, '<br>')}
</div>
<span style="font-size: 10px; color: #5e6673; margin-top: 6px;">${new Date(m.created_at).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span>
</div>
`;
});
const isAtBottom = chatBox.scrollHeight - chatBox.scrollTop <= chatBox.clientHeight + 100;
chatBox.innerHTML = html;
if (isAtBottom) chatBox.scrollTop = chatBox.scrollHeight;
}
}
} catch (e) {}
}
async function checkOrderStatus() {
try {
const resp = await fetch('api/check_order_status.php');
const res = await resp.json();
if (res.success && res.order) {
currentBankAccountInfo = res.order.bank_account_info;
if (res.order.status !== lastStatus) {
const title = res.order.order_type === 'deposit' ? '<?php echo __('matched_status'); ?>' : '<?php echo __('withdraw_format_title'); ?>';
const tip = res.order.order_type === 'deposit' ? '<?php echo __('matched_info_tip'); ?>' : '<?php echo __('withdraw_info_tip'); ?>';
showAccModal(title, tip, res.order.bank_account_info);
} else if (res.order.status === 'completed' || res.order.status === 'rejected') {
alert(res.order.status === 'completed' ? "Success!" : "Request rejected.");
window.onbeforeunload = null;
location.href = 'profile.php';
}
lastStatus = res.order.status;
}
} else if (res.success && !res.order && lastStatus !== '') {
window.onbeforeunload = null;
location.href = 'profile.php';
}
} catch (e) {}
}
function showAccModal(title, tip, info) {
if (!info) return;
document.getElementById('modal-title').innerText = title;
document.getElementById('modal-tip').innerText = tip;
document.getElementById('acc-info').innerHTML = info.replace(/\n/g, '<br>');
document.getElementById('acc-backdrop').style.display = 'block';
document.getElementById('acc-modal').style.display = 'block';
}
function showCurrentAccInfo() {
const orderType = '<?php echo $active_order['order_type'] ?? ''; ?>';
const title = orderType === 'deposit' ? '<?php echo __('view_account'); ?>' : '<?php echo __('view_withdraw_format'); ?>';
const tip = orderType === 'deposit' ? '<?php echo __('matched_info_tip'); ?>' : '<?php echo __('withdraw_info_tip'); ?>';
showAccModal(title, tip, currentBankAccountInfo);
}
function closeAccModal() {
document.getElementById('acc-backdrop').style.display = 'none';
document.getElementById('acc-modal').style.display = 'none';
}
chatForm.onsubmit = async (e) => {
e.preventDefault();
const msg = chatInput.value.trim();
if (!msg) return;
chatInput.value = '';
const formData = new FormData();
formData.append('message', msg);
await fetch('chat.php', { method: 'POST', body: formData });
loadMessages();
};
function uploadImage(input) {
if (!input.files || !input.files[0]) return;
const formData = new FormData();
formData.append('image', input.files[0]);
uploadBtn.disabled = true;
uploadBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
fetch('api/upload_chat_image.php', { method: 'POST', body: formData })
.then(res => res.json())
.then(res => {
if (res.success) {
loadMessages();
} else {
alert(res.error || 'Upload failed');
}
})
.finally(() => {
uploadBtn.disabled = false;
uploadBtn.innerHTML = '<i class="fas fa-plus"></i>';
input.value = '';
});
}
window.onload = () => {
const orderType = '<?php echo $active_order['order_type'] ?? ''; ?>';
if (lastStatus === 'matched' && currentBankAccountInfo) {
const title = orderType === 'deposit' ? '<?php echo __('matched_status'); ?>' : '<?php echo __('withdraw_format_title'); ?>';
const tip = orderType === 'deposit' ? '<?php echo __('matched_info_tip'); ?>' : '<?php echo __('withdraw_info_tip'); ?>';
showAccModal(title, tip, currentBankAccountInfo);
}
};
loadMessages();
setInterval(loadMessages, 3000);
setInterval(checkOrderStatus, 3000);
</script>
<?php include 'footer.php'; ?>

237
chat_iframe.php Normal file
View File

@ -0,0 +1,237 @@
<?php
session_start();
require_once 'db/config.php';
require_once 'includes/i18n.php';
if (!isset($_SESSION['user_id'])) {
die(__('please_login'));
}
$user_id = $_SESSION['user_id'];
$db = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['message'])) {
$msg = trim($_POST['message']);
if ($msg !== '') {
$stmt = $db->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
$stmt->execute([$user_id, $msg]);
echo json_encode(['success' => true]);
}
exit;
}
// Fetch greeting message
$stmt = $db->prepare("SELECT value FROM settings WHERE name = 'chat_greeting'");
$stmt->execute();
$greeting = $stmt->fetchColumn();
if (!$greeting) {
$greeting = ($lang == 'zh') ? '您好!欢迎咨询 NovaEx 官方客服,请问有什么可以帮您?' : 'Hello! Welcome to NovaEx official customer service. How can we help you today?';
}
?>
<!DOCTYPE html>
<html lang="<?php echo $lang; ?>">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root {
--primary-color: #f0b90b;
--bg-color: #161a1e;
--card-bg: #1e2329;
--border-color: #2b3139;
--text-color: #ffffff;
--text-muted: #848e9c;
}
body { margin: 0; padding: 0; font-family: 'Inter', sans-serif; background: var(--bg-color); color: white; height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
#chat-box { flex: 1; overflow-y: auto; padding: 15px; display: flex; flex-direction: column; gap: 12px; scroll-behavior: smooth; }
.msg { max-width: 80%; padding: 10px 14px; border-radius: 12px; font-size: 14px; line-height: 1.4; word-wrap: break-word; position: relative; }
.msg.user { align-self: flex-end; background: var(--primary-color); color: black; border-bottom-right-radius: 2px; }
.msg.admin { align-self: flex-start; background: #2b3139; color: #EAECEF; border-bottom-left-radius: 2px; border: 1px solid #3b424d; }
.msg-time { font-size: 10px; opacity: 0.5; margin-top: 4px; display: block; }
.chat-input-area { padding: 12px; background: #1e2329; border-top: 1px solid #2b3139; display: flex; gap: 10px; align-items: center; }
input[type="text"] { flex: 1; background: #0b0e11; border: 1px solid #2b3139; border-radius: 8px; padding: 10px 12px; color: white; outline: none; }
.icon-btn { background: #2b3139; border: 1px solid #3b424d; width: 40px; height: 40px; border-radius: 8px; color: var(--primary-color); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; }
.icon-btn:hover { background: #3b424d; }
.send-btn { background: var(--primary-color); border: none; width: 40px; height: 40px; border-radius: 8px; color: black; cursor: pointer; display: flex; align-items: center; justify-content: center; }
#chat-box::-webkit-scrollbar { width: 4px; }
#chat-box::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
img.chat-img { max-width: 100%; border-radius: 8px; margin-top: 5px; cursor: pointer; }
/* Modal inside iframe */
.modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 85%; background: var(--card-bg); border-radius: 16px; border: 1px solid var(--primary-color); z-index: 1000; padding: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); display: none; }
.backdrop { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 999; display: none; }
.modal-btn { width: 100%; background: var(--primary-color); border: none; padding: 10px; border-radius: 8px; font-weight: bold; cursor: pointer; margin-top: 15px; }
.sending { opacity: 0.7; }
.sending::after { content: '...'; position: absolute; right: 5px; bottom: 5px; font-size: 10px; }
</style>
</head>
<body>
<div id="acc-backdrop" class="backdrop"></div>
<div id="acc-modal" class="modal">
<div style="text-align: center; margin-bottom: 15px;">
<i class="fas fa-university" style="color: var(--primary-color); font-size: 24px;"></i>
<h4 style="margin: 10px 0 5px;" id="modal-title"><?php echo __('matched_status'); ?></h4>
<p style="color: var(--text-muted); font-size: 12px;" id="modal-tip"><?php echo __('matched_info_tip'); ?></p>
</div>
<div id="acc-info" style="background: #161a1e; padding: 15px; border-radius: 8px; font-size: 13px; line-height: 1.6; border: 1px solid #2b3139;"></div>
<button onclick="closeModal()" class="modal-btn"><?php echo __('confirm'); ?></button>
</div>
<div id="chat-box"></div>
<form id="chat-form" class="chat-input-area">
<button type="button" class="icon-btn" id="upload-btn" onclick="document.getElementById('image-input').click()">
<i class="fas fa-plus"></i>
</button>
<input type="file" id="image-input" accept="image/*" style="display: none;" onchange="uploadImage(this)">
<input type="text" id="msg-input" placeholder="<?php echo __('type_message'); ?>" autocomplete="off">
<button type="submit" class="send-btn"><i class="fas fa-paper-plane"></i></button>
</form>
<script>
const chatBox = document.getElementById('chat-box');
const msgInput = document.getElementById('msg-input');
const uploadBtn = document.getElementById('upload-btn');
const greeting = `<?php echo addslashes($greeting); ?>`;
let lastStatus = '';
let lastOrderId = 0;
let lastMessagesHtml = '';
let isSending = false;
async function loadMessages() {
if (isSending) return; // Prevent refresh while sending to avoid flickering
try {
const resp = await fetch('api/get_messages.php');
const res = await resp.json();
if (res.success) {
if (res.data.length === 0) {
chatBox.innerHTML = `
<div class="msg admin">
${greeting.replace(/\n/g, '<br>')}
</div>
`;
} else {
let html = '';
res.data.forEach(m => {
const content = m.type === 'image'
? `<img src="${m.message}" class="chat-img" onclick="window.open(this.src)">`
: m.message.replace(/\n/g, '<br>');
html += `
<div class="msg ${m.sender}">
${content}
<span class="msg-time">${new Date(m.created_at).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span>
</div>
`;
});
if (html !== lastMessagesHtml) {
const isAtBottom = chatBox.scrollHeight - chatBox.scrollTop <= chatBox.clientHeight + 100;
chatBox.innerHTML = html;
lastMessagesHtml = html;
if (isAtBottom) chatBox.scrollTop = chatBox.scrollHeight;
// Mark messages as read
fetch('api/get_messages.php?action=mark_read&user_id=<?php echo $user_id; ?>&reader=user');
}
}
}
} catch (e) {}
}
async function checkOrderStatus() {
try {
const resp = await fetch('api/check_order_status.php');
const res = await resp.json();
if (res.success && res.order) {
if (res.order.status === 'matched' && (res.order.status !== lastStatus || res.order.id !== lastOrderId)) {
const title = res.order.order_type === 'deposit' ? '<?php echo __('matched_status'); ?>' : '<?php echo __('withdraw_format_title'); ?>';
const tip = res.order.order_type === 'deposit' ? '<?php echo __('matched_info_tip'); ?>' : '<?php echo __('withdraw_info_tip'); ?>';
showModal(title, tip, res.order.bank_account_info);
lastStatus = res.order.status;
lastOrderId = res.order.id;
}
}
} catch (e) {}
}
function showModal(title, tip, info) {
if (!info) return;
document.getElementById('modal-title').innerText = title;
document.getElementById('modal-tip').innerText = tip;
document.getElementById('acc-info').innerHTML = info.replace(/\n/g, '<br>');
document.getElementById('acc-backdrop').style.display = 'block';
document.getElementById('acc-modal').style.display = 'block';
}
function closeModal() {
document.getElementById('acc-backdrop').style.display = 'none';
document.getElementById('acc-modal').style.display = 'none';
}
document.getElementById('chat-form').onsubmit = async (e) => {
e.preventDefault();
const msg = msgInput.value.trim();
if (!msg || isSending) return;
msgInput.value = '';
isSending = true;
// Optimistic UI: Add message locally
const tempMsg = document.createElement('div');
tempMsg.className = 'msg user sending';
tempMsg.innerHTML = `${msg.replace(/\n/g, '<br>')}<span class="msg-time">${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span>`;
chatBox.appendChild(tempMsg);
chatBox.scrollTop = chatBox.scrollHeight;
const formData = new FormData();
formData.append('message', msg);
try {
await fetch('chat_iframe.php', { method: 'POST', body: formData });
isSending = false;
await loadMessages();
} catch (e) {
isSending = false;
tempMsg.style.background = '#ff4d4f';
tempMsg.innerHTML += ' (Failed)';
}
};
function uploadImage(input) {
if (!input.files || !input.files[0]) return;
const formData = new FormData();
formData.append('image', input.files[0]);
uploadBtn.disabled = true;
uploadBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
fetch('api/upload_chat_image.php', { method: 'POST', body: formData })
.then(res => res.json())
.then(res => {
if (res.success) {
loadMessages();
} else {
alert(res.error || 'Upload failed');
}
})
.finally(() => {
uploadBtn.disabled = false;
uploadBtn.innerHTML = '<i class="fas fa-plus"></i>';
input.value = '';
});
}
// Initial calls
loadMessages();
checkOrderStatus();
// Polling
setInterval(loadMessages, 1000);
setInterval(checkOrderStatus, 2000);
</script>
</body>
</html>

87
convert.php Normal file
View File

@ -0,0 +1,87 @@
<?php include 'header.php'; ?>
<main style="padding: 60px 20px; background: #0b0e11; min-height: calc(100vh - 60px);">
<div style="max-width: 500px; margin: 0 auto; background: #1e2329; padding: 40px; border-radius: 20px; border: 1px solid #2b3139;">
<h2 style="margin-bottom: 30px; text-align: center; color: white;"><?php echo __('nav_convert'); ?></h2>
<div style="margin-bottom: 25px;">
<label style="color: #848e9c; font-size: 0.9rem; margin-bottom: 10px; display: block;">From</label>
<div style="display: flex; align-items: center; background: #0b0e11; padding: 15px; border-radius: 12px; border: 1px solid #2b3139;">
<input type="number" id="from-amount" value="100" style="flex: 1; background: transparent; border: none; color: white; font-size: 1.5rem; font-weight: bold; outline: none;">
<div style="display: flex; align-items: center; gap: 8px; background: #1e2329; padding: 5px 12px; border-radius: 20px; cursor: pointer;">
<img src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/usdt.png" width="24">
<span style="font-weight: bold; color: white;">USDT</span>
</div>
</div>
<div style="margin-top: 8px; color: #848e9c; font-size: 0.8rem; display: flex; justify-content: space-between;">
<span>Available: 0.00 USDT</span>
<span style="color: var(--primary-color); cursor: pointer;">Max</span>
</div>
</div>
<div style="text-align: center; margin: -10px 0 15px;">
<div style="width: 40px; height: 40px; background: #1e2329; border: 1px solid #2b3139; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; color: var(--primary-color); cursor: pointer;">
<i class="fas fa-exchange-alt fa-rotate-90"></i>
</div>
</div>
<div style="margin-bottom: 30px;">
<label style="color: #848e9c; font-size: 0.9rem; margin-bottom: 10px; display: block;">To</label>
<div style="display: flex; align-items: center; background: #0b0e11; padding: 15px; border-radius: 12px; border: 1px solid #2b3139;">
<input type="number" id="to-amount" readonly style="flex: 1; background: transparent; border: none; color: white; font-size: 1.5rem; font-weight: bold; outline: none;">
<select id="target-crypto" onchange="updateConvert()" style="background: #1e2329; border: none; color: white; padding: 5px 10px; border-radius: 20px; font-weight: bold; cursor: pointer; outline: none;">
<option value="BTC">BTC</option>
<option value="ETH">ETH</option>
<option value="SOL">SOL</option>
<option value="BNB">BNB</option>
</select>
</div>
<div id="rate-display" style="margin-top: 8px; color: #848e9c; font-size: 0.8rem; text-align: center;">
1 USDT --.--- BTC
</div>
</div>
<button class="btn-primary" style="width: 100%; padding: 16px; font-size: 1.1rem; font-weight: bold; border-radius: 12px; margin-bottom: 20px;">Preview Conversion</button>
<div style="background: rgba(240, 185, 11, 0.05); border: 1px solid rgba(240, 185, 11, 0.1); padding: 15px; border-radius: 10px;">
<div style="display: flex; align-items: center; gap: 10px; color: #F0B90B; font-size: 0.85rem;">
<i class="fas fa-info-circle"></i>
<span>Zero fees, instant settlement.</span>
</div>
</div>
</div>
</main>
<script>
const prices = {};
const symbols = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT'];
const ws = new WebSocket('wss://stream.binance.com:9443/ws/' + symbols.map(s => s.toLowerCase() + '@ticker').join('/'));
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
prices[data.s.replace('USDT', '')] = parseFloat(data.c);
updateConvert();
};
const fromInput = document.getElementById('from-amount');
const toInput = document.getElementById('to-amount');
const targetSelect = document.getElementById('target-crypto');
const rateDisplay = document.getElementById('rate-display');
function updateConvert() {
const fromVal = parseFloat(fromInput.value) || 0;
const target = targetSelect.value;
const price = prices[target];
if (price) {
const result = fromVal / price;
toInput.value = result.toFixed(8);
rateDisplay.innerText = `1 USDT ≈ ${(1/price).toFixed(8)} ${target}`;
}
}
fromInput.oninput = updateConvert;
</script>
<?php include 'footer.php'; ?>

View File

@ -1,17 +1,38 @@
<?php
// Generated by setup_mariadb_project.sh — edit as needed.
// Database configuration
define('DB_HOST', '127.0.0.1');
define('DB_NAME', 'app_38350');
define('DB_USER', 'app_38350');
define('DB_PASS', 'c79d2d31-7d44-4d51-ac22-5bfd0886fcc2');
// Set timezone to China Standard Time
date_default_timezone_set('Asia/Shanghai');
function db() {
static $pdo;
if (!$pdo) {
try {
$pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4', DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
// Auto-install check: if 'settings' table doesn't exist, run install.sql
static $checked = false;
if (!$checked) {
$checked = true;
$res = $pdo->query("SHOW TABLES LIKE 'settings'");
if ($res->rowCount() == 0) {
$sql_file = __DIR__ . '/install.sql';
if (file_exists($sql_file)) {
$sql = file_get_contents($sql_file);
$pdo->exec($sql);
}
}
}
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage());
}
}
return $pdo;
}

240
db/install.sql Normal file
View File

@ -0,0 +1,240 @@
/*M!999999\- enable the sandbox mode */
-- MariaDB dump 10.19 Distrib 10.11.14-MariaDB, for debian-linux-gnu (x86_64)
--
-- Host: 127.0.0.1 Database: app_38350
-- ------------------------------------------------------
-- Server version 10.11.14-MariaDB-0+deb12u2
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `admins`
--
DROP TABLE IF EXISTS `admins`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `admins` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`role` enum('admin','agent') DEFAULT 'agent',
`permissions` text DEFAULT NULL,
`remark` text DEFAULT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `fiat_orders`
--
DROP TABLE IF EXISTS `fiat_orders`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `fiat_orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`order_type` enum('deposit','withdrawal') NOT NULL DEFAULT 'deposit',
`amount` decimal(20,8) DEFAULT NULL,
`usdt_amount` decimal(20,8) DEFAULT NULL,
`exchange_rate` decimal(20,8) DEFAULT NULL,
`currency` varchar(10) DEFAULT NULL,
`status` varchar(20) DEFAULT NULL,
`expires_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp(),
`proof_image` varchar(255) DEFAULT NULL,
`bank_account_info` text DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `transactions`
--
DROP TABLE IF EXISTS `transactions`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `transactions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`type` varchar(50) NOT NULL,
`amount` decimal(20,8) NOT NULL,
`currency` varchar(10) DEFAULT 'USDT',
`status` varchar(20) DEFAULT 'pending',
`description` text DEFAULT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `messages`
--
DROP TABLE IF EXISTS `messages`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `messages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`sender` enum('user','admin') DEFAULT NULL,
`type` enum('text','image') DEFAULT 'text',
`message` text DEFAULT NULL,
`is_read` tinyint(4) DEFAULT 0,
`created_at` timestamp NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `option_orders`
--
DROP TABLE IF EXISTS `option_orders`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `option_orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`symbol` varchar(20) NOT NULL,
`amount` decimal(18,8) NOT NULL,
`direction` enum('up','down') NOT NULL,
`duration` int(11) NOT NULL,
`profit_rate` decimal(5,2) NOT NULL,
`opening_price` decimal(18,8) NOT NULL,
`closing_price` decimal(18,8) DEFAULT NULL,
`status` enum('pending','completed') DEFAULT 'pending',
`result` enum('none','win','loss') DEFAULT 'none',
`control` enum('none','win','loss') DEFAULT 'none',
`profit` decimal(18,8) DEFAULT 0.00000000,
`created_at` timestamp NULL DEFAULT current_timestamp(),
`settle_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `settings`
--
DROP TABLE IF EXISTS `settings`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `settings` (
`name` varchar(255) NOT NULL,
`value` text DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `trading_orders`
--
DROP TABLE IF EXISTS `trading_orders`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `trading_orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`symbol` varchar(20) NOT NULL,
`type` enum('spot','futures') NOT NULL,
`side` enum('buy','sell') NOT NULL,
`order_type` enum('limit','market') NOT NULL,
`price` decimal(18,8) NOT NULL,
`amount` decimal(18,8) NOT NULL,
`total` decimal(18,8) NOT NULL,
`leverage` int(11) DEFAULT 1,
`tp_price` decimal(18,8) DEFAULT NULL,
`sl_price` decimal(18,8) DEFAULT NULL,
`status` enum('open','closed','cancelled') DEFAULT 'open',
`win_loss` enum('none','win','loss') DEFAULT 'none',
`created_at` timestamp NULL DEFAULT current_timestamp(),
`admin_status` enum('pending','approved','rejected') DEFAULT 'approved',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `user_assets`
--
DROP TABLE IF EXISTS `user_assets`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `user_assets` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`symbol` varchar(20) NOT NULL,
`amount` decimal(30,10) DEFAULT 0.0000000000,
`created_at?` timestamp NULL DEFAULT current_timestamp(),
`updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `user_symbol` (`user_id`,`symbol`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `users`
--
DROP TABLE IF EXISTS `users`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` varchar(6) DEFAULT NULL,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp(),
`credit_score` int(11) DEFAULT 80,
`total_assets` decimal(20,8) DEFAULT 0.00000000,
`kyc_status` int(11) DEFAULT 0,
`kyc_name` varchar(255) DEFAULT NULL,
`kyc_id_number` varchar(255) DEFAULT NULL,
`kyc_id_front` varchar(255) DEFAULT NULL,
`kyc_id_back` varchar(255) DEFAULT NULL,
`kyc_id_handheld` varchar(255) DEFAULT NULL,
`trading_password` varchar(255) DEFAULT '123456',
`balance` decimal(20,8) DEFAULT 0.00000000,
`status` enum('active','disabled') DEFAULT 'active',
`win_loss_control` enum('none','win','loss') DEFAULT 'none',
`last_ip` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `uid` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2026-02-14 10:00:00
-- Dumping data
INSERT INTO `admins` (id, username, password, role, created_at) VALUES
(1,'admin','$2y$10$RJoR9U.GZwbNe14JqaWY7e2NQcJVNQYGr6rDFyzqVne4D1Ym5/ORS','admin',NOW());
INSERT INTO `settings` (name, value) VALUES
('chat_greeting','您好!欢迎咨询 NovaEx 官方客服,请问有什么可以帮您?如果是充值咨询,请提供您的充值金额和币种。'),
('price_control','0'),
('win_rate','70');

290
deposit.php Normal file
View File

@ -0,0 +1,290 @@
<?php
require_once 'db/config.php';
require_once 'includes/currency_helper.php';
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
$db = db();
include 'header.php';
$fiat_rates = get_fiat_rates();
$fiat_currencies_info = [
'USD' => ['name' => '美元', 'flag' => '🇺🇸'],
'EUR' => ['name' => '欧元', 'flag' => '🇪🇺'],
'GBP' => ['name' => '英镑', 'flag' => '🇬🇧'],
'CNY' => ['name' => '人民币', 'flag' => '🇨🇳'],
'HKD' => ['name' => '港币', 'flag' => '🇭🇰'],
'JPY' => ['name' => '日元', 'flag' => '🇯🇵'],
'KRW' => ['name' => '韩元', 'flag' => '🇰🇷'],
'SGD' => ['name' => '新加坡元', 'flag' => '🇸🇬'],
'TWD' => ['name' => '台币', 'flag' => '🇹🇼'],
'THB' => ['name' => '泰铢', 'flag' => '🇹🇭'],
'VND' => ['name' => '越南盾', 'flag' => '🇻🇳'],
'IDR' => ['name' => '印尼盾', 'flag' => '🇮🇩'],
'MYR' => ['name' => '马来西亚林吉特', 'flag' => '🇲🇾'],
];
?>
<style>
.deposit-container { padding: 40px 0; background: #0b0e11; min-height: 100vh; }
.deposit-card { background: var(--card-bg); border-radius: 24px; border: 1px solid var(--border-color); overflow: hidden; }
.method-card { padding: 30px; border-radius: 20px; border: 2px solid transparent; cursor: pointer; transition: 0.3s; background: rgba(255,255,255,0.02); }
.method-card:hover { background: rgba(255,255,255,0.05); }
.method-card.active { border-color: var(--primary-color); background: rgba(240, 185, 11, 0.05); }
.method-card .icon-box { width: 50px; height: 50px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 20px; margin-bottom: 15px; }
.instruction-item { display: flex; gap: 15px; margin-bottom: 20px; }
.instruction-number { width: 24px; height: 24px; background: var(--primary-color); color: #000; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 12px; flex-shrink: 0; }
.input-group-custom { background: #161a1e; border: 1px solid var(--border-color); border-radius: 16px; padding: 15px 20px; display: flex; align-items: center; gap: 15px; transition: 0.3s; }
.input-group-custom:focus-within { border-color: var(--primary-color); }
.input-group-custom input { background: none; border: none; color: white; font-size: 1.2rem; font-weight: 700; width: 100%; outline: none; }
.safe-banner { background: rgba(14, 203, 129, 0.1); border: 1px solid rgba(14, 203, 129, 0.2); padding: 20px; border-radius: 16px; color: var(--success-color); display: flex; gap: 15px; align-items: center; margin-bottom: 30px; }
@media (max-width: 576px) {
.method-card { padding: 20px 15px; }
.method-card .icon-box { width: 40px; height: 40px; font-size: 16px; }
.method-card div:nth-child(2) { font-size: 0.95rem !important; }
}
</style>
<div class="deposit-container">
<div class="container" style="max-width: 1100px;">
<div style="margin-bottom: 30px;">
<a href="profile.php" class="back-btn" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><i class="fas fa-arrow-left"></i> 个人中心</a>
<h1 style="font-size: 2.2rem; font-weight: 800; margin-top: 10px;">充值</h1>
<p style="color: var(--text-muted);">通过多种通道安全地为您的账户充值</p>
</div>
<div class="safe-banner">
<i class="fas fa-shield-check" style="font-size: 24px;"></i>
<div>
<div style="font-weight: 800;">安全保障</div>
<div style="font-size: 13px; opacity: 0.8;">所有交易均经过加密处理24/7 全天候监控。您的资金受到我们的安全资产基金保护。</div>
</div>
</div>
<div class="responsive-grid">
<div>
<div class="deposit-card" style="padding: 40px;">
<h3 style="margin-bottom: 25px; font-weight: 800;">1. 选择充值方式</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 40px;">
<div id="method-fiat" class="method-card active" onclick="switchDepositMethod('fiat')">
<div class="icon-box" style="background: rgba(79,172,254,0.1); color: #4facfe;"><i class="fas fa-university"></i></div>
<div style="font-weight: 800; font-size: 1.1rem;">法币充值</div>
<div style="color: var(--text-muted); font-size: 11px; margin-top: 4px;">银行转账 / OTC</div>
</div>
<div id="method-usdt" class="method-card" onclick="switchDepositMethod('usdt')">
<div class="icon-box" style="background: rgba(14,203,129,0.1); color: var(--success-color);"><i class="fas fa-coins"></i></div>
<div style="font-weight: 800; font-size: 1.1rem;">USDT 充值</div>
<div style="color: var(--text-muted); font-size: 11px; margin-top: 4px;">TRC20, ERC20...</div>
</div>
</div>
<div id="fiat-form-section">
<h3 style="margin-bottom: 25px; font-weight: 800;">2. 订单详情</h3>
<form id="fiat-deposit-form" action="matching.php" method="POST">
<input type="hidden" name="order_type" value="deposit">
<input type="hidden" name="type" value="fiat">
<div style="display: flex; flex-direction: column; gap: 20px; margin-bottom: 25px;">
<div>
<label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">充值币种</label>
<select name="currency" id="fiat-select" onchange="updateExchangeRate()" style="width: 100%; padding: 16px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 16px; outline: none; font-weight: 600;">
<?php foreach ($fiat_rates as $code => $rate): ?>
<option value="<?php echo $code; ?>" data-rate="<?php echo $rate; ?>">
<?php echo ($fiat_currencies_info[$code]['flag'] ?? '') . ' ' . $code . ' - ' . ($fiat_currencies_info[$code]['name'] ?? $code); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div>
<label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">充值金额</label>
<div class="input-group-custom">
<input type="number" name="amount" id="fiat-amount" placeholder="0.00" required oninput="updateExchangeRate()">
<span id="fiat-symbol-display" style="font-weight: 800; color: var(--text-muted);">USD</span>
</div>
</div>
</div>
<div style="background: rgba(255,255,255,0.03); padding: 25px; border-radius: 20px; margin-bottom: 30px; border: 1px dashed var(--border-color);">
<div style="display: flex; justify-content: space-between; margin-bottom: 10px; font-size: 14px;">
<span style="color: var(--text-muted);">实时汇率</span>
<span style="font-weight: 700;">1 USDT <span id="rate-text">--</span> <span class="current-fiat-code">USD</span></span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; border-top: 1px solid rgba(255,255,255,0.05); pt: 15px; margin-top: 15px; padding-top: 15px;">
<span style="font-weight: 800; font-size: 1.1rem;">预计收到</span>
<span style="font-weight: 800; font-size: 1.4rem; color: var(--primary-color);"><span id="receive-text">0.00</span> USDT</span>
</div>
</div>
<button type="submit" class="btn-primary submit-btn" style="width: 100%; padding: 20px; border-radius: 16px; font-size: 1.1rem; font-weight: 800;">
发起充值请求
</button>
</form>
</div>
<div id="usdt-form-section" style="display: none;">
<h3 style="margin-bottom: 25px; font-weight: 800;">2. 订单详情</h3>
<form id="usdt-deposit-form" action="matching.php" method="POST">
<input type="hidden" name="order_type" value="deposit">
<input type="hidden" name="type" value="usdt">
<input type="hidden" name="currency" value="USDT">
<label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 12px;">选择网络</label>
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 25px;">
<label class="network-opt"><input type="radio" name="network" value="TRC20" checked style="display:none;"><div class="network-box">TRC20</div></label>
<label class="network-opt"><input type="radio" name="network" value="ERC20" style="display:none;"><div class="network-box">ERC20</div></label>
<label class="network-opt"><input type="radio" name="network" value="BEP20" style="display:none;"><div class="network-box">BEP20</div></label>
</div>
<div style="margin-bottom: 30px;">
<label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">充值金额 (USDT)</label>
<div class="input-group-custom">
<input type="number" name="amount" placeholder="最小 10 USDT" required>
<span style="font-weight: 800; color: var(--text-muted);">USDT</span>
</div>
</div>
<button type="submit" class="btn-primary submit-btn" style="width: 100%; padding: 20px; border-radius: 16px; font-size: 1.1rem; font-weight: 800; background: var(--success-color);">
发起充值请求
</button>
</form>
</div>
</div>
</div>
<div class="sidebar-area">
<div class="deposit-card" style="padding: 30px;">
<h4 style="font-weight: 800; margin-bottom: 25px;"><i class="fas fa-info-circle" style="color: var(--primary-color);"></i> 充值步骤说明</h4>
<div class="instruction-item">
<div class="instruction-number">1</div>
<div style="font-size: 14px; color: var(--text-muted);">
<strong style="color: white; display: block; margin-bottom: 4px;">发起充值申请</strong>
输入您想要充值的金额并点击确认。
</div>
</div>
<div class="instruction-item">
<div class="instruction-number">2</div>
<div style="font-size: 14px; color: var(--text-muted);">
<strong style="color: white; display: block; margin-bottom: 4px;">联系在线客服</strong>
您将自动弹出客服聊天界面,客服将为您匹配唯一的收款账户。
</div>
</div>
<div class="instruction-item">
<div class="instruction-number">3</div>
<div style="font-size: 14px; color: var(--text-muted);">
<strong style="color: white; display: block; margin-bottom: 4px;">完成转账并上传凭证</strong>
按照客服提供的账户进行转账,并在聊天窗口中上传付款凭证截图。
</div>
</div>
<div class="instruction-item">
<div class="instruction-number">4</div>
<div style="font-size: 14px; color: var(--text-muted);">
<strong style="color: white; display: block; margin-bottom: 4px;">资金到账</strong>
客服确认凭证后USDT 将立即存入您的账户余额。
</div>
</div>
</div>
<div class="deposit-card" style="padding: 30px; margin-top: 20px; border-color: rgba(246,70,93,0.2);">
<h4 style="font-weight: 800; margin-bottom: 20px; color: var(--danger-color);"><i class="fas fa-exclamation-triangle"></i> 重要安全提示</h4>
<ul style="padding-left: 18px; color: var(--text-muted); font-size: 13px; line-height: 1.8;">
<li>请务必只使用客服在聊天窗口中提供的账户。</li>
<li>银行转账备注中请勿提及任何加密货币相关术语。</li>
<li>转账账户必须与您的实名认证身份一致。</li>
<li>如有任何疑问,请保持在聊天窗口中,直至问题解决。</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<style>
.network-box { padding: 15px; background: #161a1e; border: 1px solid var(--border-color); border-radius: 12px; text-align: center; font-weight: 700; cursor: pointer; transition: 0.3s; font-size: 13px; }
.network-opt input:checked + .network-box { border-color: var(--success-color); background: rgba(14,203,129,0.05); color: var(--success-color); }
</style>
<script>
function switchDepositMethod(method) {
document.getElementById('fiat-form-section').style.display = method === 'fiat' ? 'block' : 'none';
document.getElementById('usdt-form-section').style.display = method === 'usdt' ? 'block' : 'none';
document.getElementById('method-fiat').classList.toggle('active', method === 'fiat');
document.getElementById('method-usdt').classList.toggle('active', method === 'usdt');
}
function updateExchangeRate() {
const select = document.getElementById('fiat-select');
const rate = parseFloat(select.options[select.selectedIndex].getAttribute('data-rate'));
const code = select.value;
const amount = parseFloat(document.getElementById('fiat-amount').value) || 0;
document.getElementById('rate-text').innerText = rate.toFixed(2);
document.querySelectorAll('.current-fiat-code').forEach(el => el.innerText = code);
document.getElementById('fiat-symbol-display').innerText = code;
const receive = amount / rate;
document.getElementById('receive-text').innerText = receive.toFixed(2);
}
updateExchangeRate();
// AJAX Form Submission
const forms = ['fiat-deposit-form', 'usdt-deposit-form'];
forms.forEach(id => {
const form = document.getElementById(id);
if (form) {
form.onsubmit = async (e) => {
e.preventDefault();
const btn = form.querySelector('.submit-btn');
const originalText = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 处理中...';
try {
const formData = new FormData(form);
const resp = await fetch('matching.php', {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
const res = await resp.json();
if (res.success) {
// Trigger chat popup
if (typeof openCSChat === 'function') {
openCSChat();
// Optional: Disable forms to prevent double submission
form.style.opacity = '0.5';
form.style.pointerEvents = 'none';
btn.innerHTML = '<i class="fas fa-check"></i> 请求已发送';
} else {
window.location.href = 'chat.php';
}
} else {
alert(res.error || '提交失败,请稍后重试');
btn.disabled = false;
btn.innerHTML = originalText;
}
} catch (e) {
console.error(e);
alert('网络错误,请稍后重试');
btn.disabled = false;
btn.innerHTML = originalText;
}
};
}
});
</script>
<?php include 'footer.php'; ?>

90
fees.php Normal file
View File

@ -0,0 +1,90 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 1000px; margin: 0 auto;">
<h1 style="font-size: 2.5rem; font-weight: 800; margin-bottom: 20px; text-align: center;">Fee Schedule</h1>
<p style="color: var(--text-muted); text-align: center; margin-bottom: 60px;">Transparent and competitive fees for all users.</p>
<section style="margin-bottom: 60px;">
<h2 style="font-size: 1.8rem; margin-bottom: 30px;">Trading Fees</h2>
<div style="background: #161a1e; border-radius: 24px; border: 1px solid #2b3139; overflow: hidden;">
<table style="width: 100%; border-collapse: collapse; text-align: left;">
<thead>
<tr style="background: #2b3139; color: #848e9c; font-size: 0.9rem;">
<th style="padding: 20px;">Tier</th>
<th style="padding: 20px;">30d Trading Volume</th>
<th style="padding: 20px;">Maker Fee</th>
<th style="padding: 20px;">Taker Fee</th>
</tr>
</thead>
<tbody style="font-size: 0.95rem;">
<tr style="border-bottom: 1px solid #2b3139;">
<td style="padding: 20px; font-weight: bold;">VIP 0</td>
<td style="padding: 20px;">&lt; 1,000,000 USD</td>
<td style="padding: 20px; color: var(--primary-color);">0.100%</td>
<td style="padding: 20px; color: var(--primary-color);">0.100%</td>
</tr>
<tr style="border-bottom: 1px solid #2b3139;">
<td style="padding: 20px; font-weight: bold;">VIP 1</td>
<td style="padding: 20px;"> 1,000,000 USD</td>
<td style="padding: 20px; color: var(--primary-color);">0.090%</td>
<td style="padding: 20px; color: var(--primary-color);">0.100%</td>
</tr>
<tr style="border-bottom: 1px solid #2b3139;">
<td style="padding: 20px; font-weight: bold;">VIP 2</td>
<td style="padding: 20px;"> 5,000,000 USD</td>
<td style="padding: 20px; color: var(--primary-color);">0.080%</td>
<td style="padding: 20px; color: var(--primary-color);">0.090%</td>
</tr>
<tr>
<td style="padding: 20px; font-weight: bold;">VIP 3</td>
<td style="padding: 20px;"> 20,000,000 USD</td>
<td style="padding: 20px; color: var(--primary-color);">0.070%</td>
<td style="padding: 20px; color: var(--primary-color);">0.085%</td>
</tr>
</tbody>
</table>
</div>
</section>
<section>
<h2 style="font-size: 1.8rem; margin-bottom: 30px;">Withdrawal Fees</h2>
<div style="background: #161a1e; border-radius: 24px; border: 1px solid #2b3139; overflow: hidden;">
<table style="width: 100%; border-collapse: collapse; text-align: left;">
<thead>
<tr style="background: #2b3139; color: #848e9c; font-size: 0.9rem;">
<th style="padding: 20px;">Asset</th>
<th style="padding: 20px;">Network</th>
<th style="padding: 20px;">Min. Withdrawal</th>
<th style="padding: 20px;">Fixed Fee</th>
</tr>
</thead>
<tbody style="font-size: 0.95rem;">
<tr style="border-bottom: 1px solid #2b3139;">
<td style="padding: 20px; font-weight: bold;">BTC</td>
<td style="padding: 20px;">Bitcoin</td>
<td style="padding: 20px;">0.001</td>
<td style="padding: 20px; color: #f6465d;">0.0005</td>
</tr>
<tr style="border-bottom: 1px solid #2b3139;">
<td style="padding: 20px; font-weight: bold;">ETH</td>
<td style="padding: 20px;">ERC20</td>
<td style="padding: 20px;">0.01</td>
<td style="padding: 20px; color: #f6465d;">0.005</td>
</tr>
<tr>
<td style="padding: 20px; font-weight: bold;">USDT</td>
<td style="padding: 20px;">TRC20 / BEP20</td>
<td style="padding: 20px;">10.0</td>
<td style="padding: 20px; color: #f6465d;">1.00</td>
</tr>
</tbody>
</table>
</div>
</section>
<p style="margin-top: 40px; color: var(--text-muted); font-size: 0.85rem;">* Deposit fees are 0% for all supported assets. Withdrawal fees are adjusted periodically based on network conditions.</p>
</div>
</main>
<?php include 'footer.php'; ?>

82
footer.php Normal file
View File

@ -0,0 +1,82 @@
<footer style="margin-top: 60px; background: #0b0e11; border-top: 1px solid var(--border-color); padding: 60px 5% 40px;">
<div style="max-width: 1200px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 40px;">
<div class="col">
<div class="logo-text" style="margin-bottom: 1.5rem;">
<svg class="logo-svg" viewBox="0 0 100 100" style="width:32px; height:32px; vertical-align: middle;">
<rect x="10" y="10" width="80" height="80" rx="20" fill="url(#gradFooter)"/>
<path d="M30 30 L70 70 M70 30 L30 70" stroke="white" stroke-width="12" stroke-linecap="round"/>
<defs>
<linearGradient id="gradFooter" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#4facfe;stop-opacity:1" />
<stop offset="100%" style="stop-color:#00f2fe;stop-opacity:1" />
</linearGradient>
</defs>
</svg>
<?php echo __('site_name'); ?>
</div>
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 1.5rem;"><?php echo __('footer_desc'); ?></p>
<div style="display: flex; gap: 1.2rem; font-size: 1.2rem;">
<a href="#" style="color: var(--text-muted); transition: color 0.3s;"><i class="fab fa-twitter"></i></a>
<a href="#" style="color: var(--text-muted); transition: color 0.3s;"><i class="fab fa-telegram"></i></a>
<a href="#" style="color: var(--text-muted); transition: color 0.3s;"><i class="fab fa-facebook"></i></a>
<a href="#" style="color: var(--text-muted); transition: color 0.3s;"><i class="fab fa-discord"></i></a>
</div>
</div>
<div class="col">
<h4 style="font-size: 16px; margin-bottom: 20px; color: white;"><?php echo __('about'); ?></h4>
<div style="display: flex; flex-direction: column; gap: 10px;">
<a href="about.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('about_us'); ?></a>
<a href="careers.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('careers'); ?></a>
<a href="news.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('news'); ?></a>
<a href="privacy.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('legal_privacy'); ?></a>
<a href="terms.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('terms_service'); ?></a>
</div>
</div>
<div class="col">
<h4 style="font-size: 16px; margin-bottom: 20px; color: white;"><?php echo __('products'); ?></h4>
<div style="display: flex; flex-direction: column; gap: 10px;">
<a href="spot.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('spot_trading'); ?></a>
<a href="futures.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('futures_trading'); ?></a>
<a href="app.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('app_download'); ?></a>
<a href="convert.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('flash_swap'); ?></a>
<a href="mining.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('staking'); ?></a>
</div>
</div>
<div class="col">
<h4 style="font-size: 16px; margin-bottom: 20px; color: white;"><?php echo __('support'); ?></h4>
<div style="display: flex; flex-direction: column; gap: 10px;">
<a href="help.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('help_center'); ?></a>
<a href="request.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('submit_request'); ?></a>
<a href="api-docs.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('api_docs'); ?></a>
<a href="fees.php" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><?php echo __('fee_schedule'); ?></a>
</div>
</div>
</div>
<div class="footer-bottom" style="max-width: 1200px; margin: 40px auto 0; padding-top: 30px; border-top: 1px solid #1e2329; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
<div style="color: var(--text-muted); font-size: 12px;">
&copy; 2017-2026 <?php echo strtoupper(__('site_name')); ?>.COM <?php echo __('all_rights_reserved'); ?>
</div>
<div style="display: flex; gap: 15px; color: var(--text-muted); font-size: 12px; flex-wrap: wrap;">
<div style="display: flex; align-items: center; gap: 5px; color: var(--success-color);">
<i class="fas fa-check-circle"></i> <?php echo __('system_status_normal'); ?>
</div>
<span><?php echo __('cookie_policy'); ?></span>
<span><?php echo __('security'); ?></span>
</div>
</div>
</footer>
<style>
footer a:hover { color: white !important; }
@media (max-width: 768px) {
footer { min-width: 100% !important; padding: 40px 20px !important; margin-bottom: 65px; }
.footer-bottom { justify-content: center !important; text-align: center; }
}
</style>
</body>
</html>

400
futures.php Normal file
View File

@ -0,0 +1,400 @@
<?php
include 'header.php';
$user_id = $_SESSION['user_id'] ?? null;
$user_assets = [];
if ($user_id) {
$stmt = $db->prepare("SELECT balance FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$usdt_balance = $stmt->fetchColumn();
$user_assets['USDT'] = (float)($usdt_balance ?: 0);
$stmt = $db->prepare("SELECT symbol, amount FROM user_assets WHERE user_id = ?");
$stmt->execute([$user_id]);
$assets_data = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
if ($assets_data) {
foreach ($assets_data as $symbol => $amount) {
$user_assets[$symbol] = (float)$amount;
}
}
}
?>
<style>
.trading-page-wrapper { display: flex; flex-direction: column; min-height: 100vh; background: #0b0e11; }
.trading-container { flex-grow: 1; display: flex; min-height: 800px; max-width: 1920px; margin: 0 auto; width: 100%; }
.left-col { width: 280px; flex-shrink: 0; background: #161a1e; border-right: 1px solid #2b3139; display: flex; flex-direction: column; }
.center-col { flex: 1; min-width: 600px; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.right-col { width: 300px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; }
.chart-header { height: 55px; padding: 0 20px; display: flex; align-items: center; background: #161a1e; border-bottom: 1px solid #2b3139; gap: 20px; flex-shrink: 0; }
.chart-box { height: 450px; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.bottom-content-wrapper { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.order-box { padding: 20px; background: #161a1e; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.records-container { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.record-tabs { display: flex; padding: 0 20px; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.record-tab { padding: 12px 0; margin-right: 25px; font-size: 13px; font-weight: 600; color: #848e9c; cursor: pointer; position: relative; }
.record-tab.active { color: white; }
.record-tab.active::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 2px; background: var(--primary-color); }
#records-list-container { height: 350px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
#records-list-container::-webkit-scrollbar { width: 4px; }
#records-list-container::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
table { width: 100%; font-size: 12px; border-collapse: collapse; }
th { color: #848e9c; font-weight: 500; text-align: left; padding: 10px 15px; border-bottom: 1px solid #2b3139; background: #161a1e; position: sticky; top: 0; z-index: 10; }
td { padding: 10px 15px; border-bottom: 1px solid rgba(255,255,255,0.02); color: #eaecef; height: 38px; }
.category-tabs { display: flex; padding: 15px 15px 5px; gap: 8px; }
.category-tab { flex: 1; text-align: center; padding: 6px 0; background: #2b3139; border-radius: 4px; font-size: 12px; color: #848e9c; cursor: pointer; border: 1px solid transparent; }
.category-tab.active { background: rgba(0, 82, 255, 0.1); border-color: var(--primary-color); color: var(--primary-color); font-weight: bold; }
.search-box { padding: 10px 15px 15px; position: relative; }
.search-box i { position: absolute; left: 25px; top: 22px; color: #848e9c; font-size: 12px; }
.search-box input { width: 100%; background: #2b3139; border: 1px solid transparent; border-radius: 6px; padding: 8px 10px 8px 35px; color: white; font-size: 13px; outline: none; transition: 0.2s; }
.search-box input:focus { border-color: var(--primary-color); }
#pairs-list { height: 684px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
#pairs-list::-webkit-scrollbar { width: 4px; }
#pairs-list::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
.pair-item { display: flex; align-items: center; padding: 10px 15px; cursor: pointer; border-bottom: 1px solid rgba(255,255,255,0.02); height: 38px; }
.pair-item.active { background: #1e2329; border-left: 3px solid var(--primary-color); }
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; }
.futures-config { display: flex; gap: 10px; margin-bottom: 12px; }
.config-btn { flex: 1; background: #2b3139; color: white; padding: 8px; border-radius: 4px; text-align: center; font-size: 12px; cursor: pointer; border: 1px solid #3c424a; }
.input-group { background: #2b3139; border-radius: 4px; padding: 8px 12px; display: flex; align-items: center; margin-bottom: 10px; border: 1px solid #3c424a; }
.input-group:focus-within { border-color: var(--primary-color); }
.input-group input { background: transparent; border: none; color: white; flex: 1; outline: none; font-size: 14px; width: 100%; }
.input-group .label { color: #848e9c; font-size: 12px; margin-right: 10px; min-width: 40px; }
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 12px; }
.slider-container { margin: 15px 0 20px; }
input[type=range] { width: 100%; height: 4px; background: #2b3139; border-radius: 2px; outline: none; }
.trade-btn { width: 100%; padding: 12px; border-radius: 4px; font-weight: bold; font-size: 15px; border: none; cursor: pointer; color: white; transition: 0.2s; }
.btn-buy { background: #0ecb81; }
.btn-sell { background: #f6465d; }
.trade-btn:hover { filter: brightness(1.1); }
.right-col-tabs { display: flex; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.right-col-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 13px; font-weight: 600; color: #848e9c; cursor: pointer; }
.right-col-tab.active { color: white; background: #1e2329; }
.ob-header { display: flex; justify-content: space-between; padding: 8px 15px; font-size: 11px; color: #848e9c; border-bottom: 1px solid #2b3139; }
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; cursor: pointer; }
#ob-panel-content { flex: 1; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
#ob-panel-content::-webkit-scrollbar { width: 4px; }
#ob-panel-content::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
/* Mobile Specific Styles */
@media (max-width: 991px) {
.trading-container { flex-direction: column; min-height: auto; }
.center-col { min-width: 100%; border-right: none; }
.chart-box { height: 300px; }
.order-box { padding: 15px; }
#records-list-container { height: auto; max-height: 400px; }
.trading-page-wrapper { padding-bottom: 70px; }
.mobile-trade-nav {
display: flex; background: #161a1e; border-bottom: 1px solid #2b3139; padding: 10px 15px; gap: 10px;
}
.mobile-trade-nav a {
flex: 1; text-align: center; padding: 8px 0; background: #2b3139; border-radius: 8px; font-size: 13px; color: #848e9c; text-decoration: none; font-weight: 600; border: 1px solid transparent;
}
.mobile-trade-nav a.active {
background: rgba(0, 82, 255, 0.1); color: var(--primary-color); border-color: var(--primary-color);
}
.mobile-symbol-selector {
display: flex; align-items: center; justify-content: space-between; padding: 12px 15px; background: #161a1e; border-bottom: 1px solid #2b3139;
}
}
@media (min-width: 992px) {
.mobile-trade-nav, .mobile-symbol-selector { display: none; }
}
/* Mobile Drawer */
#mobile-pairs-drawer {
position: fixed; top: 0; left: -100%; width: 100%; height: 100%; background: #0b0e11; z-index: 3000; transition: 0.3s; padding: 20px; display: flex; flex-direction: column;
}
#mobile-pairs-drawer.open { left: 0; }
</style>
<div class="trading-page-wrapper">
<!-- Mobile Navigation Tabs -->
<div class="mobile-trade-nav">
<a href="options.php"><?php echo __('nav_options'); ?></a>
<a href="spot.php"><?php echo __('nav_spot'); ?></a>
<a href="futures.php" class="active"><?php echo __('nav_futures'); ?></a>
</div>
<!-- Mobile Symbol Selector -->
<div class="mobile-symbol-selector" onclick="toggleMobilePairs()">
<div style="display: flex; align-items: center; gap: 10px;">
<img id="curr-icon-mobile" src="" class="coin-icon" style="width: 28px; height: 28px;">
<span id="curr-pair-mobile" style="font-weight: 800; font-size: 18px; color: white;">--/--</span>
<i class="fas fa-caret-down" style="color: #848e9c;"></i>
</div>
<div style="text-align: right;">
<div id="curr-price-mobile" style="font-size: 18px; font-weight: 800; color: #0ecb81;">--</div>
<div id="curr-change-mobile" style="font-size: 12px; font-weight: 600;">--</div>
</div>
</div>
<div class="trading-container">
<!-- Left Column -->
<div class="left-col d-none d-lg-flex">
<div class="category-tabs">
<div class="category-tab" onclick="location.href='options.php'"><?php echo __('nav_options'); ?></div>
<div class="category-tab" onclick="location.href='spot.php'"><?php echo __('nav_spot'); ?></div>
<div class="category-tab active" onclick="location.href='futures.php'"><?php echo __('nav_futures'); ?></div>
</div>
<div class="search-box"><i class="fas fa-search"></i><input type="text" id="pair-search" placeholder="<?php echo __('search_contract'); ?>"></div>
<div id="pairs-list"></div>
</div>
<!-- Center Column -->
<div class="center-col">
<div class="chart-header d-none d-lg-flex">
<div style="display: flex; align-items: center; gap: 10px;">
<img id="curr-icon" src="" class="coin-icon">
<span id="curr-pair" style="font-weight: 800; font-size: 18px; color:white;">--/--</span>
</div>
<div class="stats-item">
<div id="curr-price" style="font-size: 20px; font-weight: 800; color: #0ecb81;">--</div>
<div id="curr-change" style="font-size: 12px; font-weight: 600;">--</div>
</div>
</div>
<div class="chart-box" id="tv_chart_container"></div>
<div class="bottom-content-wrapper">
<div class="order-box">
<div class="futures-config">
<div class="config-btn"><?php echo __('cross'); ?></div>
<div class="config-btn" id="leverage-val">20x</div>
</div>
<div class="input-group"><span class="label"><?php echo __('price'); ?></span><input type="text" placeholder="<?php echo __('market'); ?>" disabled><span class="unit">USDT</span></div>
<div class="input-group"><span class="label"><?php echo __('amount'); ?></span><input type="number" id="futures-amount" step="0.0001" placeholder="0.00"><span class="unit coin-name">--</span></div>
<div class="slider-container"><input type="range" id="futures-slider" min="0" max="100" value="0"></div>
<div style="font-size: 12px; color: #848e9c; margin-bottom: 12px;"><?php echo __('available'); ?>: <span id="avail-usdt" style="color:white; font-weight:600">0.00</span> USDT</div>
<div style="display: flex; gap: 15px;">
<button id="btn-buy" class="trade-btn btn-buy"><?php echo __('open_long'); ?></button>
<button id="btn-sell" class="trade-btn btn-sell"><?php echo __('open_short'); ?></button>
</div>
</div>
<div class="records-container">
<div class="record-tabs">
<div class="record-tab active" data-status="positions"><?php echo __('current_positions'); ?></div>
<div class="record-tab" data-status="history"><?php echo __('history_orders'); ?></div>
</div>
<div id="records-list-container">
<table style="width:100%;" id="records-table"></table>
</div>
</div>
</div>
</div>
<!-- Right Column -->
<div class="right-col d-none d-xl-flex">
<div class="right-col-tabs">
<div class="right-col-tab active" data-tab="ob"><?php echo __('order_book'); ?></div>
<div class="right-col-tab" data-tab="trades"><?php echo __('trades'); ?></div>
</div>
<div id="ob-panel" style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
<div class="ob-header"><span><?php echo __('price'); ?></span><span><?php echo __('amount'); ?></span></div>
<div id="ob-panel-content">
<div id="asks-list"></div>
<div id="mid-price" style="padding:10px 15px; text-align:center; font-weight:800; font-size:16px; border-top:1px solid #2b3139; border-bottom:1px solid #2b3139;">--</div>
<div id="bids-list"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Mobile Pairs Drawer -->
<div id="mobile-pairs-drawer">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<h3 style="margin: 0; font-weight: 800;"><?php echo __('market'); ?></h3>
<i class="fas fa-times" onclick="toggleMobilePairs()" style="font-size: 20px; color: #848e9c;"></i>
</div>
<div class="search-box" style="padding: 0; margin-bottom: 20px;">
<i class="fas fa-search"></i>
<input type="text" id="pair-search-mobile" placeholder="<?php echo __('search_contract'); ?>">
</div>
<div id="pairs-list-mobile" style="flex: 1; overflow-y: auto;"></div>
</div>
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script>
const userAssets = <?php echo json_encode($user_assets); ?>;
function toggleMobilePairs() {
document.getElementById('mobile-pairs-drawer').classList.toggle('open');
}
document.addEventListener('DOMContentLoaded', function() {
let currentPair = 'BTCUSDT', currentPrice = 0, ws, leverage = 20, chartWidget;
const marketData = {}, pairs = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'AVAXUSDT', 'DOTUSDT', 'MATICUSDT', 'LTCUSDT', 'TRXUSDT', 'LINKUSDT', 'UNIUSDT', 'ATOMUSDT', 'ETCUSDT', 'BCHUSDT', 'FILUSDT', 'ICPUSDT', 'NEARUSDT', 'AAVEUSDT', 'ALGOUSDT'];
const dom = {
currIcon: document.getElementById('curr-icon'),
currPair: document.getElementById('curr-pair'),
currPrice: document.getElementById('curr-price'),
currChange: document.getElementById('curr-change'),
currIconMobile: document.getElementById('curr-icon-mobile'),
currPairMobile: document.getElementById('curr-pair-mobile'),
currPriceMobile: document.getElementById('curr-price-mobile'),
currChangeMobile: document.getElementById('curr-change-mobile'),
tvContainer: document.getElementById('tv_chart_container'),
pairsList: document.getElementById('pairs-list'),
pairsListMobile: document.getElementById('pairs-list-mobile'),
pairSearchMobile: document.getElementById('pair-search-mobile'),
asksList: document.getElementById('asks-list'),
bidsList: document.getElementById('bids-list'),
midPrice: document.getElementById('mid-price'),
availUsdt: document.getElementById('avail-usdt'),
coinNames: document.querySelectorAll('.coin-name'),
amountInput: document.getElementById('futures-amount'),
slider: document.getElementById('futures-slider'),
recordsTable: document.getElementById('records-table')
};
function updateBalances() {
dom.availUsdt.innerText = parseFloat(userAssets.USDT || 0).toFixed(2);
dom.coinNames.forEach(el => el.innerText = currentPair.replace('USDT', ''));
}
function initChart(symbol) {
dom.tvContainer.innerHTML = '';
new TradingView.widget({
"autosize": true, "symbol": `BINANCE:${symbol}`, "interval": "15", "theme": "dark", "style": "1",
"locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>", "container_id": "tv_chart_container",
"hide_side_toolbar": true, "allow_symbol_change": false, "studies": ["Volume@tv-basicstudies"],
"overrides": { "paneProperties.background": "#161a1e" }
});
}
function connectWS() {
if (ws) ws.close();
const streams = pairs.map(p => `${p.toLowerCase()}@ticker`).concat([`${currentPair.toLowerCase()}@depth20@100ms`]);
ws = new WebSocket(`wss://stream.binance.com:9443/stream?streams=${streams.join('/')}`);
ws.onmessage = (e) => {
const { stream, data } = JSON.parse(e.data);
if (!data) return;
if (stream.endsWith('@ticker')) {
marketData[data.s] = data;
if (data.s === currentPair) {
currentPrice = parseFloat(data.c);
const color = data.P >= 0 ? '#0ecb81' : '#f6465d';
const priceStr = currentPrice.toLocaleString('en-US', {minimumFractionDigits:2});
const changeStr = (data.P >= 0 ? '+' : '') + parseFloat(data.P).toFixed(2) + '%';
if(dom.currPrice) dom.currPrice.innerText = priceStr;
if(dom.currChange) dom.currChange.innerText = changeStr;
if(dom.currPrice) dom.currPrice.style.color = dom.currChange.style.color = color;
dom.currPriceMobile.innerText = priceStr;
dom.currPriceMobile.style.color = color;
dom.currChangeMobile.innerText = changeStr;
dom.currChangeMobile.style.color = color;
if(dom.midPrice) dom.midPrice.innerText = currentPrice.toFixed(2);
}
if (dom.pairsList.offsetParent || dom.pairsListMobile.offsetParent) renderPairs();
} else if (stream.endsWith('@depth20@100ms')) {
if(dom.asksList) {
dom.asksList.innerHTML = data.asks.slice(0, 20).reverse().map(a => `<div class="ob-row" onclick="document.getElementById('futures-amount').value=${parseFloat(a[1]).toFixed(4)};"><span style="color:#f6465d">${parseFloat(a[0]).toFixed(2)}</span><span>${parseFloat(a[1]).toFixed(4)}</span></div>`).join('');
dom.bidsList.innerHTML = data.bids.slice(0, 20).map(b => `<div class="ob-row" onclick="document.getElementById('futures-amount').value=${parseFloat(b[1]).toFixed(4)};"><span style="color:#0ecb81">${parseFloat(b[0]).toFixed(2)}</span><span>${parseFloat(b[1]).toFixed(4)}</span></div>`).join('');
}
}
};
ws.onclose = () => setTimeout(connectWS, 5000);
}
function renderPairs() {
const query = document.getElementById('pair-search').value.toUpperCase();
const queryMobile = dom.pairSearchMobile.value.toUpperCase();
const generateHtml = (q) => pairs.filter(p => p.includes(q)).map(p => {
const d = marketData[p] || {};
return `<div class="pair-item ${p === currentPair ? 'active' : ''}" onclick="switchPair('${p}')">
<img src="https://assets.coincap.io/assets/icons/${p.replace('USDT','').toLowerCase()}@2x.png" class="coin-icon" onerror="this.style.opacity=0">
<div style="flex:1; color:white; font-weight:600">${p.replace('USDT','/USDT')}</div>
<div style="text-align:right"><div style="color:white; font-weight:600">${d.c ? parseFloat(d.c).toFixed(2) : '--'}</div><div style="color:${d.P>=0?'#0ecb81':'#f6465d'}; font-size:11px">${d.P?(d.P>=0?'+':'')+parseFloat(d.P).toFixed(2)+'%':'--'}</div></div>
</div>`;
}).join('');
dom.pairsList.innerHTML = generateHtml(query);
dom.pairsListMobile.innerHTML = generateHtml(queryMobile);
}
window.switchPair = (p) => {
currentPair = p;
if(dom.currPair) dom.currPair.innerText = p.replace('USDT', '/USDT') + ' Perp';
dom.currPairMobile.innerText = p.replace('USDT', '/USDT') + ' Perp';
if(dom.currIcon) dom.currIcon.src = `https://assets.coincap.io/assets/icons/${p.replace('USDT','').toLowerCase()}@2x.png`;
dom.currIconMobile.src = `https://assets.coincap.io/assets/icons/${p.replace('USDT','').toLowerCase()}@2x.png`;
initChart(p);
updateBalances();
connectWS();
if(document.getElementById('mobile-pairs-drawer').classList.contains('open')) toggleMobilePairs();
};
dom.pairSearchMobile.addEventListener('input', renderPairs);
async function placeOrder(side) {
const amount = parseFloat(dom.amountInput.value);
if (!amount || amount <= 0) { alert("Amount > 0"); return; }
const price = currentPrice;
const total = amount * price;
try {
const r = await fetch('api/place_order.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
symbol: currentPair, type: 'futures', side: side, order_type: 'market',
price: price, amount: amount, total: total, leverage: leverage
})
});
const res = await r.json();
if (res.success) { alert("<?php echo __('order_placed'); ?>"); fetchOrders(); }
else { alert(res.error || "Error"); }
} catch(e) { alert("Network Error"); }
}
document.getElementById('btn-buy').onclick = () => placeOrder('buy');
document.getElementById('btn-sell').onclick = () => placeOrder('sell');
let activeTab = 'positions';
async function fetchOrders() {
try {
const r = await fetch(`api/get_orders.php?type=futures&status=${activeTab}`);
const res = await r.json();
if (res.success) renderOrders(res.data);
} catch(e) {}
}
function renderOrders(orders) {
if (!orders || orders.length === 0) { dom.recordsTable.innerHTML = '<tr><td colspan="6" style="text-align:center; padding:30px; color:#848e9c"><?php echo __('no_records'); ?></td></tr>'; return; }
let h = `<thead><tr><th><?php echo __('pair'); ?></th><th><?php echo __('direction'); ?></th><th><?php echo __('price'); ?></th><th><?php echo __('amount'); ?></th><th><?php echo __('leverage'); ?></th><th><?php echo __('time'); ?></th></tr></thead><tbody>`;
orders.forEach(o => {
h += `<tr><td>${o.symbol}</td><td style="color:${o.side==='buy'?'#0ecb81':'#f6465d'}">${o.side==='buy'?'<?php echo __('buy_long'); ?>':'<?php echo __('sell_short'); ?>'}</td><td>${parseFloat(o.price).toFixed(2)}</td><td>${parseFloat(o.amount).toFixed(4)}</td><td>${o.leverage}x</td><td style="color:#848e9c">${o.created_at}</td></tr>`;
});
dom.recordsTable.innerHTML = h + '</tbody>';
}
document.querySelectorAll('.record-tab').forEach(t => t.onclick = () => {
if (!t.dataset.status) return;
document.querySelector('.record-tabs .active').classList.remove('active');
t.classList.add('active');
activeTab = t.dataset.status;
fetchOrders();
});
switchPair('BTCUSDT');
fetchOrders();
setInterval(fetchOrders, 5000);
});
</script>
<?php include 'footer.php'; ?>

318
header.php Normal file
View File

@ -0,0 +1,318 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once 'includes/i18n.php';
require_once 'db/config.php';
$db = db();
$settings_res = $db->query("SELECT * FROM settings")->fetchAll();
$settings = [];
foreach($settings_res as $s) $settings[$s['name']] = $s['value'];
$site_logo = $settings['site_logo'] ?? null;
?>
<!DOCTYPE html>
<html lang="<?php echo $lang; ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title><?php echo __('site_title'); ?></title>
<?php if($site_logo): ?>
<link rel="icon" href="<?php echo $site_logo; ?>" type="image/x-icon">
<?php endif; ?>
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root {
--app-max-width: 1920px;
--primary-color: #0052FF;
--bg-color: #0b0e11;
--card-bg: #1e2329;
--border-color: #2b3139;
--text-color: #ffffff;
--text-muted: #848e9c;
--success-color: #0ecb81;
--danger-color: #f6465d;
}
body {
margin: 0 auto;
max-width: var(--app-max-width);
background-color: var(--bg-color);
color: var(--text-color);
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
-webkit-font-smoothing: antialiased;
}
.navbar {
background-color: var(--bg-color);
padding: 0 24px;
height: 64px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border-color);
position: sticky;
top: 0;
z-index: 1000;
}
.logo-text { font-size: 1.6rem; font-weight: 800; color: white; letter-spacing: -0.5px; display: flex; align-items: center; gap: 8px; }
.logo-svg { width: 30px; height: 30px; fill: var(--primary-color); }
.site-logo-img { max-height: 32px; width: auto; }
.nav-links { display: flex; gap: 24px; align-items: center; margin-left: 30px; }
.nav-links a { color: var(--text-color); text-decoration: none; font-size: 14px; font-weight: 600; transition: color 0.2s; }
.nav-links a:hover { color: var(--primary-color); }
.nav-links a.active { color: var(--primary-color); }
/* Floating CS Chat */
.floating-service { position: fixed; bottom: 85px; right: 20px; width: 56px; height: 56px; background: var(--primary-color); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-size: 1.4rem; cursor: pointer; box-shadow: 0 8px 20px rgba(0,82,255,0.4); z-index: 999; transition: transform 0.2s; }
.floating-service:active { transform: scale(0.9); }
#cs-chat-window { position: fixed; bottom: 0; left: 0; right: 0; top: 0; width: 100%; height: 100%; background: #161a1e; display: none; flex-direction: column; z-index: 2100; }
#cs-chat-window iframe { border: none; width: 100%; height: 100%; }
.chat-header { background: #2b3139; padding: 15px; display: flex; justify-content: space-between; align-items: center; color: white; font-weight: bold; }
@media (min-width: 993px) {
#cs-chat-window { bottom: 100px; right: 30px; left: auto; top: auto; width: 400px; height: 600px; border-radius: 16px; border: 1px solid var(--border-color); overflow: hidden; box-shadow: 0 20px 50px rgba(0,0,0,0.6); }
.floating-service { bottom: 30px; right: 30px; width: 64px; height: 64px; }
}
/* Sidebar Drawer */
.mobile-sidebar { position: fixed; top: 0; left: -100%; width: 300px; height: 100%; background: var(--bg-color); z-index: 2200; transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1); box-shadow: 20px 0 50px rgba(0,0,0,0.8); padding: 0; overflow-y: auto; }
.mobile-sidebar.open { left: 0; }
.sidebar-overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.8); z-index: 2199; backdrop-filter: blur(4px); }
.sidebar-overlay.open { display: block; }
.sidebar-header { padding: 24px; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center; }
.sidebar-links { padding: 15px 0; }
.sidebar-links a { display: flex; align-items: center; gap: 16px; padding: 16px 24px; color: white; text-decoration: none; font-size: 15px; font-weight: 500; transition: background 0.2s; }
.sidebar-links a:active { background: var(--card-bg); }
.sidebar-links a i { width: 20px; font-size: 18px; text-align: center; }
@media (max-width: 992px) {
.nav-links { display: none; }
.navbar { padding: 0 16px; }
.logo-name { font-size: 1.4rem; }
#mobileMenuBtn { display: block !important; margin-right: 15px; }
}
.dropdown-content { display: none; position: absolute; background-color: var(--card-bg); min-width: 200px; box-shadow: 0 15px 40px rgba(0,0,0,0.6); z-index: 1001; border: 1px solid var(--border-color); border-radius: 12px; top: 100%; right: 0; overflow: hidden; }
.dropdown:hover .dropdown-content { display: block; }
.dropdown-content a { color: white; padding: 14px 20px; text-decoration: none; display: flex; align-items: center; gap: 12px; font-size: 14px; transition: background 0.2s; }
.dropdown-content a:hover { background-color: var(--border-color); }
</style>
</head>
<body>
<!-- Sidebar Overlay -->
<div class="sidebar-overlay" id="sidebarOverlay" onclick="toggleSidebar()"></div>
<!-- Mobile Sidebar -->
<div class="mobile-sidebar" id="mobileSidebar">
<div class="sidebar-header">
<div class="logo-text">
<?php if($site_logo): ?>
<img src="<?php echo $site_logo; ?>" class="site-logo-img" alt="Logo">
<?php else: ?>
<span style="font-size: 1.5rem; color: var(--primary-color);"><?php echo __('site_name'); ?></span>
<?php endif; ?>
</div>
<i class="fas fa-times" style="font-size: 1.4rem; color: var(--text-muted); cursor: pointer;" onclick="toggleSidebar()"></i>
</div>
<div class="sidebar-links">
<a href="index.php"><i class="fas fa-home" style="color: #5d5dff;"></i> <?php echo __('nav_home'); ?></a>
<a href="markets.php"><i class="fas fa-chart-line" style="color: #00e676;"></i> <?php echo __('nav_market'); ?></a>
<a href="options.php"><i class="fas fa-clock" style="color: #fbc02d;"></i> <?php echo __('nav_options'); ?></a>
<a href="spot.php"><i class="fas fa-coins" style="color: #ffd600;"></i> <?php echo __('nav_spot'); ?></a>
<a href="futures.php"><i class="fas fa-file-contract" style="color: #ff3d00;"></i> <?php echo __('nav_futures'); ?></a>
<a href="mining.php"><i class="fas fa-hammer" style="color: #8e24aa;"></i> <?php echo __('nav_mining'); ?></a>
<a href="app.php"><i class="fas fa-mobile-alt" style="color: #4facfe;"></i> <?php echo __('nav_app_download'); ?></a>
<div style="margin: 20px 24px; padding: 20px; background: var(--card-bg); border-radius: 16px;">
<div style="color: var(--text-muted); font-size: 12px; font-weight: 700; margin-bottom: 12px; text-transform: uppercase; letter-spacing: 1px;"><?php echo __('language'); ?></div>
<div style="display: flex; gap: 10px;">
<a href="?lang=en" style="padding: 10px; background: #0b0e11; border-radius: 8px; font-size: 14px; flex: 1; border: 1px solid var(--border-color); justify-content: center; text-decoration: none; color: white; display: flex; align-items: center; gap: 8px;">
<img src="https://flagcdn.com/w20/us.png" width="18" alt="English"> EN
</a>
<a href="?lang=zh" style="padding: 10px; background: #0b0e11; border-radius: 8px; font-size: 14px; flex: 1; border: 1px solid var(--border-color); justify-content: center; text-decoration: none; color: white; display: flex; align-items: center; gap: 8px;">
<img src="https://flagcdn.com/w20/cn.png" width="18" alt="Chinese"> 中文
</a>
</div>
</div>
</div>
</div>
<div class="floating-service" id="floatingChatBtn" onclick="toggleCSChat()" title="<?php echo __('support_online'); ?>">
<i class="fas fa-headset"></i>
</div>
<div id="cs-chat-window">
<div class="chat-header">
<span><?php echo __('support_online'); ?></span>
<i class="fas fa-times" onclick="toggleCSChat()" style="cursor: pointer;"></i>
</div>
<iframe id="cs-chat-iframe" src="chat_iframe.php"></iframe>
</div>
<nav class="navbar">
<div style="display: flex; align-items: center;">
<i class="fas fa-bars d-md-none" id="mobileMenuBtn" style="font-size: 1.4rem; cursor: pointer; display: none;" onclick="toggleSidebar()"></i>
<a href="index.php" style="text-decoration: none;">
<div class="logo-text">
<?php if($site_logo): ?>
<img src="<?php echo $site_logo; ?>" class="site-logo-img" alt="Logo">
<?php else: ?>
<svg class="logo-svg" viewBox="0 0 100 100">
<rect x="10" y="10" width="80" height="80" rx="20" fill="var(--primary-color)"/>
<path d="M30 30 L70 70 M70 30 L30 70" stroke="white" stroke-width="12" stroke-linecap="round"/>
</svg>
<span class="logo-name"><?php echo __('site_name'); ?></span>
<?php endif; ?>
</div>
</a>
<div class="nav-links">
<a href="index.php"><?php echo __('nav_home'); ?></a>
<a href="markets.php"><?php echo __('nav_market'); ?></a>
<a href="options.php"><?php echo __('nav_options'); ?></a>
<a href="spot.php"><?php echo __('nav_spot'); ?></a>
<a href="futures.php"><?php echo __('nav_futures'); ?></a>
<a href="mining.php"><?php echo __('nav_mining'); ?></a>
</div>
</div>
<div style="display: flex; gap: 1rem; align-items: center;">
<div class="dropdown d-none d-lg-block">
<a href="#" style="color: white; display: flex; align-items: center; gap: 8px; text-decoration: none; font-size: 14px; font-weight: 600;">
<i class="fas fa-globe" style="color: var(--primary-color);"></i>
<span><?php echo $lang == 'en' ? 'EN' : 'ZH'; ?></span>
</a>
<div class="dropdown-content">
<a href="?lang=en"><img src="https://flagcdn.com/w20/us.png" width="18"> English</a>
<a href="?lang=zh"><img src="https://flagcdn.com/w20/cn.png" width="18"> 简体中文</a>
</div>
</div>
<?php if(isset($_SESSION['user_id'])): ?>
<div class="dropdown">
<a href="#" style="color: white; display: flex; align-items: center; gap: 8px; text-decoration: none;">
<i class="fas fa-user-circle" style="font-size: 2rem; color: var(--primary-color);"></i>
</a>
<div class="dropdown-content">
<div style="padding: 16px; border-bottom: 1px solid var(--border-color); background: rgba(0,82,255,0.05);">
<div style="font-weight: 800; color: white; font-size: 14px;"><?php echo htmlspecialchars($_SESSION['username'] ?? 'User'); ?></div>
<div style="color: var(--text-muted); font-size: 11px; margin-top: 4px;">UID: <?php echo $_SESSION['uid'] ?? '------'; ?></div>
</div>
<a href="profile.php"><i class="fas fa-wallet" style="color: #03a9f4;"></i> <?php echo __('nav_assets'); ?></a>
<a href="deposit.php"><i class="fas fa-plus-circle" style="color: #00f2fe;"></i> <?php echo __('nav_deposit'); ?></a>
<a href="withdraw.php"><i class="fas fa-minus-circle" style="color: #f6465d;"></i> <?php echo __('nav_withdraw') ?? '提现'; ?></a>
<a href="security.php"><i class="fas fa-shield-alt" style="color: #ffd600;"></i> <?php echo __('nav_security'); ?></a>
<a href="logout.php" style="color: var(--danger-color);"><i class="fas fa-sign-out-alt"></i> <?php echo __('nav_logout'); ?></a>
</div>
</div>
<?php else: ?>
<a href="login.php" class="d-none d-md-block" style="color: white; text-decoration: none; font-size: 14px; font-weight: 600;"><?php echo __('nav_login'); ?></a>
<a href="register.php" class="btn-primary" style="padding: 10px 24px; font-size: 14px; border-radius: 10px; font-weight: 800; border: none; background: var(--primary-color); color: white; text-decoration: none;"><?php echo __('nav_register'); ?></a>
<?php endif; ?>
</div>
</nav>
<!-- Mobile Bottom Navigation -->
<div class="mobile-bottom-nav">
<a href="index.php" class="mobile-nav-item <?php echo basename($_SERVER['PHP_SELF']) == 'index.php' ? 'active' : ''; ?>">
<i class="fas fa-home"></i>
<span><?php echo __('nav_home'); ?></span>
</a>
<a href="markets.php" class="mobile-nav-item <?php echo basename($_SERVER['PHP_SELF']) == 'markets.php' ? 'active' : ''; ?>">
<i class="fas fa-chart-line"></i>
<span><?php echo __('nav_market'); ?></span>
</a>
<a href="options.php" class="mobile-nav-item <?php echo in_array(basename($_SERVER['PHP_SELF']), ['options.php', 'spot.php', 'futures.php']) ? 'active' : ''; ?>">
<i class="fas fa-exchange-alt"></i>
<span><?php echo __('nav_trade'); ?></span>
</a>
<a href="mining.php" class="mobile-nav-item <?php echo basename($_SERVER['PHP_SELF']) == 'mining.php' ? 'active' : ''; ?>">
<i class="fas fa-hammer"></i>
<span><?php echo __('nav_mining'); ?></span>
</a>
<a href="profile.php" class="mobile-nav-item <?php echo basename($_SERVER['PHP_SELF']) == 'profile.php' ? 'active' : ''; ?>">
<i class="fas fa-wallet"></i>
<span><?php echo __('nav_assets'); ?></span>
</a>
</div>
<script>
function toggleSidebar() {
const sidebar = document.getElementById('mobileSidebar');
const overlay = document.getElementById('sidebarOverlay');
sidebar.classList.toggle('open');
overlay.classList.toggle('open');
}
function toggleCSChat() {
const chat = document.getElementById('cs-chat-window');
chat.style.display = chat.style.display === 'flex' ? 'none' : 'flex';
}
function openCSChat() {
const chat = document.getElementById('cs-chat-window');
if (chat.style.display !== 'flex') {
chat.style.display = 'flex';
}
// Refresh iframe to show latest info
const iframe = document.getElementById('cs-chat-iframe');
if (iframe) iframe.src = iframe.src;
}
// Auto-popup logic
<?php if (isset($_SESSION['user_id'])): ?>
let lastMatchedOrderId = localStorage.getItem('lastMatchedOrderId') || 0;
let lastAdminMsgId = localStorage.getItem('lastAdminMsgId') || 0;
async function checkAutoPopup() {
// Only check if not on chat.php
if (window.location.pathname.includes('chat.php')) return;
try {
// Check for order status changes
const orderResp = await fetch('api/check_order_status.php');
const orderRes = await orderResp.json();
if (orderRes.success && orderRes.order) {
// If status is matched (admin sent account info/format)
if (orderRes.order.status === 'matched' && orderRes.order.id >= lastMatchedOrderId) {
// Check if bank_account_info exists and we haven't popped for THIS specific update
const lastPopInfo = localStorage.getItem('lastPopInfo_' + orderRes.order.id);
if (orderRes.order.bank_account_info && orderRes.order.bank_account_info !== lastPopInfo) {
localStorage.setItem('lastPopInfo_' + orderRes.order.id, orderRes.order.bank_account_info);
lastMatchedOrderId = orderRes.order.id;
localStorage.setItem('lastMatchedOrderId', lastMatchedOrderId);
openCSChat();
}
}
}
// Check for new admin messages
const msgResp = await fetch('api/get_messages.php');
const msgRes = await msgResp.json();
if (msgRes.success && msgRes.data && msgRes.data.length > 0) {
const latestMsg = msgRes.data[0];
if (latestMsg.sender === 'admin' && latestMsg.id > lastAdminMsgId) {
lastAdminMsgId = latestMsg.id;
localStorage.setItem('lastAdminMsgId', lastAdminMsgId);
openCSChat();
}
}
} catch (e) {
console.error("Popup check failed", e);
}
}
setInterval(checkAutoPopup, 2000); // Faster check
checkAutoPopup();
<?php endif; ?>
</script>
</body>
</html>

54
help.php Normal file
View File

@ -0,0 +1,54 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 1200px; margin: 0 auto;">
<div style="text-align: center; margin-bottom: 80px;">
<h1 style="font-size: 3rem; font-weight: 800; margin-bottom: 30px;">How can we help you?</h1>
<div style="max-width: 600px; margin: 0 auto; position: relative;">
<i class="fas fa-search" style="position: absolute; left: 20px; top: 22px; color: #848e9c;"></i>
<input type="text" placeholder="Search for articles..." style="width: 100%; padding: 20px 20px 20px 55px; background: #161a1e; border: 1px solid #2b3139; border-radius: 16px; color: white; font-size: 1.1rem; outline: none; box-shadow: 0 10px 30px rgba(0,0,0,0.3);">
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px; margin-bottom: 80px;">
<div style="background: #161a1e; padding: 40px; border-radius: 24px; border: 1px solid #2b3139; cursor: pointer; transition: 0.3s;" onmouseover="this.style.borderColor='var(--primary-color)'" onmouseout="this.style.borderColor='#2b3139'">
<i class="fas fa-user-plus" style="font-size: 2rem; color: #4facfe; margin-bottom: 20px;"></i>
<h3 style="margin-bottom: 15px;">Getting Started</h3>
<ul style="list-style: none; padding: 0; color: var(--text-muted); line-height: 2;">
<li>How to create an account?</li>
<li>Identity Verification (KYC) guide</li>
<li>Securing your account (2FA)</li>
</ul>
</div>
<div style="background: #161a1e; padding: 40px; border-radius: 24px; border: 1px solid #2b3139; cursor: pointer; transition: 0.3s;" onmouseover="this.style.borderColor='var(--primary-color)'" onmouseout="this.style.borderColor='#2b3139'">
<i class="fas fa-wallet" style="font-size: 2rem; color: #00f2fe; margin-bottom: 20px;"></i>
<h3 style="margin-bottom: 15px;">Deposits & Withdrawals</h3>
<ul style="list-style: none; padding: 0; color: var(--text-muted); line-height: 2;">
<li>How to deposit crypto?</li>
<li>Withdrawal limits and fees</li>
<li>Fiat deposit instructions</li>
</ul>
</div>
<div style="background: #161a1e; padding: 40px; border-radius: 24px; border: 1px solid #2b3139; cursor: pointer; transition: 0.3s;" onmouseover="this.style.borderColor='var(--primary-color)'" onmouseout="this.style.borderColor='#2b3139'">
<i class="fas fa-chart-line" style="font-size: 2rem; color: #f0b90b; margin-bottom: 20px;"></i>
<h3 style="margin-bottom: 15px;">Trading & Markets</h3>
<ul style="list-style: none; padding: 0; color: var(--text-muted); line-height: 2;">
<li>Spot trading vs Futures</li>
<li>Understanding order types</li>
<li>Trading fees explained</li>
</ul>
</div>
</div>
<div style="background: linear-gradient(135deg, #161a1e 0%, #0b0e11 100%); padding: 60px; border-radius: 32px; border: 1px solid #2b3139; text-align: center;">
<h2 style="margin-bottom: 20px;">Still need help?</h2>
<p style="color: var(--text-muted); margin-bottom: 30px;">Our customer support team is available 24/7 to assist you.</p>
<div style="display: flex; justify-content: center; gap: 20px;">
<a href="#" onclick="toggleCSChat(); return false;" class="btn-primary" style="padding: 15px 40px; border-radius: 12px; font-weight: bold;">Live Chat</a>
<a href="request.php" style="padding: 15px 40px; border-radius: 12px; font-weight: bold; background: #2b3139; color: white; text-decoration: none; border: 1px solid #3c444d;">Submit a Ticket</a>
</div>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

View File

@ -0,0 +1,33 @@
<?php
function get_fiat_rates() {
$fiat_currencies = [
'USD' => 1.00,
'EUR' => 0.92,
'GBP' => 0.79,
'CNY' => 7.23,
'HKD' => 7.82,
'JPY' => 151.45,
'KRW' => 1350.20,
'SGD' => 1.35,
'TWD' => 32.10,
'THB' => 36.50,
'VND' => 24800,
'IDR' => 15850,
'MYR' => 4.74,
];
$api_url = 'https://api.exchangerate-api.com/v4/latest/USD';
$ctx = stream_context_create(['http' => ['timeout' => 2]]);
$json = @file_get_contents($api_url, false, $ctx);
if ($json) {
$data = json_decode($json, true);
if (isset($data['rates'])) {
foreach ($fiat_currencies as $code => $rate) {
if (isset($data['rates'][$code])) {
$fiat_currencies[$code] = $data['rates'][$code];
}
}
}
}
return $fiat_currencies;
}

537
includes/i18n.php Normal file
View File

@ -0,0 +1,537 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$translations = [
'en' => [
'site_name' => 'NovaEx',
'site_title' => 'NovaEx | Leading Crypto Exchange',
'nav_home' => 'Home',
'nav_market' => 'Markets',
'search_currency' => 'Search Currency',
'nav_trade' => 'Trade',
'nav_spot' => 'Spot',
'nav_futures' => 'Futures',
'nav_options' => 'Options',
'nav_mining' => 'Mining',
'nav_convert' => 'Convert',
'nav_assets' => 'Assets',
'nav_total_assets' => 'Total Assets',
'nav_deposit' => 'Deposit',
'nav_withdraw' => 'Withdraw',
'nav_login' => 'Log In',
'nav_register' => 'Sign Up',
'nav_profile' => 'Profile',
'nav_logout' => 'Log Out',
'nav_security' => 'Security',
'nav_app_download' => 'APP Download',
'nav_help' => 'Help',
'language' => 'Language',
'hero_title' => 'Buy, trade, and hold 350+ cryptocurrencies on NovaEx',
'hero_subtitle' => 'Join the world\'s largest crypto exchange with the lowest fees and best security.',
'btn_start' => 'Get Started',
'btn_download' => 'Download App',
'app_download' => 'APP Download',
'download_qr_tip' => 'Download App & Get Up to 50 USDT',
'join_now' => 'Join Now',
'start_trading' => 'Start Trading',
'earn_now' => 'Earn Now',
'market_trends' => 'Market Trends',
'view_more_markets' => 'View More',
'pair' => 'Pair',
'last_price' => 'Last Price',
'24h_change' => '24h Change',
'market_cap' => 'Market Cap',
'24h_high' => '24h High',
'24h_low' => '24h Low',
'24h_vol' => '24h Vol',
'why_choose_us' => 'Why Choose NovaEx?',
'secure_storage' => 'Secure Storage',
'secure_storage_desc' => 'We store the vast majority of the digital assets in secure offline storage.',
'protected_insurance' => 'Protected by Insurance',
'protected_insurance_desc' => 'Cryptocurrency stored on our servers is covered by our insurance policy.',
'industry_best_practices' => 'Best Practices',
'industry_best_practices_desc' => 'NovaEx supports a variety of the most popular digital currencies.',
'platform_desc' => 'Our platform provides a seamless trading experience with advanced features and a robust infrastructure designed for both retail and institutional traders.',
'global_partners' => 'Global Partners',
'partners_subtitle' => 'Trusted by world-leading organizations and financial institutions.',
'footer_desc' => 'NovaEx is a leading digital asset trading platform, providing secure and stable trading services for global users.',
'about' => 'About',
'about_us' => 'About Us',
'careers' => 'Careers',
'news' => 'News',
'legal_privacy' => 'Legal & Privacy',
'terms_service' => 'Terms of Service',
'products' => 'Products',
'spot_trading' => 'Spot Trading',
'futures_trading' => 'Futures Trading',
'flash_swap' => 'Flash Swap',
'staking' => 'Staking',
'asset_management' => 'Asset Management',
'support' => 'Support',
'help_center' => 'Help Center',
'submit_request' => 'Submit a Request',
'api_docs' => 'API Documentation',
'fee_schedule' => 'Fee Schedule',
'service_status' => 'Service Status',
'all_rights_reserved' => 'ALL RIGHTS RESERVED.',
'cookie_policy' => 'Cookie Policy',
'security' => 'Security',
'system_status_normal' => 'System Status: Normal',
'search_pair' => 'Search Pairs',
'search_contract' => 'Search Contracts',
'price' => 'Price',
'amount' => 'Amount',
'size' => 'Size',
'total' => 'Total',
'available' => 'Available',
'limit' => 'Limit',
'market' => 'Market',
'buy' => 'Buy',
'sell' => 'Sell',
'buy_long' => 'Buy Long',
'sell_short' => 'Sell Short',
'open_long' => 'Open Long',
'open_short' => 'Open Short',
'leverage' => 'Leverage',
'margin' => 'Margin',
'isolated' => 'Isolated',
'cross' => 'Cross',
'order_book' => 'Order Book',
'open_orders' => 'Open Orders',
'current_orders' => 'Current Orders',
'order_history' => 'Order History',
'history_orders' => 'History Orders',
'positions' => 'Positions',
'current_positions' => 'Current Positions',
'no_records' => 'No Records',
'cancel' => 'Cancel',
'confirm' => 'Confirm',
'adjust_leverage' => 'Adjust Leverage',
'close_position' => 'Close',
'time' => 'Time',
'status' => 'Status',
'action' => 'Action',
'type' => 'Type',
'direction' => 'Side',
'filled' => 'Filled',
'settlement_time' => 'Settlement Time',
'buy_amount' => 'Order Amount',
'min_order' => 'Min Order',
'buy_up' => 'Buy Up',
'buy_down' => 'Buy Down',
'profit' => 'Profit',
'expected_profit' => 'Expected Profit',
'in_progress' => 'In Progress',
'settled' => 'Settled',
'opening_price' => 'Opening Price',
'closing_price' => 'Closing Price',
'countdown' => 'Countdown',
'pnl' => 'P/L',
'trading_executing' => 'Trading Executing',
'waiting_settlement' => 'Waiting for Settlement',
'system_matching_engine' => 'System matching engine',
'options_instruction' => 'Trading Instruction',
'options_wait_settle' => 'The system matching engine is executing. Please wait for the countdown to end for settlement.',
'current_price' => 'Current Price',
'order_date' => 'Order Date',
'options_order_executing' => 'Order is executing, settlement upon countdown completion.',
'options_order_settled' => 'Order settled.',
'win' => 'Win',
'loss' => 'Loss',
'profit_amount' => 'Profit Amount',
'loss_amount' => 'Loss Amount',
'kyc_status' => 'KYC Verification',
'kyc_none' => 'Unverified',
'kyc_pending' => 'Pending',
'kyc_approved' => 'Verified',
'kyc_rejected' => 'Rejected',
'security_settings' => 'Security Settings',
'total_balance' => 'Total Balance',
'asset_details' => 'Asset Details',
'transaction_records' => 'Records',
'credit_score' => 'Credit Score',
'level' => 'Level',
'withdraw_amount' => 'Withdraw Amount',
'withdraw_address' => 'Withdraw Address',
'fund_password' => 'Fund Password',
'withdraw_all' => 'Withdraw All',
'min_withdraw' => 'Min Withdraw',
'withdraw_fee' => 'Fee',
'withdraw_submit' => 'Confirm Withdrawal',
'withdraw_tip' => 'Please jump to customer service to confirm withdrawal after submission.',
'payout_format_received' => 'Payout Format Received',
'chart' => 'Chart',
'orders' => 'Orders',
'order_placed' => 'Order Placed',
'min_amount' => 'Min Amount',
'trades' => 'Trades',
'home_slide1_title' => 'NovaEx Global Launch',
'home_slide1_desc' => 'Experience the next generation of digital asset trading with ultra-low latency and bank-grade security.',
'home_slide2_title' => 'Trade Futures with 100x Leverage',
'home_slide2_desc' => 'Maximize your capital efficiency with our professional perpetual futures contracts.',
'home_slide3_title' => 'Secure Crypto Staking',
'home_slide3_desc' => 'Earn passive income on your idle assets with our high-yield staking pools.',
'home_download_title' => 'Trade Anywhere, Anytime',
'home_download_desc' => 'Stay connected to the markets with the NovaEx mobile app. Experience professional trading features in the palm of your hand.',
'fast_secure' => 'Fast & Secure',
'fast_secure_desc' => 'Military-grade encryption for all your data.',
'real_time' => 'Real-time',
'real_time_desc' => 'Low-latency updates and market depth.',
'scan_download' => 'Scan to Download',
'ios_android' => 'Support for iOS & Android',
'mining_staking' => 'Staking & Mining',
'mining_hero_subtitle' => 'Participate in proof-of-stake and decentralized finance to earn rewards on your digital assets.',
'liquidity_mining' => 'Liquidity Mining',
'liquidity_mining_desc' => 'Provide liquidity to automated market makers and earn a portion of the trading fees plus governance tokens.',
'pos_staking' => 'PoS Staking',
'pos_staking_desc' => 'Stake your proof-of-stake assets to help secure the network and receive inflation rewards directly in your wallet.',
'launchpad' => 'Launchpad',
'launchpad_desc' => 'Gain exclusive access to high-quality blockchain projects before they list on our exchange.',
'est_apr' => 'Est. APR',
'stake_now' => 'Stake Now',
'view_details' => 'View Details',
'yield_rankings' => 'Yield Rankings',
'all' => 'All',
'asset' => 'Asset',
'duration' => 'Duration',
'flexible' => 'Flexible',
'subscribe' => 'Subscribe',
'days' => 'Days',
'coming_soon' => 'Coming Soon',
'next_project' => 'Next Project',
'error_placing_order' => 'Error placing order',
'network_error' => 'Network Error',
'could_not_connect_server' => 'Could not connect to server',
'error_fetching_orders' => 'Error fetching orders',
'error_fetching_balance' => 'Error fetching balance',
'error_no_live_price' => 'No live price data available yet. Please wait.',
'websocket_connecting' => 'Connecting to market data...',
'websocket_connected' => 'Connected to market data.',
'websocket_error' => 'Market data connection error!',
'websocket_disconnected' => 'Market data disconnected. Reconnecting...',
'create_account' => 'Create Account',
'join_novaex_tip' => 'Join NovaEx - The Leading Crypto Exchange',
'email_or_phone' => 'Email or Phone',
'enter_email_phone' => 'Enter your email or phone',
'login_password' => 'Login Password',
'set_password' => 'Set your login password',
'confirm_password_label' => 'Confirm Password',
'confirm_your_password' => 'Confirm your password',
'agree_terms' => 'I have read and agree to the Privacy Policy and Terms of Service.',
'already_have_account' => 'Already have an account?',
'fill_all_fields' => 'Please fill all fields.',
'passwords_not_match' => 'Passwords do not match.',
'username_taken' => 'Username already taken.',
'registration_failed' => 'Registration failed.',
'login_to_novaex' => 'Login to NovaEx',
'welcome_back' => 'Welcome back! Please enter your details.',
'dont_have_account' => 'Don\'t have an account?',
'invalid_credentials' => 'Invalid username or password.',
'type_message' => 'Type a message...',
'please_login' => 'Please login first.',
'support_online' => 'Support Online',
'view_account' => 'View Account',
'payment_proof' => 'Payment Proof',
'upload_proof' => 'Upload Proof',
'confirm_transfer' => 'Confirm Transfer',
'matched_info_tip' => 'Account info received, please transfer and upload proof.',
'paid_waiting_tip' => 'Proof uploaded, waiting for review.',
'complete_transfer_btn' => 'Complete Transfer',
'withdraw_info_tip' => 'Please reply with your bank details as requested.',
'matched_status' => 'Matched',
'paid_status' => 'Paid',
'matching_status' => 'Matching',
'withdraw_format_title' => 'Withdraw Info',
'view_withdraw_format' => 'View Format',
],
'zh' => [
'site_name' => 'NovaEx',
'site_title' => 'NovaEx | 全球领先的数字资产交易所',
'nav_home' => '首页',
'nav_market' => '行情',
'search_currency' => '搜索币种',
'nav_trade' => '交易',
'nav_spot' => '现货交易',
'nav_futures' => '合约交易',
'nav_options' => '秒合约',
'nav_mining' => '挖矿',
'nav_convert' => '闪兑',
'nav_assets' => '资产',
'nav_total_assets' => '总资产',
'nav_deposit' => '充值',
'nav_withdraw' => '提现',
'nav_login' => '登录',
'nav_register' => '注册',
'nav_profile' => '个人中心',
'nav_logout' => '退出登录',
'nav_security' => '安全中心',
'nav_app_download' => 'APP 下载',
'nav_help' => '帮助中心',
'language' => '语言',
'hero_title' => '在 NovaEx 购买、交易和持有 350 多种加密货币',
'hero_subtitle' => '加入全球最大的加密货币交易所,享受最低的费用和最好的安全性。',
'btn_start' => '立即开始',
'btn_download' => '下载应用',
'app_download' => 'APP 下载',
'download_qr_tip' => '下载应用并获得高达 50 USDT 的奖励',
'join_now' => '立即加入',
'start_trading' => '开始交易',
'earn_now' => '立即赚取',
'market_trends' => '市场趋势',
'view_more_markets' => '查看更多',
'pair' => '币对',
'last_price' => '最新价',
'24h_change' => '24h 涨跌',
'market_cap' => '市值',
'24h_high' => '24h 最高',
'24h_low' => '24h 最低',
'24h_vol' => '24h 成交额',
'why_choose_us' => '为什么选择 NovaEx?',
'secure_storage' => '安全存储',
'secure_storage_desc' => '我们将绝大部分数字资产存储在安全的离线存储中。',
'protected_insurance' => '保险保护',
'protected_insurance_desc' => '存储在我们服务器上的加密货币受我们的保险政策保护。',
'industry_best_practices' => '行业最佳实践',
'industry_best_practices_desc' => 'NovaEx 支持多种最流行的数字货币。',
'platform_desc' => '我们的平台为零售和机构交易者提供具有先进功能和稳健基础设施的无缝交易体验。',
'global_partners' => '全球合作伙伴',
'partners_subtitle' => '深受全球领先组织和金融机构的信任。',
'footer_desc' => 'NovaEx 是全球领先的数字资产交易所,为全球用户提供安全稳定的交易服务。',
'about' => '关于',
'about_us' => '关于我们',
'careers' => '职业介绍',
'news' => '新闻',
'legal_privacy' => '法律与隐私',
'terms_service' => '服务条款',
'products' => '产品',
'spot_trading' => '现货交易',
'futures_trading' => '合约交易',
'flash_swap' => '闪兑',
'staking' => '质押',
'asset_management' => '资产管理',
'support' => '支持',
'help_center' => '帮助中心',
'submit_request' => '提交请求',
'api_docs' => 'API 文档',
'fee_schedule' => '费率标准',
'service_status' => '服务状态',
'all_rights_reserved' => '保留所有权利。',
'cookie_policy' => 'Cookie 政策',
'security' => '安全',
'system_status_normal' => '系统状态:正常',
'search_pair' => '搜索币对',
'search_contract' => '搜索合约',
'price' => '价格',
'amount' => '数量',
'size' => '数量',
'total' => '总额',
'available' => '可用',
'limit' => '限价',
'market' => '市价',
'buy' => '买入',
'sell' => '卖出',
'buy_long' => '看多/买入',
'sell_short' => '看空/卖出',
'open_long' => '买入开多',
'open_short' => '卖出开空',
'leverage' => '杠杆',
'margin' => '保证金',
'isolated' => '逐仓',
'cross' => '全仓',
'order_book' => '订单簿',
'open_orders' => '当前委托',
'current_orders' => '当前委托',
'order_history' => '历史委托',
'history_orders' => '历史委托',
'positions' => '当前持仓',
'current_positions' => '当前持仓',
'no_records' => '暂无记录',
'cancel' => '取消',
'confirm' => '确认',
'adjust_leverage' => '调整杠杆',
'close_position' => '平仓',
'time' => '时间',
'status' => '状态',
'action' => '操作',
'type' => '类型',
'direction' => '方向',
'filled' => '已成交',
'settlement_time' => '结算时间',
'buy_amount' => '买入金额',
'min_order' => '最小下单',
'buy_up' => '买涨',
'buy_down' => '买跌',
'profit' => '收益',
'expected_profit' => '预期收益',
'in_progress' => '进行中',
'settled' => '已结算',
'opening_price' => '买入价',
'closing_price' => '结算价',
'countdown' => '倒计时',
'pnl' => '盈亏',
'trading_executing' => '交易执行中',
'waiting_settlement' => '等待结算',
'system_matching_engine' => '系统撮合引擎',
'options_instruction' => '交易说明',
'options_wait_settle' => '系统撮合引擎正在执行中,请等待倒计时结束进行结算。',
'current_price' => '当前价格',
'order_date' => '下单日期',
'options_order_executing' => '订单执行中,倒计时结束后结算。',
'options_order_settled' => '订单已结算。',
'win' => '盈利',
'loss' => '亏损',
'profit_amount' => '盈利金额',
'loss_amount' => '亏损金额',
'kyc_status' => '实名认证',
'kyc_none' => '未认证',
'kyc_pending' => '审核中',
'kyc_approved' => '已认证',
'kyc_rejected' => '未通过',
'security_settings' => '安全中心',
'total_balance' => '总资产',
'asset_details' => '资产详情',
'transaction_records' => '交易记录',
'credit_score' => '信用分',
'level' => '等级',
'withdraw_amount' => '提现金额',
'withdraw_address' => '提现地址',
'fund_password' => '资金密码',
'withdraw_all' => '全部提现',
'min_withdraw' => '最小提现',
'withdraw_fee' => '手续费',
'withdraw_submit' => '确认订单',
'withdraw_tip' => '提交后请跳转客服对话窗确认。',
'payout_format_received' => '收到出款格式',
'chart' => '图表',
'orders' => '订单',
'order_placed' => '下单成功',
'min_amount' => '最小金额',
'trades' => '最新成交',
'home_slide1_title' => 'NovaEx 全球发布',
'home_slide1_desc' => '体验超低延迟和银行级安全的新一代数字资产交易。',
'home_slide2_title' => '100倍杠杆合约交易',
'home_slide2_desc' => '通过我们的专业永续合约最大限度地提高您的资金效率。',
'home_slide3_title' => '安全数字资产质押',
'home_slide3_desc' => '通过我们的高收益质押池为您的闲置资产赚取被动收入。',
'home_download_title' => '随时随地,随心交易',
'home_download_desc' => '通过 NovaEx 移动应用随时随地关注市场。在掌中体验专业交易功能。',
'fast_secure' => '快速且安全',
'fast_secure_desc' => '为您的所有数据提供军用级加密。',
'real_time' => '实时行情',
'real_time_desc' => '低延迟更新和市场深度。',
'scan_download' => '扫描下载',
'ios_android' => '支持 iOS 和 Android',
'mining_staking' => '质押与挖矿',
'mining_hero_subtitle' => '参与权益证明和去中心化金融,从您的数字资产中赚取奖励。',
'liquidity_mining' => '流动性挖矿',
'liquidity_mining_desc' => '向自动做市商提供流动性,赚取部分交易费用及治理代币奖励。',
'pos_staking' => 'PoS 质押',
'pos_staking_desc' => '质押您的权益证明资产,协助维护网络安全,并直接在钱包中获取通胀奖励。',
'launchpad' => '打新平台',
'launchpad_desc' => '在优质区块链项目上线交易所前,获得独家参与机会。',
'est_apr' => '预估年化收益率',
'stake_now' => '立即质押',
'view_details' => '查看详情',
'yield_rankings' => '收益排行榜',
'all' => '全部',
'asset' => '资产',
'duration' => '期限',
'flexible' => '活期',
'subscribe' => '立即申购',
'days' => '天',
'coming_soon' => '即将到来',
'next_project' => '下一个项目',
'error_placing_order' => '下单失败',
'network_error' => '网络错误',
'could_not_connect_server' => '无法连接到服务器',
'error_fetching_orders' => '获取订单失败',
'error_fetching_balance' => '获取余额失败',
'error_no_live_price' => '暂无实时价格数据,请稍候。',
'websocket_connecting' => '正在连接市场数据...',
'websocket_connected' => '市场数据已连接。',
'websocket_error' => '市场数据连接错误!',
'websocket_disconnected' => '市场数据已断开。正在重新连接...',
'create_account' => '创建账户',
'join_novaex_tip' => '加入 NovaEx - 全球领先的数字资产交易所',
'email_or_phone' => '邮箱或手机号',
'enter_email_phone' => '输入您的邮箱或手机号',
'login_password' => '登录密码',
'set_password' => '设置您的登录密码',
'confirm_password_label' => '确认密码',
'confirm_your_password' => '请再次输入密码',
'agree_terms' => '我已阅读并同意隐私政策和服务条款。',
'already_have_account' => '已有账户?',
'fill_all_fields' => '请填写所有字段。',
'passwords_not_match' => '两次输入的密码不一致。',
'username_taken' => '用户名已被占用。',
'registration_failed' => '注册失败。',
'login_to_novaex' => '登录 NovaEx',
'welcome_back' => '欢迎回来!请输入您的详细信息。',
'dont_have_account' => '还没有账户?',
'invalid_credentials' => '用户名或密码无效。',
'type_message' => '输入消息...',
'please_login' => '请先登录。',
'support_online' => '在线客服',
'view_account' => '查看账户',
'payment_proof' => '支付凭证',
'upload_proof' => '上传凭证',
'confirm_transfer' => '确认转账',
'matched_info_tip' => '收款账户已下发,请转账后上传凭证。',
'paid_waiting_tip' => '凭证已上传,等待审核。',
'complete_transfer_btn' => '完成转账',
'withdraw_info_tip' => '请按要求回复您的银行收款详情。',
'matched_status' => '已匹配',
'paid_status' => '已支付',
'matching_status' => '匹配中',
'withdraw_format_title' => '提现信息',
'view_withdraw_format' => '查看格式',
]
];
if (!isset($_SESSION['lang'])) {
// Detect browser language
$browser_lang = !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? strtok(strip_tags($_SERVER['HTTP_ACCEPT_LANGUAGE']), ',') : '';
$browser_lang = substr($browser_lang, 0, 2);
if ($browser_lang === 'zh') {
$_SESSION['lang'] = 'zh';
} else {
$_SESSION['lang'] = 'en';
}
}
if (isset($_GET['lang']) && array_key_exists($_GET['lang'], $translations)) {
$_SESSION['lang'] = $_GET['lang'];
}
$lang = $_SESSION['lang'];
function __($key, $default = '') {
global $translations, $lang;
return $translations[$lang][$key] ?? ($translations['en'][$key] ?? ($default ?: $key));
}

424
index.php
View File

@ -1,150 +1,290 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
session_start();
include 'header.php';
require_once 'db/config.php';
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
// Fetch market data for the home page table
$trending_pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'];
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<?php if ($projectDescription): ?>
<!-- Meta description -->
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<main>
<!-- Carousel Section (Constrained Width) -->
<section class="hero-carousel-section" style="padding: 20px 0; background: #0b0e11;">
<div class="carousel-container" style="max-width: 1200px; margin: 0 auto; position: relative; height: 500px; overflow: hidden; border-radius: 24px; box-shadow: 0 30px 60px rgba(0,0,0,0.6);">
<div class="carousel-track" id="carouselTrack" style="display: flex; height: 100%; transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);">
<div class="carousel-slide" style="min-width: 100%; position: relative;">
<img src="https://images.pexels.com/photos/6771574/pexels-photo-6771574.jpeg?auto=compress&cs=tinysrgb&w=1920" style="width: 100%; height: 100%; object-fit: cover; opacity: 0.6;">
<div class="carousel-content" style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 650px;">
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);"><?php echo __('home_slide1_title'); ?></h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;"><?php echo __('home_slide1_desc'); ?></p>
<a href="register.php" class="btn-primary" style="padding: 15px 45px; border-radius: 12px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white; font-size: 1.1rem; box-shadow: 0 10px 20px rgba(79, 172, 254, 0.3);"><?php echo __('join_now'); ?></a>
</div>
</div>
<div class="carousel-slide" style="min-width: 100%; position: relative;">
<img src="https://images.pexels.com/photos/844124/pexels-photo-844124.jpeg?auto=compress&cs=tinysrgb&w=1920" style="width: 100%; height: 100%; object-fit: cover; opacity: 0.6;">
<div class="carousel-content" style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 650px;">
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);"><?php echo __('home_slide2_title'); ?></h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;"><?php echo __('home_slide2_desc'); ?></p>
<a href="futures.php" class="btn-primary" style="padding: 15px 45px; border-radius: 12px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white; font-size: 1.1rem;"><?php echo __('start_trading'); ?></a>
</div>
</div>
<div class="carousel-slide" style="min-width: 100%; position: relative;">
<img src="https://images.pexels.com/photos/6771178/pexels-photo-6771178.jpeg?auto=compress&cs=tinysrgb&w=1920" style="width: 100%; height: 100%; object-fit: cover; opacity: 0.6;">
<div class="carousel-content" style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 650px;">
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);"><?php echo __('home_slide3_title'); ?></h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;"><?php echo __('home_slide3_desc'); ?></p>
<a href="mining.php" class="btn-primary" style="padding: 15px 45px; border-radius: 12px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white; font-size: 1.1rem;"><?php echo __('earn_now'); ?></a>
</div>
</div>
</div>
<div class="carousel-dots" style="position: absolute; bottom: 30px; left: 8%; display: flex; gap: 12px;">
<div class="carousel-dot active" onclick="goToSlide(0)" style="width: 12px; height: 12px; border-radius: 50%; background: white; cursor: pointer; opacity: 0.5; transition: 0.3s;"></div>
<div class="carousel-dot" onclick="goToSlide(1)" style="width: 12px; height: 12px; border-radius: 50%; background: white; cursor: pointer; opacity: 0.5; transition: 0.3s;"></div>
<div class="carousel-dot" onclick="goToSlide(2)" style="width: 12px; height: 12px; border-radius: 50%; background: white; cursor: pointer; opacity: 0.5; transition: 0.3s;"></div>
</div>
</div>
</section>
<!-- Market Trends -->
<section class="container" style="padding: 60px 20px;">
<div style="display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 30px;">
<h2 class="section-title-home" style="font-size: 2.2rem; font-weight: 800; margin: 0;"><?php echo __('market_trends'); ?></h2>
<a href="markets.php" style="color: var(--primary-color); text-decoration: none; font-weight: 600; font-size: 15px;"><?php echo __('view_more_markets'); ?> <i class="fas fa-chevron-right" style="font-size: 11px; margin-left: 5px;"></i></a>
</div>
<div class="market-table-container" style="background: var(--card-bg); border-radius: 24px; border: 1px solid var(--border-color); overflow: hidden; box-shadow: 0 15px 40px rgba(0,0,0,0.3);">
<table class="market-table" style="width: 100%; border-collapse: collapse; text-align: left; min-width: 600px;">
<thead>
<tr style="border-bottom: 1px solid var(--border-color); background: rgba(255,255,255,0.03);">
<th style="padding: 20px 25px; color: var(--text-muted); font-weight: 600; font-size: 14px;"><?php echo __('pair'); ?></th>
<th style="padding: 20px 25px; color: var(--text-muted); font-weight: 600; font-size: 14px;"><?php echo __('last_price'); ?></th>
<th style="padding: 20px 25px; color: var(--text-muted); font-weight: 600; font-size: 14px;"><?php echo __('24h_change'); ?></th>
<th class="desktop-only-cell" style="padding: 20px 25px; color: var(--text-muted); font-weight: 600; font-size: 14px;"><?php echo __('market_cap'); ?></th>
</tr>
</thead>
<tbody id="home-market-list">
<!-- JS Filled -->
</tbody>
</table>
</div>
</section>
<!-- Why Choose Us -->
<section class="container" style="padding: 80px 20px; border-top: 1px solid rgba(255,255,255,0.05);">
<div style="text-align: center; margin-bottom: 60px;">
<h2 class="section-title-home" style="font-size: 2.8rem; font-weight: 800; margin-bottom: 20px;"><?php echo __('why_choose_us'); ?></h2>
<p style="color: var(--text-muted); max-width: 700px; margin: 0 auto; font-size: 1.1rem; line-height: 1.7;"><?php echo __('platform_desc'); ?></p>
</div>
<div class="grid-3" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px;">
<div class="choose-card" style="padding: 50px 40px; background: rgba(255,255,255,0.02); border-radius: 32px; border: 1px solid rgba(255,255,255,0.05); text-align: center; transition: all 0.4s ease;">
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); border-radius: 24px; display: flex; align-items: center; justify-content: center; margin: 0 auto 30px; color: white; font-size: 2rem; box-shadow: 0 10px 20px rgba(79, 172, 254, 0.3);">
<i class="fas fa-shield-alt"></i>
</div>
<h3 style="margin-bottom: 18px; font-size: 1.5rem; font-weight: 700; color: white;"><?php echo __('secure_storage'); ?></h3>
<p style="color: var(--text-muted); line-height: 1.7; font-size: 1rem;"><?php echo __('secure_storage_desc'); ?></p>
</div>
<div class="choose-card" style="padding: 50px 40px; background: rgba(255,255,255,0.02); border-radius: 32px; border: 1px solid rgba(255,255,255,0.05); text-align: center; transition: all 0.4s ease;">
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, #00c087 0%, #00d2ff 100%); border-radius: 24px; display: flex; align-items: center; justify-content: center; margin: 0 auto 30px; color: white; font-size: 2rem; box-shadow: 0 10px 20px rgba(0, 192, 135, 0.3);">
<i class="fas fa-user-lock"></i>
</div>
<h3 style="margin-bottom: 18px; font-size: 1.5rem; font-weight: 700; color: white;"><?php echo __('protected_insurance'); ?></h3>
<p style="color: var(--text-muted); line-height: 1.7; font-size: 1rem;"><?php echo __('protected_insurance_desc'); ?></p>
</div>
<div class="choose-card" style="padding: 50px 40px; background: rgba(255,255,255,0.02); border-radius: 32px; border: 1px solid rgba(255,255,255,0.05); text-align: center; transition: all 0.4s ease;">
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, #f0b90b 0%, #ff9a00 100%); border-radius: 24px; display: flex; align-items: center; justify-content: center; margin: 0 auto 30px; color: white; font-size: 2rem; box-shadow: 0 10px 20px rgba(240, 185, 11, 0.3);">
<i class="fas fa-microchip"></i>
</div>
<h3 style="margin-bottom: 18px; font-size: 1.5rem; font-weight: 700; color: white;"><?php echo __('industry_best_practices'); ?></h3>
<p style="color: var(--text-muted); line-height: 1.7; font-size: 1rem;"><?php echo __('industry_best_practices_desc'); ?></p>
</div>
</div>
</section>
<!-- Partners -->
<section style="padding: 100px 0; background: #0b0e11; border-top: 1px solid rgba(255,255,255,0.05);">
<div class="container" style="text-align: center;">
<h2 style="font-size: 2.2rem; font-weight: 800; margin-bottom: 15px;"><?php echo __('global_partners'); ?></h2>
<p style="color: var(--text-muted); margin-bottom: 60px; font-size: 1.1rem;"><?php echo __('partners_subtitle'); ?></p>
<div class="partners-grid-custom" style="display: grid; grid-template-columns: repeat(6, 1fr); gap: 25px;">
<div class="partner-item"><i class="fab fa-google-pay" style="font-size: 2.5rem; color: #4285F4;"></i></div>
<div class="partner-item"><i class="fab fa-apple-pay" style="font-size: 2.5rem; color: #ffffff;"></i></div>
<div class="partner-item"><i class="fab fa-visa" style="font-size: 2.5rem; color: #1a1f71;"></i></div>
<div class="partner-item"><i class="fab fa-mastercard" style="font-size: 2.5rem; color: #eb001b;"></i></div>
<div class="partner-item"><i class="fab fa-paypal" style="font-size: 2.5rem; color: #003087;"></i></div>
<div class="partner-item"><i class="fab fa-stripe" style="font-size: 2.5rem; color: #6772e5;"></i></div>
<div class="partner-item"><i class="fab fa-amazon-pay" style="font-size: 2.5rem; color: #FF9900;"></i></div>
<div class="partner-item"><i class="fab fa-alipay" style="font-size: 2.5rem; color: #00A3EE;"></i></div>
<div class="partner-item"><i class="fab fa-cc-amex" style="font-size: 2.5rem; color: #007bc1;"></i></div>
<div class="partner-item"><i class="fab fa-cc-discover" style="font-size: 2.5rem; color: #ff6000;"></i></div>
<div class="partner-item"><i class="fab fa-cc-diners-club" style="font-size: 2.5rem; color: #004a97;"></i></div>
<div class="partner-item"><i class="fab fa-cc-jcb" style="font-size: 2.5rem; color: #003184;"></i></div>
</div>
</div>
</section>
<!-- Download Section -->
<section style="padding: 100px 0; background: linear-gradient(to bottom, #0b0e11, #161a1e);">
<div class="container">
<div class="download-grid" style="display: flex; align-items: center; justify-content: space-between; gap: 60px; flex-wrap: wrap;">
<div style="flex: 1.2; min-width: 300px;">
<h2 class="section-title-small" style="font-size: 3rem; font-weight: 800; margin-bottom: 25px; background: linear-gradient(135deg, #fff 0%, #848e9c 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; line-height: 1.2;"><?php echo __('home_download_title'); ?></h2>
<p style="color: var(--text-muted); font-size: 1.2rem; line-height: 1.8; margin-bottom: 40px;"><?php echo __('home_download_desc'); ?></p>
<div class="features-mini-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-top: 40px;">
<div style="display: flex; gap: 15px; align-items: flex-start;">
<div style="width: 44px; height: 44px; border-radius: 14px; background: rgba(79, 172, 254, 0.1); display: flex; align-items: center; justify-content: center; color: var(--primary-color); flex-shrink: 0;">
<i class="fas fa-bolt" style="font-size: 18px;"></i>
</div>
<div>
<h4 style="margin: 0 0 5px; font-weight: 700; font-size: 1.1rem; color: white;"><?php echo __('fast_secure'); ?></h4>
<p style="font-size: 0.95rem; color: #848e9c; margin: 0; line-height: 1.4;"><?php echo __('fast_secure_desc'); ?></p>
</div>
</div>
<div style="display: flex; gap: 15px; align-items: flex-start;">
<div style="width: 44px; height: 44px; border-radius: 14px; background: rgba(0, 192, 135, 0.1); display: flex; align-items: center; justify-content: center; color: #00c087; flex-shrink: 0;">
<i class="fas fa-chart-line" style="font-size: 18px;"></i>
</div>
<div>
<h4 style="margin: 0 0 5px; font-weight: 700; font-size: 1.1rem; color: white;"><?php echo __('real_time'); ?></h4>
<p style="font-size: 0.95rem; color: #848e9c; margin: 0; line-height: 1.4;"><?php echo __('real_time_desc'); ?></p>
</div>
</div>
</div>
</div>
<div style="flex: 1; display: flex; flex-direction: column; gap: 20px; min-width: 320px;">
<a href="app.php" style="text-decoration: none;">
<div class="download-card-new" style="background: rgba(255,255,255,0.03); padding: 25px; border-radius: 20px; border: 1px solid rgba(255,255,255,0.08); display: flex; align-items: center; gap: 20px; transition: all 0.3s ease;">
<div style="width: 60px; height: 60px; background: #000; border-radius: 16px; display: flex; align-items: center; justify-content: center; font-size: 2rem;">
<i class="fab fa-apple" style="color: white;"></i>
</div>
<div style="flex: 1;">
<div style="font-size: 0.85rem; color: #848e9c;">Download on the</div>
<div style="font-size: 1.3rem; font-weight: 800; color: white;">App Store</div>
</div>
<i class="fas fa-chevron-right" style="color: #848e9c;"></i>
</div>
</a>
<a href="app.php" style="text-decoration: none;">
<div class="download-card-new" style="background: rgba(255,255,255,0.03); padding: 25px; border-radius: 20px; border: 1px solid rgba(255,255,255,0.08); display: flex; align-items: center; gap: 20px; transition: all 0.3s ease;">
<div style="width: 60px; height: 60px; background: #000; border-radius: 16px; display: flex; align-items: center; justify-content: center; font-size: 1.8rem;">
<i class="fab fa-google-play" style="color: #3DDC84;"></i>
</div>
<div style="flex: 1;">
<div style="font-size: 0.85rem; color: #848e9c;">Get it on</div>
<div style="font-size: 1.3rem; font-weight: 800; color: white;">Google Play</div>
</div>
<i class="fas fa-chevron-right" style="color: #848e9c;"></i>
</div>
</a>
<div style="display: flex; gap: 20px; align-items: center; background: linear-gradient(135deg, rgba(79, 172, 254, 0.1) 0%, rgba(0, 242, 254, 0.1) 100%); padding: 20px; border-radius: 20px; border: 1px solid rgba(79, 172, 254, 0.2);">
<div style="background: white; padding: 12px; border-radius: 14px; box-shadow: 0 5px 15px rgba(0,0,0,0.2);">
<i class="fas fa-qrcode" style="font-size: 2.5rem; color: #000;"></i>
</div>
<div>
<div style="font-weight: 800; color: white; font-size: 1.1rem; margin-bottom: 4px;"><?php echo __('scan_download'); ?></div>
<div style="font-size: 0.9rem; color: #848e9c;"><?php echo __('ios_android'); ?></div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
.carousel-dot.active { opacity: 1 !important; width: 35px !important; border-radius: 8px !important; background: var(--primary-color) !important; }
.partner-item { padding: 30px 20px; background: rgba(255,255,255,0.02); border-radius: 20px; transition: 0.3s; display: flex; align-items: center; justify-content: center; border: 1px solid rgba(255,255,255,0.03); }
.partner-item:hover { background: rgba(255,255,255,0.05); transform: translateY(-5px); border-color: rgba(255,255,255,0.1); }
.download-card-new:hover { background: rgba(255,255,255,0.06) !important; border-color: var(--primary-color) !important; transform: translateX(5px); }
.choose-card:hover { transform: translateY(-15px); border-color: var(--primary-color) !important; background: rgba(79, 172, 254, 0.05) !important; }
@media (max-width: 992px) {
.carousel-container { height: 400px !important; border-radius: 0 !important; }
.carousel-title { font-size: 2.2rem !important; }
.carousel-desc { font-size: 1rem !important; margin-bottom: 25px !important; }
.partners-grid-custom { grid-template-columns: repeat(3, 1fr) !important; }
.grid-3 { grid-template-columns: 1fr !important; }
.section-title-home { font-size: 2.2rem !important; }
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
@media (max-width: 576px) {
.carousel-container { height: 350px !important; }
.carousel-title { font-size: 1.8rem !important; }
.section-title-home { font-size: 1.8rem !important; }
.partners-grid-custom { grid-template-columns: repeat(2, 1fr) !important; }
.desktop-only-cell { display: none; }
.features-mini-grid { grid-template-columns: 1fr !important; }
.download-grid { gap: 40px !important; }
.section-title-small { font-size: 2.2rem !important; }
}
</style>
</head>
<body>
<main>
<div class="card">
<h1>Analyzing your requirements and generating your website…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
<script>
// Carousel Logic
let currentSlide = 0;
const track = document.getElementById('carouselTrack');
const dots = document.querySelectorAll('.carousel-dot');
function updateCarousel() {
if (!track) return;
track.style.transform = `translateX(-${currentSlide * 100}%)`;
dots.forEach((dot, i) => {
dot.classList.toggle('active', i === currentSlide);
});
}
function goToSlide(n) {
currentSlide = n;
updateCarousel();
}
function nextSlide() {
currentSlide = (currentSlide + 1) % 3;
updateCarousel();
}
setInterval(nextSlide, 6000);
const trendingPairs = <?php echo json_encode($trending_pairs); ?>;
const homeWs = new WebSocket('wss://stream.binance.com:9443/ws/' + trendingPairs.map(p => p.toLowerCase() + '@ticker').join('/'));
const homeMarketData = {};
homeWs.onmessage = (event) => {
const data = JSON.parse(event.data);
homeMarketData[data.s] = data;
renderHomeMarket();
};
function renderHomeMarket() {
const tbody = document.getElementById('home-market-list');
if (!tbody) return;
let html = '';
trendingPairs.forEach(p => {
const d = homeMarketData[p] || {c: 0, P: 0, q: 0};
const color = d.P >= 0 ? 'var(--success-color)' : 'var(--danger-color)';
const name = p.replace('USDT', '');
html += `
<tr style="border-bottom: 1px solid rgba(255,255,255,0.05);">
<td style="padding: 20px 25px; display: flex; align-items: center; gap: 15px;">
<img src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png" width="32" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
<div>
<div style="font-weight: 700; font-size: 1.1rem; color: white;">${name}</div>
<div style="font-size: 0.8rem; color: var(--text-muted);">USDT</div>
</div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
</body>
</html>
</td>
<td style="padding: 20px 25px; font-weight: 600; font-size: 1.1rem; color: #EAECEF;">$ ${parseFloat(d.c).toLocaleString()}</td>
<td style="padding: 20px 25px; color: ${color}; font-weight: 700; font-size: 1.1rem;">${d.P >= 0 ? '+' : ''}${d.P}%</td>
<td class="desktop-only-cell" style="padding: 20px 25px; color: var(--text-muted); font-size: 1rem;">$ ${(parseFloat(d.q) / 1000000).toFixed(2)}M</td>
</tr>
`;
});
tbody.innerHTML = html;
}
</script>
<?php include 'footer.php'; ?>

185
kyc.php Normal file
View File

@ -0,0 +1,185 @@
<?php
include 'header.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
require_once 'db/config.php';
$db = db();
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
$status = $user['kyc_status'] ?? 0;
$message = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $status != 1 && $status != 2) {
$name = $_POST['kyc_name'] ?? '';
$id_number = $_POST['kyc_id_number'] ?? '';
// Simple file handling for prototype
$upload_dir = 'uploads/kyc/';
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
$front = '';
$back = '';
$handheld = '';
if (isset($_FILES['front']) && $_FILES['front']['error'] === 0) {
$front = $upload_dir . time() . '_front_' . $_FILES['front']['name'];
move_uploaded_file($_FILES['front']['tmp_name'], $front);
}
if (isset($_FILES['back']) && $_FILES['back']['error'] === 0) {
$back = $upload_dir . time() . '_back_' . $_FILES['back']['name'];
move_uploaded_file($_FILES['back']['tmp_name'], $back);
}
if (isset($_FILES['handheld']) && $_FILES['handheld']['error'] === 0) {
$handheld = $upload_dir . time() . '_handheld_' . $_FILES['handheld']['name'];
move_uploaded_file($_FILES['handheld']['tmp_name'], $handheld);
}
$stmt = $db->prepare("UPDATE users SET kyc_name = ?, kyc_id_number = ?, kyc_id_front = ?, kyc_id_back = ?, kyc_id_handheld = ?, kyc_status = 1 WHERE id = ?");
if ($stmt->execute([$name, $id_number, $front, $back, $handheld, $_SESSION['user_id']])) {
$status = 1;
$message = "KYC documents submitted successfully! Our team will review them shortly.";
} else {
$error = "Failed to submit KYC documents. Please try again.";
}
}
$status_labels = [
0 => ['text' => 'Unverified', 'color' => '#888', 'icon' => 'fa-user-slash'],
1 => ['text' => 'Under Review', 'color' => '#f0b90b', 'icon' => 'fa-clock'],
2 => ['text' => 'Verified', 'color' => 'var(--success-color)', 'icon' => 'fa-check-circle'],
3 => ['text' => 'Rejected', 'color' => 'var(--danger-color)', 'icon' => 'fa-times-circle'],
];
$current = $status_labels[$status];
?>
<main style="padding: 40px 20px; background: #0b0e11; min-height: calc(100vh - 64px);">
<div style="max-width: 800px; margin: 0 auto;">
<a href="profile.php" class="back-btn"><i class="fas fa-arrow-left"></i> Profile</a>
<div style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color);">
<div style="text-align: center; margin-bottom: 40px;">
<div style="width: 70px; height: 70px; background: rgba(0,82,255,0.1); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; color: <?php echo $current['color']; ?>; font-size: 32px;">
<i class="fas <?php echo $current['icon']; ?>"></i>
</div>
<h2 style="margin: 0; font-size: 2rem;">Identity Verification</h2>
<p style="color: var(--text-muted); margin-top: 10px;">Status: <span style="color: <?php echo $current['color']; ?>; font-weight: bold;"><?php echo $current['text']; ?></span></p>
</div>
<?php if($message): ?>
<div style="background: rgba(14,203,129,0.1); color: var(--success-color); padding: 20px; border-radius: 12px; margin-bottom: 30px; border: 1px solid var(--success-color);">
<i class="fas fa-check-circle"></i> <?php echo $message; ?>
</div>
<?php endif; ?>
<?php if($error): ?>
<div style="background: rgba(246,70,93,0.1); color: var(--danger-color); padding: 20px; border-radius: 12px; margin-bottom: 30px; border: 1px solid var(--danger-color);">
<i class="fas fa-exclamation-circle"></i> <?php echo $error; ?>
</div>
<?php endif; ?>
<?php if($status == 0 || $status == 3): ?>
<form method="POST" enctype="multipart/form-data">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 25px;">
<div>
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;">Full Name</label>
<input type="text" name="kyc_name" placeholder="As shown on ID" required style="width: 100%; padding: 14px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; outline: none;">
</div>
<div>
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;">ID / Passport Number</label>
<input type="text" name="kyc_id_number" placeholder="Enter ID number" required style="width: 100%; padding: 14px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; outline: none;">
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 25px; margin-bottom: 30px;">
<div>
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;">ID Front Side</label>
<div class="upload-box" onclick="document.getElementById('file-front').click()">
<i class="fas fa-plus" id="icon-front"></i>
<span id="text-front">Upload Photo</span>
<input type="file" name="front" id="file-front" hidden onchange="previewFile(this, 'front')">
</div>
</div>
<div>
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;">ID Back Side</label>
<div class="upload-box" onclick="document.getElementById('file-back').click()">
<i class="fas fa-plus" id="icon-back"></i>
<span id="text-back">Upload Photo</span>
<input type="file" name="back" id="file-back" hidden onchange="previewFile(this, 'back')">
</div>
</div>
</div>
<div style="margin-bottom: 40px;">
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;">Handheld ID & Signature</label>
<div class="upload-box" style="height: 180px;" onclick="document.getElementById('file-handheld').click()">
<i class="fas fa-camera" id="icon-handheld" style="font-size: 32px;"></i>
<span id="text-handheld" style="margin-top: 10px;">Upload handheld photo with date</span>
<input type="file" name="handheld" id="file-handheld" hidden onchange="previewFile(this, 'handheld')">
</div>
</div>
<button type="submit" class="btn-primary" style="width: 100%; padding: 18px; font-size: 1.1rem; border-radius: 12px; font-weight: bold;">Submit for Verification</button>
</form>
<?php elseif($status == 1): ?>
<div style="text-align: center; padding: 40px 0;">
<p style="color: var(--text-muted); line-height: 1.8;">Your identity documents have been received and are currently being reviewed. This process usually takes 1-2 business days. We will notify you once the review is complete.</p>
<div style="margin-top: 30px; padding: 20px; background: rgba(240,185,11,0.05); border-radius: 12px; border: 1px solid rgba(240,185,11,0.1); display: inline-block;">
<i class="fas fa-info-circle"></i> You can still trade while waiting for verification.
</div>
</div>
<?php elseif($status == 2): ?>
<div style="text-align: center; padding: 40px 0;">
<p style="color: var(--success-color); font-weight: 500;">Congratulations! Your identity has been fully verified.</p>
<p style="color: var(--text-muted); margin-top: 10px;">You now have full access to all withdrawal limits and advanced trading features.</p>
</div>
<?php endif; ?>
</div>
</div>
</main>
<style>
.upload-box {
border: 2px dashed var(--border-color);
height: 140px;
border-radius: 16px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
color: var(--text-muted);
transition: 0.3s;
background: rgba(255,255,255,0.01);
}
.upload-box:hover {
border-color: var(--primary-color);
background: rgba(0,82,255,0.02);
color: white;
}
.upload-box i { font-size: 24px; margin-bottom: 8px; }
.upload-box span { font-size: 13px; }
</style>
<script>
function previewFile(input, type) {
if (input.files && input.files[0]) {
const icon = document.getElementById('icon-' + type);
const text = document.getElementById('text-' + type);
icon.className = 'fas fa-check-circle';
icon.style.color = 'var(--success-color)';
text.innerText = input.files[0].name;
text.style.color = 'var(--success-color)';
}
}
</script>
<?php include 'footer.php'; ?>

73
login.php Normal file
View File

@ -0,0 +1,73 @@
<?php
require_once 'db/config.php';
require_once 'includes/i18n.php';
session_start();
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
// Capture and update IP correctly
$user_ip = $_SERVER['REMOTE_ADDR'];
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$user_ip = trim($ips[0]);
}
$pdo->prepare("UPDATE users SET last_ip = ? WHERE id = ?")->execute([$user_ip, $user['id']]);
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['uid'] = $user['uid'];
header("Location: index.php");
exit;
} else {
$error = __('invalid_credentials');
}
}
?>
<?php include 'header.php'; ?>
<main style="background: #0b0e11; min-height: calc(100vh - 64px); display: flex; align-items: center; justify-content: center; padding: 40px 20px;">
<div style="width: 100%; max-width: 480px; background: var(--card-bg); padding: 50px; border-radius: 32px; border: 1px solid var(--border-color); box-shadow: 0 20px 40px rgba(0,0,0,0.4);">
<h2 style="font-size: 2.2rem; font-weight: 800; margin-bottom: 10px; text-align: center; color: white;"><?php echo __('login_to_novaex'); ?></h2>
<p style="text-align: center; color: var(--text-muted); margin-bottom: 40px;"><?php echo __('welcome_back'); ?></p>
<?php if($error): ?>
<div style="background: rgba(246,70,93,0.1); color: var(--danger-color); padding: 15px; border-radius: 12px; margin-bottom: 25px; border: 1px solid var(--danger-color); text-align: center; font-size: 14px;">
<i class="fas fa-exclamation-circle"></i> <?php echo $error; ?>
</div>
<?php endif; ?>
<form method="POST">
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('email_or_phone'); ?></label>
<div style="position: relative;">
<i class="fas fa-user" style="position: absolute; left: 15px; top: 15px; color: #555;"></i>
<input type="text" name="username" required placeholder="<?php echo __('enter_email_phone'); ?>" style="width: 100%; padding: 15px 15px 15px 45px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; font-size: 1rem; outline: none; box-sizing: border-box;">
</div>
</div>
<div style="margin-bottom: 30px;">
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('login_password'); ?></label>
<div style="position: relative;">
<i class="fas fa-lock" style="position: absolute; left: 15px; top: 15px; color: #555;"></i>
<input type="password" name="password" required placeholder="<?php echo __('set_password'); ?>" style="width: 100%; padding: 15px 15px 15px 45px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; font-size: 1rem; outline: none; box-sizing: border-box;">
</div>
</div>
<button type="submit" class="btn-primary" style="width: 100%; padding: 18px; font-weight: 800; font-size: 1.1rem; border-radius: 16px; box-shadow: 0 10px 20px rgba(0,82,255,0.2);"><?php echo __('nav_login'); ?></button>
</form>
<div style="text-align: center; margin-top: 30px; border-top: 1px solid var(--border-color); padding-top: 30px;">
<span style="color: var(--text-muted);"><?php echo __('dont_have_account'); ?></span> <a href="register.php" style="color: var(--primary-color); text-decoration: none; font-weight: bold;"><?php echo __('nav_register'); ?></a>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

5
logout.php Normal file
View File

@ -0,0 +1,5 @@
<?php
session_start();
session_destroy();
header("Location: index.php");
exit;

107
markets.php Normal file
View File

@ -0,0 +1,107 @@
<?php include 'header.php'; ?>
<main style="padding: 20px 0; background: #0b0e11; min-height: calc(100vh - 65px);">
<div class="container">
<h1 style="color: white; margin-bottom: 20px; font-size: 1.8rem;"><?php echo __('crypto_markets'); ?></h1>
<div class="market-stats-grid" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-bottom: 25px;">
<div style="background: #1e2329; padding: 15px; border-radius: 12px; border: 1px solid #2b3139;">
<div style="color: #848e9c; font-size: 0.8rem;"><?php echo __('24h_volume'); ?></div>
<div style="font-size: 1.1rem; color: white; margin-top: 5px; font-weight: bold;">$ 84.2B</div>
</div>
<div style="background: #1e2329; padding: 15px; border-radius: 12px; border: 1px solid #2b3139;">
<div style="color: #848e9c; font-size: 0.8rem;"><?php echo __('fear_greed'); ?></div>
<div style="font-size: 1.1rem; color: #00c087; margin-top: 5px; font-weight: bold;">74 Greed</div>
</div>
<div style="background: #1e2329; padding: 15px; border-radius: 12px; border: 1px solid #2b3139;">
<div style="color: #848e9c; font-size: 0.8rem;"><?php echo __('btc_dominance'); ?></div>
<div style="font-size: 1.1rem; color: white; margin-top: 5px; font-weight: bold;">52.1%</div>
</div>
</div>
<div style="background: #1e2329; border-radius: 16px; border: 1px solid #2b3139; overflow: hidden;">
<div class="market-tabs" style="padding: 10px 20px; border-bottom: 1px solid #2b3139; display: flex; gap: 25px; overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch;">
<span style="color: white; border-bottom: 2px solid var(--primary-color); padding: 10px 0; cursor: pointer; font-size: 0.95rem; font-weight: 500;"><?php echo __('favorites'); ?></span>
<span style="color: #848e9c; padding: 10px 0; cursor: pointer; font-size: 0.95rem;"><?php echo __('all_crypto'); ?></span>
<span style="color: #848e9c; padding: 10px 0; cursor: pointer; font-size: 0.95rem;"><?php echo __('nav_spot'); ?></span>
<span style="color: #848e9c; padding: 10px 0; cursor: pointer; font-size: 0.95rem;"><?php echo __('nav_futures'); ?></span>
</div>
<div class="market-table-container">
<table style="width: 100%; border-collapse: collapse; min-width: 500px;">
<thead style="background: #161a1e;">
<tr>
<th style="padding: 12px 20px; text-align: left; color: #848e9c; font-weight: normal; font-size: 0.85rem;"><?php echo __('asset'); ?></th>
<th style="padding: 12px 20px; text-align: right; color: #848e9c; font-weight: normal; font-size: 0.85rem;"><?php echo __('price'); ?></th>
<th style="padding: 12px 20px; text-align: right; color: #848e9c; font-weight: normal; font-size: 0.85rem;">24h %</th>
<th class="desktop-only-cell" style="padding: 12px 20px; text-align: right; color: #848e9c; font-weight: normal; font-size: 0.85rem;"><?php echo __('24h_high_low'); ?></th>
<th class="desktop-only-cell" style="padding: 12px 20px; text-align: right; color: #848e9c; font-weight: normal; font-size: 0.85rem;"><?php echo __('trade_panel'); ?></th>
</tr>
</thead>
<tbody id="market-list-all">
<!-- Filled by WS -->
</tbody>
</table>
</div>
</div>
</div>
</main>
<style>
@media (max-width: 768px) {
.market-stats-grid { grid-template-columns: 1fr !important; }
.market-tabs::-webkit-scrollbar { display: none; }
.desktop-only-cell { display: none; }
}
</style>
<script>
const pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'LINKUSDT', 'AVAXUSDT', 'MATICUSDT', 'SHIBUSDT', 'TRXUSDT', 'LTCUSDT', 'BCHUSDT', 'UNIUSDT', 'FTMUSDT', 'NEARUSDT'];
const ws = new WebSocket('wss://stream.binance.com:9443/ws/' + pairs.map(p => p.toLowerCase() + '@ticker').join('/'));
const marketData = {};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
marketData[data.s] = data;
renderMarketList();
};
function renderMarketList() {
const tbody = document.getElementById('market-list-all');
if (!tbody) return;
let html = '';
pairs.forEach(p => {
const d = marketData[p];
if(!d) return;
const price = parseFloat(d.c).toLocaleString(undefined, {minimumFractionDigits: 2});
const change = parseFloat(d.P).toFixed(2);
const color = change >= 0 ? '#0ecb81' : '#f6465d';
const name = p.replace('USDT', '');
const icon = `https://assets.coincap.io/assets/icons/${name.toLowerCase()}@2x.png`;
html += `
<tr style="border-bottom: 1px solid #2b3139; cursor: pointer;" onclick="location.href='spot.php?symbol=${p}'">
<td style="padding: 15px 20px; display: flex; align-items: center; gap: 12px;">
<img src="${icon}" width="28" height="28" style="border-radius:50%; background:#2b3139" onerror="this.src='https://ui-avatars.com/api/?name=${name}&background=2b3139&color=fff'">
<div>
<div style="color: white; font-weight: bold; font-size: 0.95rem;">${name}</div>
<div style="color: #848e9c; font-size: 0.75rem;">${name}/USDT</div>
</div>
</td>
<td style="padding: 15px 20px; text-align: right; color: white; font-weight: bold; font-family: monospace; font-size: 0.95rem;">$ ${price}</td>
<td style="padding: 15px 20px; text-align: right; color: ${color}; font-weight: bold; font-size: 0.95rem;">${change >= 0 ? '+' : ''}${change}%</td>
<td class="desktop-only-cell" style="padding: 15px 20px; text-align: right; color: #848e9c; font-size: 0.8rem;">
<div>H: ${parseFloat(d.h).toFixed(2)}</div>
<div>L: ${parseFloat(d.l).toFixed(2)}</div>
</td>
<td class="desktop-only-cell" style="padding: 15px 20px; text-align: right;">
<a href="spot.php?symbol=${p}" class="btn-primary" style="padding: 6px 15px; font-size: 0.8rem; border-radius: 6px; text-decoration: none;"><?php echo __('buy'); ?></a>
</td>
</tr>
`;
});
tbody.innerHTML = html;
}
</script>
<?php include 'footer.php'; ?>

116
matching.php Normal file
View File

@ -0,0 +1,116 @@
<?php
require_once 'db/config.php';
require_once 'includes/currency_helper.php';
session_start();
function json_die($error) {
if (isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] === "XMLHttpRequest") {
echo json_encode(["success" => false, "error" => $error]);
} else {
die($error);
}
exit;
}
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
$user_id = $_SESSION['user_id'];
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['amount'])) {
$amount = (float)$_POST['amount'];
$order_type = $_POST['order_type'] ?? 'deposit'; // 'deposit' or 'withdrawal'
$type = $_POST['type'] ?? 'fiat'; // 'fiat' or 'usdt'
$currency = $_POST['currency'] ?? 'USDT';
$network = $_POST['network'] ?? '';
if ($amount <= 0) {
json_die("Invalid amount");
}
$fiat_rates = get_fiat_rates();
$rate = $fiat_rates[$currency] ?? 1.0;
if ($order_type === 'deposit') {
$usdt_amount = ($rate > 0) ? ($amount / $rate) : $amount;
} else {
// Withdrawal: amount is already in USDT (usually)
$usdt_amount = $amount;
// For withdrawal, we check balance first
$stmt = $pdo->prepare("SELECT balance FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$balance = (float)$stmt->fetchColumn();
if ($balance < $usdt_amount) {
json_die("余额不足");
}
// For withdrawal, we might need a trading password check if present
if (isset($_POST['trading_password'])) {
$stmt = $pdo->prepare("SELECT trading_password FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$saved_pass = $stmt->fetchColumn();
if ($saved_pass && $saved_pass !== $_POST['trading_password']) {
json_die("交易密码错误");
}
}
// Deduct balance immediately for withdrawal
$stmt = $pdo->prepare("UPDATE users SET balance = balance - ? WHERE id = ?");
$stmt->execute([$usdt_amount, $user_id]);
}
$expires_at = date('Y-m-d H:i:s', strtotime('+30 minutes'));
$pdo->beginTransaction();
try {
// Create order with status 'matching'
$stmt = $pdo->prepare("INSERT INTO fiat_orders (user_id, order_type, amount, usdt_amount, exchange_rate, currency, status, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?, 'matching', ?, CURRENT_TIMESTAMP)");
$stmt->execute([$user_id, $order_type, $amount, $usdt_amount, $rate, $currency, $expires_at]);
$order_id = $pdo->lastInsertId();
// Log to transactions table
$desc = ($order_type === 'deposit') ? "充值申请 #$order_id ($amount $currency)" : "提现申请 #$order_id ($amount $currency)";
$stmt = $pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, ?, ?, 'USDT', 'pending', ?)");
$stmt->execute([$user_id, $order_type, ($order_type === 'deposit' ? $usdt_amount : -$usdt_amount), $desc]);
// Notification message for admin/chat
$type_text = ($order_type === 'deposit') ? "充值" : "提现";
$method_info = ($type === 'usdt') ? "USDT ($network)" : "法币 ($currency)";
// More active messages as if user is typing
if ($order_type === 'deposit') {
$msg = "你好,我已发起一笔 $amount $currency 的充值申请。请为我匹配收款账户。";
} else {
$msg = "你好,我已发起一笔 $amount $currency 的提现申请。请发送收款信息格式给我。";
}
// System record (visible to admin as a request tag)
$sys_msg = "📢 订单详情\n类型: $type_text\n金额: $amount $currency\n方式: $method_info\n单号: #$order_id";
$stmt = $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
$stmt->execute([$user_id, $msg]);
$stmt = $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
$stmt->execute([$user_id, $sys_msg]);
$pdo->commit();
if (isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] === "XMLHttpRequest") {
echo json_encode(["success" => true, "order_id" => $order_id]);
exit;
} else {
header("Location: chat.php");
}
exit;
} catch (Exception $e) {
$pdo->rollBack();
json_die("Error: " . $e->getMessage());
}
} else {
header("Location: index.php");
exit;
}

113
mining.php Normal file
View File

@ -0,0 +1,113 @@
<?php include 'header.php'; ?>
<main style="padding: 40px 20px; background: #0b0e11; min-height: calc(100vh - 64px);">
<div style="max-width: 1200px; margin: 0 auto;">
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> <?php echo __('nav_home'); ?></a>
<div style="text-align: center; margin-bottom: 60px; padding: 40px 0; background: linear-gradient(180deg, rgba(0,82,255,0.05) 0%, transparent 100%); border-radius: 30px;">
<h1 style="font-size: 3.5rem; font-weight: 800; margin-bottom: 15px; color: white;"><?php echo __('mining_staking'); ?></h1>
<p style="color: var(--text-muted); font-size: 1.2rem; max-width: 700px; margin: 0 auto;"><?php echo __('mining_hero_subtitle'); ?></p>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 30px; margin-bottom: 60px;">
<div style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color); transition: 0.3s;" onmouseover="this.style.transform='translateY(-10px)'" onmouseout="this.style.transform='translateY(0)'">
<div style="width: 60px; height: 60px; background: rgba(0,82,255,0.1); border-radius: 16px; display: flex; align-items: center; justify-content: center; color: var(--primary-color); font-size: 28px; margin-bottom: 25px;">
<i class="fas fa-pickaxe"></i>
</div>
<h3 style="font-size: 1.5rem; margin-bottom: 15px;"><?php echo __('liquidity_mining'); ?></h3>
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 25px;"><?php echo __('liquidity_mining_desc'); ?></p>
<div style="display: flex; justify-content: space-between; align-items: center; padding-top: 20px; border-top: 1px solid var(--border-color);">
<div>
<div style="color: var(--text-muted); font-size: 12px;"><?php echo __('est_apr'); ?></div>
<div style="font-size: 20px; font-weight: bold; color: var(--success-color);">Up to 45.8%</div>
</div>
<button class="btn-primary" style="padding: 10px 25px; border-radius: 12px;"><?php echo __('stake_now'); ?></button>
</div>
</div>
<div style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color); transition: 0.3s;" onmouseover="this.style.transform='translateY(-10px)'" onmouseout="this.style.transform='translateY(0)'">
<div style="width: 60px; height: 60px; background: rgba(14,203,129,0.1); border-radius: 16px; display: flex; align-items: center; justify-content: center; color: var(--success-color); font-size: 28px; margin-bottom: 25px;">
<i class="fas fa-seedling"></i>
</div>
<h3 style="font-size: 1.5rem; margin-bottom: 15px;"><?php echo __('pos_staking'); ?></h3>
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 25px;"><?php echo __('pos_staking_desc'); ?></p>
<div style="display: flex; justify-content: space-between; align-items: center; padding-top: 20px; border-top: 1px solid var(--border-color);">
<div>
<div style="color: var(--text-muted); font-size: 12px;"><?php echo __('est_apr'); ?></div>
<div style="font-size: 20px; font-weight: bold; color: var(--success-color);">Up to 12.5%</div>
</div>
<button class="btn-primary" style="padding: 10px 25px; border-radius: 12px;"><?php echo __('stake_now'); ?></button>
</div>
</div>
<div style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color); transition: 0.3s;" onmouseover="this.style.transform='translateY(-10px)'" onmouseout="this.style.transform='translateY(0)'">
<div style="width: 60px; height: 60px; background: rgba(240,185,11,0.1); border-radius: 16px; display: flex; align-items: center; justify-content: center; color: var(--gold-color); font-size: 28px; margin-bottom: 25px;">
<i class="fas fa-gem"></i>
</div>
<h3 style="font-size: 1.5rem; margin-bottom: 15px;"><?php echo __('launchpad'); ?></h3>
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 25px;"><?php echo __('launchpad_desc'); ?></p>
<div style="display: flex; justify-content: space-between; align-items: center; padding-top: 20px; border-top: 1px solid var(--border-color);">
<div>
<div style="color: var(--text-muted); font-size: 12px;"><?php echo __('next_project'); ?></div>
<div style="font-size: 20px; font-weight: bold; color: var(--gold-color);"><?php echo __('coming_soon'); ?></div>
</div>
<button class="btn-primary" style="padding: 10px 25px; border-radius: 12px;"><?php echo __('view_details'); ?></button>
</div>
</div>
</div>
<div style="background: var(--card-bg); border-radius: 30px; border: 1px solid var(--border-color); overflow: hidden;">
<div style="padding: 30px 40px; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center;">
<h3 style="margin: 0;"><?php echo __('yield_rankings'); ?></h3>
<div style="display: flex; gap: 10px;">
<button style="padding: 8px 16px; background: #2b3139; border: none; color: white; border-radius: 8px; font-size: 13px;"><?php echo __('all'); ?></button>
<button style="padding: 8px 16px; background: transparent; border: 1px solid var(--border-color); color: var(--text-muted); border-radius: 8px; font-size: 13px;">DeFi</button>
<button style="padding: 8px 16px; background: transparent; border: 1px solid var(--border-color); color: var(--text-muted); border-radius: 8px; font-size: 13px;"><?php echo __('staking'); ?></button>
</div>
</div>
<div style="overflow-x: auto;">
<table style="width: 100%; border-collapse: collapse; min-width: 800px;">
<thead style="background: #161a1e;">
<tr>
<th style="padding: 20px 40px; text-align: left; color: var(--text-muted); font-weight: 500;"><?php echo __('asset'); ?></th>
<th style="padding: 20px 40px; text-align: left; color: var(--text-muted); font-weight: 500;"><?php echo __('est_apr'); ?></th>
<th style="padding: 20px 40px; text-align: left; color: var(--text-muted); font-weight: 500;"><?php echo __('duration'); ?></th>
<th style="padding: 20px 40px; text-align: right; color: var(--text-muted); font-weight: 500;"><?php echo __('action'); ?></th>
</tr>
</thead>
<tbody>
<?php
$mining_coins = [
['symbol' => 'USDT', 'apr' => '12.5%', 'duration' => __('flexible')],
['symbol' => 'BTC', 'apr' => '4.2%', 'duration' => '30 ' . __('days')],
['symbol' => 'ETH', 'apr' => '5.8%', 'duration' => __('flexible')],
['symbol' => 'SOL', 'apr' => '8.9%', 'duration' => '60 ' . __('days')],
['symbol' => 'DOT', 'apr' => '14.2%', 'duration' => '30 ' . __('days')],
];
foreach ($mining_coins as $coin):
?>
<tr style="border-bottom: 1px solid var(--border-color); transition: 0.2s;" onmouseover="this.style.background='#161a1e'" onmouseout="this.style.background='transparent'">
<td style="padding: 25px 40px;">
<div style="display: flex; align-items: center; gap: 15px;">
<img src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/<?php echo strtolower($coin['symbol']); ?>.png" width="35" height="35" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
<span style="font-weight: bold; font-size: 1.1rem;"><?php echo $coin['symbol']; ?></span>
</div>
</td>
<td style="padding: 25px 40px;">
<span style="color: var(--success-color); font-weight: bold; font-size: 1.1rem;"><?php echo $coin['apr']; ?></span>
</td>
<td style="padding: 25px 40px; color: var(--text-muted);"><?php echo $coin['duration']; ?></td>
<td style="padding: 25px 40px; text-align: right;">
<button class="btn-primary" style="padding: 8px 20px; border-radius: 10px;"><?php echo __('subscribe'); ?></button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

45
news.php Normal file
View File

@ -0,0 +1,45 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 1200px; margin: 0 auto;">
<h1 style="font-size: 3rem; font-weight: 800; margin-bottom: 50px; text-align: center;">NovaEx News & Insights</h1>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 40px; margin-bottom: 60px;">
<div style="grid-column: span 2; background: #161a1e; border-radius: 32px; overflow: hidden; border: 1px solid #2b3139;">
<div style="height: 400px; background: url('https://images.pexels.com/photos/6770610/pexels-photo-6770610.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1') center/cover;"></div>
<div style="padding: 40px;">
<span style="color: var(--primary-color); font-weight: bold; font-size: 0.9rem;">ANNOUNCEMENT</span>
<h2 style="font-size: 2.2rem; margin: 15px 0 20px;">NovaEx Launches Advanced Futures Trading Interface</h2>
<p style="color: var(--text-muted); line-height: 1.8; margin-bottom: 30px;">We are excited to announce the rollout of our next-generation trading engine, providing 10x faster execution and a highly customizable UI for professional traders.</p>
<a href="#" style="color: var(--primary-color); font-weight: bold; text-decoration: none;">Read More <i class="fas fa-arrow-right"></i></a>
</div>
</div>
<div style="background: #161a1e; border-radius: 24px; overflow: hidden; border: 1px solid #2b3139;">
<div style="height: 200px; background: url('https://images.pexels.com/photos/844124/pexels-photo-844124.jpeg?auto=compress&cs=tinysrgb&w=600') center/cover;"></div>
<div style="padding: 25px;">
<span style="color: #00c087; font-weight: bold; font-size: 0.8rem;">MARKET ANALYSIS</span>
<h3 style="font-size: 1.4rem; margin: 10px 0 15px;">The Rise of Layer 2 Solutions: What to Watch</h3>
<p style="color: var(--text-muted); font-size: 0.9rem; line-height: 1.6; margin-bottom: 20px;">An in-depth look at how scaling solutions are changing the Ethereum ecosystem and what it means for investors.</p>
<a href="#" style="color: var(--primary-color); font-weight: bold; text-decoration: none; font-size: 0.9rem;">Read More</a>
</div>
</div>
<div style="background: #161a1e; border-radius: 24px; overflow: hidden; border: 1px solid #2b3139;">
<div style="height: 200px; background: url('https://images.pexels.com/photos/5980860/pexels-photo-5980860.jpeg?auto=compress&cs=tinysrgb&w=600') center/cover;"></div>
<div style="padding: 25px;">
<span style="color: #f0b90b; font-weight: bold; font-size: 0.8rem;">SECURITY</span>
<h3 style="font-size: 1.4rem; margin: 10px 0 15px;">NovaEx Completes Annual Security Audit</h3>
<p style="color: var(--text-muted); font-size: 0.9rem; line-height: 1.6; margin-bottom: 20px;">We have successfully completed our comprehensive audit with top cybersecurity firms, reinforcing our commitment to user safety.</p>
<a href="#" style="color: var(--primary-color); font-weight: bold; text-decoration: none; font-size: 0.9rem;">Read More</a>
</div>
</div>
</div>
<div style="text-align: center;">
<button class="btn-primary" style="padding: 12px 30px; border-radius: 10px;"><?php echo __('load_more', '加载更多'); ?></button>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

712
options.php Normal file
View File

@ -0,0 +1,712 @@
<?php
if (session_status() === PHP_SESSION_NONE) { session_start(); }
if (!isset($_SESSION['user_id'])) { header('Location: login.php'); exit; }
include 'header.php';
$user_id = $_SESSION['user_id'];
$user_assets = [];
if ($user_id) {
// $db is already defined in header.php
$stmt = $db->prepare("SELECT balance FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$usdt_balance = $stmt->fetchColumn();
$user_assets['USDT'] = (float)($usdt_balance ?: 0);
$stmt = $db->prepare("SELECT symbol, amount FROM user_assets WHERE user_id = ?");
$stmt->execute([$user_id]);
$assets_data = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
if ($assets_data) {
foreach ($assets_data as $symbol => $amount) {
$user_assets[$symbol] = (float)$amount;
}
}
}
?>
<style>
.trading-page-wrapper { display: flex; flex-direction: column; min-height: 100vh; background: #0b0e11; }
.trading-container { flex-grow: 1; display: flex; min-height: 800px; max-width: 1920px; margin: 0 auto; width: 100%; }
.left-col { width: 280px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.center-col { flex: 1; min-width: 600px; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.right-col { width: 300px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; }
.chart-header { flex-shrink: 0; height: 55px; padding: 0 20px; display: flex; align-items: center; background: #161a1e; border-bottom: 1px solid #2b3139; gap: 25px; }
.chart-box { height: 450px; flex-shrink: 0; background: #161a1e; border-bottom: 1px solid #2b3139; }
.bottom-content-wrapper { flex-grow: 1; background: #161a1e; display: flex; flex-direction: column; }
.col-header { padding: 15px; font-weight: 600; border-bottom: 1px solid #2b3139; font-size: 14px; color: #eaecef; height: 50px; display: flex; align-items: center; }
#pairs-list { height: 756px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
#pairs-list::-webkit-scrollbar { width: 4px; }
#pairs-list::-webkit-scrollbar-track { background: transparent; }
#pairs-list::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
.coin-icon { width: 24px; height: 24px; margin-right: 10px; border-radius: 50%; }
.stats-item { display: flex; flex-direction: column; }
.stats-label { font-size: 11px; color: #848e9c; }
.stats-value { font-size: 13px; font-weight: 600; color: white; }
.category-tabs { display: flex; padding: 15px 15px 10px; gap: 8px; }
.category-tab { flex: 1; text-align: center; padding: 8px 0; background: #2b3139; border-radius: 6px; font-size: 12px; color: #848e9c; cursor: pointer; transition: 0.2s; border: 1px solid transparent; }
.category-tab.active { background: rgba(0, 102, 255, 0.1); color: var(--primary-color); border-color: var(--primary-color); font-weight: bold; }
.search-box { padding: 0 15px 15px; position: relative; }
.search-box i { position: absolute; left: 25px; top: 12px; color: #848e9c; font-size: 12px; }
.search-box input { width: 100%; background: #2b3139; border: 1px solid transparent; border-radius: 6px; padding: 8px 10px 8px 35px; color: white; font-size: 13px; outline: none; transition: 0.2s; }
.search-box input:focus { border-color: var(--primary-color); }
.pair-item { display: flex; align-items: center; padding: 12px 15px; cursor: pointer; border-bottom: 1px solid rgba(255,255,255,0.03); height: 42px; }
.pair-item:hover { background: #1e2329; }
.pair-item.active { background: #1e2329; border-left: 3px solid var(--primary-color); }
/* Order Panel - New Layout */
.order-panel { padding: 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
.panel-row { margin-bottom: 15px; }
.panel-label { color: #848e9c; font-size: 13px; margin-bottom: 8px; font-weight: 500; display: block; }
.duration-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.time-btn { background: #2b3139; border: 1px solid #3c424a; color: #eaecef; padding: 8px 4px; border-radius: 6px; font-size: 13px; cursor: pointer; text-align: center; font-weight: 600; transition: all 0.2s; }
.time-btn.active { background: var(--primary-color); border-color: var(--primary-color); color: white; transform: translateY(-1px); }
.time-btn .rate { font-size: 10px; font-weight: 400; color: #0ecb81; margin-top: 1px; }
.time-btn.active .rate { color: #fff; opacity: 0.9; }
.input-wrapper { position: relative; }
.amount-input-group { background: #2b3139; border-radius: 6px; padding: 10px 12px; display: flex; align-items: center; border: 1px solid #3c424a; transition: 0.2s; }
.amount-input-group:focus-within { border-color: var(--primary-color); }
.amount-input-group input { background: transparent; border: none; color: white; flex: 1; outline: none; font-size: 16px; font-weight: 600; width: 100%; }
.amount-input-group .unit { color: #848e9c; font-weight: 600; font-size: 14px; }
.balance-info-row { display: flex; justify-content: space-between; margin-top: 8px; font-size: 12px; }
.balance-info-row .label { color: #848e9c; }
.balance-info-row .value { color: #eaecef; font-weight: 600; }
.balance-info-row .profit-val { color: #0ecb81; font-weight: 700; }
.action-buttons { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 15px; }
.trade-btn { padding: 12px; border-radius: 8px; font-weight: 800; font-size: 15px; border: none; cursor: pointer; transition: 0.2s; display: flex; align-items: center; justify-content: center; gap: 8px; color: white; }
.btn-up { background: #0ecb81; }
.btn-down { background: #f6465d; }
.trade-btn:hover { filter: brightness(1.1); }
/* Records */
.records-container { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.record-tabs { display: flex; padding: 0 20px; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.record-tab { padding: 12px 0; margin-right: 25px; font-size: 13px; font-weight: 600; color: #848e9c; cursor: pointer; position: relative; }
.record-tab.active { color: white; }
.record-tab.active::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 2px; background: var(--primary-color); }
.table-responsive { height: 350px; overflow-y: auto; padding: 0; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
.table-responsive::-webkit-scrollbar { width: 4px; }
.table-responsive::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
table { width: 100%; font-size: 12px; border-collapse: collapse; }
th { color: #848e9c; font-weight: 500; text-align: left; padding: 10px 15px; border-bottom: 1px solid #2b3139; background: #161a1e; position: sticky; top: 0; z-index: 10; }
td { padding: 10px 15px; border-bottom: 1px solid rgba(255,255,255,0.02); color: #eaecef; height: 38px; }
/* Order Book */
.ob-header { display: flex; justify-content: space-between; padding: 8px 15px; background: #161a1e; font-size: 11px; color: #848e9c; border-bottom: 1px solid #2b3139; }
.ob-row { display: flex; justify-content: space-between; padding: 4px 15px; font-size: 12px; }
.ob-row .price.up { color: #0ecb81; }
.ob-row .price.down { color: #f6465d; }
#order-book-list { flex: 1; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
#order-book-list::-webkit-scrollbar { width: 4px; }
#order-book-list::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
/* Mobile Specific Styles */
@media (max-width: 991px) {
.trading-container { flex-direction: column; min-height: auto; }
.center-col { min-width: 100%; border-right: none; }
.chart-box { height: 300px; }
.order-panel { padding: 15px; }
.duration-grid { grid-template-columns: repeat(3, 1fr); }
.table-responsive { height: auto; max-height: 400px; }
.trading-page-wrapper { padding-bottom: 70px; } /* Space for bottom nav */
.mobile-trade-nav {
display: flex; background: #161a1e; border-bottom: 1px solid #2b3139; padding: 10px 15px; gap: 10px;
}
.mobile-trade-nav a {
flex: 1; text-align: center; padding: 8px 0; background: #2b3139; border-radius: 8px; font-size: 13px; color: #848e9c; text-decoration: none; font-weight: 600; border: 1px solid transparent;
}
.mobile-trade-nav a.active {
background: rgba(0, 82, 255, 0.1); color: var(--primary-color); border-color: var(--primary-color);
}
.mobile-symbol-selector {
display: flex; align-items: center; justify-content: space-between; padding: 12px 15px; background: #161a1e; border-bottom: 1px solid #2b3139;
}
}
@media (min-width: 992px) {
.mobile-trade-nav, .mobile-symbol-selector { display: none; }
}
/* Countdown Modal Styles */
.countdown-modal {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.85); display: none; align-items: center; justify-content: center; z-index: 10000;
backdrop-filter: blur(4px);
}
.modal-content-card {
background: #161a1e; width: 360px; border-radius: 20px; padding: 30px; position: relative; color: white;
box-shadow: 0 20px 50px rgba(0,0,0,0.5); border: 1px solid #2b3139;
}
.modal-close {
position: absolute; top: 15px; right: 15px; width: 32px; height: 32px;
background: #2b3139; border-radius: 50%; display: flex; align-items: center; justify-content: center;
cursor: pointer; color: #848e9c; transition: 0.2s;
}
.modal-close:hover { background: #3c424a; color: white; }
.countdown-circle-wrap { display: flex; flex-direction: column; align-items: center; margin: 25px 0; }
.circle-progress { position: relative; width: 140px; height: 140px; }
.circle-progress svg { transform: rotate(-90deg); width: 140px; height: 140px; }
.circle-bg { fill: none; stroke: #2b3139; stroke-width: 10; }
.circle-bar {
fill: none; stroke: #0ecb81; stroke-width: 10; stroke-linecap: round;
stroke-dasharray: 408; stroke-dashoffset: 408; transition: stroke-dashoffset 0.1s linear;
}
.countdown-text { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 32px; font-weight: 800; }
.modal-info-row { display: flex; justify-content: space-between; margin-bottom: 12px; font-size: 14px; }
.modal-info-label { color: #848e9c; }
.modal-info-value { font-weight: 600; color: #eaecef; }
.modal-info-value.up { color: #0ecb81; }
.modal-info-value.down { color: #f6465d; }
.modal-footer-text { text-align: center; color: #848e9c; font-size: 12px; margin-top: 20px; border-top: 1px solid #2b3139; padding-top: 15px; }
#result-overlay {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
background: #161a1e; border-radius: 20px; display: none; flex-direction: column; align-items: center; justify-content: center; z-index: 10;
}
.result-icon { font-size: 60px; margin-bottom: 20px; }
.result-title { font-size: 24px; font-weight: 800; margin-bottom: 10px; }
.result-amount { font-size: 32px; font-weight: 800; margin-bottom: 30px; }
.result-btn { background: var(--primary-color); color: white; padding: 12px 40px; border-radius: 10px; font-weight: 700; cursor: pointer; border: none; }
/* Mobile Drawer */
#mobile-pairs-drawer {
position: fixed; top: 0; left: -100%; width: 100%; height: 100%; background: #0b0e11; z-index: 3000; transition: 0.3s; padding: 20px; display: flex; flex-direction: column;
}
#mobile-pairs-drawer.open { left: 0; }
</style>
<div class="trading-page-wrapper">
<!-- Mobile Navigation Tabs -->
<div class="mobile-trade-nav">
<a href="options.php" class="active"><?php echo __('nav_options'); ?></a>
<a href="spot.php"><?php echo __('nav_spot'); ?></a>
<a href="futures.php"><?php echo __('nav_futures'); ?></a>
</div>
<!-- Mobile Symbol Selector -->
<div class="mobile-symbol-selector" onclick="toggleMobilePairs()">
<div style="display: flex; align-items: center; gap: 10px;">
<img id="curr-icon-mobile" src="" class="coin-icon" style="width: 28px; height: 28px;">
<span id="curr-pair-mobile" style="font-weight: 800; font-size: 18px; color: white;">--/--</span>
<i class="fas fa-caret-down" style="color: #848e9c;"></i>
</div>
<div style="text-align: right;">
<div id="curr-price-mobile" style="font-size: 18px; font-weight: 800; color: #0ecb81;">--</div>
<div id="curr-change-mobile" style="font-size: 12px; font-weight: 600;">--</div>
</div>
</div>
<div class="trading-container">
<!-- Left: Pair Selection (Desktop) -->
<div class="left-col d-none d-lg-flex">
<div class="category-tabs">
<div class="category-tab active" onclick="location.href='options.php'"><?php echo __('nav_options'); ?></div>
<div class="category-tab" onclick="location.href='spot.php'"><?php echo __('nav_spot'); ?></div>
<div class="category-tab" onclick="location.href='futures.php'"><?php echo __('nav_futures'); ?></div>
</div>
<div class="search-box">
<i class="fas fa-search"></i>
<input type="text" id="pair-search" placeholder="<?php echo __('search_currency'); ?>">
</div>
<div id="pairs-list"></div>
</div>
<!-- Center: Chart & Order -->
<div class="center-col">
<div class="chart-header d-none d-lg-flex">
<div class="d-flex align-items-center" style="gap:12px;">
<img id="curr-icon" src="" class="coin-icon">
<span id="curr-pair" style="font-weight: 800; font-size: 18px; color:white;">--/--</span>
</div>
<div class="stats-item">
<div id="curr-price" style="font-size: 20px; font-weight: 800; color: #0ecb81; line-height: 1;">--</div>
<div id="curr-change" style="font-size: 12px; font-weight: 600; margin-top:2px;">--</div>
</div>
<div class="stats-item d-none d-md-flex"><span class="stats-label"><?php echo __('24h_high'); ?></span><span class="stats-value" id="h-high">--</span></div>
<div class="stats-item d-none d-md-flex"><span class="stats-label"><?php echo __('24h_low'); ?></span><span class="stats-value" id="h-low">--</span></div>
</div>
<div class="chart-box" id="tv_chart_container"></div>
<div class="bottom-content-wrapper">
<div class="order-panel">
<!-- Row 1: Duration -->
<div class="panel-row">
<label class="panel-label"><?php echo __('settlement_time'); ?> / <?php echo __('profit'); ?></label>
<div class="duration-grid">
<div class="time-btn active" data-duration="60" data-rate="8" data-min="100">60s<div class="rate">+8%</div></div>
<div class="time-btn" data-duration="90" data-rate="12" data-min="5000">90s<div class="rate">+12%</div></div>
<div class="time-btn" data-duration="120" data-rate="15" data-min="30000">120s<div class="rate">+15%</div></div>
<div class="time-btn" data-duration="180" data-rate="20" data-min="100000">180s<div class="rate">+20%</div></div>
<div class="time-btn" data-duration="300" data-rate="32" data-min="300000">300s<div class="rate">+32%</div></div>
</div>
</div>
<!-- Row 2: Amount -->
<div class="panel-row" style="margin-bottom: 10px;">
<label class="panel-label"><?php echo __('buy_amount'); ?></label>
<div class="amount-input-group">
<input type="number" id="option-amount" value="100" placeholder="<?php echo __('min_amount'); ?> 100">
<span class="unit">USDT</span>
</div>
</div>
<!-- Row 2.5: Balance & Profit -->
<div class="balance-info-row">
<div>
<span class="label"><?php echo __('available'); ?>: </span>
<span class="value"><span id="usdt-balance">0.00</span> USDT</span>
</div>
<div>
<span class="label"><?php echo __('expected_profit'); ?>: </span>
<span class="profit-val" id="potential-profit">+0.00</span>
</div>
</div>
<!-- Row 3: Buttons -->
<div class="action-buttons">
<button class="trade-btn btn-up" id="btn-buy-up">
<i class="fas fa-arrow-up"></i> <?php echo __('buy_up'); ?>
</button>
<button class="trade-btn btn-down" id="btn-buy-down">
<i class="fas fa-arrow-down"></i> <?php echo __('buy_down'); ?>
</button>
</div>
</div>
<div class="records-container">
<div class="record-tabs">
<div class="record-tab active" data-status="pending"><?php echo __('in_progress'); ?></div>
<div class="record-tab" data-status="completed"><?php echo __('settled'); ?></div>
</div>
<div class="table-responsive">
<table id="records-list"></table>
</div>
</div>
</div>
</div>
<!-- Right: Order Book (Desktop) -->
<div class="right-col d-none d-xl-flex">
<div class="col-header"><?php echo __('order_book'); ?></div>
<div class="ob-header">
<span><?php echo __('price'); ?>(USDT)</span>
<span><?php echo __('amount'); ?></span>
</div>
<div id="order-book-list">
<div id="asks-list"></div>
<div id="price-mid" style="padding:10px 15px; font-weight:800; text-align:center; font-size:16px; border-top:1px solid #2b3139; border-bottom:1px solid #2b3139;">--</div>
<div id="bids-list"></div>
</div>
</div>
</div>
</div>
<!-- Mobile Pairs Drawer -->
<div id="mobile-pairs-drawer">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<h3 style="margin: 0; font-weight: 800;"><?php echo __('market'); ?></h3>
<i class="fas fa-times" onclick="toggleMobilePairs()" style="font-size: 20px; color: #848e9c;"></i>
</div>
<div class="search-box" style="padding: 0; margin-bottom: 20px;">
<i class="fas fa-search"></i>
<input type="text" id="pair-search-mobile" placeholder="<?php echo __('search_currency'); ?>">
</div>
<div id="pairs-list-mobile" style="flex: 1; overflow-y: auto;"></div>
</div>
<!-- Countdown Modal -->
<div id="countdown-modal" class="countdown-modal">
<div class="modal-content-card">
<div class="modal-close" onclick="closeCountdownModal()"><i class="fas fa-times"></i></div>
<div style="font-size: 20px; font-weight: 800; text-align: left;" id="modal-symbol">--</div>
<div class="countdown-circle-wrap">
<div class="circle-progress">
<svg>
<circle class="circle-bg" cx="70" cy="70" r="65"></circle>
<circle id="circle-bar" class="circle-bar" cx="70" cy="70" r="65"></circle>
</svg>
<div class="countdown-text" id="countdown-timer">00:00</div>
</div>
</div>
<div class="modal-info-row">
<span class="modal-info-label"><?php echo __('current_price'); ?></span>
<span class="modal-info-value" id="modal-curr-price">--</span>
</div>
<div class="modal-info-row">
<span class="modal-info-label"><?php echo __('period'); ?></span>
<span class="modal-info-value" id="modal-period">--</span>
</div>
<div class="modal-info-row">
<span class="modal-info-label"><?php echo __('direction'); ?></span>
<span class="modal-info-value" id="modal-direction">--</span>
</div>
<div class="modal-info-row">
<span class="modal-info-label"><?php echo __('amount'); ?></span>
<span class="modal-info-value" id="modal-amount">--</span>
</div>
<div class="modal-info-row">
<span class="modal-info-label"><?php echo __('price'); ?></span>
<span class="modal-info-value" id="modal-price">--</span>
</div>
<div class="modal-info-row">
<span class="modal-info-label"><?php echo __('expected_profit'); ?></span>
<span class="modal-info-value up" id="modal-profit">--</span>
</div>
<div class="modal-footer-text">
<?php echo __('final_price_notice'); ?>
</div>
<div id="result-overlay">
<div class="result-icon" id="result-icon"></div>
<div class="result-title" id="result-title"></div>
<div class="result-amount" id="result-amount"></div>
<button class="result-btn" onclick="closeCountdownModal()"><?php echo __('confirm'); ?></button>
</div>
</div>
</div>
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script>
const userAssets = <?php echo json_encode($user_assets); ?>;
function toggleMobilePairs() {
document.getElementById('mobile-pairs-drawer').classList.toggle('open');
}
document.addEventListener('DOMContentLoaded', function() {
let currentPair = 'BTCUSDT', currentPrice = 0, ws, chartWidget;
let selectedDuration = 60, selectedRate = 8, minAmount = 100;
const marketData = {};
const pairs = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'AVAXUSDT', 'DOTUSDT', 'MATICUSDT', 'LTCUSDT', 'TRXUSDT', 'LINKUSDT', 'UNIUSDT', 'ATOMUSDT', 'ETCUSDT', 'BCHUSDT', 'FILUSDT', 'ICPUSDT', 'NEARUSDT', 'AAVEUSDT', 'ALGOUSDT'];
let fetchOrdersInterval;
let activeOrdersTab = 'pending';
let countdownInterval;
const dom = {
currIcon: document.getElementById('curr-icon'),
currPair: document.getElementById('curr-pair'),
currPrice: document.getElementById('curr-price'),
currChange: document.getElementById('curr-change'),
currIconMobile: document.getElementById('curr-icon-mobile'),
currPairMobile: document.getElementById('curr-pair-mobile'),
currPriceMobile: document.getElementById('curr-price-mobile'),
currChangeMobile: document.getElementById('curr-change-mobile'),
hHigh: document.getElementById('h-high'),
hLow: document.getElementById('h-low'),
pairsList: document.getElementById('pairs-list'),
pairsListMobile: document.getElementById('pairs-list-mobile'),
pairSearch: document.getElementById('pair-search'),
pairSearchMobile: document.getElementById('pair-search-mobile'),
asksList: document.getElementById('asks-list'),
bidsList: document.getElementById('bids-list'),
midPrice: document.getElementById('price-mid'),
optionAmountInput: document.getElementById('option-amount'),
potentialProfit: document.getElementById('potential-profit'),
usdtBalance: document.getElementById('usdt-balance'),
recordsList: document.getElementById('records-list'),
// Modal DOM
modal: document.getElementById('countdown-modal'),
modalSymbol: document.getElementById('modal-symbol'),
modalTimer: document.getElementById('countdown-timer'),
modalCircle: document.getElementById('circle-bar'),
modalCurrPrice: document.getElementById('modal-curr-price'),
modalPeriod: document.getElementById('modal-period'),
modalDirection: document.getElementById('modal-direction'),
modalAmount: document.getElementById('modal-amount'),
modalPrice: document.getElementById('modal-price'),
modalProfit: document.getElementById('modal-profit'),
resultOverlay: document.getElementById('result-overlay'),
resultIcon: document.getElementById('result-icon'),
resultTitle: document.getElementById('result-title'),
resultAmount: document.getElementById('result-amount')
};
function updateAvailableBalance() {
dom.usdtBalance.innerText = parseFloat(userAssets.USDT || 0).toFixed(2);
}
function initChartWidget(symbol) {
if (chartWidget) { chartWidget = null; }
document.getElementById('tv_chart_container').innerHTML = '';
chartWidget = new TradingView.widget({
"autosize": true, "symbol": `BINANCE:${symbol}`,
"interval": "1", "timezone": "Etc/UTC", "theme": "dark", "style": "1",
"locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>",
"toolbar_bg": "#161a1e", "enable_publishing": false, "hide_side_toolbar": true, "allow_symbol_change": false,
"container_id": "tv_chart_container",
"studies": ["Volume@tv-basicstudies"],
"overrides": {
"paneProperties.background": "#161a1e",
"paneProperties.vertGridProperties.color": "rgba(255, 255, 255, 0.03)",
"paneProperties.horzGridProperties.color": "rgba(255, 255, 255, 0.03)",
"scalesProperties.textColor" : "#848e9c",
}
});
}
function connectWebSocket() {
if (ws) ws.close();
const tickerStreams = pairs.map(p => `${p.toLowerCase()}@ticker`).join('/');
const depthStream = `${currentPair.toLowerCase()}@depth20@100ms`;
ws = new WebSocket(`wss://stream.binance.com:9443/stream?streams=${tickerStreams}/${depthStream}`);
ws.onmessage = (event) => {
const { stream, data } = JSON.parse(event.data);
if (!data) return;
if (stream.endsWith('@ticker')) {
marketData[data.s] = data;
if (data.s === currentPair) {
currentPrice = parseFloat(data.c);
updatePriceUI(data);
if(dom.midPrice) {
dom.midPrice.innerText = currentPrice.toFixed(2);
dom.midPrice.style.color = data.P >= 0 ? '#0ecb81' : '#f6465d';
}
if (dom.modal.style.display === 'flex') {
dom.modalCurrPrice.innerText = currentPrice.toFixed(4);
dom.modalCurrPrice.style.color = data.P >= 0 ? '#0ecb81' : '#f6465d';
}
}
if (dom.pairsList.offsetParent || dom.pairsListMobile.offsetParent) renderPairs();
} else if (stream.endsWith('@depth20@100ms')) {
if(dom.asksList) renderOrderBook(data.bids, data.asks);
}
};
ws.onclose = () => setTimeout(connectWebSocket, 5000);
}
function renderOrderBook(bids, asks) {
const formatRow = (row, type) => `<div class="ob-row"><div class="price ${type}">${parseFloat(row[0]).toFixed(2)}</div><div>${parseFloat(row[1]).toFixed(3)}</div></div>`;
dom.asksList.innerHTML = asks.slice(0, 20).reverse().map(a => formatRow(a, 'down')).join('');
dom.bidsList.innerHTML = bids.slice(0, 20).map(b => formatRow(b, 'up')).join('');
}
function updatePriceUI(d) {
const color = d.P >= 0 ? '#0ecb81' : '#f6465d';
const priceStr = parseFloat(d.c).toLocaleString('en-US', {minimumFractionDigits: 2});
if(dom.currPrice) dom.currPrice.innerText = priceStr;
if(dom.currPrice) dom.currPrice.style.color = color;
if(dom.currChange) dom.currChange.innerText = `${d.P >= 0 ? '+' : ''}${parseFloat(d.P).toFixed(2)}%`;
if(dom.currChange) dom.currChange.style.color = color;
dom.currPriceMobile.innerText = priceStr;
dom.currPriceMobile.style.color = color;
dom.currChangeMobile.innerText = `${d.P >= 0 ? '+' : ''}${parseFloat(d.P).toFixed(2)}%`;
dom.currChangeMobile.style.color = color;
if(dom.hHigh) dom.hHigh.innerText = parseFloat(d.h).toFixed(2);
if(dom.hLow) dom.hLow.innerText = parseFloat(d.l).toFixed(2);
document.title = `${priceStr} | ${currentPair}`;
}
function renderPairs() {
const query = dom.pairSearch.value.toUpperCase();
const queryMobile = dom.pairSearchMobile.value.toUpperCase();
const generateHtml = (q) => pairs.filter(p => p.includes(q)).map(p => {
const d = marketData[p] || {};
const price = d.c ? parseFloat(d.c).toFixed(2) : '--';
const change = d.P ? `${parseFloat(d.P) >= 0 ? '+' : ''}${parseFloat(d.P).toFixed(2)}%` : '--';
const color = (d.P && parseFloat(d.P) >= 0) ? '#0ecb81' : '#f6465d';
return `<div class="pair-item ${p === currentPair ? 'active' : ''}" data-pair="${p}">
<img src="https://assets.coincap.io/assets/icons/${p.replace('USDT','').toLowerCase()}@2x.png" class="coin-icon" onerror="this.style.opacity=0">
<div style="flex:1"><div style="font-weight:600; color:white;">${p.replace('USDT','/USDT')}</div></div>
<div style="text-align:right"><div style="font-weight:600; color:white;">${price}</div><div style="font-size:11px; color:${color}">${change}</div></div>
</div>`;
}).join('');
dom.pairsList.innerHTML = generateHtml(query);
dom.pairsListMobile.innerHTML = generateHtml(queryMobile);
}
function switchPair(pair) {
currentPair = pair;
dom.currPair.innerText = `${pair.replace('USDT', '/USDT')}`;
dom.currPairMobile.innerText = `${pair.replace('USDT', '/USDT')}`;
dom.currIcon.src = `https://assets.coincap.io/assets/icons/${pair.replace('USDT','').toLowerCase()}@2x.png`;
dom.currIconMobile.src = `https://assets.coincap.io/assets/icons/${pair.replace('USDT','').toLowerCase()}@2x.png`;
initChartWidget(pair);
renderPairs();
connectWebSocket();
if(document.getElementById('mobile-pairs-drawer').classList.contains('open')) toggleMobilePairs();
}
function updatePotentialProfit() {
const amount = parseFloat(dom.optionAmountInput.value) || 0;
dom.potentialProfit.innerText = `+${(amount * (selectedRate / 100)).toFixed(2)}`;
}
window.closeCountdownModal = () => {
dom.modal.style.display = 'none';
dom.resultOverlay.style.display = 'none';
if (countdownInterval) clearInterval(countdownInterval);
};
function startCountdown(duration, orderId) {
let timeLeft = duration;
const total = duration;
dom.modalTimer.innerText = `00:${timeLeft < 10 ? '0' + timeLeft : timeLeft}`;
dom.modalCircle.style.strokeDashoffset = 0;
if (countdownInterval) clearInterval(countdownInterval);
countdownInterval = setInterval(async () => {
timeLeft--;
if (timeLeft <= 0) {
clearInterval(countdownInterval);
dom.modalTimer.innerText = "00:00";
dom.modalCircle.style.strokeDashoffset = 408;
// Show final result
try {
const r = await fetch(`api/get_option_orders.php?status=completed`);
const orders = await r.json();
const order = orders.find(o => o.id == orderId);
if (order) {
const profit = parseFloat(order.profit);
dom.resultIcon.innerHTML = profit > 0 ? '<i class="fas fa-trophy" style="color:#0ecb81"></i>' : '<i class="fas fa-times-circle" style="color:#f6465d"></i>';
dom.resultTitle.innerText = profit > 0 ? '<?php echo __('win'); ?>' : '<?php echo __('loss'); ?>';
dom.resultTitle.style.color = profit > 0 ? '#0ecb81' : '#f6465d';
dom.resultAmount.innerText = (profit > 0 ? '+' : '') + profit.toFixed(2) + ' USDT';
dom.resultAmount.style.color = profit > 0 ? '#0ecb81' : '#f6465d';
dom.resultOverlay.style.display = 'flex';
} else {
// Fallback if order not found immediately
setTimeout(() => startCountdown(0, orderId), 2000);
}
} catch(e) {}
return;
}
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
dom.modalTimer.innerText = `${minutes < 10 ? '0' + minutes : minutes}:${seconds < 10 ? '0' + seconds : seconds}`;
const offset = (408 * (total - timeLeft) / total);
dom.modalCircle.style.strokeDashoffset = offset;
}, 1000);
}
async function placeOrder(direction) {
const amount = parseFloat(dom.optionAmountInput.value);
if (isNaN(amount) || amount < minAmount) { alert("<?php echo __('min_amount'); ?>: " + minAmount + " USDT"); return; }
const btn = direction === 'up' ? document.getElementById('btn-buy-up') : document.getElementById('btn-buy-down');
const originalText = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
try {
const response = await fetch('api/place_option_order.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
pair: currentPair, amount: amount, direction: direction,
duration: selectedDuration, rate: selectedRate, price: currentPrice
})
});
const result = await response.json();
if (result.success) {
// Show Modal
dom.modalSymbol.innerText = currentPair.replace('USDT', '');
dom.modalPeriod.innerText = selectedDuration + 's';
dom.modalDirection.innerText = direction === 'up' ? '<?php echo __('buy_up'); ?>' : '<?php echo __('buy_down'); ?>';
dom.modalDirection.className = 'modal-info-value ' + (direction === 'up' ? 'up' : 'down');
dom.modalAmount.innerText = amount + ' USDT';
dom.modalPrice.innerText = currentPrice.toFixed(4);
dom.modalProfit.innerText = '+' + (amount * (selectedRate / 100)).toFixed(2) + ' USDT';
dom.modalProfit.className = 'modal-info-value up';
dom.modal.style.display = 'flex';
dom.resultOverlay.style.display = 'none';
startCountdown(selectedDuration, result.order.id);
fetchOrders();
} else {
alert(result.error || "<?php echo __('error_placing_order'); ?>");
}
} catch(e) { alert("<?php echo __('network_error'); ?>"); }
finally { btn.disabled = false; btn.innerHTML = originalText; }
}
async function fetchOrders() {
try {
const r = await fetch(`api/get_option_orders.php?status=${activeOrdersTab}`);
const orders = await r.json();
renderOrders(orders);
} catch (e) {}
}
function renderOrders(orders) {
if (!orders || orders.length === 0) {
dom.recordsList.innerHTML = '<tr><td colspan="8" style="text-align:center; padding:40px; color:#848e9c"><?php echo __('no_records'); ?></td></tr>';
return;
}
let html = `<thead><tr><th><?php echo __('pair'); ?></th><th><?php echo __('direction'); ?></th><th><?php echo __('amount'); ?></th><th><?php echo __('opening_price'); ?></th><th><?php echo __('closing_price'); ?></th><th><?php echo __('profit'); ?></th><th><?php echo __('status'); ?></th><th><?php echo __('time'); ?></th></tr></thead><tbody>`;
orders.forEach(o => {
const color = o.direction === 'up' ? '#0ecb81' : '#f6465d';
const statusColor = o.status === 'completed' ? (parseFloat(o.profit) > 0 ? '#0ecb81' : '#f6465d') : '#ffc107';
html += `<tr>
<td style="font-weight:600">${o.symbol}</td>
<td style="color:${color}">${o.direction === 'up' ? '<?php echo __('buy_up'); ?>' : '<?php echo __('buy_down'); ?>'}</td>
<td>${parseFloat(o.amount).toFixed(2)}</td>
<td>${parseFloat(o.opening_price).toFixed(4)}</td>
<td>${o.closing_price ? parseFloat(o.closing_price).toFixed(4) : '--'}</td>
<td style="color:${statusColor}">${o.status === 'completed' ? (parseFloat(o.profit) > 0 ? '+' : '') + parseFloat(o.profit).toFixed(2) : '--'}</td>
<td style="color:${statusColor}">${o.status === 'completed' ? (parseFloat(o.profit) > 0 ? '<?php echo __('win'); ?>' : '<?php echo __('loss'); ?>') : '<?php echo __('in_progress'); ?>'}</td>
<td style="color:#848e9c">${o.created_at}</td>
</tr>`;
});
dom.recordsList.innerHTML = html + '</tbody>';
}
dom.pairsList.addEventListener('click', e => { const item = e.target.closest('.pair-item'); if (item) switchPair(item.dataset.pair); });
dom.pairsListMobile.addEventListener('click', e => { const item = e.target.closest('.pair-item'); if (item) switchPair(item.dataset.pair); });
dom.pairSearch.addEventListener('input', renderPairs);
dom.pairSearchMobile.addEventListener('input', renderPairs);
document.querySelectorAll('.time-btn').forEach(btn => btn.addEventListener('click', () => {
document.querySelector('.time-btn.active').classList.remove('active');
btn.classList.add('active');
selectedDuration = parseInt(btn.dataset.duration);
selectedRate = parseInt(btn.dataset.rate);
minAmount = parseInt(btn.dataset.min);
dom.optionAmountInput.placeholder = "<?php echo __('min_amount'); ?> " + minAmount;
updatePotentialProfit();
}));
dom.optionAmountInput.addEventListener('input', updatePotentialProfit);
document.getElementById('btn-buy-up').addEventListener('click', () => placeOrder('up'));
document.getElementById('btn-buy-down').addEventListener('click', () => placeOrder('down'));
document.querySelectorAll('.record-tab').forEach(tab => tab.addEventListener('click', () => {
document.querySelector('.record-tab.active').classList.remove('active');
tab.classList.add('active');
activeOrdersTab = tab.dataset.status;
fetchOrders();
}));
updateAvailableBalance();
switchPair('BTCUSDT');
updatePotentialProfit();
fetchOrders();
setInterval(fetchOrders, 5000);
});
</script>
<?php include 'footer.php'; ?>

52
privacy.php Normal file
View File

@ -0,0 +1,52 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 900px; margin: 0 auto; background: #161a1e; padding: 60px; border-radius: 32px; border: 1px solid #2b3139;">
<h1 style="font-size: 2.5rem; margin-bottom: 20px;">Legal & Privacy Policy</h1>
<p style="color: var(--text-muted); margin-bottom: 40px;">Last Updated: February 2026</p>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.8rem; margin-bottom: 20px; color: #4facfe;">1. Introduction</h2>
<p style="color: var(--text-muted); line-height: 1.8;">NovaEx ("we", "our", or "us") is committed to protecting your privacy. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you visit our website or use our services.</p>
</section>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.8rem; margin-bottom: 20px; color: #4facfe;">2. Information We Collect</h2>
<p style="color: var(--text-muted); line-height: 1.8;">We collect information that you provide directly to us, such as when you create an account, verify your identity (KYC), or contact support. This includes:</p>
<ul style="color: var(--text-muted); line-height: 1.8; margin-top: 15px;">
<li>Personal identifiers (Name, Email, Phone Number)</li>
<li>Identity documentation (Passport, ID Card, Driver's License)</li>
<li>Financial information (Wallet addresses, Transaction history)</li>
<li>Technical data (IP address, Browser type, Device info)</li>
</ul>
</section>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.8rem; margin-bottom: 20px; color: #4facfe;">3. How We Use Your Information</h2>
<p style="color: var(--text-muted); line-height: 1.8;">We use your information to provide and improve our services, including:</p>
<ul style="color: var(--text-muted); line-height: 1.8; margin-top: 15px;">
<li>Processing transactions and managing your account</li>
<li>Complying with legal and regulatory requirements (AML/KYC)</li>
<li>Detecting and preventing fraudulent activities</li>
<li>Communicating with you about updates and promotions</li>
</ul>
</section>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.8rem; margin-bottom: 20px; color: #4facfe;">4. Data Security</h2>
<p style="color: var(--text-muted); line-height: 1.8;">We implement robust security measures to protect your data, including end-to-end encryption, multi-factor authentication, and secure cold storage for digital assets. However, no method of transmission over the internet is 100% secure.</p>
</section>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.8rem; margin-bottom: 20px; color: #4facfe;">5. Your Rights</h2>
<p style="color: var(--text-muted); line-height: 1.8;">Depending on your location, you may have rights regarding your personal data, including the right to access, correct, or delete your information. Contact our privacy team at privacy@novaex.com for assistance.</p>
</section>
<div style="margin-top: 60px; padding-top: 40px; border-top: 1px solid #2b3139; text-align: center;">
<p style="color: var(--text-muted);">If you have any questions about this policy, please contact us.</p>
<a href="request.php" class="btn-primary" style="margin-top: 20px; display: inline-block;">Submit a Privacy Request</a>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

442
profile.php Normal file
View File

@ -0,0 +1,442 @@
<?php
session_start();
include 'header.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
require_once 'db/config.php';
$db = db();
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
$kyc_status = $user['kyc_status'] ?? 0;
$kyc_labels = [
0 => '未认证',
1 => '审核中',
2 => '已认证',
3 => '未通过',
];
$kyc_colors = [0 => '#888', 1 => '#f0b90b', 2 => 'var(--success-color)', 3 => 'var(--danger-color)'];
?>
<style>
.profile-container {
padding: 40px 0;
background: #0b0e11;
min-height: 100vh;
}
.profile-grid {
display: grid;
grid-template-columns: 340px 1fr;
gap: 30px;
}
.profile-card {
background: var(--card-bg);
border: 1px solid var(--border-color);
border-radius: 24px;
overflow: hidden;
}
.user-info-card {
padding: 40px 30px;
text-align: center;
background: linear-gradient(180deg, #1e2329 0%, #161a1e 100%);
}
.avatar-circle {
width: 100px;
height: 100px;
background: linear-gradient(135deg, #f0b90b, #f8d33a);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 25px;
font-size: 2.5rem;
font-weight: 900;
color: #000;
box-shadow: 0 15px 35px rgba(240, 185, 11, 0.25);
}
.uid-badge {
display: inline-block;
padding: 6px 16px;
background: rgba(255, 255, 255, 0.05);
border-radius: 20px;
color: var(--text-muted);
font-size: 0.85rem;
margin-top: 10px;
font-family: 'Roboto Mono', monospace;
}
.sidebar-menu { padding: 15px; }
.sidebar-menu-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 22px;
border-radius: 18px;
color: white;
text-decoration: none;
transition: all 0.3s ease;
margin-bottom: 10px;
}
.sidebar-menu-item:hover { background: rgba(255, 255, 255, 0.04); transform: translateX(5px); }
.balance-card {
padding: 50px;
margin-bottom: 30px;
background: url('https://www.transparenttextures.com/patterns/carbon-fibre.png'), linear-gradient(135deg, #1e2329 0%, #0b0e11 100%);
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
}
.balance-val {
font-size: 3.5rem;
font-weight: 800;
color: white;
letter-spacing: -1px;
margin: 10px 0;
}
.balance-actions { display: flex; gap: 20px; margin-top: 40px; }
.balance-actions .btn {
flex: 1;
padding: 18px;
border-radius: 16px;
font-weight: 800;
font-size: 1.1rem;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
transition: 0.3s;
text-decoration: none;
}
.btn-deposit { background: var(--primary-color); color: white; }
.btn-withdraw { background: #2b3139; color: white; border: 1px solid #3b424d; }
.btn-deposit:hover { background: #0042cc; transform: translateY(-3px); box-shadow: 0 10px 20px rgba(0, 82, 255, 0.2); }
.btn-withdraw:hover { background: #3b424d; transform: translateY(-3px); }
.profile-tabs {
display: flex;
gap: 50px;
padding: 0 50px;
border-bottom: 1px solid var(--border-color);
background: rgba(255,255,255,0.01);
}
.profile-tab-btn {
padding: 20px 0;
background: none;
border: none;
color: var(--text-muted);
font-weight: 700;
font-size: 1.1rem;
cursor: pointer;
border-bottom: 4px solid transparent;
transition: 0.3s;
}
.profile-tab-btn.active { color: var(--primary-color); border-bottom-color: var(--primary-color); }
.record-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.record-card {
background: #161a1e;
border-radius: 20px;
padding: 25px;
border: 1px solid #2b3139;
transition: 0.3s;
}
.record-card:hover { border-color: rgba(0, 82, 255, 0.3); transform: translateY(-5px); }
.status-badge {
padding: 5px 12px;
border-radius: 8px;
font-size: 11px;
font-weight: 800;
}
@media (max-width: 1200px) {
.record-grid { grid-template-columns: 1fr; }
}
@media (max-width: 992px) {
.profile-grid { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
.balance-card { padding: 30px 20px; }
.balance-val { font-size: 2.5rem; }
.profile-tabs { gap: 20px; padding: 0 20px; }
.profile-tab-btn { font-size: 1rem; }
.tab-content { padding: 25px 15px !important; }
.record-card { padding: 15px; }
}
@media (max-width: 480px) {
.assets-grid { grid-template-columns: 1fr !important; }
}
</style>
<div class="profile-container">
<div class="container">
<div class="profile-grid">
<!-- 侧边栏 -->
<div class="profile-sidebar">
<div class="profile-card user-info-card">
<div class="avatar-circle">
<?php echo strtoupper(substr($user['username'], 0, 1)); ?>
</div>
<h2 style="color: white; margin: 0; font-size: 1.8rem; font-weight: 800;"><?php echo $user['username']; ?></h2>
<div class="uid-badge">UID: <?php echo $user['uid'] ?: '618120'; ?></div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 40px; padding-top: 30px; border-top: 1px solid rgba(255,255,255,0.05);">
<div>
<div style="color: var(--text-muted); font-size: 13px; margin-bottom: 6px;">信用评分</div>
<div style="font-weight: 800; font-size: 1.4rem; color: var(--success-color);"><?php echo $user['credit_score'] ?? 100; ?></div>
</div>
<div style="border-left: 1px solid rgba(255,255,255,0.05);">
<div style="color: var(--text-muted); font-size: 13px; margin-bottom: 6px;">账户等级</div>
<div style="font-weight: 800; font-size: 1.4rem; color: #f0b90b;">VIP 0</div>
</div>
</div>
</div>
<div class="profile-card sidebar-menu">
<a href="kyc.php" class="sidebar-menu-item">
<div style="display: flex; align-items: center; gap: 15px;">
<div style="width: 45px; height: 45px; background: rgba(79,172,254,0.1); border-radius: 14px; display: flex; align-items: center; justify-content: center; color: #4facfe;">
<i class="fas fa-id-card fa-lg"></i>
</div>
<span style="font-weight: 700;">身份认证 (KYC)</span>
</div>
<div style="display: flex; align-items: center; gap: 10px;">
<span style="font-size: 12px; font-weight: 800; color: <?php echo $kyc_colors[$kyc_status]; ?>"><?php echo $kyc_labels[$kyc_status]; ?></span>
<i class="fas fa-chevron-right" style="font-size: 12px; color: var(--text-muted);"></i>
</div>
</a>
<a href="security.php" class="sidebar-menu-item">
<div style="display: flex; align-items: center; gap: 15px;">
<div style="width: 45px; height: 45px; background: rgba(14,203,129,0.1); border-radius: 14px; display: flex; align-items: center; justify-content: center; color: var(--success-color);">
<i class="fas fa-shield-alt fa-lg"></i>
</div>
<span style="font-weight: 700;">安全设置</span>
</div>
<i class="fas fa-chevron-right" style="font-size: 12px; color: var(--text-muted);"></i>
</a>
<a href="logout.php" class="sidebar-menu-item" style="margin-top: 15px; color: var(--danger-color);">
<div style="display: flex; align-items: center; gap: 15px;">
<div style="width: 45px; height: 45px; background: rgba(246,70,93,0.1); border-radius: 14px; display: flex; align-items: center; justify-content: center;">
<i class="fas fa-sign-out-alt fa-lg"></i>
</div>
<span style="font-weight: 700;">退出登录</span>
</div>
</a>
</div>
</div>
<!-- 主内容区 -->
<div>
<div class="profile-card balance-card">
<div style="color: var(--text-muted); font-size: 16px; font-weight: 600;">账户总净资产 (USDT)</div>
<div class="balance-val"><?php echo number_format($user['balance'] ?? 0, 2); ?></div>
<div style="color: var(--text-muted); font-size: 1.1rem; display: flex; align-items: center; gap: 12px;">
<span style="font-family: 'Roboto Mono', monospace;"> $ <?php echo number_format($user['balance'] ?? 0, 2); ?></span>
<i class="fas fa-eye" style="cursor: pointer; font-size: 16px; color: var(--primary-color);"></i>
</div>
<div class="balance-actions">
<a href="deposit.php" class="btn btn-deposit">
<i class="fas fa-wallet"></i> 充值
</a>
<a href="withdraw.php" class="btn btn-withdraw">
<i class="fas fa-paper-plane"></i> 提现
</a>
</div>
</div>
<div class="profile-card">
<div class="profile-tabs">
<button class="profile-tab-btn active" onclick="switchProfileTab(this, 'assets-tab')">资产详情</button>
<button class="profile-tab-btn" onclick="switchProfileTab(this, 'records-tab')">交易记录</button>
</div>
<!-- 资产页签 -->
<div id="assets-tab" class="tab-content" style="padding: 40px;">
<div class="assets-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
<?php
$coins = [
['symbol' => 'USDT', 'name' => 'Tether', 'balance' => $user['balance'] ?? 0],
['symbol' => 'BTC', 'name' => 'Bitcoin', 'balance' => 0],
['symbol' => 'ETH', 'name' => 'Ethereum', 'balance' => 0],
['symbol' => 'SOL', 'name' => 'Solana', 'balance' => 0],
['symbol' => 'BNB', 'name' => 'Binance Coin', 'balance' => 0],
['symbol' => 'XRP', 'name' => 'Ripple', 'balance' => 0],
];
try {
$asset_stmt = $db->prepare("SELECT * FROM user_assets WHERE user_id = ?");
$asset_stmt->execute([$_SESSION['user_id']]);
$db_assets = $asset_stmt->fetchAll();
foreach ($db_assets as $da) {
$found = false;
foreach ($coins as &$c) {
if ($c['symbol'] === $da['symbol']) {
$c['balance'] = $da['amount'];
$found = true;
}
}
if (!$found) {
$coins[] = ['symbol' => $da['symbol'], 'name' => '', 'balance' => $da['amount']];
}
}
} catch (Exception $e) {}
foreach ($coins as $coin):
?>
<div style="display: flex; align-items: center; justify-content: space-between; padding: 22px; background: rgba(255,255,255,0.02); border-radius: 20px; border: 1px solid rgba(255,255,255,0.05); transition: 0.3s;">
<div style="display: flex; align-items: center; gap: 12px;">
<img src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/<?php echo strtolower($coin['symbol']); ?>.png" width="36" height="36" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
<div>
<div style="font-weight: 800; font-size: 1.1rem; color: white;"><?php echo $coin['symbol']; ?></div>
<div style="font-size: 0.75rem; color: var(--text-muted);"><?php echo $coin['name']; ?></div>
</div>
</div>
<div style="text-align: right;">
<div style="font-weight: 800; font-family: 'Roboto Mono', monospace; font-size: 1.1rem; color: white;">
<?php echo number_format($coin['balance'], $coin['symbol'] === 'USDT' ? 2 : 6); ?>
</div>
<div style="font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase;">余额</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- 记录页签 -->
<div id="records-tab" class="tab-content" style="display: none; padding: 40px;">
<div id="records-list" class="record-grid" style="max-height: 800px; overflow-y: auto; padding-right: 10px;">
<div style="grid-column: span 2; text-align: center; padding: 60px;">
<div class="spinner-border text-warning" role="status"></div>
<p style="margin-top: 15px; color: var(--text-muted);">正在加载交易记录...</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function switchProfileTab(btn, tabId) {
document.querySelectorAll('.profile-tab-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('.tab-content').forEach(c => c.style.display = 'none');
document.getElementById(tabId).style.display = 'block';
if (tabId === 'records-tab') { loadTransactionRecords(); }
}
async function loadTransactionRecords() {
const container = document.getElementById('records-list');
try {
const [spotResp, futuresResp, optionsResp, transResp] = await Promise.all([
fetch('api/get_orders.php?type=spot&status=history'),
fetch('api/get_orders.php?type=futures&status=history'),
fetch('api/get_option_orders.php?status=history'),
fetch('api/get_transactions.php')
]);
const spotRes = await spotResp.json();
const futuresRes = await futuresResp.json();
const optionsRes = await optionsResp.json();
const transRes = await transResp.json();
let allRecords = [];
if (spotRes.success) spotRes.data.forEach(r => { r.display_type = 'trade'; r.trade_label = '现货交易'; allRecords.push(r); });
if (futuresRes.success) futuresRes.data.forEach(r => { r.display_type = 'trade'; r.trade_label = '永续合约'; allRecords.push(r); });
if (optionsRes.success) optionsRes.data.forEach(r => { r.display_type = 'option'; r.trade_label = '秒合约'; allRecords.push(r); });
if (transRes.success) transRes.data.forEach(t => { t.display_type = 'transaction'; allRecords.push(t); });
allRecords.sort((a, b) => new Date(b.created_at || b.open_time) - new Date(a.created_at || a.open_time));
if (allRecords.length === 0) {
container.innerHTML = '<div style="grid-column: span 1; text-align: center; padding: 100px; color: var(--text-muted);"><i class="fas fa-file-invoice" style="font-size: 4rem; opacity: 0.2; margin-bottom: 25px;"></i><br>暂无任何交易记录</div>';
return;
}
let html = '';
allRecords.forEach(r => {
if (r.display_type === 'trade' || r.display_type === 'option') {
const profit = parseFloat(r.profit || 0);
const isProfit = profit > 0;
const profitColor = isProfit ? 'var(--success-color)' : (profit < 0 ? 'var(--danger-color)' : 'var(--text-muted)');
const symbol = r.symbol || r.pair;
const time = r.created_at || r.open_time;
html += `
<div class="record-card">
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 18px;">
<div>
<div style="display: flex; align-items: center; gap: 8px;">
<span style="font-weight: 800; color: white; font-size: 1.1rem;">${symbol}</span>
<span style="background: rgba(0,82,255,0.1); color: var(--primary-color); padding: 3px 8px; border-radius: 6px; font-size: 9px; font-weight: 800;">${r.trade_label}</span>
</div>
<div style="font-size: 11px; color: var(--text-muted); margin-top: 6px;">${time}</div>
</div>
<div style="text-align: right;">
<div style="font-size: 9px; color: var(--text-muted); text-transform: uppercase; margin-bottom: 2px;">盈利 (USDT)</div>
<div style="font-weight: 800; color: ${profitColor}; font-size: 1.2rem;">${isProfit ? '+' : ''}${profit.toFixed(2)}</div>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; background: rgba(0,0,0,0.2); padding: 12px; border-radius: 12px; border: 1px solid rgba(255,255,255,0.03);">
<div>
<div style="font-size: 9px; color: var(--text-muted); margin-bottom: 4px;">类型</div>
<div style="font-weight: 800; color: ${r.side === 'buy' || r.direction === 'up' ? 'var(--success-color)' : 'var(--danger-color)'}; font-size: 12px;">${(r.side === 'buy' || r.direction === 'up') ? '看涨' : '看跌'}</div>
</div>
<div>
<div style="font-size: 9px; color: var(--text-muted); margin-bottom: 4px;">金额</div>
<div style="font-weight: 800; color: white; font-size: 12px;">${parseFloat(r.amount || r.invest).toFixed(2)}</div>
</div>
<div>
<div style="font-size: 9px; color: var(--text-muted); margin-bottom: 4px;">价格</div>
<div style="font-weight: 800; color: white; font-size: 12px;">${parseFloat(r.price || r.open_price).toLocaleString()}</div>
</div>
</div>
</div>
`;
} else {
const amount = parseFloat(r.amount);
const isPositive = amount > 0;
const amountColor = isPositive ? 'var(--success-color)' : 'var(--danger-color)';
let typeLabel = r.type === 'deposit' ? '充值' : (r.type === 'withdrawal' ? '提现' : (r.type === 'withdraw_return' ? '提现退回' : r.type));
let statusLabel = r.status === 'completed' ? '已成功' : (r.status === 'pending' || r.status === 'matching' ? '处理中' : (r.status === 'rejected' ? '已拒绝' : r.status));
let statusColor = r.status === 'completed' ? 'var(--success-color)' : (r.status === 'rejected' ? 'var(--danger-color)' : '#f0b90b');
html += `
<div class="record-card">
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
<div>
<div style="display: flex; align-items: center; gap: 10px;">
<span style="font-weight: 800; color: white; font-size: 1.1rem;">${typeLabel}</span>
<span style="font-size: 10px; font-weight: 800; color: ${statusColor}; background: ${statusColor}1A; padding: 4px 8px; border-radius: 6px;">${statusLabel}</span>
</div>
<div style="font-size: 11px; color: var(--text-muted); margin-top: 10px; font-family: 'Roboto Mono', monospace;">${r.created_at}</div>
</div>
<div style="text-align: right;">
<div style="font-size: 9px; color: var(--text-muted); text-transform: uppercase; margin-bottom: 4px;">变动 (USDT)</div>
<div style="font-weight: 800; color: ${amountColor}; font-size: 1.3rem;">${isPositive ? '+' : ''}${amount.toFixed(2)}</div>
</div>
</div>
</div>
`;
}
});
container.innerHTML = html;
} catch (e) {
container.innerHTML = '<div style="grid-column: span 1; text-align: center; padding: 60px; color: var(--danger-color); font-weight: 800;"><i class="fas fa-exclamation-triangle fa-2x"></i><br>数据加载失败</div>';
}
}
</script>
<?php include 'footer.php'; ?>

101
register.php Normal file
View File

@ -0,0 +1,101 @@
<?php
require_once 'db/config.php';
require_once 'includes/i18n.php';
session_start();
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$confirm_password = $_POST['confirm_password'] ?? '';
if (empty($username) || empty($password)) {
$error = __('fill_all_fields');
} elseif ($password !== $confirm_password) {
$error = __('passwords_not_match');
} else {
$pdo = db();
// Check if user exists
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
$stmt->execute([$username]);
if ($stmt->fetch()) {
$error = __('username_taken');
} else {
// Generate UID starting from 618120
$stmt = $pdo->query("SELECT COUNT(*) FROM users");
$count = $stmt->fetchColumn();
$uid = 618120 + $count + mt_rand(1, 9);
// Capture IP correctly
$user_ip = $_SERVER['REMOTE_ADDR'];
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$user_ip = trim($ips[0]);
}
// Register and auto-login
$stmt = $pdo->prepare("INSERT INTO users (uid, username, password, trading_password, balance, last_ip) VALUES (?, ?, ?, '123456', 0, ?)");
if ($stmt->execute([$uid, $username, password_hash($password, PASSWORD_DEFAULT), $user_ip])) {
$user_id = $pdo->lastInsertId();
$_SESSION['user_id'] = $user_id;
$_SESSION['username'] = $username;
$_SESSION['uid'] = $uid;
header("Location: index.php");
exit;
} else {
$error = __('registration_failed');
}
}
}
}
?>
<?php include 'header.php'; ?>
<main style="background: #0b0e11; min-height: calc(100vh - 64px); display: flex; align-items: center; justify-content: center; padding: 40px 20px;">
<div style="width: 100%; max-width: 480px; background: var(--card-bg); padding: 50px; border-radius: 32px; border: 1px solid var(--border-color); box-shadow: 0 20px 40px rgba(0,0,0,0.4);">
<h2 style="font-size: 2.2rem; font-weight: 800; margin-bottom: 10px; text-align: center; color: white;"><?php echo __('create_account'); ?></h2>
<p style="text-align: center; color: var(--text-muted); margin-bottom: 40px;"><?php echo __('join_novaex_tip'); ?></p>
<?php if($error): ?>
<div style="background: rgba(246,70,93,0.1); color: var(--danger-color); padding: 15px; border-radius: 12px; margin-bottom: 25px; border: 1px solid var(--danger-color); text-align: center; font-size: 14px;">
<i class="fas fa-exclamation-circle"></i> <?php echo $error; ?>
</div>
<?php endif; ?>
<form method="POST">
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('email_or_phone'); ?></label>
<div style="position: relative;">
<i class="fas fa-envelope" style="position: absolute; left: 15px; top: 15px; color: #555;"></i>
<input type="text" name="username" required placeholder="<?php echo __('enter_email_phone'); ?>" style="width: 100%; padding: 15px 15px 15px 45px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; font-size: 1rem; outline: none; box-sizing: border-box;">
</div>
</div>
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('login_password'); ?></label>
<div style="position: relative;">
<i class="fas fa-lock" style="position: absolute; left: 15px; top: 15px; color: #555;"></i>
<input type="password" name="password" required placeholder="<?php echo __('set_password'); ?>" style="width: 100%; padding: 15px 15px 15px 45px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; font-size: 1rem; outline: none; box-sizing: border-box;">
</div>
</div>
<div style="margin-bottom: 30px;">
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('confirm_password_label'); ?></label>
<div style="position: relative;">
<i class="fas fa-check-double" style="position: absolute; left: 15px; top: 15px; color: #555;"></i>
<input type="password" name="confirm_password" required placeholder="<?php echo __('confirm_your_password'); ?>" style="width: 100%; padding: 15px 15px 15px 45px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; font-size: 1rem; outline: none; box-sizing: border-box;">
</div>
</div>
<div style="margin-bottom: 30px; display: flex; align-items: flex-start; gap: 12px;">
<input type="checkbox" required style="margin-top: 4px; accent-color: var(--primary-color);">
<span style="font-size: 0.85rem; color: var(--text-muted); line-height: 1.5;"><?php echo __('agree_terms'); ?></span>
</div>
<button type="submit" class="btn-primary" style="width: 100%; padding: 18px; font-weight: 800; font-size: 1.1rem; border-radius: 16px; box-shadow: 0 10px 20px rgba(0,82,255,0.2);"><?php echo __('nav_register'); ?></button>
</form>
<div style="text-align: center; margin-top: 30px; border-top: 1px solid var(--border-color); padding-top: 30px;">
<span style="color: var(--text-muted);"><?php echo __('already_have_account'); ?></span> <a href="login.php" style="color: var(--primary-color); text-decoration: none; font-weight: bold;"><?php echo __('nav_login'); ?></a>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

49
request.php Normal file
View File

@ -0,0 +1,49 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 700px; margin: 0 auto; background: #161a1e; padding: 50px; border-radius: 32px; border: 1px solid #2b3139;">
<h1 style="font-size: 2.2rem; margin-bottom: 10px;">Submit a Request</h1>
<p style="color: var(--text-muted); margin-bottom: 40px;">Please provide the details of your request and we will get back to you as soon as possible.</p>
<form action="#" method="POST">
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 10px; color: #848e9c; font-size: 0.9rem;">Email Address</label>
<input type="email" required placeholder="your@email.com" style="width: 100%; padding: 15px; background: #0b0e11; border: 1px solid #2b3139; color: white; border-radius: 12px; outline: none; box-sizing: border-box;">
</div>
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 10px; color: #848e9c; font-size: 0.9rem;">Issue Category</label>
<select style="width: 100%; padding: 15px; background: #0b0e11; border: 1px solid #2b3139; color: white; border-radius: 12px; outline: none; box-sizing: border-box;">
<option>Account Security</option>
<option>Deposit/Withdrawal Issue</option>
<option>Trading Error</option>
<option>Identity Verification (KYC)</option>
<option>Bug Report</option>
<option>Other</option>
</select>
</div>
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 10px; color: #848e9c; font-size: 0.9rem;">Subject</label>
<input type="text" required placeholder="Brief summary of your issue" style="width: 100%; padding: 15px; background: #0b0e11; border: 1px solid #2b3139; color: white; border-radius: 12px; outline: none; box-sizing: border-box;">
</div>
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 10px; color: #848e9c; font-size: 0.9rem;">Description</label>
<textarea rows="6" required placeholder="Please provide as much detail as possible..." style="width: 100%; padding: 15px; background: #0b0e11; border: 1px solid #2b3139; color: white; border-radius: 12px; outline: none; box-sizing: border-box; resize: none;"></textarea>
</div>
<div style="margin-bottom: 30px;">
<label style="display: block; margin-bottom: 10px; color: #848e9c; font-size: 0.9rem;">Attachments (Optional)</label>
<div style="border: 2px dashed #2b3139; padding: 30px; text-align: center; border-radius: 12px; cursor: pointer;" onmouseover="this.style.borderColor='var(--primary-color)'" onmouseout="this.style.borderColor='#2b3139'">
<i class="fas fa-cloud-upload-alt" style="font-size: 2rem; color: #848e9c; margin-bottom: 10px;"></i>
<p style="color: #848e9c; margin: 0; font-size: 0.9rem;">Click or drag files to upload</p>
</div>
</div>
<button type="submit" class="btn-primary" style="width: 100%; padding: 18px; border-radius: 12px; font-weight: bold; font-size: 1.1rem;">Submit Ticket</button>
</form>
</div>
</main>
<?php include 'footer.php'; ?>

119
security.php Normal file
View File

@ -0,0 +1,119 @@
<?php
include 'header.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
require_once 'db/config.php';
$db = db();
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
$message = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$type = $_POST['type']; // login or trading
$old_pass = $_POST['old_password'];
$new_pass = $_POST['new_password'];
$confirm_pass = $_POST['confirm_password'];
if ($new_pass !== $confirm_pass) {
$error = "New passwords do not match";
} else {
if ($type === 'login') {
if (password_verify($old_pass, $user['password'])) {
$hashed = password_hash($new_pass, PASSWORD_DEFAULT);
$stmt = $db->prepare("UPDATE users SET password = ? WHERE id = ?");
$stmt->execute([$hashed, $_SESSION['user_id']]);
$message = "Login password updated successfully";
} else {
$error = "Old login password incorrect";
}
} else {
// Trading password (simple for demo, but should be hashed in production)
if ($old_pass === $user['trading_password']) {
$stmt = $db->prepare("UPDATE users SET trading_password = ? WHERE id = ?");
$stmt->execute([$new_pass, $_SESSION['user_id']]);
$message = "Trading password updated successfully";
} else {
$error = "Old trading password incorrect";
}
}
}
}
?>
<main style="padding: 40px 20px; background: #0b0e11; min-height: 100vh;">
<div style="max-width: 600px; margin: 0 auto;">
<a href="profile.php" class="back-btn"><i class="fas fa-arrow-left"></i> Profile</a>
<h2 style="margin-bottom: 30px;">Security Settings</h2>
<?php if($message): ?>
<div style="background: rgba(14,203,129,0.1); color: var(--success-color); padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 1px solid var(--success-color);">
<?php echo $message; ?>
</div>
<?php endif; ?>
<?php if($error): ?>
<div style="background: rgba(246,70,93,0.1); color: var(--danger-color); padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 1px solid var(--danger-color);">
<?php echo $error; ?>
</div>
<?php endif; ?>
<!-- Login Password Form -->
<div style="background: var(--card-bg); padding: 30px; border-radius: 20px; border: 1px solid var(--border-color); margin-bottom: 30px;">
<h3 style="margin-bottom: 20px; display: flex; align-items: center; gap: 10px;">
<i class="fas fa-key" style="color: var(--primary-color);"></i> Change Login Password
</h3>
<form method="POST">
<input type="hidden" name="type" value="login">
<div style="margin-bottom: 20px;">
<label style="display: block; color: var(--text-muted); font-size: 14px; margin-bottom: 8px;">Old Password</label>
<input type="password" name="old_password" required style="width: 100%; padding: 12px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 8px;">
</div>
<div style="margin-bottom: 20px;">
<label style="display: block; color: var(--text-muted); font-size: 14px; margin-bottom: 8px;">New Password</label>
<input type="password" name="new_password" required style="width: 100%; padding: 12px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 8px;">
</div>
<div style="margin-bottom: 25px;">
<label style="display: block; color: var(--text-muted); font-size: 14px; margin-bottom: 8px;">Confirm New Password</label>
<input type="password" name="confirm_password" required style="width: 100%; padding: 12px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 8px;">
</div>
<button type="submit" class="btn-primary" style="width: 100%; padding: 12px; border-radius: 8px;">Update Login Password</button>
</form>
</div>
<!-- Trading Password Form -->
<div style="background: var(--card-bg); padding: 30px; border-radius: 20px; border: 1px solid var(--border-color);">
<h3 style="margin-bottom: 20px; display: flex; align-items: center; gap: 10px;">
<i class="fas fa-shield-alt" style="color: var(--success-color);"></i> Change Trading Password
</h3>
<p style="font-size: 13px; color: var(--text-muted); margin-bottom: 20px;">Default trading password is <b>123456</b></p>
<form method="POST">
<input type="hidden" name="type" value="trading">
<div style="margin-bottom: 20px;">
<label style="display: block; color: var(--text-muted); font-size: 14px; margin-bottom: 8px;">Old Trading Password</label>
<input type="password" name="old_password" required style="width: 100%; padding: 12px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 8px;">
</div>
<div style="margin-bottom: 20px;">
<label style="display: block; color: var(--text-muted); font-size: 14px; margin-bottom: 8px;">New Trading Password</label>
<input type="password" name="new_password" required style="width: 100%; padding: 12px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 8px;">
</div>
<div style="margin-bottom: 25px;">
<label style="display: block; color: var(--text-muted); font-size: 14px; margin-bottom: 8px;">Confirm New Trading Password</label>
<input type="password" name="confirm_password" required style="width: 100%; padding: 12px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 8px;">
</div>
<button type="submit" class="btn-primary" style="width: 100%; padding: 12px; border-radius: 8px; background: var(--success-color);">Update Trading Password</button>
</form>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

409
spot.php Normal file
View File

@ -0,0 +1,409 @@
<?php
include 'header.php';
$user_id = $_SESSION['user_id'] ?? null;
$user_assets = [];
if ($user_id) {
$stmt = $db->prepare("SELECT balance FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$usdt_balance = $stmt->fetchColumn();
$user_assets['USDT'] = (float)($usdt_balance ?: 0);
$stmt = $db->prepare("SELECT symbol, amount FROM user_assets WHERE user_id = ?");
$stmt->execute([$user_id]);
$assets_data = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
if ($assets_data) {
foreach ($assets_data as $symbol => $amount) {
$user_assets[$symbol] = (float)$amount;
}
}
}
?>
<style>
.trading-page-wrapper { display: flex; flex-direction: column; min-height: 100vh; background: #0b0e11; }
.trading-container { flex-grow: 1; display: flex; min-height: 800px; max-width: 1920px; margin: 0 auto; width: 100%; }
.left-col { width: 280px; flex-shrink: 0; background: #161a1e; border-right: 1px solid #2b3139; display: flex; flex-direction: column; }
.center-col { flex: 1; min-width: 600px; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.right-col { width: 300px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; }
.chart-header { height: 55px; padding: 0 20px; display: flex; align-items: center; background: #161a1e; border-bottom: 1px solid #2b3139; gap: 20px; flex-shrink: 0; }
.chart-box { height: 450px; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.bottom-content-wrapper { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.order-box { padding: 20px; background: #161a1e; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.records-container { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.record-tabs { display: flex; padding: 0 20px; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.record-tab { padding: 12px 0; margin-right: 25px; font-size: 13px; font-weight: 600; color: #848e9c; cursor: pointer; position: relative; }
.record-tab.active { color: white; }
.record-tab.active::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 2px; background: var(--primary-color); }
#records-list-container { height: 350px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
#records-list-container::-webkit-scrollbar { width: 4px; }
#records-list-container::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
table { width: 100%; font-size: 12px; border-collapse: collapse; }
th { color: #848e9c; font-weight: 500; text-align: left; padding: 10px 15px; border-bottom: 1px solid #2b3139; background: #161a1e; position: sticky; top: 0; z-index: 10; }
td { padding: 10px 15px; border-bottom: 1px solid rgba(255,255,255,0.02); color: #eaecef; height: 38px; }
.category-tabs { display: flex; padding: 15px 15px 5px; gap: 8px; }
.category-tab { flex: 1; text-align: center; padding: 6px 0; background: #2b3139; border-radius: 4px; font-size: 12px; color: #848e9c; cursor: pointer; border: 1px solid transparent; }
.category-tab.active { background: rgba(0, 82, 255, 0.1); border-color: var(--primary-color); color: var(--primary-color); font-weight: bold; }
.search-box { padding: 10px 15px 15px; position: relative; }
.search-box i { position: absolute; left: 25px; top: 22px; color: #848e9c; font-size: 12px; }
.search-box input { width: 100%; background: #2b3139; border: 1px solid transparent; border-radius: 6px; padding: 8px 10px 8px 35px; color: white; font-size: 13px; outline: none; transition: 0.2s; }
.search-box input:focus { border-color: var(--primary-color); }
#pairs-list { height: 684px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
#pairs-list::-webkit-scrollbar { width: 4px; }
#pairs-list::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
.pair-item { display: flex; align-items: center; padding: 10px 15px; cursor: pointer; border-bottom: 1px solid rgba(255,255,255,0.02); height: 38px; }
.pair-item.active { background: #1e2329; border-left: 3px solid var(--primary-color); }
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; }
.input-group { background: #2b3139; border-radius: 4px; padding: 8px 12px; display: flex; align-items: center; margin-bottom: 10px; border: 1px solid #3c424a; }
.input-group:focus-within { border-color: var(--primary-color); }
.input-group input { background: transparent; border: none; color: white; flex: 1; outline: none; font-size: 14px; width: 100%; }
.input-group .label { color: #848e9c; font-size: 12px; margin-right: 10px; min-width: 40px; }
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 12px; }
.slider-container { margin: 15px 0 20px; }
input[type=range] { width: 100%; height: 4px; background: #2b3139; border-radius: 2px; outline: none; }
.trade-btn { width: 100%; padding: 12px; border-radius: 4px; font-weight: bold; font-size: 15px; border: none; cursor: pointer; color: white; transition: 0.2s; }
.btn-buy { background: #0ecb81; }
.btn-sell { background: #f6465d; }
.btn-buy:hover, .btn-sell:hover { filter: brightness(1.1); }
.right-col-tabs { display: flex; border-bottom: 1px solid #2b3139; flex-shrink: 0; }
.right-col-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 13px; font-weight: 600; color: #848e9c; cursor: pointer; }
.right-col-tab.active { color: white; background: #1e2329; }
.ob-header { display: flex; justify-content: space-between; padding: 8px 15px; font-size: 11px; color: #848e9c; border-bottom: 1px solid #2b3139; }
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; cursor: pointer; }
#ob-panel-content { flex: 1; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #2b3139 transparent; }
#ob-panel-content::-webkit-scrollbar { width: 4px; }
#ob-panel-content::-webkit-scrollbar-thumb { background: #2b3139; border-radius: 10px; }
/* Mobile Specific Styles */
@media (max-width: 991px) {
.trading-container { flex-direction: column; min-height: auto; }
.center-col { min-width: 100%; border-right: none; }
.chart-box { height: 300px; }
.order-box { padding: 15px; }
#records-list-container { height: auto; max-height: 400px; }
.trading-page-wrapper { padding-bottom: 70px; }
.mobile-trade-nav {
display: flex; background: #161a1e; border-bottom: 1px solid #2b3139; padding: 10px 15px; gap: 10px;
}
.mobile-trade-nav a {
flex: 1; text-align: center; padding: 8px 0; background: #2b3139; border-radius: 8px; font-size: 13px; color: #848e9c; text-decoration: none; font-weight: 600; border: 1px solid transparent;
}
.mobile-trade-nav a.active {
background: rgba(0, 82, 255, 0.1); color: var(--primary-color); border-color: var(--primary-color);
}
.mobile-symbol-selector {
display: flex; align-items: center; justify-content: space-between; padding: 12px 15px; background: #161a1e; border-bottom: 1px solid #2b3139;
}
}
@media (min-width: 992px) {
.mobile-trade-nav, .mobile-symbol-selector { display: none; }
}
/* Mobile Drawer */
#mobile-pairs-drawer {
position: fixed; top: 0; left: -100%; width: 100%; height: 100%; background: #0b0e11; z-index: 3000; transition: 0.3s; padding: 20px; display: flex; flex-direction: column;
}
#mobile-pairs-drawer.open { left: 0; }
</style>
<div class="trading-page-wrapper">
<!-- Mobile Navigation Tabs -->
<div class="mobile-trade-nav">
<a href="options.php"><?php echo __('nav_options'); ?></a>
<a href="spot.php" class="active"><?php echo __('nav_spot'); ?></a>
<a href="futures.php"><?php echo __('nav_futures'); ?></a>
</div>
<!-- Mobile Symbol Selector -->
<div class="mobile-symbol-selector" onclick="toggleMobilePairs()">
<div style="display: flex; align-items: center; gap: 10px;">
<img id="curr-icon-mobile" src="" class="coin-icon" style="width: 28px; height: 28px;">
<span id="curr-pair-mobile" style="font-weight: 800; font-size: 18px; color: white;">--/--</span>
<i class="fas fa-caret-down" style="color: #848e9c;"></i>
</div>
<div style="text-align: right;">
<div id="curr-price-mobile" style="font-size: 18px; font-weight: 800; color: #0ecb81;">--</div>
<div id="curr-change-mobile" style="font-size: 12px; font-weight: 600;">--</div>
</div>
</div>
<div class="trading-container">
<!-- Left Column -->
<div class="left-col d-none d-lg-flex">
<div class="category-tabs">
<div class="category-tab" onclick="location.href='options.php'"><?php echo __('nav_options'); ?></div>
<div class="category-tab active" onclick="location.href='spot.php'"><?php echo __('nav_spot'); ?></div>
<div class="category-tab" onclick="location.href='futures.php'"><?php echo __('nav_futures'); ?></div>
</div>
<div class="search-box"><i class="fas fa-search"></i><input type="text" id="pair-search" placeholder="<?php echo __('search_currency'); ?>"></div>
<div id="pairs-list"></div>
</div>
<!-- Center Column -->
<div class="center-col">
<div class="chart-header d-none d-lg-flex">
<div style="display: flex; align-items: center; gap: 10px;">
<img id="curr-icon" src="" class="coin-icon">
<span id="curr-pair" style="font-weight: 800; font-size: 18px; color:white;">--/--</span>
</div>
<div class="stats-item">
<div id="curr-price" style="font-size: 20px; font-weight: 800; color: #0ecb81;">--</div>
<div id="curr-change" style="font-size: 12px; font-weight: 600;">--</div>
</div>
</div>
<div class="chart-box" id="tv_chart_container"></div>
<div class="bottom-content-wrapper">
<div class="order-box">
<div style="display: flex; gap: 20px; margin-bottom: 15px;">
<div class="record-tab active"><?php echo __('market'); ?></div>
</div>
<div class="input-group"><span class="label"><?php echo __('price'); ?></span><input type="text" placeholder="<?php echo __('market'); ?>" disabled><span class="unit">USDT</span></div>
<div class="input-group"><span class="label"><?php echo __('amount'); ?></span><input type="number" id="spot-amount" step="0.0001" placeholder="0.00"><span class="unit coin-name">--</span></div>
<div class="slider-container"><input type="range" id="spot-slider" min="0" max="100" value="0"></div>
<div style="display: flex; gap: 15px;">
<div style="flex: 1;">
<div style="font-size: 12px; color: #848e9c; margin-bottom: 8px;"><?php echo __('available'); ?>: <span id="avail-usdt" style="color:white; font-weight:600">0.00</span> USDT</div>
<button id="btn-buy" class="trade-btn btn-buy"><?php echo __('buy'); ?> <span class="coin-name">--</span></button>
</div>
<div style="flex: 1;">
<div style="font-size: 12px; color: #848e9c; margin-bottom: 8px;"><?php echo __('available'); ?>: <span id="avail-coin" style="color:white; font-weight:600">0.00</span> <span class="coin-name">--</span></div>
<button id="btn-sell" class="trade-btn btn-sell"><?php echo __('sell'); ?> <span class="coin-name">--</span></button>
</div>
</div>
</div>
<div class="records-container">
<div class="record-tabs">
<div class="record-tab active" data-status="open"><?php echo __('open_orders'); ?></div>
<div class="record-tab" data-status="history"><?php echo __('history_orders'); ?></div>
</div>
<div id="records-list-container">
<table style="width:100%;" id="records-table"></table>
</div>
</div>
</div>
</div>
<!-- Right Column -->
<div class="right-col d-none d-xl-flex">
<div class="right-col-tabs">
<div class="right-col-tab active" data-tab="ob"><?php echo __('order_book'); ?></div>
<div class="right-col-tab" data-tab="trades"><?php echo __('trades'); ?></div>
</div>
<div id="ob-panel" style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
<div class="ob-header"><span><?php echo __('price'); ?></span><span><?php echo __('amount'); ?></span></div>
<div id="ob-panel-content">
<div id="asks-list"></div>
<div id="mid-price" style="padding:10px 15px; text-align:center; font-weight:800; font-size:16px; border-top:1px solid #2b3139; border-bottom:1px solid #2b3139;">--</div>
<div id="bids-list"></div>
</div>
</div>
<div id="trades-panel" style="display:none; overflow-y:auto; flex:1;">
<div id="trades-list"></div>
</div>
</div>
</div>
</div>
<!-- Mobile Pairs Drawer -->
<div id="mobile-pairs-drawer">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<h3 style="margin: 0; font-weight: 800;"><?php echo __('market'); ?></h3>
<i class="fas fa-times" onclick="toggleMobilePairs()" style="font-size: 20px; color: #848e9c;"></i>
</div>
<div class="search-box" style="padding: 0; margin-bottom: 20px;">
<i class="fas fa-search"></i>
<input type="text" id="pair-search-mobile" placeholder="<?php echo __('search_currency'); ?>">
</div>
<div id="pairs-list-mobile" style="flex: 1; overflow-y: auto;"></div>
</div>
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script>
const userAssets = <?php echo json_encode($user_assets); ?>;
function toggleMobilePairs() {
document.getElementById('mobile-pairs-drawer').classList.toggle('open');
}
document.addEventListener('DOMContentLoaded', function() {
let currentPair = 'BTCUSDT', currentPrice = 0, ws, chartWidget;
const marketData = {}, pairs = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'AVAXUSDT', 'DOTUSDT', 'MATICUSDT', 'LTCUSDT', 'TRXUSDT', 'LINKUSDT', 'UNIUSDT', 'ATOMUSDT', 'ETCUSDT', 'BCHUSDT', 'FILUSDT', 'ICPUSDT', 'NEARUSDT', 'AAVEUSDT', 'ALGOUSDT'];
const dom = {
currIcon: document.getElementById('curr-icon'),
currPair: document.getElementById('curr-pair'),
currPrice: document.getElementById('curr-price'),
currChange: document.getElementById('curr-change'),
currIconMobile: document.getElementById('curr-icon-mobile'),
currPairMobile: document.getElementById('curr-pair-mobile'),
currPriceMobile: document.getElementById('curr-price-mobile'),
currChangeMobile: document.getElementById('curr-change-mobile'),
tvContainer: document.getElementById('tv_chart_container'),
pairsList: document.getElementById('pairs-list'),
pairsListMobile: document.getElementById('pairs-list-mobile'),
pairSearchMobile: document.getElementById('pair-search-mobile'),
asksList: document.getElementById('asks-list'),
bidsList: document.getElementById('bids-list'),
midPrice: document.getElementById('mid-price'),
availUsdt: document.getElementById('avail-usdt'),
availCoin: document.getElementById('avail-coin'),
coinNames: document.querySelectorAll('.coin-name'),
amountInput: document.getElementById('spot-amount'),
slider: document.getElementById('spot-slider'),
recordsTable: document.getElementById('records-table')
};
function updateBalances() {
const coin = currentPair.replace('USDT', '');
dom.availUsdt.innerText = parseFloat(userAssets.USDT || 0).toFixed(2);
dom.availCoin.innerText = parseFloat(userAssets[coin] || 0).toFixed(4);
dom.coinNames.forEach(el => el.innerText = coin);
}
function initChart(symbol) {
dom.tvContainer.innerHTML = '';
new TradingView.widget({
"autosize": true, "symbol": `BINANCE:${symbol}`, "interval": "15", "theme": "dark", "style": "1",
"locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>", "container_id": "tv_chart_container",
"hide_side_toolbar": true, "allow_symbol_change": false, "studies": ["Volume@tv-basicstudies"],
"overrides": { "paneProperties.background": "#161a1e" }
});
}
function connectWS() {
if (ws) ws.close();
const streams = pairs.map(p => `${p.toLowerCase()}@ticker`).concat([`${currentPair.toLowerCase()}@depth20@100ms`]);
ws = new WebSocket(`wss://stream.binance.com:9443/stream?streams=${streams.join('/')}`);
ws.onmessage = (e) => {
const { stream, data } = JSON.parse(e.data);
if (!data) return;
const type = stream.split('@')[1];
if (type === 'ticker') {
marketData[data.s] = data;
if (data.s === currentPair) {
currentPrice = parseFloat(data.c);
const color = data.P >= 0 ? '#0ecb81' : '#f6465d';
const priceStr = currentPrice.toLocaleString('en-US', {minimumFractionDigits:2});
const changeStr = (data.P >= 0 ? '+' : '') + parseFloat(data.P).toFixed(2) + '%';
if(dom.currPrice) dom.currPrice.innerText = priceStr;
if(dom.currChange) dom.currChange.innerText = changeStr;
if(dom.currPrice) dom.currPrice.style.color = dom.currChange.style.color = color;
dom.currPriceMobile.innerText = priceStr;
dom.currPriceMobile.style.color = color;
dom.currChangeMobile.innerText = changeStr;
dom.currChangeMobile.style.color = color;
if(dom.midPrice) dom.midPrice.innerText = currentPrice.toFixed(2);
}
if (dom.pairsList.offsetParent || dom.pairsListMobile.offsetParent) renderPairs();
} else if (type.startsWith('depth')) {
if(dom.asksList) {
const row = (p, q, c) => `<div class="ob-row" onclick="document.getElementById('spot-amount').value=${parseFloat(q).toFixed(4)};"><span style="color:${c}">${parseFloat(p).toFixed(2)}</span><span>${parseFloat(q).toFixed(4)}</span></div>`;
dom.asksList.innerHTML = data.asks.slice(0, 20).reverse().map(a => row(a[0], a[1], '#f6465d')).join('');
dom.bidsList.innerHTML = data.bids.slice(0, 20).map(b => row(b[0], b[1], '#0ecb81')).join('');
}
}
};
ws.onclose = () => setTimeout(connectWS, 5000);
}
function renderPairs() {
const query = document.getElementById('pair-search').value.toUpperCase();
const queryMobile = dom.pairSearchMobile.value.toUpperCase();
const generateHtml = (q) => pairs.filter(p => p.includes(q)).map(p => {
const d = marketData[p] || {};
return `<div class="pair-item ${p === currentPair ? 'active' : ''}" onclick="switchPair('${p}')">
<img src="https://assets.coincap.io/assets/icons/${p.replace('USDT','').toLowerCase()}@2x.png" class="coin-icon" onerror="this.style.opacity=0">
<div style="flex:1; color:white; font-weight:600">${p.replace('USDT','/USDT')}</div>
<div style="text-align:right"><div style="color:white; font-weight:600">${d.c ? parseFloat(d.c).toFixed(2) : '--'}</div><div style="color:${d.P>=0?'#0ecb81':'#f6465d'}; font-size:11px">${d.P?(d.P>=0?'+':'')+parseFloat(d.P).toFixed(2)+'%':'--'}</div></div>
</div>`;
}).join('');
dom.pairsList.innerHTML = generateHtml(query);
dom.pairsListMobile.innerHTML = generateHtml(queryMobile);
}
window.switchPair = (p) => {
currentPair = p;
if(dom.currPair) dom.currPair.innerText = p.replace('USDT', '/USDT');
dom.currPairMobile.innerText = p.replace('USDT', '/USDT');
if(dom.currIcon) dom.currIcon.src = `https://assets.coincap.io/assets/icons/${p.replace('USDT','').toLowerCase()}@2x.png`;
dom.currIconMobile.src = `https://assets.coincap.io/assets/icons/${p.replace('USDT','').toLowerCase()}@2x.png`;
initChart(p);
updateBalances();
connectWS();
if(document.getElementById('mobile-pairs-drawer').classList.contains('open')) toggleMobilePairs();
};
dom.pairSearchMobile.addEventListener('input', renderPairs);
async function placeOrder(side) {
const amount = parseFloat(dom.amountInput.value);
if (!amount || amount <= 0) { alert("<?php echo __('amount'); ?> > 0"); return; }
const price = currentPrice;
const total = amount * price;
try {
const r = await fetch('api/place_order.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
symbol: currentPair, type: 'spot', side: side, order_type: 'market',
price: price, amount: amount, total: total
})
});
const res = await r.json();
if (res.success) { alert("<?php echo __('order_placed'); ?>"); fetchOrders(); }
else { alert(res.error || "Error"); }
} catch(e) { alert("Network Error"); }
}
document.getElementById('btn-buy').onclick = () => placeOrder('buy');
document.getElementById('btn-sell').onclick = () => placeOrder('sell');
let activeTab = 'open';
async function fetchOrders() {
try {
const r = await fetch(`api/get_orders.php?type=spot&status=${activeTab}`);
const res = await r.json();
if (res.success) renderOrders(res.data);
} catch(e) {}
}
function renderOrders(orders) {
if (!orders || orders.length === 0) { dom.recordsTable.innerHTML = '<tr><td colspan="6" style="text-align:center; padding:30px; color:#848e9c"><?php echo __('no_records'); ?></td></tr>'; return; }
let h = `<thead><tr><th><?php echo __('pair'); ?></th><th><?php echo __('direction'); ?></th><th><?php echo __('price'); ?></th><th><?php echo __('amount'); ?></th><th><?php echo __('status'); ?></th><th><?php echo __('time'); ?></th></tr></thead><tbody>`;
orders.forEach(o => {
h += `<tr><td>${o.symbol}</td><td style="color:${o.side==='buy'?'#0ecb81':'#f6465d'}">${o.side==='buy'?'<?php echo __('buy'); ?>':'<?php echo __('sell'); ?>'}</td><td>${parseFloat(o.price).toFixed(2)}</td><td>${parseFloat(o.amount).toFixed(4)}</td><td>${o.status}</td><td style="color:#848e9c">${o.created_at}</td></tr>`;
});
dom.recordsTable.innerHTML = h + '</tbody>';
}
document.querySelectorAll('.record-tab').forEach(t => t.onclick = () => {
if (!t.dataset.status) return;
document.querySelector('.record-tabs .active').classList.remove('active');
t.classList.add('active');
activeTab = t.dataset.status;
fetchOrders();
});
switchPair('BTCUSDT');
fetchOrders();
setInterval(fetchOrders, 5000);
});
</script>
<?php include 'footer.php'; ?>

44
status.php Normal file
View File

@ -0,0 +1,44 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 800px; margin: 0 auto;">
<div style="background: rgba(14,203,129,0.1); border: 1px solid var(--success-color); padding: 30px; border-radius: 24px; text-align: center; margin-bottom: 50px;">
<i class="fas fa-check-circle" style="font-size: 3rem; color: var(--success-color); margin-bottom: 15px;"></i>
<h1 style="font-size: 2rem; margin-bottom: 10px;">All Systems Operational</h1>
<p style="color: var(--text-muted);">Last checked: <?php echo date('Y-m-d H:i:s'); ?> UTC</p>
</div>
<div style="background: #161a1e; border-radius: 24px; border: 1px solid #2b3139; padding: 40px;">
<h2 style="font-size: 1.5rem; margin-bottom: 30px;">Service Status</h2>
<div style="display: flex; flex-direction: column; gap: 25px;">
<div style="display: flex; justify-content: space-between; align-items: center; padding-bottom: 20px; border-bottom: 1px solid #2b3139;">
<span style="font-weight: 500;">Trading Engine</span>
<span style="background: rgba(14,203,129,0.2); color: var(--success-color); padding: 5px 15px; border-radius: 20px; font-size: 0.8rem; font-weight: bold;">OPERATIONAL</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; padding-bottom: 20px; border-bottom: 1px solid #2b3139;">
<span style="font-weight: 500;">Matching System</span>
<span style="background: rgba(14,203,129,0.2); color: var(--success-color); padding: 5px 15px; border-radius: 20px; font-size: 0.8rem; font-weight: bold;">OPERATIONAL</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; padding-bottom: 20px; border-bottom: 1px solid #2b3139;">
<span style="font-weight: 500;">API Access</span>
<span style="background: rgba(14,203,129,0.2); color: var(--success-color); padding: 5px 15px; border-radius: 20px; font-size: 0.8rem; font-weight: bold;">OPERATIONAL</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; padding-bottom: 20px; border-bottom: 1px solid #2b3139;">
<span style="font-weight: 500;">Deposits & Withdrawals</span>
<span style="background: rgba(14,203,129,0.2); color: var(--success-color); padding: 5px 15px; border-radius: 20px; font-size: 0.8rem; font-weight: bold;">OPERATIONAL</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center;">
<span style="font-weight: 500;">Mobile App</span>
<span style="background: rgba(14,203,129,0.2); color: var(--success-color); padding: 5px 15px; border-radius: 20px; font-size: 0.8rem; font-weight: bold;">OPERATIONAL</span>
</div>
</div>
</div>
<div style="margin-top: 50px; text-align: center; color: var(--text-muted); font-size: 0.9rem;">
<p>Subscribe to updates via <a href="#" style="color: var(--primary-color);">Email</a> or <a href="#" style="color: var(--primary-color);">RSS</a>.</p>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

44
terms.php Normal file
View File

@ -0,0 +1,44 @@
<?php include 'header.php'; ?>
<main style="background: #0b0e11; color: white; min-height: 100vh; padding: 100px 5%;">
<div style="max-width: 900px; margin: 0 auto; background: #161a1e; padding: 60px; border-radius: 32px; border: 1px solid #2b3139;">
<h1 style="font-size: 2.5rem; margin-bottom: 20px;">Terms of Service</h1>
<p style="color: var(--text-muted); margin-bottom: 40px;">Effective Date: February 2026</p>
<div style="background: rgba(246,70,93,0.1); border-left: 4px solid var(--danger-color); padding: 20px; border-radius: 8px; margin-bottom: 40px;">
<p style="color: var(--danger-color); font-weight: bold; margin-bottom: 5px;">Risk Warning:</p>
<p style="font-size: 0.9rem; color: #EAECEF; line-height: 1.6;">Trading cryptocurrencies involves significant risk and can result in the loss of your invested capital. You should not invest more than you can afford to lose and should ensure that you fully understand the risks involved.</p>
</div>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.6rem; margin-bottom: 15px;">1. Agreement to Terms</h2>
<p style="color: var(--text-muted); line-height: 1.8;">By accessing or using the NovaEx platform, you agree to be bound by these Terms of Service and all applicable laws and regulations. If you do not agree with any of these terms, you are prohibited from using this site.</p>
</section>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.6rem; margin-bottom: 15px;">2. Eligibility</h2>
<p style="color: var(--text-muted); line-height: 1.8;">You must be at least 18 years old and have the legal capacity to enter into this agreement. By using NovaEx, you represent that you are not on any trade embargo or economic sanctions lists.</p>
</section>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.6rem; margin-bottom: 15px;">3. Account Security</h2>
<p style="color: var(--text-muted); line-height: 1.8;">You are responsible for maintaining the confidentiality of your account credentials and for all activities that occur under your account. You must notify us immediately of any unauthorized use of your account.</p>
</section>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.6rem; margin-bottom: 15px;">4. Prohibited Activities</h2>
<p style="color: var(--text-muted); line-height: 1.8;">You agree not to engage in market manipulation, money laundering, or any other illegal activity using our platform. We reserve the right to suspend or terminate accounts found in violation of these terms.</p>
</section>
<section style="margin-bottom: 40px;">
<h2 style="font-size: 1.6rem; margin-bottom: 15px;">5. Limitation of Liability</h2>
<p style="color: var(--text-muted); line-height: 1.8;">NovaEx shall not be liable for any indirect, incidental, special, or consequential damages arising out of or in connection with your use of the platform, including but not limited to trading losses.</p>
</section>
<div style="margin-top: 60px; text-align: center;">
<p style="color: var(--text-muted);">Please read these terms carefully before using our services.</p>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

5
test_spot.php Normal file
View File

@ -0,0 +1,5 @@
<?php
include 'header.php';
echo "<h1>Test Page</h1>";
include 'footer.php';
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

260
withdraw.php Normal file
View File

@ -0,0 +1,260 @@
<?php
require_once 'db/config.php';
require_once 'includes/currency_helper.php';
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
$db = db();
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
include 'header.php';
$fiat_rates = get_fiat_rates();
$fiat_currencies_info = [
'USD' => ['name' => '美元', 'flag' => '🇺🇸'],
'EUR' => ['name' => '欧元', 'flag' => '🇪🇺'],
'GBP' => ['name' => '英镑', 'flag' => '🇬🇧'],
'CNY' => ['name' => '人民币', 'flag' => '🇨🇳'],
'HKD' => ['name' => '港币', 'flag' => '🇭🇰'],
'JPY' => ['name' => '日元', 'flag' => '🇯🇵'],
'KRW' => ['name' => '韩元', 'flag' => '🇰🇷'],
'SGD' => ['name' => '新加坡元', 'flag' => '🇸🇬'],
'TWD' => ['name' => '台币', 'flag' => '🇹🇼'],
'THB' => ['name' => '泰铢', 'flag' => '🇹🇭'],
'VND' => ['name' => '越南盾', 'flag' => '🇻🇳'],
'IDR' => ['name' => '印尼盾', 'flag' => '🇮🇩'],
'MYR' => ['name' => '马来西亚林吉特', 'flag' => '🇲🇾'],
];
$error = '';
?>
<style>
.withdraw-container { padding: 40px 0; background: #0b0e11; min-height: 100vh; }
.withdraw-card { background: var(--card-bg); border-radius: 24px; border: 1px solid var(--border-color); overflow: hidden; padding: 40px; }
.method-card { padding: 30px; border-radius: 20px; border: 2px solid transparent; cursor: pointer; transition: 0.3s; background: rgba(255,255,255,0.02); }
.method-card:hover { background: rgba(255,255,255,0.05); }
.method-card.active { border-color: var(--danger-color); background: rgba(246, 70, 93, 0.05); }
.method-card .icon-box { width: 50px; height: 50px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 20px; margin-bottom: 15px; }
.input-group-custom { background: #161a1e; border: 1px solid var(--border-color); border-radius: 16px; padding: 15px 20px; display: flex; align-items: center; gap: 15px; transition: 0.3s; }
.input-group-custom:focus-within { border-color: var(--primary-color); }
.input-group-custom input { background: none; border: none; color: white; font-size: 1.2rem; font-weight: 700; width: 100%; outline: none; }
.safety-alert { background: rgba(246, 70, 93, 0.1); border: 1px solid rgba(246, 70, 93, 0.2); padding: 20px; border-radius: 16px; color: var(--danger-color); display: flex; gap: 15px; align-items: center; margin-bottom: 30px; }
@media (max-width: 576px) {
.method-card { padding: 20px 15px; }
.method-card .icon-box { width: 40px; height: 40px; font-size: 16px; }
.method-card div:nth-child(2) { font-size: 0.95rem !important; }
}
</style>
<div class="withdraw-container">
<div class="container" style="max-width: 1100px;">
<div style="margin-bottom: 30px;">
<a href="profile.php" class="back-btn" style="color: var(--text-muted); text-decoration: none; font-size: 14px;"><i class="fas fa-arrow-left"></i> 个人中心</a>
<h1 style="font-size: 2.2rem; font-weight: 800; margin-top: 10px;">提现</h1>
<p style="color: var(--text-muted);">安全地将您的资产提取至个人账户</p>
</div>
<?php if($error): ?>
<div class="safety-alert">
<i class="fas fa-exclamation-circle" style="font-size: 24px;"></i>
<div style="font-weight: 700;"><?php echo $error; ?></div>
</div>
<?php endif; ?>
<div class="responsive-grid">
<div>
<div class="withdraw-card">
<h3 style="margin-bottom: 25px; font-weight: 800;">1. 选择提现方式</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 40px;">
<div id="method-fiat" class="method-card" onclick="switchWithdrawMethod('fiat')">
<div class="icon-box" style="background: rgba(79,172,254,0.1); color: #4facfe;"><i class="fas fa-university"></i></div>
<div style="font-weight: 800; font-size: 1.1rem;">法币提现</div>
<div style="color: var(--text-muted); font-size: 11px; margin-top: 4px;">银行转账 / OTC</div>
</div>
<div id="method-usdt" class="method-card active" onclick="switchWithdrawMethod('usdt')">
<div class="icon-box" style="background: rgba(14,203,129,0.1); color: var(--success-color);"><i class="fas fa-coins"></i></div>
<div style="font-weight: 800; font-size: 1.1rem;">USDT 提现</div>
<div style="color: var(--text-muted); font-size: 11px; margin-top: 4px;">区块链转账</div>
</div>
</div>
<form action="matching.php" method="POST" id="withdraw-form">
<input type="hidden" name="order_type" value="withdrawal">
<input type="hidden" name="type" id="withdraw-type" value="usdt">
<h3 style="margin-bottom: 25px; font-weight: 800;">2. 提现详情</h3>
<!-- Fiat Options -->
<div id="fiat-options" style="display: none;">
<div style="margin-bottom: 25px;">
<label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">接收币种</label>
<select name="currency" id="fiat-currency" onchange="updateWithdrawRate()" style="width: 100%; padding: 16px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 16px; outline: none; font-weight: 600;">
<?php foreach ($fiat_rates as $code => $rate): ?>
<option value="<?php echo $code; ?>" data-rate="<?php echo $rate; ?>">
<?php echo ($fiat_currencies_info[$code]['flag'] ?? '') . ' ' . $code . ' - ' . ($fiat_currencies_info[$code]['name'] ?? $code); ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<!-- USDT Options -->
<div id="usdt-options">
<div style="margin-bottom: 25px;">
<label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">网络</label>
<select name="network" style="width: 100%; padding: 16px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 16px; outline: none; font-weight: 600;">
<option value="TRC20">USDT - TRC20 (快速 & 低手续费)</option>
<option value="ERC20">USDT - ERC20</option>
<option value="BEP20">USDT - BEP20 (BSC)</option>
</select>
</div>
</div>
<!-- Amount & Password -->
<div style="margin-bottom: 25px;">
<label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">提现金额 (USDT)</label>
<div class="input-group-custom">
<input type="number" name="amount" id="amount-input" oninput="updateWithdrawRate()" placeholder="最小 10.00" step="0.01" required>
<span onclick="document.getElementById('amount-input').value = '<?php echo $user['balance']; ?>'; updateWithdrawRate();" style="color: var(--primary-color); font-weight: 800; cursor: pointer; white-space: nowrap;">全部</span>
</div>
<div style="display: flex; justify-content: space-between; margin-top: 10px; font-size: 13px;">
<span style="color: var(--text-muted);">可用余额: <strong style="color: white;"><?php echo number_format($user['balance'], 2); ?> USDT</strong></span>
<span id="fiat-equiv-display" style="color: var(--success-color); font-weight: 800; display: none;"> <span id="fiat-val">0.00</span> <span id="fiat-code">USD</span></span>
</div>
</div>
<div style="margin-bottom: 35px;">
<label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">交易密码</label>
<div class="input-group-custom">
<input type="password" name="trading_password" placeholder="6 位安全密码" required style="letter-spacing: 5px;">
</div>
</div>
<button type="submit" id="submit-btn" class="btn-primary" style="width: 100%; padding: 20px; border-radius: 16px; font-size: 1.1rem; font-weight: 800; background: var(--danger-color);">
发起提现请求
</button>
</form>
</div>
</div>
<div class="sidebar-area">
<div class="withdraw-card" style="padding: 30px;">
<h4 style="font-weight: 800; margin-bottom: 25px;"><i class="fas fa-shield-check" style="color: var(--success-color);"></i> 提现安全说明</h4>
<div style="font-size: 13px; color: var(--text-muted); line-height: 1.8;">
<p style="margin-bottom: 15px;">为了您的账户安全,提现申请将由人工审核,您将自动弹出在线客服界面完成后续步骤。</p>
<p style="margin-bottom: 15px;">发起申请后,请按照客服要求提供您的收款账户信息。</p>
<div style="background: rgba(255, 255, 255, 0.03); padding: 15px; border-radius: 12px; border-left: 3px solid var(--primary-color);">
请确保您的收款账户信息 100% 正确。资金一旦发出,将无法追回。
</div>
</div>
</div>
<div class="withdraw-card" style="padding: 30px; margin-top: 20px;">
<h4 style="font-weight: 800; margin-bottom: 20px;"><i class="fas fa-history"></i> 帮助与支持</h4>
<div style="font-size: 13px; color: var(--text-muted);">
提现过程中遇到问题?联系我们的 24/7 在线客服。
<div style="margin-top: 20px;">
<a href="javascript:void(0)" onclick="openCSChat()" class="btn" style="width: 100%; background: #2b3139; color: white; border-radius: 10px; padding: 10px; text-decoration: none; display: block; text-align: center;">联系客服</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function switchWithdrawMethod(method) {
document.getElementById('fiat-options').style.display = method === 'fiat' ? 'block' : 'none';
document.getElementById('usdt-options').style.display = method === 'usdt' ? 'block' : 'none';
document.getElementById('method-fiat').classList.toggle('active', method === 'fiat');
document.getElementById('method-usdt').classList.toggle('active', method === 'usdt');
document.getElementById('withdraw-type').value = method;
document.getElementById('fiat-equiv-display').style.display = method === 'fiat' ? 'block' : 'none';
updateWithdrawRate();
}
function updateWithdrawRate() {
const amount = parseFloat(document.getElementById('amount-input').value) || 0;
const select = document.getElementById('fiat-currency');
const rate = parseFloat(select.options[select.selectedIndex].getAttribute('data-rate'));
const code = select.value;
document.getElementById('fiat-val').innerText = (amount * rate).toFixed(2);
document.getElementById('fiat-code').innerText = code;
}
updateWithdrawRate();
// AJAX Form Submission
const withdrawForm = document.getElementById('withdraw-form');
if (withdrawForm) {
withdrawForm.onsubmit = async (e) => {
e.preventDefault();
const btn = document.getElementById('submit-btn');
const originalText = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 处理中...';
try {
const formData = new FormData(withdrawForm);
const resp = await fetch('matching.php', {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
// For withdrawals, matching.php might return plain text if balance is insufficient
const text = await resp.text();
let res;
try {
res = JSON.parse(text);
} catch (e) {
alert(text || '提交失败,请检查余额或密码');
btn.disabled = false;
btn.innerHTML = originalText;
return;
}
if (res.success) {
// Trigger chat popup
if (typeof openCSChat === 'function') {
openCSChat();
withdrawForm.style.opacity = '0.5';
withdrawForm.style.pointerEvents = 'none';
btn.innerHTML = '<i class="fas fa-check"></i> 请求已发送';
} else {
window.location.href = 'chat.php';
}
} else {
alert(res.error || '提交失败,请稍后重试');
btn.disabled = false;
btn.innerHTML = originalText;
}
} catch (e) {
console.error(e);
alert('网络错误,请稍后重试');
btn.disabled = false;
btn.innerHTML = originalText;
}
};
}
</script>
<?php include 'footer.php'; ?>