Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c93c7ad3ca | ||
|
|
b61cbbc19a | ||
|
|
f5c7fa12cc | ||
|
|
5464b9a32d | ||
|
|
a22438663d | ||
|
|
5e2fe8c059 | ||
|
|
79b07243ce | ||
|
|
7c4904baad | ||
|
|
cc38735373 | ||
|
|
396b0e8f02 |
67
about.php
Normal file
67
about.php
Normal 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'; ?>
|
||||
147
admin/chat.php
Normal file
147
admin/chat.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
session_start();
|
||||
$pdo = db();
|
||||
|
||||
// Handle deletion of chat
|
||||
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['delete_user_id'])) {
|
||||
$del_id = $_GET['delete_user_id'];
|
||||
// Delete messages
|
||||
$pdo->prepare("DELETE FROM messages WHERE user_id = ?")->execute([$del_id]);
|
||||
// Optionally update orders to not show in chat (e.g., mark as rejected or hidden if they are just 'matching')
|
||||
$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: var(--danger-color); 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(255, 60, 0, 0.2); color: #ff3c00; 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; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<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"><?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="settings.php" class="menu-item"><i class="fas fa-cog"></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>
|
||||
<?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 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="../assets/notification.mp3" preload="auto"></audio>
|
||||
|
||||
<script>
|
||||
// Notification polling
|
||||
let lastCount = <?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 > lastCount) {
|
||||
document.getElementById('notif-sound').play().catch(e => {});
|
||||
if (confirm('有新的消息或充值申请,是否刷新页面?')) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
lastCount = data.total;
|
||||
});
|
||||
}
|
||||
setInterval(checkNotifications, 10000);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
219
admin/chat_iframe.php
Normal file
219
admin/chat_iframe.php
Normal file
@ -0,0 +1,219 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
require_once '../includes/currency_helper.php';
|
||||
session_start();
|
||||
$pdo = db();
|
||||
|
||||
$user_id = $_GET['user_id'] ?? null;
|
||||
if (!$user_id) die("User ID required");
|
||||
|
||||
// Mark as read
|
||||
$pdo->prepare("UPDATE messages SET is_read = 1 WHERE user_id = ? AND sender = 'user'")->execute([$user_id]);
|
||||
|
||||
// Handle Message Sending
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['message'])) {
|
||||
$msg = $_POST['message'];
|
||||
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $msg]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Handle Recharge Actions
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) {
|
||||
$oid = $_POST['order_id'];
|
||||
if ($_POST['action'] == 'match') {
|
||||
$bank = $_POST['bank_name'] ?? '';
|
||||
$name = $_POST['account_name'] ?? '';
|
||||
$number = $_POST['account_number'] ?? '';
|
||||
$remarks = $_POST['remarks'] ?? '';
|
||||
|
||||
$info = "🏦 银行名称:$bank\n👤 收款姓名:$name\n💳 收款账号:$number\n📝 备注说明:$remarks";
|
||||
|
||||
$pdo->prepare("UPDATE fiat_orders SET status = 'matched', bank_account_info = ? WHERE id = ?")->execute([$info, $oid]);
|
||||
|
||||
$notif = "✅ 匹配成功!收款账户已下发。请在页面强制弹窗中查看详细信息并进行转账。";
|
||||
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $notif]);
|
||||
} elseif ($_POST['action'] == 'complete') {
|
||||
$stmt = $pdo->prepare("SELECT amount, currency, exchange_rate FROM fiat_orders WHERE id = ?");
|
||||
$stmt->execute([$oid]);
|
||||
$order = $stmt->fetch();
|
||||
$amt = $order['amount'];
|
||||
$cur = $order['currency'];
|
||||
|
||||
$fiat_rates = get_fiat_rates();
|
||||
$real_time_rate = $fiat_rates[$cur] ?? $order['exchange_rate'];
|
||||
$usdt_amt = ($real_time_rate > 0) ? ($amt / $real_time_rate) : $amt;
|
||||
|
||||
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$usdt_amt, $user_id]);
|
||||
$pdo->prepare("UPDATE fiat_orders SET status = 'completed', usdt_amount = ?, exchange_rate = ? WHERE id = ?")
|
||||
->execute([$usdt_amt, $real_time_rate, $oid]);
|
||||
|
||||
$notif = "🎉 充值已确认到账!\n金额:" . number_format($amt, 2) . " $cur\n实时汇率:1 USDT = " . number_format($real_time_rate, 4) . " $cur\n入账:" . number_format($usdt_amt, 2) . " USDT";
|
||||
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $notif]);
|
||||
} elseif ($_POST['action'] == 'reject') {
|
||||
$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, "❌ 您的充值申请 #$oid 已被拒绝。"]);
|
||||
}
|
||||
}
|
||||
|
||||
$user = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$user->execute([$user_id]);
|
||||
$userData = $user->fetch();
|
||||
|
||||
$messages = $pdo->prepare("SELECT * FROM messages WHERE user_id = ? ORDER BY created_at ASC");
|
||||
$messages->execute([$user_id]);
|
||||
$msgs = $messages->fetchAll();
|
||||
|
||||
$orders = $pdo->prepare("SELECT * FROM fiat_orders WHERE user_id = ? AND status IN ('matching', 'submitting', 'matched') ORDER BY id DESC");
|
||||
$orders->execute([$user_id]);
|
||||
$pending_orders = $orders->fetchAll();
|
||||
|
||||
$current_rates = get_fiat_rates();
|
||||
?>
|
||||
<!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: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: #0B0E11; color: white; display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
|
||||
.chat-header { padding: 15px 20px; background: #1E2329; border-bottom: 1px solid #2B3139; display: flex; justify-content: space-between; align-items: center; z-index: 10; }
|
||||
.main-content { flex: 1; display: flex; flex-direction: column; overflow-y: auto; }
|
||||
.chat-box { flex: 1; padding: 20px; display: flex; flex-direction: column; gap: 15px; }
|
||||
.msg { max-width: 85%; padding: 12px 16px; border-radius: 12px; font-size: 14px; line-height: 1.6; position: relative; }
|
||||
.msg.admin { align-self: flex-end; background: #377aff; color: white; border-bottom-right-radius: 2px; }
|
||||
.msg.user { align-self: flex-start; background: #2B3139; color: #EAECEF; border-bottom-left-radius: 2px; }
|
||||
.msg-time { font-size: 10px; color: #848E9C; margin-top: 5px; display: block; text-align: right; }
|
||||
.recharge-panel { background: #1E2329; border-bottom: 1px solid #2B3139; padding: 15px 20px; }
|
||||
.order-card { background: #161A1E; border: 1px solid #2B3139; border-radius: 16px; padding: 15px; margin-bottom: 12px; }
|
||||
.input-area { padding: 15px 20px; background: #1E2329; border-top: 1px solid #2B3139; display: flex; gap: 12px; }
|
||||
input[type="text"], input[type="number"], textarea { width: 100%; background: #0B0E11; border: 1px solid #2B3139; color: white; padding: 10px; border-radius: 8px; outline: none; margin-bottom: 8px; font-size: 13px; }
|
||||
button { background: #377aff; border: none; color: white; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-weight: bold; }
|
||||
.status-badge { font-size: 10px; padding: 4px 10px; border-radius: 6px; font-weight: 800; }
|
||||
.matching { background: rgba(240, 185, 11, 0.1); color: #f0b90b; }
|
||||
.submitting { background: rgba(0, 192, 135, 0.1); color: #00c087; }
|
||||
.btn-complete { background: #00c087; }
|
||||
.btn-reject { background: #f6465d; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="chat-header">
|
||||
<div>
|
||||
<span style="font-weight: 800;"><?php echo htmlspecialchars($userData['username'] ?? 'User'); ?></span>
|
||||
<span style="color: #848E9C; font-size: 11px; margin-left: 8px;">UID: <?php echo $userData['uid'] ?? 'N/A'; ?></span>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-size: 11px; color: #848E9C;">余额: <span style="color: #00c087;"><?php echo number_format($userData['balance'] ?? 0, 2); ?> USDT</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
<?php if (!empty($pending_orders)): ?>
|
||||
<div class="recharge-panel">
|
||||
<div style="font-weight: bold; color: #F0B90B; margin-bottom: 10px; font-size: 12px;">待处理充值</div>
|
||||
<?php foreach($pending_orders as $o):
|
||||
$is_matching = ($o['status'] == 'matching');
|
||||
$live_rate = $current_rates[$o['currency']] ?? $o['exchange_rate'];
|
||||
$live_usdt = ($live_rate > 0) ? ($o['amount'] / $live_rate) : $o['amount'];
|
||||
?>
|
||||
<div class="order-card">
|
||||
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
||||
<div>
|
||||
<div style="font-size: 1rem; font-weight: 900;"><?php echo number_format($o['amount'], 2); ?> <?php echo $o['currency']; ?></div>
|
||||
<div style="font-size: 11px; color: #848E9C;">≈ <?php echo number_format($live_usdt, 2); ?> USDT (汇率: <?php echo number_format($live_rate, 4); ?>)</div>
|
||||
</div>
|
||||
<span class="status-badge <?php echo $o['status']; ?>">
|
||||
<?php
|
||||
if($o['status'] == 'matching') echo '等待分配账户';
|
||||
elseif($o['status'] == 'matched') echo '已分配/待支付';
|
||||
elseif($o['status'] == 'submitting') echo '已提交凭证';
|
||||
?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<?php if($is_matching): ?>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
|
||||
<input type="hidden" name="action" value="match">
|
||||
<input type="text" name="bank_name" placeholder="银行名称 (如: 中国工商银行)" required>
|
||||
<input type="text" name="account_name" placeholder="收款人姓名" required>
|
||||
<input type="text" name="account_number" placeholder="银行账号" required>
|
||||
<textarea name="remarks" placeholder="注意事项 (可选)" style="height: 50px;"></textarea>
|
||||
<button type="submit" style="width: 100%;">确认匹配账户</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<div style="background: rgba(255,255,255,0.03); padding: 10px; border-radius: 8px; margin-bottom: 10px; font-size: 12px;">
|
||||
<?php echo nl2br(htmlspecialchars($o['bank_account_info'])); ?>
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px; align-items: center;">
|
||||
<?php if($o['proof_image']): ?>
|
||||
<a href="../<?php echo $o['proof_image']; ?>" target="_blank" style="color: #00c087; font-size: 12px; text-decoration: none; border: 1px solid #00c087; padding: 5px 10px; border-radius: 5px;">查看凭证</a>
|
||||
<?php endif; ?>
|
||||
<div style="flex: 1; display: flex; gap: 5px; justify-content: flex-end;">
|
||||
<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-complete" style="padding: 5px 10px; font-size: 12px;">同意</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-reject" style="padding: 5px 10px; font-size: 12px;">拒绝</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="chat-box" id="chat-box">
|
||||
<?php foreach($msgs as $m): ?>
|
||||
<div class="msg <?php echo $m['sender']; ?>">
|
||||
<?php echo nl2br(htmlspecialchars($m['message'])); ?>
|
||||
<span class="msg-time"><?php echo date('H:i', strtotime($m['created_at'])); ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="input-area" id="msg-form">
|
||||
<input type="text" id="msg-input" placeholder="输入消息..." autocomplete="off">
|
||||
<button type="submit"><i class="fas fa-paper-plane"></i></button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
|
||||
document.getElementById('msg-form').onsubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const input = document.getElementById('msg-input');
|
||||
const msg = input.value.trim();
|
||||
if (!msg) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('message', msg);
|
||||
input.value = '';
|
||||
|
||||
const msgDiv = document.createElement('div');
|
||||
msgDiv.className = 'msg admin';
|
||||
msgDiv.innerHTML = msg.replace(/\n/g, '<br>') + `<span class="msg-time">${new Date().getHours()}:${new Date().getMinutes()}</span>`;
|
||||
chatBox.appendChild(msgDiv);
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
|
||||
await fetch(window.location.href, { method: 'POST', body: formData });
|
||||
};
|
||||
|
||||
setInterval(async () => {
|
||||
const res = await fetch('../api/get_messages.php?user_id=<?php echo $user_id; ?>');
|
||||
const data = await res.json();
|
||||
if (data && data.count > <?php echo count($msgs); ?>) {
|
||||
location.reload();
|
||||
}
|
||||
}, 5000);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
153
admin/futures_orders.php
Normal file
153
admin/futures_orders.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
session_start();
|
||||
$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
|
||||
// The requirement says: "后台可以按照用户下单的止盈价格接受,同意就是按照止盈价格计算出盈利"
|
||||
$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;
|
||||
}
|
||||
|
||||
// Apply leverage to profit or it's already calculated in nominal?
|
||||
// Nominal is amount * 10 (value in USDT).
|
||||
// PNL = (PriceChange / EntryPrice) * NominalValue. This is correct.
|
||||
|
||||
$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' 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' 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; }
|
||||
.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; }
|
||||
</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="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="settings.php" class="menu-item"><i class="fas fa-cog"></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>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($orders as $o): ?>
|
||||
<tr>
|
||||
<td>#<?php echo $o['id']; ?></td>
|
||||
<td><?php echo htmlspecialchars($o['username']); ?></td>
|
||||
<td><?php echo $o['symbol']; ?></td>
|
||||
<td><span style="color: <?php echo $o['side'] == 'buy' ? '#00c087' : '#f6465d'; ?>"><?php echo strtoupper($o['side'] == 'buy' ? '做多' : '做空'); ?></span></td>
|
||||
<td><?php echo $o['leverage']; ?>x</td>
|
||||
<td><?php echo number_format($o['price'], 4); ?></td>
|
||||
<td><span style="color: #00c087; font-weight: bold;"><?php echo $o['tp_price'] ? number_format($o['tp_price'], 4) : '--'; ?></span></td>
|
||||
<td><?php echo number_format($o['total'] / $o['leverage'], 2); ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if ($o['status'] == 'open') echo '<span style="color: #f0b90b; font-weight: bold;">待结算</span>';
|
||||
elseif ($o['status'] == 'closed') echo '<span style="color: #00c087;">已止盈结算</span>';
|
||||
else echo '<span style="color: #f6465d;">已判定亏损</span>';
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if($o['status'] == 'open'): ?>
|
||||
<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="approve">
|
||||
<button type="submit" class="btn-sm btn-approve" title="按止盈价结算盈利">同意(盈)</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-sm btn-reject" title="判定为亏损">拒绝(亏)</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
97
admin/index.php
Normal file
97
admin/index.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
session_start();
|
||||
|
||||
$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="../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; }
|
||||
.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; }
|
||||
.stat-card { background: #F9FAFB; padding: 20px; border-radius: 8px; border: 1px solid #EAECEF; }
|
||||
</style>
|
||||
</head>
|
||||
<body style="background-color: #FFFFFF; color: #1E2329;">
|
||||
<div class="admin-layout">
|
||||
<div class="sidebar">
|
||||
<h3 style="color: #1E2329; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<a href="index.php" class="menu-item active"><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 审核
|
||||
<?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-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="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="settings.php" class="menu-item"><i class="fas fa-cog"></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">
|
||||
<h2 style="color: #1E2329; margin-bottom: 2rem;">系统概览</h2>
|
||||
<div style="grid-template-columns: repeat(4, 1fr); display: grid; gap: 1.5rem;">
|
||||
<div class="stat-card">
|
||||
<div style="color: #707A8A; font-size: 0.9rem;">总注册人数</div>
|
||||
<div style="font-size: 2rem; color: #1E2329; margin-top: 10px;"><?php echo $total_users; ?></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div style="color: #707A8A; font-size: 0.9rem;">待处理 KYC</div>
|
||||
<div style="font-size: 2rem; color: #F0B90B; margin-top: 10px;"><?php echo $pending_kyc; ?></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div style="color: #707A8A; font-size: 0.9rem;">待匹配/审核充值</div>
|
||||
<div style="font-size: 2rem; color: #F0B90B; margin-top: 10px;"><?php echo $pending_orders; ?></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div style="color: #707A8A; font-size: 0.9rem;">未读消息</div>
|
||||
<div style="font-size: 2rem; color: #00C087; margin-top: 10px;"><?php echo $unread_msgs; ?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 3rem; background: #F9FAFB; padding: 25px; border-radius: 8px; border: 1px solid #EAECEF;">
|
||||
<h3 style="color: #1E2329; margin-bottom: 20px;">控制中心</h3>
|
||||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
|
||||
<div style="border: 1px solid #EAECEF; padding: 20px; border-radius: 6px; background: white;">
|
||||
<h4 style="color: #474D57;">客服与充值管理</h4>
|
||||
<p style="color: #707A8A; font-size: 0.8rem;">与用户对话并处理实时的充值匹配请求。</p>
|
||||
<a href="chat.php" class="btn-primary" style="display: inline-block; margin-top: 15px; font-size: 0.8rem; padding: 8px 15px;">进入工作台</a>
|
||||
</div>
|
||||
<div style="border: 1px solid #EAECEF; padding: 20px; border-radius: 6px; background: white;">
|
||||
<h4 style="color: #474D57;">交易管理</h4>
|
||||
<p style="color: #707A8A; font-size: 0.8rem;">审核并处理现货及合约交易订单。</p>
|
||||
<div style="display:flex; gap: 10px; margin-top: 15px;">
|
||||
<a href="spot_orders.php" class="btn-primary" style="font-size: 0.75rem; padding: 5px 10px; background: #377aff;">现货</a>
|
||||
<a href="futures_orders.php" class="btn-primary" style="font-size: 0.75rem; padding: 5px 10px; background: #f0b90b; color: white;">合约</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="border: 1px solid #EAECEF; padding: 20px; border-radius: 6px; background: white;">
|
||||
<h4 style="color: #474D57;">价格控制</h4>
|
||||
<p style="color: #707A8A; font-size: 0.8rem;">手动覆盖特定交易对的实时价格及插针控制。</p>
|
||||
<a href="settings.php" class="btn-primary" style="display: inline-block; margin-top: 15px; font-size: 0.8rem; padding: 8px 15px;">立即配置</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
91
admin/kyc.php
Normal file
91
admin/kyc.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
session_start();
|
||||
$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]);
|
||||
}
|
||||
|
||||
$kyc_list = $pdo->query("SELECT * FROM users WHERE kyc_status = 1 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>KYC 审核 - 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; }
|
||||
.kyc-card { background: #F9FAFB; border: 1px solid #EAECEF; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
|
||||
.kyc-img { width: 200px; height: 120px; object-fit: cover; border-radius: 4px; cursor: pointer; border: 1px solid #EAECEF; }
|
||||
.back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
.btn-primary { padding: 10px 20px; border-radius: 4px; border: none; cursor: pointer; color: white; font-weight: bold; }
|
||||
</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 active"><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="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="settings.php" class="menu-item"><i class="fas fa-cog"></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;">待审核 KYC</h2>
|
||||
|
||||
<?php if(empty($kyc_list)): ?>
|
||||
<p style="color: #707A8A; margin-top: 2rem;">暂无待审核申请。</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach($kyc_list as $k): ?>
|
||||
<div class="kyc-card">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
|
||||
<div>
|
||||
<h4 style="margin-bottom: 10px; color: #1E2329;"><?php echo htmlspecialchars($k['kyc_name']); ?></h4>
|
||||
<p style="color: #707A8A; font-size: 0.9rem;">身份证号: <?php echo htmlspecialchars($k['kyc_id_number']); ?></p>
|
||||
<p style="color: #707A8A; font-size: 0.8rem; margin-top: 5px;">用户名: <?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-primary" style="background: #00c087;">通过审核</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-primary" style="background: #f6465d;">拒绝申请</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 15px; margin-top: 20px;">
|
||||
<img src="../<?php echo $k['kyc_id_front']; ?>" class="kyc-img" onclick="window.open(this.src)">
|
||||
<img src="../<?php echo $k['kyc_id_back']; ?>" class="kyc-img" onclick="window.open(this.src)">
|
||||
<img src="../<?php echo $k['kyc_id_handheld']; ?>" class="kyc-img" onclick="window.open(this.src)">
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
147
admin/orders.php
Normal file
147
admin/orders.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
session_start();
|
||||
$pdo = db();
|
||||
|
||||
// Handle Actions
|
||||
if (isset($_POST['action'])) {
|
||||
$id = $_POST['order_id'];
|
||||
$table = $_POST['order_table'] === 'fiat' ? 'fiat_orders' : 'orders';
|
||||
|
||||
if ($_POST['action'] == 'match') {
|
||||
$info = $_POST['account_info'];
|
||||
$column = ($table === 'fiat_orders') ? 'bank_account_info' : 'account_info';
|
||||
$pdo->prepare("UPDATE $table SET status = 'matched', $column = ? 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 匹配成功。请刷新支付页面查看收款账户详情并按要求完成转账。";
|
||||
$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 FROM $table WHERE id = ?");
|
||||
$orderStmt->execute([$id]);
|
||||
$order = $orderStmt->fetch();
|
||||
if ($order) {
|
||||
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['amount'], $order['user_id']]);
|
||||
$pdo->prepare("UPDATE $table SET status = 'completed' WHERE id = ?")->execute([$id]);
|
||||
|
||||
$msg = "您的充值 " . $order['amount'] . " " . ($order['currency'] ?? 'USDT') . " 已确认到账。";
|
||||
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
|
||||
}
|
||||
} elseif ($_POST['action'] == 'reject') {
|
||||
$pdo->prepare("UPDATE $table SET status = 'rejected' WHERE id = ?")->execute([$id]);
|
||||
}
|
||||
}
|
||||
|
||||
$fiat_orders = $pdo->query("SELECT o.*, u.username, u.uid, 'fiat' as tbl FROM fiat_orders o JOIN users u ON o.user_id = u.id ORDER BY o.id DESC")->fetchAll();
|
||||
$usdt_orders = $pdo->query("SELECT o.*, u.username, u.uid, 'usdt' as tbl FROM orders o JOIN users u ON o.user_id = u.id ORDER BY o.id DESC")->fetchAll();
|
||||
$all_deposits = array_merge($fiat_orders, $usdt_orders);
|
||||
|
||||
usort($all_deposits, function($a, $b) {
|
||||
$priority = ['matching' => 3, 'submitting' => 2, 'pending' => 2, 'matched' => 1, 'completed' => 0];
|
||||
$pA = $priority[$a['status']] ?? 0;
|
||||
$pB = $priority[$b['status']] ?? 0;
|
||||
if ($pA != $pB) return $pB - $pA;
|
||||
return $b['id'] - $a['id'];
|
||||
});
|
||||
|
||||
$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', '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: #1E2329; border-right: 1px solid #2B3139; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #0B0E11; color: white; overflow-x: auto; }
|
||||
.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: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; margin-bottom: 3rem; }
|
||||
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #2B3139; 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; animation: blink 1s infinite; }
|
||||
.submitting { 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; }
|
||||
@keyframes blink { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } }
|
||||
.back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<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">
|
||||
<i class="fas fa-headset"></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="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="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h2>充值申请管理</h2>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th><th>用户</th><th>类型</th><th>金额</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: <?php echo $o['tbl'] == 'usdt' ? '#26a17b' : '#007bff'; ?>"><?php echo strtoupper($o['tbl']); ?></span></td>
|
||||
<td><b><?php echo number_format($o['amount'], 2); ?> <?php echo $o['currency']; ?></b></td>
|
||||
<td>
|
||||
<?php
|
||||
$img = ($o['tbl'] == 'fiat' ? ($o['proof_image'] ?? null) : ($o['proof_img'] ?? null));
|
||||
if($img): ?>
|
||||
<a href="../<?php echo $img; ?>" 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 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="order_table" value="<?php echo $o['tbl']; ?>">
|
||||
<input type="hidden" name="action" value="match">
|
||||
<input type="text" name="account_info" placeholder="收款账户信息" required style="padding: 8px; background: #1e2329; border: 1px solid #2b3139; color: white; border-radius: 4px;">
|
||||
<button type="submit" class="btn-primary" style="background: #ff3c00;">分配账户</button>
|
||||
</form>
|
||||
<?php elseif($o['status'] == 'submitting' || $o['status'] == 'matched'): ?>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
|
||||
<input type="hidden" name="order_table" value="<?php echo $o['tbl']; ?>">
|
||||
<input type="hidden" name="action" value="complete">
|
||||
<button type="submit" class="btn-primary" style="background: #00c087;">确认入金</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
119
admin/settings.php
Normal file
119
admin/settings.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
session_start();
|
||||
$db = db();
|
||||
|
||||
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 = "系统设置已成功更新。";
|
||||
}
|
||||
|
||||
$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>系统设置 - 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; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #0B0E11; color: white; }
|
||||
.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: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.form-group { margin-bottom: 25px; background: #1E2329; padding: 20px; border-radius: 8px; border: 1px solid #2B3139; }
|
||||
.form-group label { display: block; margin-bottom: 10px; color: #848E9C; font-weight: bold; }
|
||||
input[type="text"], input[type="number"], select { width: 100%; padding: 10px; background: #0B0E11; border: 1px solid #2B3139; color: white; border-radius: 4px; outline: none; }
|
||||
.back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
.back-btn:hover { color: white; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<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">
|
||||
<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="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="settings.php" class="menu-item active"><i class="fas fa-cog"></i> 系统设置</a>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h2>系统控制面板</h2>
|
||||
|
||||
<?php if(isset($message)): ?>
|
||||
<div style="background: rgba(0,255,0,0.1); color: #00ff00; padding: 15px; border-radius: 4px; margin-bottom: 20px;"><i class="fas fa-check-circle"></i> <?php echo $message; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="POST">
|
||||
<h3 style="margin: 30px 0 15px 0; color: #F0B90B;">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">
|
||||
<p style="font-size: 0.8rem; color: #5e6673; margin-top: 5px;">设置用户在秒合约/永续合约中的全局获利概率 (0-100)。</p>
|
||||
</div>
|
||||
|
||||
<h3 style="margin: 30px 0 15px 0; color: #F0B90B;">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">
|
||||
<p style="font-size: 0.75rem; color: #f6465d; margin-top: 5px;">插针价格用于瞬间触发用户的止盈或爆仓。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
||||
<div class="form-group">
|
||||
<label>ETH 指定价格 ($)</label>
|
||||
<input type="number" name="settings[manual_eth_price]" value="<?php echo $settings['manual_eth_price'] ?? 0; ?>" step="0.01">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>ETH 插针价格 ($)</label>
|
||||
<input type="number" name="settings[pin_eth_price]" value="<?php echo $settings['pin_eth_price'] ?? 0; ?>" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin: 30px 0 15px 0; color: #F0B90B;">3. 其他配置</h3>
|
||||
<div class="form-group">
|
||||
<label>系统公告内容 (简体中文)</label>
|
||||
<input type="text" name="settings[announcement_zh]" value="<?php echo $settings['announcement_zh'] ?? ''; ?>" placeholder="输入显示在首页顶部的公告...">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn-primary" style="padding: 12px 40px; font-weight: bold; border-radius: 8px; cursor: pointer;">保存所有设置</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
153
admin/spot_orders.php
Normal file
153
admin/spot_orders.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
session_start();
|
||||
$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' WHERE id = ?")->execute([$oid]);
|
||||
} elseif ($action == 'reject') {
|
||||
// "LOSS": Reject. No assets returned.
|
||||
$pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected' 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; }
|
||||
.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; }
|
||||
</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="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="settings.php" class="menu-item"><i class="fas fa-cog"></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>总计(USDT)</th>
|
||||
<th>盈利差额</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($orders as $o):
|
||||
$diff = 0;
|
||||
if ($o['side'] == 'sell' && $o['tp_price'] > 0) {
|
||||
$diff = ($o['price'] - $o['tp_price']) * $o['amount'];
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td>#<?php echo $o['id']; ?></td>
|
||||
<td><?php echo htmlspecialchars($o['username']); ?></td>
|
||||
<td><?php echo $o['symbol']; ?></td>
|
||||
<td><span style="color: <?php echo $o['side'] == 'buy' ? '#00c087' : '#f6465d'; ?>"><?php echo strtoupper($o['side'] == 'buy' ? '买入' : '卖出'); ?></span></td>
|
||||
<td><?php echo number_format($o['tp_price'], 4); ?></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'], 2); ?></td>
|
||||
<td>
|
||||
<?php if($o['side'] == 'sell'): ?>
|
||||
<span style="color: <?php echo $diff >= 0 ? '#00c087' : '#f6465d'; ?>; font-weight: bold;">
|
||||
<?php echo ($diff >= 0 ? '+' : '') . number_format($diff, 2); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
--
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if ($o['status'] == 'open') echo '<span style="color: #f0b90b; font-weight: bold;">待处理</span>';
|
||||
elseif ($o['status'] == 'closed') echo '<span style="color: #00c087;">已结算</span>';
|
||||
else echo '<span style="color: #f6465d;">已亏损</span>';
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if($o['status'] == 'open'): ?>
|
||||
<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="approve">
|
||||
<button type="submit" class="btn-sm btn-approve">同意(盈)</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-sm btn-reject">拒绝(亏)</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
242
admin/users.php
Normal file
242
admin/users.php
Normal file
@ -0,0 +1,242 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
session_start();
|
||||
$pdo = db();
|
||||
|
||||
// Handle Actions
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) {
|
||||
if ($_POST['action'] == 'add_user') {
|
||||
$username = $_POST['username'];
|
||||
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
|
||||
$uid = str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT);
|
||||
$pdo->prepare("INSERT INTO users (uid, username, password, balance, credit_score) VALUES (?, ?, ?, ?, ?)")
|
||||
->execute([$uid, $username, $password, $_POST['balance'] ?? 0, $_POST['credit_score'] ?? 80]);
|
||||
} elseif (isset($_POST['user_id'])) {
|
||||
$uid = $_POST['user_id'];
|
||||
if ($_POST['action'] == 'update_user') {
|
||||
$score = $_POST['score'];
|
||||
$balance = $_POST['balance'];
|
||||
$win_loss = $_POST['win_loss_control'];
|
||||
$status = $_POST['status'];
|
||||
|
||||
$sql = "UPDATE users SET credit_score = ?, balance = ?, win_loss_control = ?, status = ? WHERE id = ?";
|
||||
$params = [$score, $balance, $win_loss, $status, $uid];
|
||||
|
||||
if (!empty($_POST['password'])) {
|
||||
$sql = "UPDATE users SET credit_score = ?, balance = ?, win_loss_control = ?, status = ?, password = ? WHERE id = ?";
|
||||
$params = [$score, $balance, $win_loss, $status, password_hash($_POST['password'], PASSWORD_DEFAULT), $uid];
|
||||
}
|
||||
$pdo->prepare($sql)->execute($params);
|
||||
} elseif ($_POST['action'] == 'delete_user') {
|
||||
$pdo->prepare("DELETE FROM users WHERE id = ?")->execute([$uid]);
|
||||
} elseif ($_POST['action'] == 'toggle_status') {
|
||||
$user = $pdo->prepare("SELECT status FROM users WHERE id = ?");
|
||||
$user->execute([$uid]);
|
||||
$new_status = ($user->fetchColumn() == 'active' ? 'disabled' : 'active');
|
||||
$pdo->prepare("UPDATE users SET status = ? WHERE id = ?")->execute([$new_status, $uid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$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();
|
||||
?>
|
||||
<!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; text-decoration: none; display: inline-block; }
|
||||
.btn-edit { background: #f0b90b; color: #000; }
|
||||
.btn-delete { background: #f6465d; color: white; }
|
||||
.btn-status { background: #5e6673; color: white; }
|
||||
.btn-add { background: #00c087; color: white; padding: 10px 20px; border-radius: 4px; border: none; cursor: pointer; margin-bottom: 20px; }
|
||||
|
||||
.modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; }
|
||||
.modal-content { background: #FFFFFF; width: 500px; margin: 50px auto; padding: 30px; border-radius: 8px; border: 1px solid #EAECEF; color: #1E2329; }
|
||||
.form-group { margin-bottom: 15px; }
|
||||
.form-group label { display: block; margin-bottom: 5px; color: #474D57; }
|
||||
.form-group input, .form-group select { width: 100%; padding: 8px; background: #F9FAFB; border: 1px solid #EAECEF; color: #1E2329; border-radius: 4px; outline: none; }
|
||||
.modal-footer { margin-top: 20px; text-align: right; }
|
||||
|
||||
.header-actions { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
|
||||
.back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; }
|
||||
.back-btn:hover { color: #1E2329; }
|
||||
</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 active"><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="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="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<div class="header-actions">
|
||||
<div>
|
||||
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h2 style="margin-top: 10px;">用户管理</h2>
|
||||
</div>
|
||||
<button class="btn-add" onclick="showModal('addModal')"><i class="fas fa-user-plus"></i> 添加新用户</button>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>UID</th>
|
||||
<th>用户名</th>
|
||||
<th>余额 (USDT)</th>
|
||||
<th>信用分</th>
|
||||
<th>盈亏控制</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($users as $u): ?>
|
||||
<tr>
|
||||
<td><?php echo $u['uid']; ?></td>
|
||||
<td><?php echo htmlspecialchars($u['username']); ?></td>
|
||||
<td><b><?php echo number_format($u['balance'], 2); ?></b></td>
|
||||
<td><?php echo $u['credit_score']; ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if ($u['win_loss_control'] == 'win') echo '<span style="color: #00c087;">强制盈利</span>';
|
||||
elseif ($u['win_loss_control'] == 'loss') echo '<span style="color: #f6465d;">强制亏损</span>';
|
||||
else echo '<span style="color: #848e9c;">默认</span>';
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo $u['status'] == 'active' ? '<span style="color: #00c087;">正常</span>' : '<span style="color: #f6465d;">已禁用</span>'; ?></td>
|
||||
<td>
|
||||
<button class="btn-sm btn-edit" onclick='editUser(<?php echo json_encode($u); ?>)'>编辑</button>
|
||||
<form method="POST" style="display:inline;" onsubmit="return confirm('确定要删除此用户吗?')">
|
||||
<input type="hidden" name="user_id" value="<?php echo $u['id']; ?>">
|
||||
<input type="hidden" name="action" value="delete_user">
|
||||
<button type="submit" class="btn-sm btn-delete">删除</button>
|
||||
</form>
|
||||
<form method="POST" style="display:inline;">
|
||||
<input type="hidden" name="user_id" value="<?php echo $u['id']; ?>">
|
||||
<input type="hidden" name="action" value="toggle_status">
|
||||
<button type="submit" class="btn-sm btn-status"><?php echo $u['status'] == 'active' ? '禁用' : '启用'; ?></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add User Modal -->
|
||||
<div id="addModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h3>添加新用户</h3>
|
||||
<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="text" name="password" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>初始余额 (USDT)</label>
|
||||
<input type="number" step="0.01" name="balance" value="0.00">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>信用分</label>
|
||||
<input type="number" name="credit_score" value="80">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn-sm btn-status" onclick="hideModal('addModal')">取消</button>
|
||||
<button type="submit" class="btn-sm btn-edit">确认添加</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit User Modal -->
|
||||
<div id="editModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h3>编辑用户信息</h3>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="update_user">
|
||||
<input type="hidden" name="user_id" id="edit_user_id">
|
||||
<div class="form-group">
|
||||
<label>用户名 (不可更改)</label>
|
||||
<input type="text" id="edit_username" readonly style="opacity: 0.6;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>修改密码 (不改留空)</label>
|
||||
<input type="text" name="password" placeholder="留空则不修改">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>余额 (USDT)</label>
|
||||
<input type="number" step="0.01" name="balance" id="edit_balance">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>信用分</label>
|
||||
<input type="number" name="score" id="edit_score">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>盈亏控制</label>
|
||||
<select name="win_loss_control" id="edit_win_loss">
|
||||
<option value="none">正常 (默认)</option>
|
||||
<option value="win">强制盈利 (Win)</option>
|
||||
<option value="loss">强制亏损 (Loss)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>用户状态</label>
|
||||
<select name="status" id="edit_status">
|
||||
<option value="active">正常 (Active)</option>
|
||||
<option value="disabled">禁用 (Disabled)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn-sm btn-status" onclick="hideModal('editModal')">取消</button>
|
||||
<button type="submit" class="btn-sm btn-edit">保存修改</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showModal(id) { document.getElementById(id).style.display = 'block'; }
|
||||
function hideModal(id) { document.getElementById(id).style.display = 'none'; }
|
||||
|
||||
function editUser(user) {
|
||||
document.getElementById('edit_user_id').value = user.id;
|
||||
document.getElementById('edit_username').value = user.username;
|
||||
document.getElementById('edit_balance').value = user.balance;
|
||||
document.getElementById('edit_score').value = user.credit_score;
|
||||
document.getElementById('edit_win_loss').value = user.win_loss_control;
|
||||
document.getElementById('edit_status').value = user.status;
|
||||
showModal('editModal');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
59
api-docs.php
Normal file
59
api-docs.php
Normal 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: <your_api_key><br>
|
||||
X-NOVA-SIGNATURE: <hmac_sha256_signature>
|
||||
</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>
|
||||
"symbol": "BTCUSDT",<br>
|
||||
"priceChange": "105.15",<br>
|
||||
"priceChangePercent": "0.162",<br>
|
||||
"lastPrice": "65120.50",<br>
|
||||
"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
64
api/cancel_order.php
Normal 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
22
api/check_order.php
Normal 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']);
|
||||
}
|
||||
26
api/check_order_status.php
Normal file
26
api/check_order_status.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($_SESSION['user_id']) || !isset($_GET['order_id'])) {
|
||||
echo json_encode(['error' => 'Unauthorized']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$order_id = $_GET['order_id'];
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
$stmt = db()->prepare("SELECT status, bank_account_info FROM fiat_orders WHERE id = ? AND user_id = ?");
|
||||
$stmt->execute([$order_id, $user_id]);
|
||||
$order = $stmt->fetch();
|
||||
|
||||
if ($order) {
|
||||
echo json_encode([
|
||||
'status' => $order['status'],
|
||||
'bank_account_info' => $order['bank_account_info']
|
||||
]);
|
||||
} else {
|
||||
echo json_encode(['error' => 'Order not found']);
|
||||
}
|
||||
39
api/get_assets.php
Normal file
39
api/get_assets.php
Normal 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()]);
|
||||
}
|
||||
41
api/get_messages.php
Normal file
41
api/get_messages.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
echo json_encode(['error' => 'Unauthorized']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Support both regular user and admin polling
|
||||
$user_id = isset($_GET['user_id']) ? $_GET['user_id'] : $_SESSION['user_id'];
|
||||
|
||||
// Admin Poll Logic (Global notifications)
|
||||
if (isset($_GET['admin_poll'])) {
|
||||
// Check for latest message ID
|
||||
$last_id = db()->query("SELECT MAX(id) FROM messages")->fetchColumn() ?: 0;
|
||||
|
||||
// Check for pending/matching orders
|
||||
$pending_orders = db()->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn() ?: 0;
|
||||
|
||||
// Get latest message content if it's a recharge notification
|
||||
$latest_msg = db()->query("SELECT message FROM messages WHERE sender = 'user' ORDER BY id DESC LIMIT 1")->fetchColumn();
|
||||
$is_recharge = ($latest_msg && strpos($latest_msg, '[RECHARGE_') === 0);
|
||||
|
||||
echo json_encode([
|
||||
'last_id' => (int)$last_id,
|
||||
'pending_orders' => (int)$pending_orders,
|
||||
'is_recharge' => $is_recharge,
|
||||
'latest_msg' => $latest_msg
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Regular User or specific Chat Polling Logic
|
||||
$stmt = db()->prepare("SELECT COUNT(*) FROM messages WHERE user_id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$count = $stmt->fetchColumn();
|
||||
|
||||
echo json_encode(['count' => (int)$count]);
|
||||
38
api/get_orders.php
Normal file
38
api/get_orders.php
Normal 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()]);
|
||||
}
|
||||
95
api/place_order.php
Normal file
95
api/place_order.php
Normal 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()]);
|
||||
}
|
||||
@ -1,346 +1,330 @@
|
||||
* { 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);
|
||||
overflow-x: hidden;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .navbar-brand {
|
||||
font-family: var(--font-heading);
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
/* 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-link {
|
||||
.nav-links a {
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text);
|
||||
margin-left: 1rem;
|
||||
transition: color 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.nav-link-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Colorful Menu Icons */
|
||||
.fa-home { color: #5d5dff; }
|
||||
.fa-chart-line { color: #00e676; }
|
||||
.fa-coins { color: #ffd600; }
|
||||
.fa-file-contract { color: #ff3d00; }
|
||||
.fa-bolt { color: #fbc02d; }
|
||||
.fa-pickaxe { color: #8e24aa; }
|
||||
.fa-wallet { color: #03a9f4; }
|
||||
|
||||
.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: 1;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
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;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #1d4ed8;
|
||||
border-color: #000;
|
||||
color: #fff;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.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 & Carousel */
|
||||
.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%;
|
||||
padding: 80px 5%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4rem;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.project-card:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 8px 8px 0 #000;
|
||||
.hero-content { flex: 1; }
|
||||
.hero-image { flex: 1; position: relative; }
|
||||
|
||||
.hero-carousel {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.card-img-holder {
|
||||
height: 250px;
|
||||
.carousel-inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.carousel-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
transition: opacity 1s ease-in-out;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.carousel-item.active { opacity: 1; }
|
||||
|
||||
.carousel-caption {
|
||||
background: rgba(0,0,0,0.6);
|
||||
padding: 15px 25px;
|
||||
border-radius: 8px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
.section-title {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.market-table-card {
|
||||
background: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.market-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.market-table th, .market-table td {
|
||||
padding: 16px 24px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.market-table th {
|
||||
color: var(--text-muted);
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Why Choose Us */
|
||||
.why-section {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
margin: 80px auto;
|
||||
max-width: 1200px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.why-left { flex: 1.5; }
|
||||
.why-right { flex: 1; background: var(--card-bg); padding: 40px; border-radius: 20px; border: 1px solid var(--border-color); }
|
||||
|
||||
.why-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.why-item {
|
||||
background: var(--card-bg);
|
||||
padding: 30px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.why-icon {
|
||||
font-size: 40px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Partners */
|
||||
.partners-section {
|
||||
padding: 80px 5%;
|
||||
background: #0d1117;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.partners-grid {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 40px;
|
||||
margin-top: 40px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.partner-logo {
|
||||
height: 40px;
|
||||
filter: grayscale(1);
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.partner-logo:hover {
|
||||
filter: grayscale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Floating Service */
|
||||
.floating-service {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
right: 30px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: var(--primary-color);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: 2px solid #000;
|
||||
position: relative;
|
||||
font-size: 4rem;
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 10px 25px rgba(0,82,255,0.3);
|
||||
z-index: 1000;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.placeholder-art {
|
||||
transition: transform 0.3s ease;
|
||||
.floating-service:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.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 {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
font-weight: 700;
|
||||
/* Back Button */
|
||||
.back-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-top: auto;
|
||||
gap: 8px;
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
margin-bottom: 20px;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.link-arrow i { transition: transform 0.2s; margin-left: 5px; }
|
||||
.link-arrow:hover i { transform: translateX(5px); }
|
||||
|
||||
/* About */
|
||||
.about-image-stack {
|
||||
position: relative;
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
.back-btn:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.stack-card {
|
||||
position: absolute;
|
||||
width: 80%;
|
||||
height: 100%;
|
||||
border-radius: var(--radius-card);
|
||||
border: 2px solid #000;
|
||||
box-shadow: var(--shadow-hard);
|
||||
left: 10%;
|
||||
transform: rotate(-3deg);
|
||||
background-size: cover;
|
||||
/* Trading Pages specific */
|
||||
.trading-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 320px 320px;
|
||||
height: calc(100vh - 64px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Forms */
|
||||
.form-control {
|
||||
border: 2px solid #000;
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
font-weight: 500;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
.chart-area { flex: 1; border-right: 1px solid var(--border-color); display: flex; flex-direction: column; }
|
||||
.orderbook-area { width: 320px; border-right: 1px solid var(--border-color); display: flex; flex-direction: column; }
|
||||
.trade-area { width: 320px; padding: 20px; display: flex; flex-direction: column; gap: 20px; overflow-y: auto; }
|
||||
|
||||
.form-control:focus {
|
||||
box-shadow: 4px 4px 0 var(--color-primary);
|
||||
border-color: #000;
|
||||
background: #fff;
|
||||
}
|
||||
.trade-tabs { display: flex; border-bottom: 1px solid var(--border-color); margin-bottom: 15px; }
|
||||
.trade-tab { flex: 1; padding: 10px; text-align: center; cursor: pointer; color: var(--text-muted); }
|
||||
.trade-tab.active { color: var(--primary-color); border-bottom: 2px solid var(--primary-color); }
|
||||
|
||||
/* Animations */
|
||||
.animate-up {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
animation: fadeUp 0.8s ease forwards;
|
||||
}
|
||||
.input-group { margin-bottom: 15px; }
|
||||
.input-label { font-size: 12px; color: var(--text-muted); margin-bottom: 5px; display: flex; justify-content: space-between; }
|
||||
.trade-input-wrapper { background: #2b3139; border-radius: 4px; display: flex; align-items: center; padding: 0 12px; border: 1px solid transparent; }
|
||||
.trade-input-wrapper:focus-within { border-color: var(--primary-color); }
|
||||
.trade-input { background: transparent; border: none; color: white; padding: 10px 0; width: 100%; outline: none; font-size: 14px; }
|
||||
|
||||
.delay-100 { animation-delay: 0.1s; }
|
||||
.delay-200 { animation-delay: 0.2s; }
|
||||
.slider-container { margin: 20px 0; }
|
||||
.slider { width: 100%; cursor: pointer; }
|
||||
|
||||
@keyframes fadeUp {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Social */
|
||||
.social-links a {
|
||||
transition: transform 0.2s;
|
||||
display: inline-block;
|
||||
}
|
||||
.social-links a:hover {
|
||||
transform: scale(1.2) rotate(10deg);
|
||||
color: var(--color-accent) !important;
|
||||
}
|
||||
.btn-buy { background: var(--success-color); color: white; width: 100%; padding: 12px; border-radius: 4px; border: none; font-weight: bold; cursor: pointer; }
|
||||
.btn-sell { background: var(--danger-color); color: white; width: 100%; padding: 12px; border-radius: 4px; border: none; font-weight: bold; cursor: pointer; }
|
||||
|
||||
/* 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%; }
|
||||
@media (max-width: 992px) {
|
||||
.hero-section { flex-direction: column; text-align: center; }
|
||||
.why-section { flex-direction: column; }
|
||||
.trading-container { grid-template-columns: 1fr; height: auto; }
|
||||
.orderbook-area, .trade-area { width: 100%; }
|
||||
}
|
||||
BIN
assets/pasted-20260211-111828-54780d6a.png
Normal file
BIN
assets/pasted-20260211-111828-54780d6a.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 158 KiB |
BIN
assets/pasted-20260211-113703-755ed1d2.png
Normal file
BIN
assets/pasted-20260211-113703-755ed1d2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 109 KiB |
BIN
assets/pasted-20260211-115218-2bf8b7ce.png
Normal file
BIN
assets/pasted-20260211-115218-2bf8b7ce.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 169 KiB |
BIN
assets/pasted-20260212-045129-d8e4cda7.png
Normal file
BIN
assets/pasted-20260212-045129-d8e4cda7.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
55
careers.php
Normal file
55
careers.php
Normal 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'; ?>
|
||||
111
chat.php
Normal file
111
chat.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?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 for UID
|
||||
$stmt = $pdo->prepare("SELECT uid, username FROM users WHERE id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
// Get user IP
|
||||
$user_ip = $_SERVER['REMOTE_ADDR'];
|
||||
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$user_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
}
|
||||
|
||||
// Handle message sending
|
||||
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]);
|
||||
}
|
||||
header("Location: chat.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch messages
|
||||
$stmt = $pdo->prepare("SELECT * FROM messages WHERE user_id = ? ORDER BY created_at ASC");
|
||||
$stmt->execute([$user_id]);
|
||||
$messages = $stmt->fetchAll();
|
||||
|
||||
// Mark admin messages as read
|
||||
$stmt = $pdo->prepare("UPDATE messages SET is_read = 1 WHERE user_id = ? AND sender = 'admin'");
|
||||
$stmt->execute([$user_id]);
|
||||
?>
|
||||
|
||||
<div class="container" style="max-width: 800px; margin: 40px auto; padding: 0 20px;">
|
||||
<div class="card" style="background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 16px; display: flex; flex-direction: column; height: 600px;">
|
||||
<div class="card-header" style="padding: 20px; border-bottom: 1px solid var(--border-color); display: flex; align-items: center; gap: 15px;">
|
||||
<div style="width: 40px; height: 40px; background: var(--primary-color); border-radius: 50%; display: flex; align-items: center; justify-content: center;">
|
||||
<i class="fas fa-headset"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="margin: 0; font-size: 18px;"><?php echo __('customer_service', '在线客服'); ?></h3>
|
||||
<span style="font-size: 12px; color: var(--success-color);"><i class="fas fa-circle" style="font-size: 8px;"></i> 在线</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="chat-box" style="flex: 1; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 15px; scroll-behavior: smooth;">
|
||||
<!-- User Identification Info -->
|
||||
<div style="text-align: center; margin-bottom: 20px;">
|
||||
<div style="display: inline-block; padding: 8px 16px; background: rgba(255, 255, 255, 0.05); border-radius: 20px; font-size: 12px; color: var(--text-muted);">
|
||||
<i class="fas fa-info-circle" style="margin-right: 5px;"></i>
|
||||
当前用户: <span style="color: white;"><?php echo htmlspecialchars($user['username']); ?></span> (UID: <?php echo $user['uid']; ?>)
|
||||
| 登录IP: <span style="color: white;"><?php echo $user_ip; ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (empty($messages)): ?>
|
||||
<div style="text-align: center; color: var(--text-muted); margin-top: 50px;">
|
||||
<i class="fas fa-comments" style="font-size: 48px; opacity: 0.2; margin-bottom: 15px;"></i>
|
||||
<p><?php echo __('chat_welcome', '您好!请问有什么可以帮您?'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach ($messages as $m): ?>
|
||||
<div style="display: flex; flex-direction: column; align-items: <?php echo $m['sender'] === 'user' ? 'flex-end' : 'flex-start'; ?>;">
|
||||
<div style="max-width: 70%; padding: 12px 16px; border-radius: 12px; font-size: 14px; line-height: 1.5;
|
||||
<?php echo $m['sender'] === 'user' ? 'background: var(--primary-color); color: white; border-bottom-right-radius: 2px;' : 'background: #2b3139; color: white; border-bottom-left-radius: 2px;'; ?>">
|
||||
<?php echo nl2br(htmlspecialchars($m['message'])); ?>
|
||||
</div>
|
||||
<span style="font-size: 10px; color: var(--text-muted); margin-top: 4px;"><?php echo date('H:i', strtotime($m['created_at'])); ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="chat-input" style="padding: 20px; border-top: 1px solid var(--border-color);">
|
||||
<form method="POST" style="display: flex; gap: 10px;">
|
||||
<input type="text" name="message" autocomplete="off" placeholder="<?php echo __('type_message', '请输入消息...'); ?>"
|
||||
style="flex: 1; background: #2b3139; border: 1px solid var(--border-color); border-radius: 8px; padding: 12px 15px; color: white; outline: none;">
|
||||
<button type="submit" class="btn-primary" style="padding: 0 25px; border-radius: 8px;">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
|
||||
// Auto refresh chat
|
||||
setInterval(() => {
|
||||
fetch('api/get_messages.php')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.count > <?php echo count($messages); ?>) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}, 3000);
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
99
chat_iframe.php
Normal file
99
chat_iframe.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
die("Please login first.");
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$db = db();
|
||||
|
||||
// Handle message sending via AJAX
|
||||
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 messages for initial load
|
||||
$stmt = $db->prepare("SELECT * FROM messages WHERE user_id = ? ORDER BY created_at ASC");
|
||||
$stmt->execute([$user_id]);
|
||||
$messages = $stmt->fetchAll();
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<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; padding: 0; font-family: 'Inter', sans-serif; background: #161a1e; color: white; height: 100vh; display: flex; flex-direction: column; }
|
||||
#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; position: relative; }
|
||||
.msg.user { align-self: flex-end; background: #4facfe; color: white; border-bottom-right-radius: 2px; }
|
||||
.msg.admin { align-self: flex-start; background: #2b3139; color: #EAECEF; border-bottom-left-radius: 2px; }
|
||||
.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; }
|
||||
input { flex: 1; background: #0b0e11; border: 1px solid #2b3139; border-radius: 8px; padding: 10px 12px; color: white; outline: none; }
|
||||
button { background: #4facfe; border: none; width: 40px; height: 40px; border-radius: 8px; color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: 0.2s; }
|
||||
button:hover { background: #00f2fe; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="chat-box">
|
||||
<?php foreach ($messages as $m): ?>
|
||||
<div class="msg <?php echo $m['sender']; ?>">
|
||||
<?php echo nl2br(htmlspecialchars($m['message'])); ?>
|
||||
<span class="msg-time"><?php echo date('H:i', strtotime($m['created_at'])); ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<form id="chat-form" class="chat-input-area">
|
||||
<input type="text" id="msg-input" placeholder="Type a message..." autocomplete="off">
|
||||
<button type="submit"><i class="fas fa-paper-plane"></i></button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
const chatForm = document.getElementById('chat-form');
|
||||
const msgInput = document.getElementById('msg-input');
|
||||
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
|
||||
chatForm.onsubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const msg = msgInput.value.trim();
|
||||
if (!msg) return;
|
||||
|
||||
// Optimistic UI update
|
||||
const msgDiv = document.createElement('div');
|
||||
msgDiv.className = 'msg user';
|
||||
msgDiv.innerHTML = msg.replace(/\n/g, '<br>') + '<span class="msg-time">' + new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) + '</span>';
|
||||
chatBox.appendChild(msgDiv);
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
msgInput.value = '';
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('message', msg);
|
||||
await fetch('chat_iframe.php', { method: 'POST', body: formData });
|
||||
};
|
||||
|
||||
// Auto refresh for new messages from admin
|
||||
let lastMsgCount = <?php echo count($messages); ?>;
|
||||
setInterval(async () => {
|
||||
const res = await fetch('api/get_messages.php');
|
||||
const data = await res.json();
|
||||
if (data.count > lastMsgCount) {
|
||||
location.reload();
|
||||
}
|
||||
}, 3000);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
87
convert.php
Normal file
87
convert.php
Normal 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'; ?>
|
||||
9
db/migrations/01_create_user_assets.sql
Normal file
9
db/migrations/01_create_user_assets.sql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE TABLE IF NOT EXISTS user_assets (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
symbol VARCHAR(20) NOT NULL,
|
||||
amount DECIMAL(30, 10) DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY user_symbol (user_id, symbol)
|
||||
);
|
||||
346
deposit.php
Normal file
346
deposit.php
Normal file
@ -0,0 +1,346 @@
|
||||
<?php
|
||||
include 'header.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'db/config.php';
|
||||
require_once 'includes/currency_helper.php';
|
||||
|
||||
$db = db();
|
||||
|
||||
// Check for existing pending orders to force workflow
|
||||
$stmt = $db->prepare("SELECT id FROM fiat_orders WHERE user_id = ? AND status IN ('matching', 'matched', 'submitting') ORDER BY id DESC LIMIT 1");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$pending_order = $stmt->fetch();
|
||||
if ($pending_order) {
|
||||
header("Location: matching.php?order_id=" . $pending_order['id']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
$fiat_rates = get_fiat_rates();
|
||||
$fiat_currencies_info = [
|
||||
'USD' => 'US Dollar',
|
||||
'EUR' => 'Euro',
|
||||
'GBP' => 'British Pound',
|
||||
'CNY' => 'Chinese Yuan',
|
||||
'HKD' => 'Hong Kong Dollar',
|
||||
'JPY' => 'Japanese Yen',
|
||||
'KRW' => 'Korean Won',
|
||||
'SGD' => 'Singapore Dollar',
|
||||
'TWD' => 'Taiwan Dollar',
|
||||
'THB' => 'Thai Baht',
|
||||
'VND' => 'Vietnamese Dong',
|
||||
'IDR' => 'Indonesian Rupiah',
|
||||
'MYR' => 'Malaysian Ringgit',
|
||||
];
|
||||
?>
|
||||
|
||||
<main style="padding: 40px 20px; background: #0b0e11; min-height: calc(100vh - 64px);">
|
||||
<div style="max-width: 1000px; margin: 0 auto;">
|
||||
|
||||
<a href="profile.php" class="back-btn"><i class="fas fa-arrow-left"></i> <?php echo __('nav_profile'); ?></a>
|
||||
|
||||
<div style="margin-bottom: 40px;">
|
||||
<h1 style="font-size: 2.5rem; font-weight: bold; margin-bottom: 10px;"><?php echo __('deposit_assets', '充值资产'); ?></h1>
|
||||
<p style="color: var(--text-muted);"><?php echo __('deposit_method_tip', '请选择您偏好的充值方式'); ?></p>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-bottom: 40px;">
|
||||
<div id="card-fiat" style="background: var(--card-bg); padding: 35px; border-radius: 24px; border: 2px solid var(--primary-color); cursor: pointer;" onclick="switchMethod('fiat')">
|
||||
<div style="display: flex; align-items: center; gap: 20px; margin-bottom: 25px;">
|
||||
<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: 24px;">
|
||||
<i class="fas fa-university"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="margin: 0;"><?php echo __('fiat_deposit', '法币充值'); ?></h3>
|
||||
<p style="margin: 5px 0 0; color: var(--text-muted); font-size: 14px;"><?php echo __('bank_transfer', '银行转账 / OTC'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="color: var(--text-muted); font-size: 13px; line-height: 2;">
|
||||
<div style="display: flex; align-items: center; gap: 10px;"><i class="fas fa-check-circle" style="color: var(--success-color); font-size: 12px;"></i> Support 20+ Global Currencies</div>
|
||||
<div style="display: flex; align-items: center; gap: 10px;"><i class="fas fa-check-circle" style="color: var(--success-color); font-size: 12px;"></i> Secure Bank-Grade Processing</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="card-usdt" style="background: var(--card-bg); padding: 35px; border-radius: 24px; border: 2px solid transparent; cursor: pointer;" onclick="switchMethod('usdt')">
|
||||
<div style="display: flex; align-items: center; gap: 20px; margin-bottom: 25px;">
|
||||
<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: 24px;">
|
||||
<i class="fas fa-coins"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="margin: 0;"><?php echo __('crypto_deposit', '数字货币充值'); ?></h3>
|
||||
<p style="margin: 5px 0 0; color: var(--text-muted); font-size: 14px;">Blockchain Transfer</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="color: var(--text-muted); font-size: 13px; line-height: 2;">
|
||||
<div style="display: flex; align-items: center; gap: 10px;"><i class="fas fa-check-circle" style="color: var(--success-color); font-size: 12px;"></i> USDT (TRC20, ERC20, BEP20)</div>
|
||||
<div style="display: flex; align-items: center; gap: 10px;"><i class="fas fa-check-circle" style="color: var(--success-color); font-size: 12px;"></i> Low Service Fees</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="fiat-section" style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color);">
|
||||
<form action="matching.php" method="POST" id="fiat-form" onsubmit="return handleDeposit(event, 'fiat')">
|
||||
<input type="hidden" name="type" value="fiat">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-bottom: 30px;">
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('select_currency', '选择币种'); ?></label>
|
||||
<select name="currency" id="currency-select" style="width: 100%; padding: 15px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; font-size: 1rem; outline: none;">
|
||||
<?php foreach ($fiat_rates as $code => $rate): ?>
|
||||
<option value="<?php echo $code; ?>" data-rate="<?php echo $rate; ?>"><?php echo $code; ?> - <?php echo $fiat_currencies_info[$code] ?? $code; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('deposit_amount', '充值金额'); ?></label>
|
||||
<input type="number" name="amount" id="amount-input" placeholder="Min. 100" required style="width: 100%; padding: 15px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; font-size: 1.2rem; font-weight: bold; outline: none;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px;">
|
||||
<div id="rate-display" style="padding: 20px; background: #161a1e; border-radius: 12px; border: 1px dashed var(--border-color); display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center;">
|
||||
<div style="color: var(--text-muted); font-size: 12px; margin-bottom: 5px;">Real-time Exchange Rate</div>
|
||||
<div style="font-weight: bold; font-size: 1.1rem;"><span id="rate-value">...</span> <span id="rate-currency">...</span> = 1 USDT</div>
|
||||
</div>
|
||||
<div id="result-display" style="padding: 20px; background: rgba(79, 172, 254, 0.05); border-radius: 12px; border: 1px solid rgba(79, 172, 254, 0.2); display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center;">
|
||||
<div style="color: var(--primary-color); font-size: 12px; margin-bottom: 5px;">You will receive</div>
|
||||
<div style="font-weight: 800; font-size: 1.5rem; color: var(--primary-color);"><span id="receive-amount">0.00</span> USDT</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 30px; padding: 25px; background: rgba(0,82,255,0.03); border-radius: 16px; border: 1px solid rgba(0,82,255,0.1); margin-bottom: 30px;">
|
||||
<div style="display: flex; align-items: center; gap: 10px; color: var(--primary-color); margin-bottom: 10px; font-weight: bold;">
|
||||
<i class="fas fa-info-circle"></i> Instructions
|
||||
</div>
|
||||
<p style="color: var(--text-muted); font-size: 14px; margin: 0; line-height: 1.6;">
|
||||
Please complete the payment within the time limit after matching. Once submitted, our customer service will verify your deposit.
|
||||
</p>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary" style="width: 100%; padding: 18px; font-size: 1.1rem; border-radius: 12px;">Match Account / 匹配充值账户</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="usdt-section" style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color); display: none;">
|
||||
<form action="matching.php" method="POST" id="usdt-form" onsubmit="return handleDeposit(event, 'usdt')">
|
||||
<input type="hidden" name="type" value="usdt">
|
||||
<div style="margin-bottom: 30px;">
|
||||
<label style="display: block; margin-bottom: 15px; color: var(--text-muted); font-size: 14px;">Select Network</label>
|
||||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px;">
|
||||
<label class="network-label active">
|
||||
<input type="radio" name="network" value="TRC20" checked style="display: none;">
|
||||
<div style="font-weight: bold;">TRC20</div>
|
||||
<div style="font-size: 11px; opacity: 0.7; margin-top: 4px;">≈ 2 Mins</div>
|
||||
</label>
|
||||
<label class="network-label">
|
||||
<input type="radio" name="network" value="ERC20" style="display: none;">
|
||||
<div style="font-weight: bold;">ERC20</div>
|
||||
<div style="font-size: 11px; opacity: 0.7; margin-top: 4px;">≈ 5 Mins</div>
|
||||
</label>
|
||||
<label class="network-label">
|
||||
<input type="radio" name="network" value="BEP20" style="display: none;">
|
||||
<div style="font-weight: bold;">BEP20</div>
|
||||
<div style="font-size: 11px; opacity: 0.7; margin-top: 4px;">≈ 1 Min</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 35px;">
|
||||
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;">Deposit Amount (USDT)</label>
|
||||
<input type="number" name="amount" placeholder="Min. 10" required style="width: 100%; padding: 15px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; font-size: 1.2rem; font-weight: bold; outline: none;">
|
||||
</div>
|
||||
<button type="submit" class="btn-primary" style="width: 100%; padding: 18px; font-size: 1.1rem; border-radius: 12px; background: var(--success-color);">Get Address / 获取充值地址</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Enhanced Deposit Matching Modal -->
|
||||
<div id="matching-modal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); display: none; align-items: center; justify-content: center; z-index: 10000; backdrop-filter: blur(10px);">
|
||||
<div style="background: #161a1e; width: 500px; border-radius: 32px; border: 1px solid rgba(255,255,255,0.1); overflow: hidden; box-shadow: 0 30px 70px rgba(0,0,0,0.8); position: relative;">
|
||||
|
||||
<div style="height: 6px; width: 100%; background: #2b3139;">
|
||||
<div id="modal-progress" style="height: 100%; width: 0%; background: var(--primary-color); transition: width 0.5s;"></div>
|
||||
</div>
|
||||
|
||||
<div style="padding: 30px; background: #1e2329; border-bottom: 1px solid #2b3139; display: flex; align-items: center; justify-content: space-between;">
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<div style="width: 45px; height: 45px; background: var(--primary-color); border-radius: 12px; display: flex; align-items: center; justify-content: center; color: white; box-shadow: 0 10px 20px rgba(0,82,255,0.3);">
|
||||
<i class="fas fa-headset"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 800; font-size: 18px; letter-spacing: 0.5px;">在线客服 / ONLINE SUPPORT</div>
|
||||
<div id="matching-status-text" style="font-size: 11px; color: #00c087; font-weight: bold;"><i class="fas fa-circle-notch fa-spin"></i> 正在安全握手 / Establishing Connection...</div>
|
||||
</div>
|
||||
</div>
|
||||
<button onclick="document.getElementById('matching-modal').style.display='none'" style="background: none; border: none; color: #848e9c; cursor: pointer; font-size: 20px;"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
|
||||
<div style="padding: 40px; text-align: center;">
|
||||
<div id="step-visual" style="margin-bottom: 30px; position: relative; height: 100px; display: flex; align-items: center; justify-content: center;">
|
||||
<div class="pulse-ring-large"></div>
|
||||
<div class="pulse-ring-small"></div>
|
||||
<i id="step-icon" class="fas fa-shield-alt" style="font-size: 50px; color: var(--primary-color); position: relative; z-index: 2; transition: 0.3s;"></i>
|
||||
</div>
|
||||
|
||||
<h3 id="step-title" style="margin: 0 0 10px 0; font-size: 1.6rem; font-weight: 800;">账户安全检测中...</h3>
|
||||
<p id="step-desc" style="color: var(--text-muted); font-size: 14px; line-height: 1.8; margin-bottom: 30px; height: 50px;">
|
||||
系统正在对您的交易环境进行全方位安全扫描,确保资金链路 100% 可信。
|
||||
</p>
|
||||
|
||||
<div style="background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.05); border-radius: 20px; padding: 25px; margin-bottom: 35px; text-align: left;">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 15px;">
|
||||
<div style="width: 24px; height: 24px; background: rgba(240, 185, 11, 0.1); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #f0b90b; font-size: 12px;">
|
||||
<i class="fas fa-lock"></i>
|
||||
</div>
|
||||
<div style="font-weight: bold; font-size: 14px; color: #f0b90b;">入金安全协议声明</div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #848e9c; line-height: 1.8;">
|
||||
• 本次充值将由官方承兑商提供实时结算支持。<br>
|
||||
• 严禁向任何非系统分配的账户进行转账。<br>
|
||||
• 确认订单后,系统将为您开启专属绿色通道。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="confirm-deposit-btn" disabled style="width: 100%; padding: 20px; background: #2b3139; border: none; color: #5e6673; border-radius: 16px; font-weight: 800; font-size: 1.1rem; cursor: not-allowed; transition: 0.3s; box-shadow: 0 15px 30px rgba(0,0,0,0.2);">
|
||||
请等待安全匹配 / PLEASE WAIT...
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.network-label { padding: 20px; background: #161a1e; border: 1px solid var(--border-color); border-radius: 16px; cursor: pointer; text-align: center; transition: 0.2s; }
|
||||
.network-label.active { border-color: var(--success-color); background: rgba(14,203,129,0.05); color: var(--success-color); }
|
||||
|
||||
.pulse-ring-large { position: absolute; width: 120px; height: 120px; border: 2px solid var(--primary-color); border-radius: 50%; animation: pulse-anim 2s infinite; opacity: 0; }
|
||||
.pulse-ring-small { position: absolute; width: 80px; height: 80px; border: 1px solid var(--primary-color); border-radius: 50%; animation: pulse-anim 2s infinite 0.5s; opacity: 0; }
|
||||
|
||||
@keyframes pulse-anim {
|
||||
0% { transform: scale(0.6); opacity: 0; }
|
||||
50% { opacity: 0.5; }
|
||||
100% { transform: scale(1.4); opacity: 0; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
let currentFormId = '';
|
||||
|
||||
const steps = [
|
||||
{
|
||||
title: "安全链路检测中...",
|
||||
desc: "系统正在对您的交易环境进行全方位安全扫描,确保资金链路 100% 可信。",
|
||||
icon: "fa-shield-alt",
|
||||
progress: 33,
|
||||
status: "Establishing Secure Link..."
|
||||
},
|
||||
{
|
||||
title: "匹配最优承兑商...",
|
||||
desc: "正在为您筛选当前响应最快、额度最充足的合规承兑商账户。",
|
||||
icon: "fa-user-check",
|
||||
progress: 66,
|
||||
status: "Matching Liquidator..."
|
||||
},
|
||||
{
|
||||
title: "准备就绪",
|
||||
desc: "安全验证已通过。点击下方按钮,进入专属客服对话窗口获取收款信息。",
|
||||
icon: "fa-check-double",
|
||||
progress: 100,
|
||||
status: "Ready for Connection"
|
||||
}
|
||||
];
|
||||
|
||||
function handleDeposit(event, type) {
|
||||
event.preventDefault();
|
||||
currentFormId = type + '-form';
|
||||
document.getElementById('matching-modal').style.display = 'flex';
|
||||
|
||||
let step = 0;
|
||||
const interval = setInterval(() => {
|
||||
if (step >= steps.length) {
|
||||
clearInterval(interval);
|
||||
const btn = document.getElementById('confirm-deposit-btn');
|
||||
btn.disabled = false;
|
||||
btn.style.background = 'var(--primary-color)';
|
||||
btn.style.color = 'white';
|
||||
btn.style.cursor = 'pointer';
|
||||
btn.innerText = '确认充值订单 / CONFIRM ORDER';
|
||||
return;
|
||||
}
|
||||
|
||||
const s = steps[step];
|
||||
document.getElementById('modal-progress').style.width = s.progress + '%';
|
||||
document.getElementById('matching-status-text').innerHTML = `<i class="fas fa-circle-notch fa-spin"></i> ${s.status}`;
|
||||
document.getElementById('step-title').innerText = s.title;
|
||||
document.getElementById('step-desc').innerText = s.desc;
|
||||
document.getElementById('step-icon').className = `fas ${s.icon}`;
|
||||
|
||||
step++;
|
||||
}, 1500);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
document.getElementById('confirm-deposit-btn').onclick = function() {
|
||||
this.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 正在连接客服...';
|
||||
this.disabled = true;
|
||||
setTimeout(() => {
|
||||
document.getElementById(currentFormId).submit();
|
||||
}, 800);
|
||||
};
|
||||
|
||||
function switchMethod(method) {
|
||||
if(method === 'fiat') {
|
||||
document.getElementById('fiat-section').style.display = 'block';
|
||||
document.getElementById('usdt-section').style.display = 'none';
|
||||
document.getElementById('card-fiat').style.borderColor = 'var(--primary-color)';
|
||||
document.getElementById('card-usdt').style.borderColor = 'transparent';
|
||||
} else {
|
||||
document.getElementById('fiat-section').style.display = 'none';
|
||||
document.getElementById('usdt-section').style.display = 'block';
|
||||
document.getElementById('card-fiat').style.borderColor = 'transparent';
|
||||
document.getElementById('card-usdt').style.borderColor = 'var(--success-color)';
|
||||
}
|
||||
}
|
||||
|
||||
const select = document.getElementById('currency-select');
|
||||
const amountInput = document.getElementById('amount-input');
|
||||
const rateVal = document.getElementById('rate-value');
|
||||
const rateCur = document.getElementById('rate-currency');
|
||||
const receiveAmount = document.getElementById('receive-amount');
|
||||
|
||||
function calculate() {
|
||||
const option = select.options[select.selectedIndex];
|
||||
const rate = parseFloat(option.getAttribute('data-rate'));
|
||||
const amount = parseFloat(amountInput.value) || 0;
|
||||
|
||||
rateVal.innerText = rate.toFixed(4);
|
||||
rateCur.innerText = select.value;
|
||||
|
||||
if (rate > 0) {
|
||||
receiveAmount.innerText = (amount / rate).toFixed(2);
|
||||
} else {
|
||||
receiveAmount.innerText = '0.00';
|
||||
}
|
||||
}
|
||||
|
||||
select.onchange = calculate;
|
||||
amountInput.oninput = calculate;
|
||||
calculate();
|
||||
|
||||
document.querySelectorAll('.network-label').forEach(label => {
|
||||
label.onclick = function() {
|
||||
document.querySelectorAll('.network-label').forEach(l => l.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
this.querySelector('input').checked = true;
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
90
fees.php
Normal file
90
fees.php
Normal 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;">< 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'; ?>
|
||||
110
footer.php
Normal file
110
footer.php
Normal file
@ -0,0 +1,110 @@
|
||||
<footer style="margin-top: 100px; background: #0b0e11; border-top: 1px solid var(--border-color); padding: 80px 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>
|
||||
NovaEx
|
||||
</div>
|
||||
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 1.5rem;"><?php echo __('footer_desc', 'NovaEx is a leading global digital asset trading platform, committed to providing secure, professional, and efficient crypto trading services.'); ?></p>
|
||||
<div style="display: flex; gap: 1.2rem; font-size: 1.2rem;">
|
||||
<a href="#" style="color: var(--text-muted); transition: color 0.3s;" onmouseover="this.style.color='#1DA1F2'" onmouseout="this.style.color='var(--text-muted)'"><i class="fab fa-twitter"></i></a>
|
||||
<a href="#" style="color: var(--text-muted); transition: color 0.3s;" onmouseover="this.style.color='#0088cc'" onmouseout="this.style.color='var(--text-muted)'"><i class="fab fa-telegram"></i></a>
|
||||
<a href="#" style="color: var(--text-muted); transition: color 0.3s;" onmouseover="this.style.color='#4267B2'" onmouseout="this.style.color='var(--text-muted)'"><i class="fab fa-facebook"></i></a>
|
||||
<a href="#" style="color: var(--text-muted); transition: color 0.3s;" onmouseover="this.style.color='#7289da'" onmouseout="this.style.color='var(--text-muted)'"><i class="fab fa-discord"></i></a>
|
||||
<a href="#" style="color: var(--text-muted); transition: color 0.3s;" onmouseover="this.style.color='#E1306C'" onmouseout="this.style.color='var(--text-muted)'"><i class="fab fa-instagram"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<h4 style="font-size: 18px; margin-bottom: 25px; color: white;"><?php echo __('about', '关于'); ?></h4>
|
||||
<div style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<a href="about.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-info-circle" style="width: 16px; color: #4facfe;"></i> <?php echo __('about_us', '关于我们'); ?>
|
||||
</a>
|
||||
<a href="careers.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-briefcase" style="width: 16px; color: #00f2fe;"></i> <?php echo __('careers', '职业介绍'); ?>
|
||||
</a>
|
||||
<a href="news.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-newspaper" style="width: 16px; color: #4facfe;"></i> <?php echo __('news', '新闻'); ?>
|
||||
</a>
|
||||
<a href="privacy.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-user-shield" style="width: 16px; color: #00f2fe;"></i> <?php echo __('legal_privacy', '法律与隐私'); ?>
|
||||
</a>
|
||||
<a href="terms.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-file-contract" style="width: 16px; color: #4facfe;"></i> <?php echo __('terms_service', '服务条款'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<h4 style="font-size: 18px; margin-bottom: 25px; color: white;"><?php echo __('products', '产品'); ?></h4>
|
||||
<div style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<a href="spot.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-coins" style="width: 16px; color: #f0b90b;"></i> <?php echo __('spot_trading', '现货交易'); ?>
|
||||
</a>
|
||||
<a href="futures.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-file-contract" style="width: 16px; color: #f0b90b;"></i> <?php echo __('futures_trading', '合约交易'); ?>
|
||||
</a>
|
||||
<a href="convert.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-bolt" style="width: 16px; color: #f0b90b;"></i> <?php echo __('flash_swap', '闪兑'); ?>
|
||||
</a>
|
||||
<a href="mining.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-pickaxe" style="width: 16px; color: #f0b90b;"></i> <?php echo __('staking', '挖矿'); ?>
|
||||
</a>
|
||||
<a href="profile.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-wallet" style="width: 16px; color: #f0b90b;"></i> <?php echo __('asset_management', '资产'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<h4 style="font-size: 18px; margin-bottom: 25px; color: white;"><?php echo __('support', '支持'); ?></h4>
|
||||
<div style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<a href="help.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-question-circle" style="width: 16px; color: #00c087;"></i> <?php echo __('help_center', '帮助中心'); ?>
|
||||
</a>
|
||||
<a href="request.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-paper-plane" style="width: 16px; color: #00c087;"></i> <?php echo __('submit_request', '提交请求'); ?>
|
||||
</a>
|
||||
<a href="api-docs.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-code" style="width: 16px; color: #00c087;"></i> <?php echo __('api_docs', 'API 文档'); ?>
|
||||
</a>
|
||||
<a href="fees.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-percentage" style="width: 16px; color: #00c087;"></i> <?php echo __('fee_schedule', '费率标准'); ?>
|
||||
</a>
|
||||
<a href="status.php" style="display: flex; align-items: center; gap: 10px; color: var(--text-muted); text-decoration: none; font-size: 14px;">
|
||||
<i class="fas fa-server" style="width: 16px; color: #00c087;"></i> <?php echo __('service_status', '服务状态'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="max-width: 1200px; margin: 60px auto 0; padding-top: 30px; border-top: 1px solid #1e2329; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 20px;">
|
||||
<div style="color: var(--text-muted); font-size: 13px;">
|
||||
© 2017-2026 NOVAEX.COM <?php echo __('all_rights_reserved', '版权所有'); ?>
|
||||
</div>
|
||||
<div style="display: flex; gap: 20px; color: var(--text-muted); font-size: 13px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; color: var(--success-color);">
|
||||
<i class="fas fa-check-circle"></i> <?php echo __('system_status_normal', '系统状态正常'); ?>
|
||||
</div>
|
||||
<span><?php echo __('cookie_policy', 'Cookie 政策'); ?></span>
|
||||
<span><?php echo __('security', '安全'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer a:hover { color: white !important; }
|
||||
</style>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
599
futures.php
Normal file
599
futures.php
Normal file
@ -0,0 +1,599 @@
|
||||
<?php
|
||||
session_start();
|
||||
include 'header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
$balance = 0;
|
||||
if ($user_id) {
|
||||
$stmt = db()->prepare("SELECT balance FROM users WHERE id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
$balance = $user['balance'] ?? 0;
|
||||
}
|
||||
?>
|
||||
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
:root {
|
||||
--bg-color: #0b0e11;
|
||||
--panel-bg: #161a1e;
|
||||
--border-color: #2b3139;
|
||||
--text-primary: #EAECEF;
|
||||
--text-secondary: #848e9c;
|
||||
--accent-color: #4facfe;
|
||||
--up-color: #00c087;
|
||||
--down-color: #f6465d;
|
||||
--input-bg: #1e2329;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-primary);
|
||||
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||
margin: 0;
|
||||
overflow: hidden; /* Prevent whole page scroll */
|
||||
height: 100vh;
|
||||
}
|
||||
.trading-layout {
|
||||
display: flex;
|
||||
height: calc(100vh - 64px);
|
||||
gap: 1px;
|
||||
background: var(--border-color);
|
||||
overflow: hidden;
|
||||
}
|
||||
.panel {
|
||||
background: var(--panel-bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
/* Left: Markets - Scrollable */
|
||||
.market-panel {
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.search-box { padding: 12px; border-bottom: 1px solid var(--border-color); width: 100%; position: sticky; top: 0; background: var(--panel-bg); z-index: 5; }
|
||||
.search-input-wrapper { position: relative; width: 100%; }
|
||||
.search-input-wrapper input { width: 100%; background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 6px 12px 6px 32px; border-radius: 4px; font-size: 13px; outline: none; display: block; }
|
||||
.search-input-wrapper i { position: absolute; left: 10px; top: 9px; color: var(--text-secondary); }
|
||||
.market-list-header { display: flex; padding: 8px 12px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); position: sticky; top: 57px; background: var(--panel-bg); z-index: 5; }
|
||||
.pair-item { display: flex; justify-content: space-between; padding: 10px 12px; cursor: pointer; transition: background 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
|
||||
.pair-item:hover { background: rgba(255,255,255,0.05); }
|
||||
.pair-item.active { background: rgba(79, 172, 254, 0.1); }
|
||||
|
||||
/* Center: Chart (Fixed) and scrollable content below */
|
||||
.center-panel {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.info-bar { height: 50px; display: flex; align-items: center; padding: 0 15px; gap: 20px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; background: var(--panel-bg); }
|
||||
.chart-container { height: 350px; background: var(--bg-color); flex-shrink: 0; border-bottom: 1px solid var(--border-color); }
|
||||
|
||||
/* Scrollable content below chart */
|
||||
.center-content-scroll {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.order-form-panel { padding: 20px; background: var(--panel-bg); border-bottom: 1px solid var(--border-color); }
|
||||
.order-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; }
|
||||
.margin-controls { display: flex; gap: 10px; margin-bottom: 15px; align-items: center; }
|
||||
.ctrl-btn { background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 5px 12px; border-radius: 4px; font-size: 12px; cursor: pointer; transition: all 0.2s; }
|
||||
.ctrl-btn.active { border-color: var(--accent-color); color: var(--accent-color); }
|
||||
.order-type-tabs { display: flex; gap: 15px; margin-left: 10px; }
|
||||
.order-type-btn { background: none; border: none; color: var(--text-secondary); font-size: 13px; cursor: pointer; padding: 0; }
|
||||
.order-type-btn.active { color: var(--accent-color); font-weight: bold; }
|
||||
.input-row { background: var(--input-bg); border: 1px solid var(--border-color); border-radius: 4px; display: flex; align-items: center; margin-bottom: 12px; padding: 8px 12px; }
|
||||
.input-label { color: var(--text-secondary); font-size: 13px; width: 60px; }
|
||||
.input-row input { flex: 1; background: transparent; border: none; color: white; text-align: right; outline: none; font-size: 14px; }
|
||||
.input-row input:disabled { color: var(--text-secondary); cursor: not-allowed; }
|
||||
.input-unit { color: var(--text-secondary); font-size: 12px; margin-left: 8px; width: 40px; text-align: right; }
|
||||
.slider-container { margin: 15px 0 25px 0; padding: 0 5px; position: relative; }
|
||||
.slider-marks { display: flex; justify-content: space-between; margin-top: -10px; position: relative; padding: 0 8px; pointer-events: none; }
|
||||
.mark-dot { width: 8px; height: 8px; background: var(--border-color); border: 2px solid var(--input-bg); border-radius: 50%; cursor: pointer; z-index: 2; pointer-events: auto; transform: translateY(-2px); }
|
||||
.mark-dot.active { background: var(--accent-color); border-color: var(--accent-color); }
|
||||
.slider-labels { display: flex; justify-content: space-between; margin-top: 8px; padding: 0 2px; }
|
||||
.label-item { color: var(--text-secondary); font-size: 10px; cursor: pointer; user-select: none; width: 25px; text-align: center; }
|
||||
.label-item.active { color: var(--text-primary); }
|
||||
.trade-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 20px; }
|
||||
.btn-trade { padding: 12px; border: none; border-radius: 4px; font-weight: bold; font-size: 15px; cursor: pointer; color: white; transition: opacity 0.2s; }
|
||||
.btn-trade:active { opacity: 0.8; }
|
||||
.btn-trade.buy { background: var(--up-color); }
|
||||
.btn-trade.sell { background: var(--down-color); }
|
||||
|
||||
.tabs-section { min-height: 400px; }
|
||||
.tabs-header { display: flex; border-bottom: 1px solid var(--border-color); padding: 0 15px; position: sticky; top: 0; background: var(--panel-bg); z-index: 9; }
|
||||
.tab-btn { background: none; border: none; color: var(--text-secondary); padding: 12px 15px; font-size: 14px; cursor: pointer; border-bottom: 2px solid transparent; }
|
||||
.tab-btn.active { color: var(--accent-color); border-bottom-color: var(--accent-color); }
|
||||
|
||||
/* Right Panel - Scrollable */
|
||||
.order-book-panel {
|
||||
width: 300px;
|
||||
flex-shrink: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.ob-header { padding: 10px 15px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; position: sticky; top: 0; background: var(--panel-bg); z-index: 5; }
|
||||
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; }
|
||||
.ob-bar { position: absolute; right: 0; top: 0; bottom: 0; z-index: 0; }
|
||||
.ob-val { z-index: 1; position: relative; }
|
||||
|
||||
input[type=range] { -webkit-appearance: none; width: 100%; background: transparent; margin: 0; padding: 0; }
|
||||
input[type=range]:focus { outline: none; }
|
||||
input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; background: var(--border-color); border-radius: 2px; }
|
||||
input[type=range]::-webkit-slider-thumb { height: 14px; width: 14px; border-radius: 50%; background: white; cursor: pointer; -webkit-appearance: none; margin-top: -5px; box-shadow: 0 0 2px rgba(0,0,0,0.5); border: 2px solid var(--accent-color); z-index: 3; position: relative; }
|
||||
|
||||
.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: 1000; }
|
||||
.modal-box { background: var(--panel-bg); padding: 30px; border-radius: 8px; width: 400px; border: 1px solid var(--border-color); }
|
||||
|
||||
::-webkit-scrollbar { width: 4px; }
|
||||
::-webkit-scrollbar-thumb { background: #333; border-radius: 10px; }
|
||||
|
||||
#pairs-list { }
|
||||
#asks-list, #bids-list { }
|
||||
</style>
|
||||
|
||||
<div class="trading-layout">
|
||||
<!-- Left Panel -->
|
||||
<div class="panel market-panel">
|
||||
<div class="search-box">
|
||||
<div class="search-input-wrapper">
|
||||
<i class="fas fa-search"></i>
|
||||
<input type="text" id="market-search" placeholder="搜索永续合约" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="market-list-header">
|
||||
<span style="flex: 1.5;">币对</span>
|
||||
<span style="flex: 1; text-align: right;">价格</span>
|
||||
<span style="flex: 1; text-align: right;">涨跌</span>
|
||||
</div>
|
||||
<div id="pairs-list"></div>
|
||||
</div>
|
||||
|
||||
<!-- Center Panel -->
|
||||
<div class="panel center-panel">
|
||||
<div class="info-bar">
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<img id="current-logo" src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/btc.png" width="24" height="24" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
||||
<div style="display: flex; flex-direction: column;">
|
||||
<span id="current-pair-display" style="font-size: 15px; font-weight: bold;">BTC/USDT 永续</span>
|
||||
<span id="leverage-display" style="font-size: 10px; color: var(--accent-color); cursor: pointer;" onclick="showLevModal()">20x</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="last-price" style="font-size: 16px; font-weight: bold; color: var(--up-color);">--</div>
|
||||
<div id="price-change" style="font-size: 12px;">--</div>
|
||||
<div style="display: flex; gap: 20px; margin-left: auto; font-size: 12px;">
|
||||
<div style="color: var(--text-secondary);">标记 <span id="mark-price" style="color: white; margin-left: 4px;">--</span></div>
|
||||
<div style="color: var(--text-secondary);">指数 <span id="index-price" style="color: white; margin-left: 4px;">--</span></div>
|
||||
<div style="color: var(--text-secondary);">24h额 <span id="vol-24h" style="color: white; margin-left: 4px;">--</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<div id="tv_chart_container" style="height: 100%;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Scrollable content below chart -->
|
||||
<div class="center-content-scroll">
|
||||
<div class="order-form-panel">
|
||||
<div class="margin-controls">
|
||||
<button class="ctrl-btn active" id="margin-isolated" onclick="setMargin('isolated')">逐仓</button>
|
||||
<button class="ctrl-btn" id="margin-cross" onclick="setMargin('cross')">全仓</button>
|
||||
<button class="ctrl-btn" onclick="showLevModal()"><span id="leverage-val">20</span>x</button>
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn active" id="order-type-limit" onclick="setOrderType('limit')">限价</button>
|
||||
<button class="order-type-btn" id="order-type-market" onclick="setOrderType('market')">市价</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="order-form-grid">
|
||||
<div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">合约开仓</span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="available-bal" style="color: white;"><?php echo number_format($balance, 2); ?></span> USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="order-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" id="market-price-display" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="order-amount" placeholder="0" step="1">
|
||||
<span class="input-unit">张</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<div class="input-row" style="flex: 1;">
|
||||
<span class="input-label" style="width: 40px;">止盈</span>
|
||||
<input type="number" id="tp-price" placeholder="价格">
|
||||
</div>
|
||||
<div class="input-row" style="flex: 1;">
|
||||
<span class="input-label" style="width: 40px;">止损</span>
|
||||
<input type="number" id="sl-price" placeholder="价格">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="slider-container" style="margin-top: 25px;">
|
||||
<input type="range" min="0" max="100" value="0" id="order-slider" oninput="updateFromSlider(this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider(0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(100)"></div>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider(0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider(25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider(50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider(75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider(100)">100%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">所需成本</span>
|
||||
<span><span id="order-cost">0.00</span> USDT</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="trade-btns">
|
||||
<button class="btn-trade buy" onclick="placeOrder('buy')">买入/开多</button>
|
||||
<button class="btn-trade sell" onclick="placeOrder('sell')">卖出/开空</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tabs-section">
|
||||
<div class="tabs-header">
|
||||
<button class="tab-btn active" id="tab-positions" onclick="switchTab(this, 'positions')">当前持仓</button>
|
||||
<button class="tab-btn" id="tab-orders" onclick="switchTab(this, 'open')">当前委托</button>
|
||||
<button class="tab-btn" id="tab-history" onclick="switchTab(this, 'history')">历史委托</button>
|
||||
</div>
|
||||
<div id="tab-content" style="padding: 0; min-height: 250px;">
|
||||
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||
<thead id="data-thead" style="color: var(--text-secondary); text-align: left; background: rgba(0,0,0,0.1);">
|
||||
</thead>
|
||||
<tbody id="data-tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div class="panel order-book-panel">
|
||||
<div class="ob-header"><span>价格(USDT)</span><span>数量(张)</span></div>
|
||||
<div id="asks-list" style="display: flex; flex-direction: column-reverse;"></div>
|
||||
<div id="mid-price-area" style="padding: 10px 15px; border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); text-align: center;">
|
||||
<div id="ob-mid-price" style="font-size: 16px; font-weight: bold;">--</div>
|
||||
<div style="font-size: 11px; color: var(--text-secondary);">指数价格 <span id="ob-index-price">--</span></div>
|
||||
</div>
|
||||
<div id="bids-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="lev-modal" class="modal">
|
||||
<div class="modal-box">
|
||||
<h3 style="margin: 0 0 20px 0;">调整杠杆</h3>
|
||||
<input type="range" min="1" max="125" value="20" id="lev-range" style="margin: 20px 0;" oninput="document.getElementById('lev-val-big').innerText = this.value + 'x'">
|
||||
<div id="lev-val-big" style="text-align: center; font-size: 36px; font-weight: bold; color: var(--accent-color); margin-bottom: 30px;">20x</div>
|
||||
<div style="display: flex; gap: 15px;">
|
||||
<button onclick="hideLevModal()" style="flex: 1; padding: 12px; background: #2b3139; border: none; color: white; border-radius: 4px; cursor: pointer;">取消</button>
|
||||
<button onclick="confirmLev()" style="flex: 1; padding: 12px; background: var(--accent-color); border: none; color: white; border-radius: 4px; cursor: pointer;">确认</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
|
||||
<script>
|
||||
let currentPair = 'BTCUSDT';
|
||||
let currentPrice = 0;
|
||||
let leverage = 20;
|
||||
let usdtBalance = <?php echo $balance; ?>;
|
||||
let marketData = {};
|
||||
let orderType = 'market';
|
||||
let activeTab = 'positions';
|
||||
const faceValue = 10;
|
||||
|
||||
const pairs = [
|
||||
'BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'AVAXUSDT', 'TRXUSDT', 'DOTUSDT',
|
||||
'LINKUSDT', 'PEPEUSDT', 'SHIBUSDT', 'NEARUSDT', 'LTCUSDT', 'MATICUSDT', 'UNIUSDT', 'ATOMUSDT', 'ETCUSDT', 'FILUSDT',
|
||||
'APTUSDT', 'ARBUSDT', 'OPUSDT', 'TIAUSDT', 'ORDIUSDT', 'SUIUSDT', 'RNDRUSDT', 'FETUSDT', 'AGIXUSDT', 'WLDUSDT'
|
||||
];
|
||||
|
||||
function initChart(symbol) {
|
||||
new TradingView.widget({
|
||||
"width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "15", "timezone": "Etc/UTC", "theme": "dark", "style": "1", "locale": "zh_CN", "container_id": "tv_chart_container", "backgroundColor": "#0b0e11", "gridColor": "rgba(42, 46, 57, 0.05)", "hide_side_toolbar": true, "allow_symbol_change": false, "save_image": false
|
||||
});
|
||||
}
|
||||
initChart(currentPair);
|
||||
|
||||
let ws;
|
||||
function connectWS() {
|
||||
if (ws) ws.close();
|
||||
const streams = pairs.map(p => p.toLowerCase() + '@ticker').join('/');
|
||||
ws = new WebSocket(`wss://fstream.binance.com/ws/${streams}`);
|
||||
ws.onmessage = (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
marketData[data.s] = data;
|
||||
renderPairs();
|
||||
if (data.s === currentPair) {
|
||||
updateUIWithData(data);
|
||||
}
|
||||
if (activeTab === 'positions') fetchOrders();
|
||||
};
|
||||
}
|
||||
connectWS();
|
||||
|
||||
function updateUIWithData(data) {
|
||||
currentPrice = parseFloat(data.c);
|
||||
document.getElementById('last-price').innerText = currentPrice.toLocaleString();
|
||||
document.getElementById('last-price').style.color = data.P >= 0 ? 'var(--up-color)' : 'var(--down-color)';
|
||||
document.getElementById('price-change').innerText = (data.P >= 0 ? '+' : '') + data.P + '%';
|
||||
document.getElementById('price-change').style.color = data.P >= 0 ? 'var(--up-color)' : 'var(--down-color)';
|
||||
document.getElementById('mark-price').innerText = currentPrice.toLocaleString();
|
||||
document.getElementById('index-price').innerText = (currentPrice * 0.9998).toFixed(2);
|
||||
document.getElementById('vol-24h').innerText = parseFloat(data.q).toLocaleString();
|
||||
document.getElementById('ob-mid-price').innerText = currentPrice.toLocaleString();
|
||||
document.getElementById('ob-index-price').innerText = (currentPrice * 0.9998).toFixed(2);
|
||||
|
||||
document.getElementById('market-price-display').value = currentPrice.toFixed(2);
|
||||
|
||||
updateOrderBook();
|
||||
|
||||
const op = document.getElementById('order-price');
|
||||
if (!op.value || op.getAttribute('data-auto') === 'true') {
|
||||
op.value = currentPrice;
|
||||
op.setAttribute('data-auto', 'true');
|
||||
}
|
||||
|
||||
if (orderType === 'market') updateFromSlider(document.getElementById('order-slider').value);
|
||||
}
|
||||
|
||||
function renderPairs() {
|
||||
const list = document.getElementById('pairs-list');
|
||||
if (!list) return;
|
||||
const search = document.getElementById('market-search').value.toUpperCase();
|
||||
let html = '';
|
||||
pairs.forEach(p => {
|
||||
if (search && !p.includes(search)) return;
|
||||
const d = marketData[p] || {c: 0, P: 0};
|
||||
const name = p.replace('USDT', '');
|
||||
html += `
|
||||
<div class="pair-item ${currentPair === p ? 'active' : ''}" onclick="switchPair('${p}')">
|
||||
<div style="display: flex; align-items: center; gap: 8px; flex: 1.5;">
|
||||
<img src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png" width="18" height="18" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
||||
<div>
|
||||
<div style="font-weight: bold; font-size: 13px;">${name}/USDT</div>
|
||||
<div style="font-size: 10px; color: var(--text-secondary);">永续</div>
|
||||
</div>
|
||||
</div>
|
||||
<span style="flex: 1; text-align: right; font-size: 13px;">${parseFloat(d.c).toLocaleString()}</span>
|
||||
<span style="flex: 1; text-align: right; font-size: 13px; color: ${d.P >= 0 ? 'var(--up-color)' : 'var(--down-color)'}">${(d.P >= 0 ? '+' : '') + d.P}%</span>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
list.innerHTML = html;
|
||||
}
|
||||
|
||||
function switchPair(p) {
|
||||
currentPair = p;
|
||||
const name = p.replace('USDT', '');
|
||||
document.getElementById('current-pair-display').innerText = name + '/USDT 永续';
|
||||
document.getElementById('current-logo').src = `https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png`;
|
||||
|
||||
if (marketData[p]) {
|
||||
updateUIWithData(marketData[p]);
|
||||
} else {
|
||||
document.getElementById('last-price').innerText = '--';
|
||||
document.getElementById('order-price').value = '';
|
||||
}
|
||||
|
||||
document.getElementById('order-price').setAttribute('data-auto', 'true');
|
||||
document.getElementById('order-amount').value = '';
|
||||
document.getElementById('order-slider').value = 0;
|
||||
document.getElementById('order-cost').innerText = '0.00';
|
||||
document.getElementById('tp-price').value = '';
|
||||
document.getElementById('sl-price').value = '';
|
||||
updateSliderMarks(0);
|
||||
initChart(p);
|
||||
renderPairs();
|
||||
}
|
||||
|
||||
function setOrderType(type) {
|
||||
orderType = type;
|
||||
document.getElementById('order-type-limit').classList.toggle('active', type === 'limit');
|
||||
document.getElementById('order-type-market').classList.toggle('active', type === 'market');
|
||||
document.getElementById('price-row').style.display = type === 'limit' ? 'flex' : 'none';
|
||||
document.getElementById('market-price-row').style.display = type === 'market' ? 'flex' : 'none';
|
||||
updateFromSlider(document.getElementById('order-slider').value);
|
||||
}
|
||||
|
||||
function updateOrderBook() {
|
||||
const asks = document.getElementById('asks-list');
|
||||
const bids = document.getElementById('bids-list');
|
||||
if (!asks || !bids) return;
|
||||
let asksHtml = ''; let bidsHtml = '';
|
||||
const step = currentPrice * 0.0001;
|
||||
for(let i=0; i<15; i++) {
|
||||
const askPrice = currentPrice + (i + 1) * step;
|
||||
const bidPrice = currentPrice - (i + 1) * step;
|
||||
asksHtml += `<div class="ob-row"><div class="ob-bar" style="background: rgba(246, 70, 93, 0.1); width: ${Math.random()*100}%;"></div><span class="ob-val" style="color: var(--down-color);">${askPrice.toFixed(1)}</span><span class="ob-val">${(Math.random()*200).toFixed(0)}</span></div>`;
|
||||
bidsHtml += `<div class="ob-row"><div class="ob-bar" style="background: rgba(0, 192, 135, 0.1); width: ${Math.random()*100}%;"></div><span class="ob-val" style="color: var(--up-color);">${bidPrice.toFixed(1)}</span><span class="ob-val">${(Math.random()*200).toFixed(0)}</span></div>`;
|
||||
}
|
||||
asks.innerHTML = asksHtml; bids.innerHTML = bidsHtml;
|
||||
}
|
||||
|
||||
function updateFromSlider(val) {
|
||||
val = parseFloat(val);
|
||||
const cost = usdtBalance * (val / 100);
|
||||
const amount = Math.floor((cost * leverage) / faceValue);
|
||||
document.getElementById('order-amount').value = amount > 0 ? amount : '';
|
||||
document.getElementById('order-cost').innerText = cost.toFixed(2);
|
||||
updateSliderMarks(val);
|
||||
}
|
||||
|
||||
function updateFromInputs() {
|
||||
const amount = parseFloat(document.getElementById('order-amount').value) || 0;
|
||||
const cost = (amount * faceValue) / leverage;
|
||||
document.getElementById('order-cost').innerText = cost.toFixed(2);
|
||||
let percentage = usdtBalance > 0 ? (cost / usdtBalance) * 100 : 0;
|
||||
percentage = Math.min(Math.max(percentage, 0), 100);
|
||||
document.getElementById('order-slider').value = percentage;
|
||||
updateSliderMarks(percentage);
|
||||
}
|
||||
|
||||
function updateSliderMarks(val) {
|
||||
document.querySelectorAll('.mark-dot').forEach((m, i) => { if (i * 25 <= val) m.classList.add('active'); else m.classList.remove('active'); });
|
||||
document.querySelectorAll('.label-item').forEach((l, i) => { if (Math.abs(i * 25 - val) < 5) l.classList.add('active'); else l.classList.remove('active'); });
|
||||
}
|
||||
|
||||
function setSlider(val) { document.getElementById('order-slider').value = val; updateFromSlider(val); }
|
||||
|
||||
document.getElementById('order-amount').addEventListener('input', updateFromInputs);
|
||||
document.getElementById('order-price').addEventListener('input', (e) => {
|
||||
e.target.setAttribute('data-auto', 'false');
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
function showLevModal() {
|
||||
document.getElementById('lev-range').value = leverage;
|
||||
document.getElementById('lev-val-big').innerText = leverage + 'x';
|
||||
document.getElementById('lev-modal').style.display = 'flex';
|
||||
}
|
||||
function hideLevModal() { document.getElementById('lev-modal').style.display = 'none'; }
|
||||
function confirmLev() {
|
||||
leverage = document.getElementById('lev-range').value;
|
||||
document.getElementById('leverage-display').innerText = leverage + 'x';
|
||||
document.getElementById('leverage-val').innerText = leverage;
|
||||
hideLevModal();
|
||||
updateFromSlider(document.getElementById('order-slider').value);
|
||||
}
|
||||
|
||||
function setMargin(type) {
|
||||
document.querySelectorAll('.ctrl-btn').forEach(btn => { if (btn.innerText.includes('仓')) btn.classList.toggle('active', btn.id.includes(type)); });
|
||||
}
|
||||
|
||||
async function placeOrder(side) {
|
||||
const amount = parseFloat(document.getElementById('order-amount').value);
|
||||
if (!amount) return alert('请输入数量');
|
||||
const price = orderType === 'limit' ? parseFloat(document.getElementById('order-price').value || currentPrice) : currentPrice;
|
||||
const tp = document.getElementById('tp-price').value;
|
||||
const sl = document.getElementById('sl-price').value;
|
||||
|
||||
const response = await fetch('api/place_order.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
symbol: currentPair, type: 'futures', side: side,
|
||||
order_type: orderType, price: price, amount: amount, leverage: leverage, total: amount * faceValue,
|
||||
tp_price: tp, sl_price: sl
|
||||
})
|
||||
});
|
||||
const res = await response.json();
|
||||
if (res.success) { alert('下单成功'); fetchOrders(); updateBalance(); } else { alert('失败: ' + res.error); }
|
||||
}
|
||||
|
||||
async function updateBalance() {
|
||||
const resp = await fetch('api/get_assets.php');
|
||||
const res = await resp.json();
|
||||
if (res.success) {
|
||||
const usdt = res.data.find(a => a.symbol === 'USDT');
|
||||
if (usdt) {
|
||||
usdtBalance = parseFloat(usdt.amount);
|
||||
document.getElementById('available-bal').innerText = usdtBalance.toFixed(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchOrders() {
|
||||
const response = await fetch(`api/get_orders.php?type=futures&status=${activeTab}`);
|
||||
const res = await response.json();
|
||||
const tbody = document.getElementById('data-tbody');
|
||||
const thead = document.getElementById('data-thead');
|
||||
if (!tbody || !thead) return;
|
||||
|
||||
if (activeTab === 'positions') {
|
||||
thead.innerHTML = `<tr><th style="padding: 12px;">合约</th><th style="padding: 12px;">仓位</th><th style="padding: 12px;">开仓价</th><th style="padding: 12px;">当前价</th><th style="padding: 12px;">盈亏</th><th style="padding: 12px; text-align: right;">操作</th></tr>`;
|
||||
} else {
|
||||
thead.innerHTML = `<tr><th style="padding: 12px;">时间</th><th style="padding: 12px;">合约</th><th style="padding: 12px;">方向</th><th style="padding: 12px;">委托价</th><th style="padding: 12px;">数量(张)</th><th style="padding: 12px;">状态</th><th style="padding: 12px; text-align: right;">操作</th></tr>`;
|
||||
}
|
||||
|
||||
if (res.success && res.data.length > 0) {
|
||||
let html = '';
|
||||
res.data.forEach(o => {
|
||||
if (activeTab === 'positions') {
|
||||
const price = marketData[o.symbol] ? parseFloat(marketData[o.symbol].c) : o.price;
|
||||
const nominal = o.amount * faceValue;
|
||||
let pnl = 0;
|
||||
if (o.side === 'buy') pnl = (price / o.price - 1) * nominal;
|
||||
else pnl = (1 - price / o.price) * nominal;
|
||||
|
||||
const color = o.side === 'buy' ? 'var(--up-color)' : 'var(--down-color)';
|
||||
html += `
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 12px;"><div style="font-weight: bold;">${o.symbol}</div><div style="font-size: 10px; color: var(--text-secondary);">永续</div></td>
|
||||
<td style="padding: 12px;"><span style="color: ${color};">${o.side === 'buy' ? '做多' : '做空'} ${o.leverage}x</span><br>${o.amount} 张</td>
|
||||
<td style="padding: 12px;">${parseFloat(o.price).toLocaleString()}</td>
|
||||
<td style="padding: 12px;">${price.toLocaleString()}</td>
|
||||
<td style="padding: 12px; color: ${pnl >= 0 ? 'var(--up-color)' : 'var(--down-color)'}">${(pnl >= 0 ? '+' : '') + pnl.toFixed(2)} USDT</td>
|
||||
<td style="padding: 12px; text-align: right;">
|
||||
<button onclick="closePosition(${o.id})" style="background: none; border: 1px solid var(--text-secondary); color: white; padding: 4px 10px; border-radius: 4px; cursor: pointer; font-size: 12px;">平仓</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
} else {
|
||||
html += `
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 12px;">${o.created_at}</td>
|
||||
<td style="padding: 12px; font-weight: bold;">${o.symbol}</td>
|
||||
<td style="padding: 12px; color: ${o.side === 'buy' ? 'var(--up-color)' : 'var(--down-color)'}">${o.side === 'buy' ? '开多' : '开空'}</td>
|
||||
<td style="padding: 12px;">${parseFloat(o.price).toLocaleString()}</td>
|
||||
<td style="padding: 12px;">${o.amount}</td>
|
||||
<td style="padding: 12px;">${o.status === 'open' ? '委托中' : '已完成'}</td>
|
||||
<td style="padding: 12px; text-align: right;">
|
||||
${o.status === 'open' ? `<button onclick="closePosition(${o.id})" style="background: none; border: 1px solid var(--down-color); color: var(--down-color); padding: 2px 8px; border-radius: 4px; cursor: pointer;">取消</button>` : '--'}
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
});
|
||||
tbody.innerHTML = html;
|
||||
} else {
|
||||
tbody.innerHTML = `<tr><td colspan="7" style="text-align: center; padding: 50px; color: var(--text-secondary); opacity: 0.5;">暂无记录</td></tr>`;
|
||||
}
|
||||
}
|
||||
|
||||
function switchTab(btn, tab) {
|
||||
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
activeTab = tab;
|
||||
fetchOrders();
|
||||
}
|
||||
|
||||
async function closePosition(id) {
|
||||
if (!confirm('确定执行此操作?')) return;
|
||||
const resp = await fetch('api/cancel_order.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({order_id: id})
|
||||
});
|
||||
if ((await resp.json()).success) { fetchOrders(); updateBalance(); }
|
||||
}
|
||||
|
||||
document.getElementById('market-search').addEventListener('input', renderPairs);
|
||||
fetchOrders();
|
||||
updateBalance();
|
||||
setInterval(() => { if (activeTab === 'positions') fetchOrders(); }, 3000);
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
110
header.php
Normal file
110
header.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php require_once 'includes/i18n.php'; ?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?php echo $lang; ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NovaEx | Leading Crypto Exchange</title>
|
||||
<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">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>
|
||||
.logo-text { font-size: 1.8rem; font-weight: 800; color: white; letter-spacing: -1px; display: flex; align-items: center; gap: 8px; font-family: 'Inter', sans-serif; }
|
||||
.logo-svg { width: 32px; height: 32px; fill: #4facfe; }
|
||||
|
||||
/* Floating CS Chat */
|
||||
.floating-service { position: fixed; bottom: 30px; right: 30px; width: 60px; height: 60px; background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-size: 1.5rem; cursor: pointer; box-shadow: 0 10px 25px rgba(0,242,254,0.3); z-index: 1000; transition: transform 0.3s ease; }
|
||||
.floating-service:hover { transform: scale(1.1) rotate(5deg); }
|
||||
|
||||
#cs-chat-window { position: fixed; bottom: 100px; right: 30px; width: 380px; height: 500px; background: #161a1e; border: 1px solid #2b3139; border-radius: 16px; display: none; flex-direction: column; box-shadow: 0 20px 40px rgba(0,0,0,0.5); z-index: 1001; overflow: hidden; }
|
||||
#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; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="floating-service" onclick="toggleCSChat()" title="Customer Service">
|
||||
<i class="fas fa-headset"></i>
|
||||
</div>
|
||||
|
||||
<div id="cs-chat-window">
|
||||
<div class="chat-header">
|
||||
<span>NovaEx Support</span>
|
||||
<i class="fas fa-times" onclick="toggleCSChat()" style="cursor: pointer;"></i>
|
||||
</div>
|
||||
<iframe src="chat_iframe.php"></iframe>
|
||||
</div>
|
||||
|
||||
<nav class="navbar">
|
||||
<div style="display: flex; align-items: center; gap: 2rem;">
|
||||
<a href="index.php" style="text-decoration: none;">
|
||||
<div class="logo-text">
|
||||
<svg class="logo-svg" viewBox="0 0 100 100">
|
||||
<rect x="10" y="10" width="80" height="80" rx="20" fill="url(#grad1)"/>
|
||||
<path d="M30 30 L70 70 M70 30 L30 70" stroke="white" stroke-width="12" stroke-linecap="round"/>
|
||||
<defs>
|
||||
<linearGradient id="grad1" 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>
|
||||
NovaEx
|
||||
</div>
|
||||
</a>
|
||||
<div class="nav-links">
|
||||
<a href="index.php"><i class="fas fa-home nav-link-icon"></i><?php echo __('nav_home', '首页'); ?></a>
|
||||
<a href="markets.php"><i class="fas fa-chart-line nav-link-icon"></i><?php echo __('nav_market', '行情'); ?></a>
|
||||
<a href="spot.php"><i class="fas fa-coins nav-link-icon"></i><?php echo __('nav_spot', '现货交易'); ?></a>
|
||||
<a href="futures.php"><i class="fas fa-file-contract nav-link-icon"></i><?php echo __('nav_futures', '合约交易'); ?></a>
|
||||
<a href="convert.php"><i class="fas fa-bolt nav-link-icon"></i><?php echo __('nav_convert', '闪兑'); ?></a>
|
||||
<a href="mining.php"><i class="fas fa-pickaxe nav-link-icon"></i><?php echo __('nav_mining', '挖矿'); ?></a>
|
||||
<a href="profile.php"><i class="fas fa-wallet nav-link-icon"></i><?php echo __('nav_assets', '资产'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 1.5rem; align-items: center;">
|
||||
<div class="dropdown">
|
||||
<a href="#" style="color: white; display: flex; align-items: center; gap: 5px;">
|
||||
<i class="fas fa-globe"></i>
|
||||
<span style="font-size: 13px;"><?php echo strtoupper($lang); ?></span>
|
||||
</a>
|
||||
<div class="dropdown-content" style="right: 0; min-width: 120px;">
|
||||
<a href="?lang=en" style="display: flex; align-items: center; gap: 10px;">
|
||||
<img src="https://flagcdn.com/w20/us.png" width="20" alt="English"> English
|
||||
</a>
|
||||
<a href="?lang=zh" style="display: flex; align-items: center; gap: 10px;">
|
||||
<img src="https://flagcdn.com/w20/cn.png" width="20" alt="Chinese"> 简体中文
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if(isset($_SESSION['user_id'])): ?>
|
||||
<div class="dropdown">
|
||||
<a href="#" style="color: white; display: flex; align-items: center; gap: 8px;">
|
||||
<i class="fas fa-user-circle" style="font-size: 1.5rem;"></i>
|
||||
<i class="fas fa-chevron-down" style="font-size: 10px;"></i>
|
||||
</a>
|
||||
<div class="dropdown-content user-profile-dropdown" style="right: 0;">
|
||||
<div class="user-info-header">
|
||||
<div style="font-weight: bold; margin-bottom: 4px;"><?php echo $_SESSION['username'] ?? 'User'; ?></div>
|
||||
<div class="uid-badge">UID: <?php echo $_SESSION['uid'] ?? '------'; ?></div>
|
||||
</div>
|
||||
<a href="profile.php"><i class="fas fa-id-card" style="color: #4facfe;"></i> <?php echo __('nav_profile', '个人中心'); ?></a>
|
||||
<a href="deposit.php"><i class="fas fa-plus-circle" style="color: #00f2fe;"></i> <?php echo __('nav_deposit', '充值'); ?></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" style="color: white; text-decoration: none; font-size: 14px;"><?php echo __('nav_login'); ?></a>
|
||||
<a href="register.php" class="btn-primary"><?php echo __('nav_register'); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<script>
|
||||
function toggleCSChat() {
|
||||
const chat = document.getElementById('cs-chat-window');
|
||||
chat.style.display = chat.style.display === 'flex' ? 'none' : 'flex';
|
||||
}
|
||||
</script>
|
||||
54
help.php
Normal file
54
help.php
Normal 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'; ?>
|
||||
33
includes/currency_helper.php
Normal file
33
includes/currency_helper.php
Normal 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;
|
||||
}
|
||||
338
includes/i18n.php
Normal file
338
includes/i18n.php
Normal file
@ -0,0 +1,338 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
$translations = [
|
||||
'en' => [
|
||||
'nav_home' => 'Home',
|
||||
'nav_market' => 'Markets',
|
||||
'nav_trade' => 'Trade',
|
||||
'nav_spot' => 'Spot',
|
||||
'nav_futures' => 'Futures',
|
||||
'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',
|
||||
'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',
|
||||
'download_qr_tip' => 'Download App & Get Up to 50 USDT',
|
||||
'market_trends' => 'Market Trends',
|
||||
'view_more_markets' => 'View More Markets',
|
||||
'why_choose_us' => 'Why Choose Us?',
|
||||
'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' => 'Industry 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.',
|
||||
'partners' => 'Our 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',
|
||||
'personal_center' => 'Personal Center',
|
||||
'uid' => 'UID',
|
||||
'credit_score' => 'Credit Score',
|
||||
'kyc_status' => 'Identity Verification',
|
||||
'kyc_none' => 'Not Verified',
|
||||
'kyc_pending' => 'Pending Review',
|
||||
'kyc_approved' => 'Verified',
|
||||
'kyc_rejected' => 'Verification Failed',
|
||||
'kyc_submit' => 'Submit Verification',
|
||||
'total_balance' => 'Total Balance',
|
||||
'available_balance' => 'Available',
|
||||
'order_book' => 'Order Book',
|
||||
'trade_panel' => 'Trade Panel',
|
||||
'k_line' => 'K-Line',
|
||||
'open_orders' => 'Open Orders',
|
||||
'order_history' => 'Order History',
|
||||
'trade_history' => 'Trade History',
|
||||
'funds_flow' => 'Funds Flow',
|
||||
'current_positions' => 'Current Positions',
|
||||
'limit' => 'Limit',
|
||||
'market' => 'Market',
|
||||
'price' => 'Price',
|
||||
'amount' => 'Amount',
|
||||
'total' => 'Total',
|
||||
'buy' => 'Buy',
|
||||
'sell' => 'Sell',
|
||||
'leverage' => 'Leverage',
|
||||
'tp_sl' => 'TP/SL',
|
||||
'take_profit' => 'Take Profit',
|
||||
'stop_loss' => 'Stop Loss',
|
||||
'cost' => 'Cost',
|
||||
'open_long' => 'Open Long',
|
||||
'open_short' => 'Open Short',
|
||||
'security_settings' => 'Security Settings',
|
||||
'asset_details' => 'Asset Details',
|
||||
'transaction_records' => 'Transaction Records',
|
||||
'level' => 'Level',
|
||||
'crypto_markets' => 'Crypto Markets',
|
||||
'24h_volume' => '24h Volume',
|
||||
'fear_greed' => 'Fear & Greed Index',
|
||||
'btc_dominance' => 'BTC Dominance',
|
||||
'favorites' => 'Favorites',
|
||||
'all_crypto' => 'All Crypto',
|
||||
'asset' => 'Asset',
|
||||
'24h_high_low' => '24h High/Low',
|
||||
'deposit_assets' => 'Deposit Assets',
|
||||
'deposit_method_tip' => 'Select your preferred method to fund your account.',
|
||||
'fiat_deposit' => 'Fiat Deposit',
|
||||
'crypto_deposit' => 'Crypto Deposit',
|
||||
'bank_transfer' => 'Local Bank Transfer',
|
||||
'blockchain_transfer' => 'Blockchain Transfer',
|
||||
'support_20_global' => 'Support 20+ Global Currencies',
|
||||
'safe_compliant' => 'Safe & Compliant Channel',
|
||||
'fast_processing' => '24/7 Fast Processing',
|
||||
'no_service_fee' => 'No Service Fee',
|
||||
'select_currency' => 'Select Currency',
|
||||
'deposit_amount' => 'Deposit Amount',
|
||||
'matching_instructions' => 'Matching Instructions',
|
||||
'matching_tip' => 'Our intelligent matching system will pair you with a verified merchant. After confirming, you will receive the bank account details. Please complete the transfer within the time limit.',
|
||||
'match_now' => 'Match Merchant Now',
|
||||
'select_network' => 'Select Network',
|
||||
'get_address' => 'Get Deposit Address',
|
||||
'withdraw_assets' => 'Withdraw Assets',
|
||||
'withdraw_tip' => 'Securely withdraw USDT to your external wallet.',
|
||||
'withdraw_address' => 'Withdrawal Address',
|
||||
'trading_password' => 'Trading Password',
|
||||
'submit_withdrawal' => 'Submit Withdrawal',
|
||||
'withdrawal_tips' => 'Withdrawal Tips',
|
||||
'withdrawal_tip_1' => 'Double check the destination address. We cannot recover funds sent to wrong addresses.',
|
||||
'withdrawal_tip_2' => 'TRC20 withdrawals usually take 5-10 minutes to arrive.',
|
||||
'withdrawal_tip_3' => 'Withdrawals are processed manually for security audits during peak hours.',
|
||||
'withdrawal_tip_4' => 'Handling fee: 1 USDT per transaction.',
|
||||
'recent_history' => 'Recent History',
|
||||
'no_records' => 'No records found',
|
||||
'max' => 'MAX',
|
||||
'customer_service' => 'Online Support',
|
||||
'chat_welcome' => 'Hello! How can we help you today?',
|
||||
'type_message' => 'Type your message...',
|
||||
'matching_account' => 'Matching Payment Account...',
|
||||
'matching_desc' => 'Our system is matching a secure local account for your deposit. Please wait a moment.',
|
||||
'crypto' => 'Cryptocurrency',
|
||||
'search_market' => 'Search Market',
|
||||
'more_pairs' => 'More Pairs',
|
||||
'limit_order' => 'Limit',
|
||||
'market_order' => 'Market',
|
||||
'available' => 'Available',
|
||||
'buy_long' => 'Buy / Long',
|
||||
'sell_short' => 'Sell / Short',
|
||||
'open_position' => 'Open',
|
||||
'close_position' => 'Close',
|
||||
'cross' => 'Cross',
|
||||
'isolated' => 'Isolated',
|
||||
'positions' => 'Positions',
|
||||
'no_positions' => 'No positions found',
|
||||
'perpetual' => 'Perpetual',
|
||||
'delivery' => 'Delivery',
|
||||
'fee' => 'Fee',
|
||||
'max_open' => 'Max Open',
|
||||
'time' => 'Time',
|
||||
'pair' => 'Pair',
|
||||
'side' => 'Side',
|
||||
'filled' => 'Filled',
|
||||
'status' => 'Status',
|
||||
'load_more' => 'Load More',
|
||||
],
|
||||
'zh' => [
|
||||
'nav_home' => '首页',
|
||||
'nav_market' => '行情',
|
||||
'nav_trade' => '交易',
|
||||
'nav_spot' => '现货交易',
|
||||
'nav_futures' => '合约交易',
|
||||
'nav_mining' => '挖矿',
|
||||
'nav_convert' => '闪兑',
|
||||
'nav_assets' => '资产',
|
||||
'nav_total_assets' => '总资产',
|
||||
'nav_deposit' => '充值',
|
||||
'nav_withdraw' => '提现',
|
||||
'nav_login' => '登录',
|
||||
'nav_register' => '注册',
|
||||
'nav_profile' => '个人中心',
|
||||
'nav_logout' => '退出登录',
|
||||
'hero_title' => '在 NovaEx 购买、交易和持有 350 多种加密货币',
|
||||
'hero_subtitle' => '加入全球最大的加密货币交易所,享受最低的费用和最好的安全性。',
|
||||
'btn_start' => '立即开始',
|
||||
'btn_download' => '下载应用',
|
||||
'download_qr_tip' => '下载应用并获得高达 50 USDT 的奖励',
|
||||
'market_trends' => '市场趋势',
|
||||
'view_more_markets' => '查看更多市场',
|
||||
'why_choose_us' => '为什么选择我们?',
|
||||
'secure_storage' => '安全存储',
|
||||
'secure_storage_desc' => '我们将绝大部分数字资产存储在安全的离线存储中。',
|
||||
'protected_insurance' => '保险保护',
|
||||
'protected_insurance_desc' => '存储在我们服务器上的加密货币受我们的保险政策保护。',
|
||||
'industry_best_practices' => '行业最佳实践',
|
||||
'industry_best_practices_desc' => 'NovaEx 支持多种最流行的数字货币。',
|
||||
'platform_desc' => '我们的平台为零售和机构交易者提供具有先进功能和稳健基础设施的无缝交易体验。',
|
||||
'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' => '系统状态:正常',
|
||||
'personal_center' => '个人中心',
|
||||
'uid' => 'UID',
|
||||
'credit_score' => '信用分',
|
||||
'kyc_status' => '身份认证',
|
||||
'kyc_none' => '未认证',
|
||||
'kyc_pending' => '审核中',
|
||||
'kyc_approved' => '已认证',
|
||||
'kyc_rejected' => '认证失败',
|
||||
'kyc_submit' => '提交认证',
|
||||
'total_balance' => '总资产',
|
||||
'available_balance' => '可用余额',
|
||||
'order_book' => '订单簿',
|
||||
'trade_panel' => '下单面板',
|
||||
'k_line' => 'K线图',
|
||||
'open_orders' => '当前委托',
|
||||
'order_history' => '历史委托',
|
||||
'trade_history' => '成交记录',
|
||||
'funds_flow' => '资金流水',
|
||||
'current_positions' => '当前持仓',
|
||||
'limit' => '限价',
|
||||
'market' => '市价',
|
||||
'price' => '价格',
|
||||
'amount' => '数量',
|
||||
'total' => '总额',
|
||||
'buy' => '买入',
|
||||
'sell' => '卖出',
|
||||
'leverage' => '杠杆',
|
||||
'tp_sl' => '止盈止损',
|
||||
'take_profit' => '止盈',
|
||||
'stop_loss' => '止损',
|
||||
'cost' => '成本',
|
||||
'open_long' => '做多',
|
||||
'open_short' => '做空',
|
||||
'security_settings' => '安全设置',
|
||||
'asset_details' => '资产详情',
|
||||
'transaction_records' => '交易记录',
|
||||
'level' => '等级',
|
||||
'crypto_markets' => '加密货币行情',
|
||||
'24h_volume' => '24小时成交量',
|
||||
'fear_greed' => '贪婪恐惧指数',
|
||||
'btc_dominance' => '比特币占有率',
|
||||
'favorites' => '自选',
|
||||
'all_crypto' => '所有币种',
|
||||
'asset' => '资产',
|
||||
'24h_high_low' => '24小时最高/最低',
|
||||
'deposit_assets' => '充值资产',
|
||||
'deposit_method_tip' => '请选择您偏好的充值方式。',
|
||||
'fiat_deposit' => '法币充值',
|
||||
'crypto_deposit' => '加密货币充值',
|
||||
'bank_transfer' => '本地银行转账',
|
||||
'blockchain_transfer' => '区块链转账',
|
||||
'support_20_global' => '支持20多种全球货币',
|
||||
'safe_compliant' => '安全合规的通道',
|
||||
'fast_processing' => '24/7 快速处理',
|
||||
'no_service_fee' => '无服务费',
|
||||
'select_currency' => '选择币种',
|
||||
'deposit_amount' => '充值金额',
|
||||
'matching_instructions' => '匹配说明',
|
||||
'matching_tip' => '我们的智能匹配系统将为您匹配认证商户。确认后,您将收到银行账户详情。请在时限内完成转账。',
|
||||
'match_now' => '立即匹配商户',
|
||||
'select_network' => '选择网络',
|
||||
'get_address' => '获取充值地址',
|
||||
'withdraw_assets' => '提现资产',
|
||||
'withdraw_tip' => '安全地将 USDT 提现到您的外部钱包。',
|
||||
'withdraw_address' => '提现地址',
|
||||
'trading_password' => '交易密码',
|
||||
'submit_withdrawal' => '提交提现',
|
||||
'withdrawal_tips' => '提现提示',
|
||||
'withdrawal_tip_1' => '请仔细检查目标地址。我们无法找回发送到错误地址的资金。',
|
||||
'withdrawal_tip_2' => 'TRC20 提现通常在 5-10 分钟内到账。',
|
||||
'withdrawal_tip_3' => '高峰时段,提现将进行人工安全审计。',
|
||||
'withdrawal_tip_4' => '手续费:每笔交易 1 USDT。',
|
||||
'recent_history' => '最近记录',
|
||||
'no_records' => '暂无记录',
|
||||
'max' => '最大',
|
||||
'customer_service' => '在线客服',
|
||||
'chat_welcome' => '您好!请问有什么可以帮您?',
|
||||
'type_message' => '输入消息...',
|
||||
'matching_account' => '正在匹配收款账户...',
|
||||
'matching_desc' => '系统正在为您匹配安全的本地收款账户。请稍候。',
|
||||
'crypto' => '加密货币',
|
||||
'search_market' => '搜索币种',
|
||||
'more_pairs' => '更多币种',
|
||||
'limit_order' => '限价',
|
||||
'market_order' => '市价',
|
||||
'available' => '可用',
|
||||
'buy_long' => '买入开多',
|
||||
'sell_short' => '卖出开空',
|
||||
'open_position' => '开仓',
|
||||
'close_position' => '平仓',
|
||||
'cross' => '全仓',
|
||||
'isolated' => '逐仓',
|
||||
'positions' => '当前持仓',
|
||||
'no_positions' => '暂无持仓',
|
||||
'perpetual' => '永续合约',
|
||||
'delivery' => '交割合约',
|
||||
'fee' => '手续费',
|
||||
'max_open' => '最大可开',
|
||||
'time' => '时间',
|
||||
'pair' => '币对',
|
||||
'side' => '方向',
|
||||
'filled' => '已成交',
|
||||
'status' => '状态',
|
||||
'load_more' => '加载更多',
|
||||
]
|
||||
];
|
||||
|
||||
$lang = $_SESSION['lang'] ?? 'en';
|
||||
if (isset($_GET['lang']) && array_key_exists($_GET['lang'], $translations)) {
|
||||
$_SESSION['lang'] = $_GET['lang'];
|
||||
$lang = $_GET['lang'];
|
||||
}
|
||||
|
||||
function __($key, $default = '') {
|
||||
global $translations, $lang;
|
||||
return $translations[$lang][$key] ?? ($default ?: $key);
|
||||
}
|
||||
441
index.php
441
index.php
@ -1,150 +1,305 @@
|
||||
<?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">
|
||||
<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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
</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>
|
||||
<!-- Carousel Section (Constrained Width) -->
|
||||
<section style="padding-top: 20px; background: #0b0e11;">
|
||||
<div style="max-width: 1200px; margin: 0 auto; position: relative; height: 450px; overflow: hidden; border-radius: 24px; box-shadow: 0 20px 50px rgba(0,0,0,0.5);">
|
||||
<div class="carousel-track" id="carouselTrack" style="display: flex; height: 100%; transition: transform 0.5s ease-in-out;">
|
||||
<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 style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 600px;">
|
||||
<h2 style="font-size: 3rem; font-weight: 800; margin-bottom: 20px; text-shadow: 0 5px 15px rgba(0,0,0,0.5);">NovaEx Global Launch</h2>
|
||||
<p style="font-size: 1.1rem; opacity: 0.9; margin-bottom: 30px;">Experience the next generation of digital asset trading with ultra-low latency and bank-grade security.</p>
|
||||
<a href="register.php" class="btn-primary" style="padding: 12px 35px; border-radius: 8px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white;"><?php echo __('join_now', 'Join Now'); ?></a>
|
||||
</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>
|
||||
<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 style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 600px;">
|
||||
<h2 style="font-size: 3rem; font-weight: 800; margin-bottom: 20px; text-shadow: 0 5px 15px rgba(0,0,0,0.5);">Trade Futures with 100x Leverage</h2>
|
||||
<p style="font-size: 1.1rem; opacity: 0.9; margin-bottom: 30px;">Maximize your capital efficiency with our professional perpetual futures contracts.</p>
|
||||
<a href="futures.php" class="btn-primary" style="padding: 12px 35px; border-radius: 8px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white;"><?php echo __('start_trading', '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 style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 600px;">
|
||||
<h2 style="font-size: 3rem; font-weight: 800; margin-bottom: 20px; text-shadow: 0 5px 15px rgba(0,0,0,0.5);">Secure Crypto Staking</h2>
|
||||
<p style="font-size: 1.1rem; opacity: 0.9; margin-bottom: 30px;">Earn passive income on your idle assets with our high-yield staking pools.</p>
|
||||
<a href="mining.php" class="btn-primary" style="padding: 12px 35px; border-radius: 8px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white;"><?php echo __('earn_now', 'Earn Now'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div 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 style="padding: 60px 0; max-width: 1200px; margin: 0 auto;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 30px;">
|
||||
<h2 style="font-size: 2rem; font-weight: 800;"><?php echo __('market_trends', '市场趋势'); ?></h2>
|
||||
<a href="markets.php" style="color: var(--primary-color); text-decoration: none; font-weight: 600; font-size: 14px;"><?php echo __('view_more_markets', '查看更多'); ?> <i class="fas fa-chevron-right" style="font-size: 10px;"></i></a>
|
||||
</div>
|
||||
|
||||
<div style="background: var(--card-bg); border-radius: 24px; border: 1px solid var(--border-color); overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,0.2);">
|
||||
<table style="width: 100%; border-collapse: collapse; text-align: left;">
|
||||
<thead>
|
||||
<tr style="border-bottom: 1px solid var(--border-color); background: rgba(255,255,255,0.02);">
|
||||
<th style="padding: 20px 30px; color: var(--text-muted); font-weight: 500; font-size: 14px;"><?php echo __('pair', '币对'); ?></th>
|
||||
<th style="padding: 20px 30px; color: var(--text-muted); font-weight: 500; font-size: 14px;"><?php echo __('last_price', '最新价'); ?></th>
|
||||
<th style="padding: 20px 30px; color: var(--text-muted); font-weight: 500; font-size: 14px;"><?php echo __('24h_change', '24h 涨跌'); ?></th>
|
||||
<th style="padding: 20px 30px; color: var(--text-muted); font-weight: 500; font-size: 14px;"><?php echo __('market_cap', '市值'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="home-market-list">
|
||||
<!-- JS Filled -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Download Section (Beautified and Constrained) -->
|
||||
<section style="padding: 80px 0; background: #0b0e11; border-top: 1px solid rgba(255,255,255,0.05);">
|
||||
<div style="max-width: 1200px; margin: 0 auto;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 60px; flex-wrap: wrap;">
|
||||
<div style="flex: 1; min-width: 400px;">
|
||||
<h2 style="font-size: 2.5rem; font-weight: 800; margin-bottom: 25px; background: linear-gradient(135deg, #fff 0%, #848e9c 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">Trade Anywhere, Anytime</h2>
|
||||
<p style="color: var(--text-muted); font-size: 1.1rem; line-height: 1.6; margin-bottom: 40px;">Stay connected to the markets with the NovaEx mobile app. Experience professional trading features in the palm of your hand, featuring real-time alerts, advanced charting, and instant deposits.</p>
|
||||
|
||||
<div 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: 40px; height: 40px; border-radius: 12px; background: rgba(79, 172, 254, 0.1); display: flex; align-items: center; justify-content: center; color: var(--primary-color);">
|
||||
<i class="fas fa-bolt"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 style="margin: 0 0 5px; font-weight: 700;">Fast & Secure</h4>
|
||||
<p style="font-size: 0.9rem; color: #848e9c; margin: 0;">Optimized performance with military-grade encryption.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 15px; align-items: flex-start;">
|
||||
<div style="width: 40px; height: 40px; border-radius: 12px; background: rgba(0, 192, 135, 0.1); display: flex; align-items: center; justify-content: center; color: #00c087;">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 style="margin: 0 0 5px; font-weight: 700;">Real-time Data</h4>
|
||||
<p style="font-size: 0.9rem; color: #848e9c; margin: 0;">Low-latency market updates for precise execution.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="flex: 1; display: flex; flex-direction: column; gap: 20px; min-width: 300px;">
|
||||
<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: 0.3s; cursor: pointer;">
|
||||
<div style="width: 60px; height: 60px; background: #000; border-radius: 15px; 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; font-weight: 500;">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>
|
||||
|
||||
<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: 0.3s; cursor: pointer;">
|
||||
<div style="width: 60px; height: 60px; background: #000; border-radius: 15px; 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; font-weight: 500;">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>
|
||||
|
||||
<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: 10px; border-radius: 12px;">
|
||||
<i class="fas fa-qrcode" style="font-size: 2.5rem; color: #000;"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 700; color: white; font-size: 1rem;">Scan to Download</div>
|
||||
<div style="font-size: 0.85rem; color: #848e9c; margin-top: 4px;">Supports iOS & Android</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us -->
|
||||
<section style="padding: 100px 0; background: #0b0e11;">
|
||||
<div style="max-width: 1200px; margin: 0 auto;">
|
||||
<div style="text-align: center; margin-bottom: 80px;">
|
||||
<h2 style="font-size: 2.8rem; font-weight: 800; margin-bottom: 20px;"><?php echo __('why_choose_us', '为什么选择 NovaEx?'); ?></h2>
|
||||
<p style="color: var(--text-muted); max-width: 700px; margin: 0 auto; font-size: 1.1rem;"><?php echo __('platform_desc', 'NovaEx is the world\'s most trusted cryptocurrency exchange, offering professional trading tools and deep liquidity.'); ?></p>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px;">
|
||||
<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;">
|
||||
<div style="width: 100px; height: 100px; background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); border-radius: 30px; display: flex; align-items: center; justify-content: center; margin: 0 auto 35px; color: white; font-size: 2.5rem; box-shadow: 0 15px 30px rgba(79, 172, 254, 0.3);">
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
</div>
|
||||
<h3 style="margin-bottom: 20px; font-size: 1.8rem; font-weight: 700;"><?php echo __('secure_storage', 'Secure Storage'); ?></h3>
|
||||
<p style="color: var(--text-muted); line-height: 1.8; font-size: 1rem;"><?php echo __('secure_storage_desc', 'Most of our digital assets are stored in secure offline cold storage, providing institutional-grade protection for your funds.'); ?></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;">
|
||||
<div style="width: 100px; height: 100px; background: linear-gradient(135deg, #00c087 0%, #00d2ff 100%); border-radius: 30px; display: flex; align-items: center; justify-content: center; margin: 0 auto 35px; color: white; font-size: 2.5rem; box-shadow: 0 15px 30px rgba(0, 192, 135, 0.3);">
|
||||
<i class="fas fa-user-lock"></i>
|
||||
</div>
|
||||
<h3 style="margin-bottom: 20px; font-size: 1.8rem; font-weight: 700;"><?php echo __('protected_insurance', 'Protected by Insurance'); ?></h3>
|
||||
<p style="color: var(--text-muted); line-height: 1.8; font-size: 1rem;"><?php echo __('protected_insurance_desc', 'NovaEx maintains an asset insurance fund to cover potential security breaches, ensuring user peace of mind.'); ?></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;">
|
||||
<div style="width: 100px; height: 100px; background: linear-gradient(135deg, #f0b90b 0%, #ff9a00 100%); border-radius: 30px; display: flex; align-items: center; justify-content: center; margin: 0 auto 35px; color: white; font-size: 2.5rem; box-shadow: 0 15px 30px rgba(240, 185, 11, 0.3);">
|
||||
<i class="fas fa-microchip"></i>
|
||||
</div>
|
||||
<h3 style="margin-bottom: 20px; font-size: 1.8rem; font-weight: 700;"><?php echo __('industry_best_practices', 'Best Practices'); ?></h3>
|
||||
<p style="color: var(--text-muted); line-height: 1.8; font-size: 1rem;"><?php echo __('industry_best_practices_desc', 'NovaEx supports a variety of the most popular digital currencies and keeps adding more based on rigorous security standards.'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Partners (Colorful and Beautiful) -->
|
||||
<section style="padding: 80px 0; background: #161a1e;">
|
||||
<div style="max-width: 1200px; margin: 0 auto; text-align: center;">
|
||||
<h2 style="font-size: 2.2rem; font-weight: 800; margin-bottom: 60px;"><?php echo __('global_partners', 'Global Strategic Partners'); ?></h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(6, 1fr); gap: 30px;">
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-google-pay" style="font-size: 3rem; color: #4285F4;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Google Pay</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-apple-pay" style="font-size: 3rem; color: #ffffff;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Apple Pay</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-visa" style="font-size: 3rem; color: #1a1f71;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">VISA</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-mastercard" style="font-size: 3rem; color: #eb001b;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Mastercard</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-paypal" style="font-size: 3rem; color: #003087;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">PayPal</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-stripe" style="font-size: 3rem; color: #6772e5;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Stripe</div>
|
||||
</div>
|
||||
<!-- Row 2 -->
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-amazon" style="font-size: 2.8rem; color: #ff9900;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Amazon</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-microsoft" style="font-size: 2.8rem; color: #00a4ef;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Microsoft</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-salesforce" style="font-size: 2.8rem; color: #00a1e0;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Salesforce</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-slack" style="font-size: 2.8rem; color: #4a154b;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Slack</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-atlassian" style="font-size: 2.8rem; color: #0052cc;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">Atlassian</div>
|
||||
</div>
|
||||
<div class="partner-item">
|
||||
<i class="fab fa-github" style="font-size: 2.8rem; color: #ffffff;"></i>
|
||||
<div style="margin-top: 15px; font-weight: 600; opacity: 0.9;">GitHub</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
.carousel-dot.active { opacity: 1 !important; width: 35px !important; border-radius: 6px !important; background: var(--primary-color) !important; }
|
||||
.partner-item { padding: 35px 20px; background: rgba(255,255,255,0.02); border-radius: 24px; transition: 0.3s; border: 1px solid transparent; }
|
||||
.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; }
|
||||
</style>
|
||||
|
||||
<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, 5000);
|
||||
|
||||
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); transition: 0.2s;" onmouseover="this.style.background='rgba(255,255,255,0.02)'" onmouseout="this.style.background='transparent'">
|
||||
<td style="padding: 25px 30px; 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;">${name}</div>
|
||||
<div style="font-size: 0.8rem; color: var(--text-muted);">USDT</div>
|
||||
</div>
|
||||
</td>
|
||||
<td style="padding: 25px 30px; font-weight: 600; font-size: 1.1rem; color: #EAECEF;">$ ${parseFloat(d.c).toLocaleString()}</td>
|
||||
<td style="padding: 25px 30px; color: ${color}; font-weight: 700; font-size: 1.1rem;">${d.P >= 0 ? '+' : ''}${d.P}%</td>
|
||||
<td style="padding: 25px 30px; color: var(--text-muted); font-family: monospace; font-size: 0.9rem;">$ ${(parseFloat(d.q) / 1000000).toFixed(2)}M</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
tbody.innerHTML = html;
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
185
kyc.php
Normal file
185
kyc.php
Normal 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'; ?>
|
||||
75
login.php
Normal file
75
login.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?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
|
||||
$user_ip = $_SERVER['REMOTE_ADDR'];
|
||||
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$user_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
}
|
||||
$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 username or password.";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?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;">Welcome Back</h2>
|
||||
<p style="text-align: center; color: var(--text-muted); margin-bottom: 40px;">Log in to your account to continue trading</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;">Account</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="Enter your email or 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;">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="Enter 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="display: flex; justify-content: flex-end; margin-bottom: 30px;">
|
||||
<a href="#" style="color: var(--primary-color); text-decoration: none; font-size: 0.85rem;">Forgot Password?</a>
|
||||
</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);">Don't have an 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
5
logout.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
session_start();
|
||||
session_destroy();
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
95
markets.php
Normal file
95
markets.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php include 'header.php'; ?>
|
||||
|
||||
<main style="padding: 40px 20px; background: #0b0e11; min-height: calc(100vh - 60px);">
|
||||
<div style="max-width: 1200px; margin: 0 auto;">
|
||||
<h1 style="color: white; margin-bottom: 30px;"><?php echo __('crypto_markets'); ?></h1>
|
||||
|
||||
<div style="display: flex; gap: 20px; margin-bottom: 30px;">
|
||||
<div style="flex: 1; background: #1e2329; padding: 20px; border-radius: 12px; border: 1px solid #2b3139;">
|
||||
<div style="color: #848e9c; font-size: 0.9rem;"><?php echo __('24h_volume'); ?></div>
|
||||
<div style="font-size: 1.5rem; color: white; margin-top: 10px; font-weight: bold;">$ 84.23B</div>
|
||||
</div>
|
||||
<div style="flex: 1; background: #1e2329; padding: 20px; border-radius: 12px; border: 1px solid #2b3139;">
|
||||
<div style="color: #848e9c; font-size: 0.9rem;"><?php echo __('fear_greed'); ?></div>
|
||||
<div style="font-size: 1.5rem; color: #00c087; margin-top: 10px; font-weight: bold;">74 (Greed)</div>
|
||||
</div>
|
||||
<div style="flex: 1; background: #1e2329; padding: 20px; border-radius: 12px; border: 1px solid #2b3139;">
|
||||
<div style="color: #848e9c; font-size: 0.9rem;"><?php echo __('btc_dominance'); ?></div>
|
||||
<div style="font-size: 1.5rem; color: white; margin-top: 10px; font-weight: bold;">52.1%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background: #1e2329; border-radius: 16px; border: 1px solid #2b3139; overflow: hidden;">
|
||||
<div style="padding: 20px 30px; border-bottom: 1px solid #2b3139; display: flex; gap: 30px;">
|
||||
<span style="color: white; border-bottom: 2px solid var(--primary-color); padding-bottom: 15px; cursor: pointer;"><?php echo __('favorites'); ?></span>
|
||||
<span style="color: #848e9c; cursor: pointer;"><?php echo __('all_crypto'); ?></span>
|
||||
<span style="color: #848e9c; cursor: pointer;"><?php echo __('nav_spot'); ?></span>
|
||||
<span style="color: #848e9c; cursor: pointer;"><?php echo __('nav_futures'); ?></span>
|
||||
</div>
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<thead style="background: #161a1e;">
|
||||
<tr>
|
||||
<th style="padding: 15px 30px; text-align: left; color: #848e9c; font-weight: normal; font-size: 0.9rem;"><?php echo __('asset'); ?></th>
|
||||
<th style="padding: 15px 30px; text-align: right; color: #848e9c; font-weight: normal; font-size: 0.9rem;"><?php echo __('price'); ?></th>
|
||||
<th style="padding: 15px 30px; text-align: right; color: #848e9c; font-weight: normal; font-size: 0.9rem;">24h Change</th>
|
||||
<th style="padding: 15px 30px; text-align: right; color: #848e9c; font-weight: normal; font-size: 0.9rem;"><?php echo __('24h_high_low'); ?></th>
|
||||
<th style="padding: 15px 30px; text-align: right; color: #848e9c; font-weight: normal; font-size: 0.9rem;"><?php echo __('trade_panel'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="market-list-all">
|
||||
<!-- Filled by WS -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
const pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'LINKUSDT', 'AVAXUSDT', 'MATICUSDT', 'SHIBUSDT'];
|
||||
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');
|
||||
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 ? '#00c087' : '#f6465d';
|
||||
const name = p.replace('USDT', '');
|
||||
|
||||
html += `
|
||||
<tr style="border-bottom: 1px solid #2b3139; transition: background 0.2s; cursor: pointer;" onmouseover="this.style.background='rgba(255,255,255,0.02)'" onmouseout="this.style.background='transparent'">
|
||||
<td style="padding: 20px 30px; 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="color: white; font-weight: bold;">${name}</div>
|
||||
<div style="color: #666; font-size: 0.8rem;">${name}/USDT</div>
|
||||
</div>
|
||||
</td>
|
||||
<td style="padding: 20px 30px; text-align: right; color: white; font-weight: bold; font-family: monospace;">$ ${price}</td>
|
||||
<td style="padding: 20px 30px; text-align: right; color: ${color}; font-weight: bold;">${change >= 0 ? '+' : ''}${change}%</td>
|
||||
<td style="padding: 20px 30px; text-align: right; color: #848e9c; font-size: 0.85rem;">
|
||||
<div>H: ${parseFloat(d.h).toFixed(2)}</div>
|
||||
<div>L: ${parseFloat(d.l).toFixed(2)}</div>
|
||||
</td>
|
||||
<td style="padding: 20px 30px; text-align: right;">
|
||||
<a href="spot.php?symbol=${p}" class="btn-primary" style="padding: 8px 20px; font-size: 0.85rem; border-radius: 6px; text-decoration: none;"><?php echo __('buy'); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
tbody.innerHTML = html;
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
451
matching.php
Normal file
451
matching.php
Normal file
@ -0,0 +1,451 @@
|
||||
<?php
|
||||
include 'header.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'db/config.php';
|
||||
require_once 'includes/currency_helper.php';
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
// Step 1: Handle initial order creation from deposit.php
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['amount']) && !isset($_GET['order_id'])) {
|
||||
$amount = (float)$_POST['amount'];
|
||||
$type = $_POST['type'] ?? 'fiat';
|
||||
$currency = $_POST['currency'] ?? 'USDT';
|
||||
|
||||
$fiat_rates = get_fiat_rates();
|
||||
$rate = $fiat_rates[$currency] ?? 1.0;
|
||||
$usdt_amount = ($rate > 0) ? ($amount / $rate) : $amount;
|
||||
|
||||
$expires_at = date('Y-m-d H:i:s', strtotime('+30 minutes'));
|
||||
|
||||
// Status starts as 'matching' (待匹配)
|
||||
$stmt = db()->prepare("INSERT INTO fiat_orders (user_id, amount, usdt_amount, exchange_rate, currency, status, expires_at, created_at) VALUES (?, ?, ?, ?, ?, 'matching', ?, CURRENT_TIMESTAMP)");
|
||||
$stmt->execute([$user_id, $amount, $usdt_amount, $rate, $currency, $expires_at]);
|
||||
$order_id = db()->lastInsertId();
|
||||
|
||||
// Immediate notification to admin (用户一点击确认,后台立刻收到请求)
|
||||
$msg = "[RECHARGE_NOTIFICATION] 🚨 新充值申请! 用户 {$_SESSION['email']} (UID: {$_SESSION['uid']}) 正在等待匹配: **$amount $currency**。请尽快分配收款账户。";
|
||||
$stmt = db()->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
|
||||
$stmt->execute([$user_id, $msg]);
|
||||
|
||||
header("Location: matching.php?order_id=" . $order_id);
|
||||
exit;
|
||||
}
|
||||
|
||||
$order_id = $_GET['order_id'] ?? null;
|
||||
if (!$order_id) {
|
||||
header("Location: deposit.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM fiat_orders WHERE id = ? AND user_id = ?");
|
||||
$stmt->execute([$order_id, $user_id]);
|
||||
$order = $stmt->fetch();
|
||||
|
||||
if (!$order) {
|
||||
header("Location: deposit.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($order['status'] === 'completed') {
|
||||
header("Location: profile.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Step 6: Handle Proof Submission (已提交凭证)
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['proof'])) {
|
||||
$file = $_FILES['proof'];
|
||||
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
||||
$allowed = ['jpg', 'jpeg', 'png', 'gif'];
|
||||
|
||||
if (in_array($ext, $allowed)) {
|
||||
$filename = 'proof_' . $order_id . '_' . time() . '.' . $ext;
|
||||
$target = 'assets/images/proofs/' . $filename;
|
||||
|
||||
if (!is_dir('assets/images/proofs/')) mkdir('assets/images/proofs/', 0775, true);
|
||||
|
||||
if (move_uploaded_file($file['tmp_name'], $target)) {
|
||||
$stmt = db()->prepare("UPDATE fiat_orders SET proof_image = ?, status = 'submitting' WHERE id = ?");
|
||||
$stmt->execute(['assets/images/proofs/' . $filename, $order_id]);
|
||||
|
||||
$msg = "[RECHARGE_SUBMITTED] ✅ 用户已完成转账并提交凭证 (订单 #$order_id)。请进入后台核对。";
|
||||
$stmt = db()->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
|
||||
$stmt->execute([$user_id, $msg]);
|
||||
|
||||
header("Location: matching.php?order_id=" . $order_id);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM messages WHERE user_id = ? AND message NOT LIKE '[RECHARGE_%' ORDER BY created_at ASC");
|
||||
$stmt->execute([$user_id]);
|
||||
$messages = $stmt->fetchAll();
|
||||
?>
|
||||
|
||||
<main style="background: #0b0e11; min-height: calc(100vh - 64px); padding: 40px 20px;">
|
||||
|
||||
<!-- Step 4: MANDATORY LOCK OVERLAY for matched status (已匹配) -->
|
||||
<?php if ($order['status'] === 'matched' || ($order['bank_account_info'] && $order['status'] === 'matching')): ?>
|
||||
<div id="mandatory-lock" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #0b0e11; z-index: 100000; overflow-y: auto; padding: 20px;">
|
||||
<div style="max-width: 600px; margin: 20px auto;">
|
||||
<div style="background: #161a1e; border-radius: 32px; border: 1px solid rgba(255,255,255,0.1); overflow: hidden; box-shadow: 0 40px 100px rgba(0,0,0,0.8);">
|
||||
|
||||
<!-- Success Header -->
|
||||
<div style="background: linear-gradient(135deg, #00c087, #008960); padding: 40px 30px; text-align: center; color: white; position: relative; overflow: hidden;">
|
||||
<div style="position: absolute; top: -50px; right: -50px; width: 150px; height: 150px; background: rgba(255,255,255,0.05); border-radius: 50%;"></div>
|
||||
<div style="width: 80px; height: 80px; background: rgba(255,255,255,0.2); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; border: 3px solid white; box-shadow: 0 10px 20px rgba(0,0,0,0.2);">
|
||||
<i class="fas fa-check" style="font-size: 35px;"></i>
|
||||
</div>
|
||||
<h2 style="margin: 0; font-size: 2rem; font-weight: 900; letter-spacing: -0.5px;">账户匹配成功</h2>
|
||||
<p style="margin: 10px 0 0; opacity: 0.9; font-size: 15px; font-weight: 500;">请按以下信息完成转账并上传凭证</p>
|
||||
</div>
|
||||
|
||||
<div style="padding: 40px;">
|
||||
<!-- Step Indicator -->
|
||||
<div style="display: flex; justify-content: space-between; margin-bottom: 40px; position: relative;">
|
||||
<div style="position: absolute; top: 12px; left: 0; width: 100%; height: 2px; background: rgba(255,255,255,0.05); z-index: 1;"></div>
|
||||
<div style="z-index: 2; text-align: center; width: 33%;">
|
||||
<div style="width: 26px; height: 26px; background: #00c087; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; font-size: 12px; font-weight: bold; border: 4px solid #161a1e;">1</div>
|
||||
<div style="font-size: 11px; color: #00c087; font-weight: bold;">查看账户</div>
|
||||
</div>
|
||||
<div style="z-index: 2; text-align: center; width: 33%;">
|
||||
<div id="step-dot-2" style="width: 26px; height: 26px; background: #2b3139; color: #848e9c; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; font-size: 12px; font-weight: bold; border: 4px solid #161a1e;">2</div>
|
||||
<div id="step-text-2" style="font-size: 11px; color: #848e9c; font-weight: bold;">完成支付</div>
|
||||
</div>
|
||||
<div style="z-index: 2; text-align: center; width: 33%;">
|
||||
<div id="step-dot-3" style="width: 26px; height: 26px; background: #2b3139; color: #848e9c; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 8px; font-size: 12px; font-weight: bold; border: 4px solid #161a1e;">3</div>
|
||||
<div id="step-text-3" style="font-size: 11px; color: #848e9c; font-weight: bold;">上传凭证</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Amount Highlight -->
|
||||
<div style="background: rgba(240, 185, 11, 0.05); padding: 30px; border-radius: 24px; border: 1px solid rgba(240, 185, 11, 0.2); text-align: center; margin-bottom: 35px; box-shadow: inset 0 0 20px rgba(0,0,0,0.2);">
|
||||
<div style="font-size: 12px; color: #f0b90b; font-weight: bold; margin-bottom: 15px; text-transform: uppercase; letter-spacing: 2px;">应转账金额 / Amount Due</div>
|
||||
<div style="font-size: 3rem; font-weight: 900; color: white; display: flex; align-items: baseline; justify-content: center; gap: 10px;">
|
||||
<?php echo number_format($order['amount'], 2); ?> <span style="font-size: 20px; color: #f0b90b;"><?php echo $order['currency']; ?></span>
|
||||
</div>
|
||||
<div style="font-size: 13px; color: #848e9c; margin-top: 15px;"><i class="fas fa-exclamation-circle"></i> 请务必转入精确金额,包含小数点</div>
|
||||
</div>
|
||||
|
||||
<!-- Bank Details -->
|
||||
<div style="background: #0b0e11; padding: 30px; border-radius: 24px; border: 1px solid rgba(255,255,255,0.05); margin-bottom: 35px; position: relative;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px;">
|
||||
<div style="font-weight: 800; color: #848e9c; font-size: 14px; text-transform: uppercase; letter-spacing: 1px;"><i class="fas fa-university" style="margin-right: 8px;"></i> 收款账户信息</div>
|
||||
<button onclick="copyToClipboard('<?php echo str_replace(["\r", "\n"], ' ', $order['bank_account_info']); ?>')" style="background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); color: white; padding: 8px 16px; border-radius: 12px; font-size: 12px; cursor: pointer; transition: 0.2s; font-weight: bold;">
|
||||
<i class="fas fa-copy"></i> 复制
|
||||
</button>
|
||||
</div>
|
||||
<div style="font-size: 1.2rem; line-height: 2; color: white; font-family: 'Roboto Mono', monospace; background: rgba(255,255,255,0.02); padding: 20px; border-radius: 16px;">
|
||||
<?php echo nl2br(htmlspecialchars($order['bank_account_info'])); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div id="action-area">
|
||||
<button onclick="showUploadForm()" style="width: 100%; padding: 24px; background: #00c087; color: white; border: none; border-radius: 20px; font-size: 1.3rem; font-weight: 900; cursor: pointer; box-shadow: 0 15px 35px rgba(0,192,135,0.4); transition: 0.3s; transform: perspective(1px) translateZ(0);">
|
||||
我已完成转账,去上传凭证
|
||||
</button>
|
||||
<p style="text-align: center; color: #5e6673; font-size: 12px; margin-top: 20px;">
|
||||
<i class="fas fa-lock"></i> 资金安全由区块链技术加密保护
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Step 5: Hidden Upload Form (上传转账凭证界面) -->
|
||||
<div id="upload-form-container" style="display: none; animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1);">
|
||||
<div style="text-align: center; margin-bottom: 30px;">
|
||||
<h3 style="margin: 0 0 10px 0; font-size: 1.5rem; font-weight: 900;">上传转账凭证</h3>
|
||||
<p style="color: #848e9c; font-size: 14px;">请上传包含交易单号、金额、时间的支付截图</p>
|
||||
</div>
|
||||
<form method="POST" enctype="multipart/form-data" id="main-proof-form">
|
||||
<div id="upload-dropzone" style="background: #0b0e11; border: 2px dashed rgba(255,255,255,0.1); border-radius: 24px; padding: 50px 30px; text-align: center; cursor: pointer; margin-bottom: 30px; transition: 0.3s;" onclick="document.getElementById('file-input').click()">
|
||||
<div id="file-idle">
|
||||
<div style="width: 80px; height: 80px; background: rgba(132, 142, 156, 0.1); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 20px;">
|
||||
<i class="fas fa-cloud-upload-alt" style="font-size: 40px; color: #848e9c;"></i>
|
||||
</div>
|
||||
<div style="font-weight: 900; font-size: 18px; color: white;">点击选择转账截图</div>
|
||||
<div style="font-size: 13px; color: #5e6673; margin-top: 8px;">支持 JPG, PNG, JPEG 格式</div>
|
||||
</div>
|
||||
<div id="file-selected" style="display: none;">
|
||||
<div style="width: 80px; height: 80px; background: rgba(0, 192, 135, 0.1); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 20px;">
|
||||
<i class="fas fa-file-image" style="font-size: 40px; color: #00c087;"></i>
|
||||
</div>
|
||||
<div style="font-weight: 900; font-size: 18px; color: #00c087;" id="selected-name"></div>
|
||||
<div style="font-size: 13px; color: #848e9c; margin-top: 8px;">文件已就绪,点击重新选择</div>
|
||||
</div>
|
||||
<input type="file" name="proof" id="file-input" accept="image/*" style="display: none;" onchange="updateFilePreview(this)">
|
||||
</div>
|
||||
|
||||
<!-- 逻辑限制:没有图片不允许提交 -->
|
||||
<button type="submit" id="final-submit" disabled style="width: 100%; padding: 22px; background: #2b3139; color: #5e6673; border: none; border-radius: 20px; font-size: 1.2rem; font-weight: 900; cursor: not-allowed; transition: 0.3s; box-shadow: 0 10px 30px rgba(0,0,0,0.2);">
|
||||
确认提交并通知客服
|
||||
</button>
|
||||
<button type="button" onclick="hideUploadForm()" style="width: 100%; margin-top: 20px; background: transparent; color: #848e9c; border: none; font-size: 14px; cursor: pointer; font-weight: bold;">
|
||||
<i class="fas fa-arrow-left"></i> 返回查看账户
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div style="max-width: 1200px; margin: 0 auto; background: #161a1e; border: 1px solid rgba(255,255,255,0.08); border-radius: 32px; height: 85vh; display: grid; grid-template-columns: 1fr 400px; overflow: hidden; box-shadow: 0 40px 100px rgba(0,0,0,0.6);">
|
||||
|
||||
<!-- Left Panel: Status Info -->
|
||||
<div style="display: flex; flex-direction: column; background: #0b0e11; border-right: 1px solid rgba(255,255,255,0.08);">
|
||||
|
||||
<div style="padding: 25px 40px; border-bottom: 1px solid rgba(255,255,255,0.08); background: #161a1e; display: flex; align-items: center; justify-content: space-between;">
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<div style="width: 45px; height: 45px; background: var(--primary-color); border-radius: 12px; display: flex; align-items: center; justify-content: center; color: white;">
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 800; font-size: 16px;">安全充值通道</div>
|
||||
<div style="font-size: 10px; color: #848e9c; font-family: monospace;">#<?php echo $order_id; ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div id="countdown" style="font-size: 1.4rem; font-weight: 900; color: #f0b90b; font-family: monospace;">30:00</div>
|
||||
<div style="font-size: 10px; color: #848e9c;">剩余支付时间</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="flex: 1; overflow-y: auto; padding: 60px;">
|
||||
<!-- Step 2: 前端显示“匹配中” (待匹配) -->
|
||||
<?php if ($order['status'] === 'matching' && !$order['bank_account_info']): ?>
|
||||
<div style="text-align: center;">
|
||||
<div class="loader-container" style="margin-bottom: 40px;">
|
||||
<div class="loader"></div>
|
||||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center;">
|
||||
<i class="fas fa-user-clock" style="font-size: 40px; color: var(--primary-color);"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h2 style="font-size: 2.2rem; font-weight: 900; margin-bottom: 20px;">正在为您匹配收款账户</h2>
|
||||
<div style="background: rgba(255,255,255,0.02); padding: 25px; border-radius: 20px; border: 1px solid rgba(255,255,255,0.05); max-width: 500px; margin: 0 auto;">
|
||||
<p style="color: #848e9c; font-size: 16px; line-height: 1.8; margin: 0;">
|
||||
系统正在为您对接在线财务专员,匹配成功后将自动弹出收款账户详情,请保持页面开启不要离开。
|
||||
</p>
|
||||
</div>
|
||||
<div style="margin-top: 40px; display: flex; justify-content: center; gap: 15px;">
|
||||
<div class="dot-typing"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php elseif ($order['status'] === 'submitting'): ?>
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 140px; height: 140px; background: rgba(0, 192, 135, 0.1); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 35px; border: 2px solid rgba(0, 192, 135, 0.2);">
|
||||
<i class="fas fa-file-invoice-dollar" style="font-size: 60px; color: #00c087;"></i>
|
||||
</div>
|
||||
<h2 style="font-size: 2.2rem; font-weight: 900; margin-bottom: 20px;">支付凭证已提交</h2>
|
||||
<p style="color: #848e9c; font-size: 16px; line-height: 1.8; max-width: 500px; margin: 0 auto;">
|
||||
我们已收到您的转账凭证,财务人员正在核实入账情况。通常在 5-10 分钟内完成,完成后您的余额将自动增加。
|
||||
</p>
|
||||
<div style="margin-top: 50px; display: flex; gap: 20px; justify-content: center;">
|
||||
<a href="profile.php" style="background: var(--primary-color); color: white; padding: 18px 45px; border-radius: 16px; text-decoration: none; font-weight: 900; box-shadow: 0 10px 25px rgba(0,82,255,0.3);">查看我的钱包</a>
|
||||
<a href="chat.php" style="background: #2b3139; color: white; padding: 18px 45px; border-radius: 16px; text-decoration: none; font-weight: 900;">联系人工客服</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php elseif ($order['status'] === 'rejected'): ?>
|
||||
<div style="text-align: center;">
|
||||
<div style="width: 140px; height: 140px; background: rgba(246, 70, 93, 0.1); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 35px; border: 2px solid rgba(246, 70, 93, 0.2);">
|
||||
<i class="fas fa-times-circle" style="font-size: 60px; color: #f6465d;"></i>
|
||||
</div>
|
||||
<h2 style="font-size: 2.2rem; font-weight: 900; margin-bottom: 20px; color: #f6465d;">订单审核未通过</h2>
|
||||
<p style="color: #848e9c; font-size: 16px; line-height: 1.8; max-width: 500px; margin: 0 auto;">
|
||||
非常抱歉,您的充值申请未能通过。可能是因为凭证不清晰、金额不匹配或转账未到账。
|
||||
</p>
|
||||
<a href="deposit.php" style="display: inline-block; margin-top: 50px; background: #f6465d; color: white; padding: 18px 45px; border-radius: 16px; text-decoration: none; font-weight: 900;">重新发起充值</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel: Chat -->
|
||||
<div style="display: flex; flex-direction: column; background: #161a1e;">
|
||||
<div style="padding: 20px 25px; border-bottom: 1px solid rgba(255,255,255,0.08); background: #1e2329; display: flex; align-items: center; gap: 12px;">
|
||||
<div style="width: 10px; height: 10px; background: #00c087; border-radius: 50%; box-shadow: 0 0 10px #00c087;"></div>
|
||||
<div style="font-weight: bold; font-size: 14px;">在线客服 (Online)</div>
|
||||
</div>
|
||||
|
||||
<div id="chat-box" style="flex: 1; overflow-y: auto; padding: 25px; display: flex; flex-direction: column; gap: 15px; background: #0b0e11;">
|
||||
<?php foreach ($messages as $m):
|
||||
$align = $m['sender'] === 'user' ? 'flex-end' : 'flex-start';
|
||||
$bg = $m['sender'] === 'user' ? 'var(--primary-color)' : '#2b3139';
|
||||
?>
|
||||
<div style="align-self: <?php echo $align; ?>; max-width: 85%;">
|
||||
<div style="padding: 12px 16px; border-radius: 15px; background: <?php echo $bg; ?>; color: white; font-size: 14px; line-height: 1.5;">
|
||||
<?php echo nl2br(htmlspecialchars($m['message'])); ?>
|
||||
</div>
|
||||
<div style="font-size: 10px; color: #5e6673; margin-top: 5px; text-align: <?php echo $m['sender'] === 'user' ? 'right' : 'left'; ?>;">
|
||||
<?php echo date('H:i', strtotime($m['created_at'])); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div style="padding: 20px; background: #1e2329;">
|
||||
<form id="chat-form" style="display: flex; gap: 10px;">
|
||||
<input type="text" id="chat-input" placeholder="输入消息..." style="flex: 1; background: #0b0e11; border: 1px solid rgba(255,255,255,0.1); border-radius: 10px; padding: 12px 15px; color: white; outline: none;">
|
||||
<button type="submit" style="background: var(--primary-color); border: none; color: white; width: 45px; height: 45px; border-radius: 10px; cursor: pointer;">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|
||||
@keyframes slideUp { from { transform: translateY(40px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
||||
.loader-container { position: relative; width: 120px; height: 120px; margin: 0 auto; }
|
||||
.loader { width: 120px; height: 120px; border: 4px solid rgba(0,82,255,0.05); border-top-color: var(--primary-color); border-radius: 50%; animation: spin 1.5s cubic-bezier(0.68, -0.55, 0.265, 1.55) infinite; }
|
||||
|
||||
.dot-typing { position: relative; left: -9999px; width: 10px; height: 10px; border-radius: 5px; background-color: var(--primary-color); color: var(--primary-color); box-shadow: 9984px 0 0 0 var(--primary-color), 9999px 0 0 0 var(--primary-color), 10014px 0 0 0 var(--primary-color); animation: dot-typing 1.5s infinite linear; }
|
||||
@keyframes dot-typing { 0% { box-shadow: 9984px 0 0 0 var(--primary-color), 9999px 0 0 0 var(--primary-color), 10014px 0 0 0 var(--primary-color); } 16.667% { box-shadow: 9984px -10px 0 0 var(--primary-color), 9999px 0 0 0 var(--primary-color), 10014px 0 0 0 var(--primary-color); } 33.333% { box-shadow: 9984px 0 0 0 var(--primary-color), 9999px 0 0 0 var(--primary-color), 10014px 0 0 0 var(--primary-color); } 50% { box-shadow: 9984px 0 0 0 var(--primary-color), 9999px -10px 0 0 var(--primary-color), 10014px 0 0 0 var(--primary-color); } 66.667% { box-shadow: 9984px 0 0 0 var(--primary-color), 9999px 0 0 0 var(--primary-color), 10014px 0 0 0 var(--primary-color); } 83.333% { box-shadow: 9984px 0 0 0 var(--primary-color), 9999px 0 0 0 var(--primary-color), 10014px -10px 0 0 var(--primary-color); } 100% { box-shadow: 9984px 0 0 0 var(--primary-color), 9999px 0 0 0 var(--primary-color), 10014px 0 0 0 var(--primary-color); } }
|
||||
|
||||
body { overflow: hidden; }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Copy function
|
||||
function copyToClipboard(text) {
|
||||
const el = document.createElement('textarea');
|
||||
el.value = text;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
alert('复制成功 / Copied');
|
||||
}
|
||||
|
||||
// Force Lock Logic
|
||||
const isMatched = <?php echo ($order['bank_account_info'] ? 'true' : 'false'); ?>;
|
||||
const status = '<?php echo $order['status']; ?>';
|
||||
|
||||
if (isMatched && status !== 'submitting' && status !== 'completed' && status !== 'rejected') {
|
||||
// Prevent back button and refresh alert
|
||||
window.history.pushState(null, null, window.location.href);
|
||||
window.onpopstate = function() {
|
||||
window.history.pushState(null, null, window.location.href);
|
||||
};
|
||||
window.onbeforeunload = function() {
|
||||
return "交易正在进行中,请勿离开!";
|
||||
};
|
||||
}
|
||||
|
||||
// Polling for status updates
|
||||
setInterval(() => {
|
||||
fetch('api/check_order_status.php?order_id=<?php echo $order_id; ?>')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.status === 'completed') {
|
||||
window.onbeforeunload = null;
|
||||
location.href = 'profile.php';
|
||||
} else if (data.status === 'rejected' && status !== 'rejected') {
|
||||
location.reload();
|
||||
} else if (data.status === 'matched' && status === 'matching') {
|
||||
location.reload(); // Trigger mandatory Step 4 popup
|
||||
} else if (data.bank_account_info && !isMatched) {
|
||||
location.reload(); // Admin matched while polling
|
||||
}
|
||||
});
|
||||
}, 3000);
|
||||
|
||||
// Countdown logic
|
||||
let expiresAt = new Date('<?php echo $order['expires_at']; ?>').getTime();
|
||||
function updateCountdown() {
|
||||
let now = new Date().getTime();
|
||||
let diff = expiresAt - now;
|
||||
let el = document.getElementById('countdown');
|
||||
if (!el) return;
|
||||
if (diff <= 0) { el.innerText = "00:00"; el.style.color = "#f6465d"; return; }
|
||||
let mins = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
||||
let secs = Math.floor((diff % (1000 * 60)) / 1000);
|
||||
el.innerText = (mins < 10 ? "0" + mins : mins) + ":" + (secs < 10 ? "0" + secs : secs);
|
||||
}
|
||||
updateCountdown();
|
||||
setInterval(updateCountdown, 1000);
|
||||
|
||||
// Upload Form Handlers
|
||||
function showUploadForm() {
|
||||
document.getElementById('action-area').style.display = 'none';
|
||||
document.getElementById('upload-form-container').style.display = 'block';
|
||||
|
||||
// Update Steps
|
||||
document.getElementById('step-dot-2').style.background = '#00c087';
|
||||
document.getElementById('step-dot-2').style.color = 'white';
|
||||
document.getElementById('step-text-2').style.color = '#00c087';
|
||||
}
|
||||
|
||||
function hideUploadForm() {
|
||||
document.getElementById('action-area').style.display = 'block';
|
||||
document.getElementById('upload-form-container').style.display = 'none';
|
||||
|
||||
// Revert Steps
|
||||
document.getElementById('step-dot-2').style.background = '#2b3139';
|
||||
document.getElementById('step-dot-2').style.color = '#848e9c';
|
||||
document.getElementById('step-text-2').style.color = '#848e9c';
|
||||
}
|
||||
|
||||
function updateFilePreview(input) {
|
||||
if (input.files && input.files[0]) {
|
||||
document.getElementById('file-idle').style.display = 'none';
|
||||
document.getElementById('file-selected').style.display = 'block';
|
||||
document.getElementById('selected-name').innerText = input.files[0].name;
|
||||
|
||||
const btn = document.getElementById('final-submit');
|
||||
btn.disabled = false;
|
||||
btn.style.background = '#00c087';
|
||||
btn.style.color = 'white';
|
||||
btn.style.cursor = 'pointer';
|
||||
btn.style.boxShadow = '0 10px 20px rgba(0,192,135,0.2)';
|
||||
|
||||
// Step 3 active
|
||||
document.getElementById('step-dot-3').style.background = '#00c087';
|
||||
document.getElementById('step-dot-3').style.color = 'white';
|
||||
document.getElementById('step-text-3').style.color = '#00c087';
|
||||
|
||||
// Highlight dropzone
|
||||
document.getElementById('upload-dropzone').style.borderColor = '#00c087';
|
||||
document.getElementById('upload-dropzone').style.background = 'rgba(0,192,135,0.02)';
|
||||
}
|
||||
}
|
||||
|
||||
// Chat Logic
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
|
||||
document.getElementById('chat-form').onsubmit = function(e) {
|
||||
e.preventDefault();
|
||||
const input = document.getElementById('chat-input');
|
||||
const msg = input.value.trim();
|
||||
if (!msg) return;
|
||||
|
||||
const time = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
||||
const html = `
|
||||
<div style="align-self: flex-end; max-width: 85%;">
|
||||
<div style="padding: 12px 16px; border-radius: 15px; background: var(--primary-color); color: white; font-size: 14px; line-height: 1.5;">${msg}</div>
|
||||
<div style="font-size: 10px; color: #5e6673; margin-top: 5px; text-align: right;">
|
||||
${time}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
chatBox.insertAdjacentHTML('beforeend', html);
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
input.value = '';
|
||||
|
||||
fetch('chat.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: 'message=' + encodeURIComponent(msg)
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
111
mining.php
Normal file
111
mining.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?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> 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;">Staking & Mining</h1>
|
||||
<p style="color: var(--text-muted); font-size: 1.2rem; max-width: 700px; margin: 0 auto;">Participate in proof-of-stake and decentralized finance to earn rewards on your digital assets.</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;">Liquidity Mining</h3>
|
||||
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 25px;">Provide liquidity to automated market makers and earn a portion of the trading fees plus governance tokens.</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;">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;">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;">PoS Staking</h3>
|
||||
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 25px;">Stake your proof-of-stake assets to help secure the network and receive inflation rewards directly in your wallet.</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;">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;">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;">Launchpad</h3>
|
||||
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 25px;">Gain exclusive access to high-quality blockchain projects before they list on our exchange.</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;">Next Project</div>
|
||||
<div style="font-size: 20px; font-weight: bold; color: var(--gold-color);">Coming Soon</div>
|
||||
</div>
|
||||
<button class="btn-primary" style="padding: 10px 25px; border-radius: 12px;">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;">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;">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;">Staking</button>
|
||||
</div>
|
||||
</div>
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<thead style="background: #161a1e;">
|
||||
<tr>
|
||||
<th style="padding: 20px 40px; text-align: left; color: var(--text-muted); font-weight: 500;">Asset</th>
|
||||
<th style="padding: 20px 40px; text-align: left; color: var(--text-muted); font-weight: 500;">Est. APR</th>
|
||||
<th style="padding: 20px 40px; text-align: left; color: var(--text-muted); font-weight: 500;">Duration</th>
|
||||
<th style="padding: 20px 40px; text-align: right; color: var(--text-muted); font-weight: 500;">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;">Subscribe</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
45
news.php
Normal file
45
news.php
Normal 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'; ?>
|
||||
52
privacy.php
Normal file
52
privacy.php
Normal 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'; ?>
|
||||
238
profile.php
Normal file
238
profile.php
Normal file
@ -0,0 +1,238 @@
|
||||
<?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 => __('kyc_none', '未认证'),
|
||||
1 => __('kyc_pending', '审核中'),
|
||||
2 => __('kyc_approved', '已认证'),
|
||||
3 => __('kyc_rejected', '未通过'),
|
||||
];
|
||||
$kyc_colors = [0 => '#888', 1 => '#f0b90b', 2 => 'var(--success-color)', 3 => 'var(--danger-color)'];
|
||||
?>
|
||||
|
||||
<style>
|
||||
.profile-tabs { display: flex; gap: 30px; border-bottom: 1px solid var(--border-color); margin-bottom: 30px; }
|
||||
.profile-tab-btn { background: none; border: none; color: var(--text-muted); padding: 10px 0; font-size: 1.1rem; font-weight: 600; cursor: pointer; border-bottom: 2px solid transparent; }
|
||||
.profile-tab-btn.active { color: white; border-bottom-color: var(--primary-color); }
|
||||
.record-item { padding: 15px; background: rgba(255,255,255,0.02); border-radius: 12px; border: 1px solid var(--border-color); margin-bottom: 10px; }
|
||||
</style>
|
||||
|
||||
<main style="padding: 40px 20px; background: #0b0e11; min-height: 100vh;">
|
||||
<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="display: grid; grid-template-columns: 350px 1fr; gap: 30px;">
|
||||
<!-- Left Panel -->
|
||||
<div>
|
||||
<div style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color); text-align: center;">
|
||||
<div style="width: 100px; height: 100px; background: linear-gradient(135deg, #4facfe, #00f2fe); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; font-size: 2.5rem; font-weight: bold; color: white; box-shadow: 0 10px 20px rgba(79,172,254,0.2);">
|
||||
<?php echo strtoupper(substr($user['username'], 0, 1)); ?>
|
||||
</div>
|
||||
<h2 style="margin-bottom: 5px; color: white;"><?php echo $user['username']; ?></h2>
|
||||
<div style="background: rgba(255,255,255,0.05); display: inline-block; padding: 4px 15px; border-radius: 20px; color: var(--text-muted); font-size: 0.85rem; margin-bottom: 25px;">UID: <?php echo $user['uid'] ?: '618120'; ?></div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; padding-top: 25px; border-top: 1px solid var(--border-color);">
|
||||
<div>
|
||||
<div style="color: var(--text-muted); font-size: 0.8rem; margin-bottom: 5px;"><?php echo __('credit_score', '信用分'); ?></div>
|
||||
<div style="font-weight: bold; font-size: 1.2rem; color: var(--success-color);"><?php echo $user['credit_score'] ?? 100; ?></div>
|
||||
</div>
|
||||
<div style="border-left: 1px solid var(--border-color);">
|
||||
<div style="color: var(--text-muted); font-size: 0.8rem; margin-bottom: 5px;"><?php echo __('level', '等级'); ?></div>
|
||||
<div style="font-weight: bold; font-size: 1.2rem; color: #f0b90b;">VIP 0</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 25px; display: flex; flex-direction: column; gap: 15px;">
|
||||
<div style="background: var(--card-bg); padding: 20px; border-radius: 16px; border: 1px solid var(--border-color);">
|
||||
<a href="kyc.php" style="display: flex; align-items: center; justify-content: space-between; text-decoration: none; color: white;">
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<div style="width: 40px; height: 40px; background: rgba(79,172,254,0.1); border-radius: 10px; display: flex; align-items: center; justify-content: center; color: var(--primary-color);">
|
||||
<i class="fas fa-id-card"></i>
|
||||
</div>
|
||||
<span style="font-weight: 500;"><?php echo __('kyc_status', '实名认证'); ?></span>
|
||||
</div>
|
||||
<span style="font-size: 0.85rem; font-weight: bold; color: <?php echo $kyc_colors[$kyc_status]; ?>"><?php echo $kyc_labels[$kyc_status]; ?> <i class="fas fa-chevron-right" style="margin-left: 5px; font-size: 10px;"></i></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div style="background: var(--card-bg); padding: 20px; border-radius: 16px; border: 1px solid var(--border-color);">
|
||||
<a href="security.php" style="display: flex; align-items: center; justify-content: space-between; text-decoration: none; color: white;">
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<div style="width: 40px; height: 40px; background: rgba(14,203,129,0.1); border-radius: 10px; display: flex; align-items: center; justify-content: center; color: var(--success-color);">
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
</div>
|
||||
<span style="font-weight: 500;"><?php echo __('security_settings', '安全设置'); ?></span>
|
||||
</div>
|
||||
<i class="fas fa-chevron-right" style="color: var(--text-muted); font-size: 10px;"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 40px;">
|
||||
<div>
|
||||
<div style="color: var(--text-muted); margin-bottom: 10px; font-size: 14px;"><?php echo __('total_balance', '总资产'); ?> (USDT)</div>
|
||||
<div style="font-size: 3rem; font-weight: bold; letter-spacing: -1px; color: white;">
|
||||
<?php echo number_format($user['balance'] ?? 0, 2); ?>
|
||||
</div>
|
||||
<div style="color: var(--text-muted); font-size: 1rem; margin-top: 5px;">≈ $ <?php echo number_format($user['balance'] ?? 0, 2); ?></div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 15px;">
|
||||
<a href="deposit.php" class="btn-primary" style="padding: 12px 30px; border-radius: 10px; font-weight: bold;"><i class="fas fa-arrow-down" style="margin-right: 10px;"></i> <?php echo __('nav_deposit', '充值'); ?></a>
|
||||
<a href="withdraw.php" class="btn-primary" style="background: #2b3139; padding: 12px 30px; border-radius: 10px; font-weight: bold;"><i class="fas fa-arrow-up" style="margin-right: 10px;"></i> <?php echo __('nav_withdraw', '提现'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="profile-tabs">
|
||||
<button class="profile-tab-btn active" onclick="switchProfileTab(this, 'assets-tab')"><?php echo __('asset_details', '资产详情'); ?></button>
|
||||
<button class="profile-tab-btn" onclick="switchProfileTab(this, 'records-tab')"><?php echo __('transaction_records', '交易记录'); ?></button>
|
||||
</div>
|
||||
|
||||
<!-- Assets Tab -->
|
||||
<div id="assets-tab" class="tab-content">
|
||||
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||
<?php
|
||||
$coins = [
|
||||
['symbol' => 'USDT', 'name' => 'Tether', 'balance' => $user['balance'] ?? 0, 'price' => 1.00],
|
||||
['symbol' => 'BTC', 'name' => 'Bitcoin', 'balance' => 0.0000, 'price' => 0],
|
||||
['symbol' => 'ETH', 'name' => 'Ethereum', 'balance' => 0.0000, 'price' => 0],
|
||||
['symbol' => 'SOL', 'name' => 'Solana', 'balance' => 0.0000, 'price' => 0],
|
||||
['symbol' => 'BNB', 'name' => 'Binance Coin', 'balance' => 0.0000, 'price' => 0],
|
||||
];
|
||||
// Fetch real user assets if table exists
|
||||
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'], 'price' => 0];
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {}
|
||||
|
||||
foreach ($coins as $coin):
|
||||
?>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; padding: 20px; background: rgba(255,255,255,0.02); border-radius: 16px; border: 1px solid transparent; transition: 0.2s;" onmouseover="this.style.borderColor='var(--border-color)'; this.style.background='rgba(255,255,255,0.04)'" onmouseout="this.style.borderColor='transparent'; this.style.background='rgba(255,255,255,0.02)'">
|
||||
<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="40" height="40" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
||||
<div>
|
||||
<div style="font-weight: bold; font-size: 1.1rem; color: white;"><?php echo $coin['symbol']; ?></div>
|
||||
<div style="font-size: 0.8rem; color: var(--text-muted);"><?php echo $coin['name']; ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-weight: bold; font-family: monospace; font-size: 1.1rem; color: white;"><?php echo number_format($coin['balance'], $coin['symbol'] === 'USDT' ? 2 : 6); ?></div>
|
||||
<div style="font-size: 0.8rem; color: var(--text-muted);">USDT</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Records Tab -->
|
||||
<div id="records-tab" class="tab-content" style="display: none;">
|
||||
<div id="records-list">
|
||||
<div style="text-align: center; padding: 40px; color: var(--text-muted);">加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<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] = await Promise.all([
|
||||
fetch('api/get_orders.php?type=spot&status=history'),
|
||||
fetch('api/get_orders.php?type=futures&status=history')
|
||||
]);
|
||||
const spotRes = await spotResp.json();
|
||||
const futuresRes = await futuresResp.json();
|
||||
|
||||
let allRecords = [];
|
||||
if (spotRes.success) {
|
||||
spotRes.data.forEach(r => { r.trade_type = '现货'; allRecords.push(r); });
|
||||
}
|
||||
if (futuresRes.success) {
|
||||
futuresRes.data.forEach(r => { r.trade_type = '合约'; allRecords.push(r); });
|
||||
}
|
||||
|
||||
allRecords.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
||||
|
||||
if (allRecords.length === 0) {
|
||||
container.innerHTML = '<div style="text-align: center; padding: 40px; color: var(--text-muted);">暂无交易记录</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '';
|
||||
allRecords.forEach(r => {
|
||||
const isProfit = parseFloat(r.profit) > 0;
|
||||
const profitText = r.profit ? (isProfit ? '+' : '') + parseFloat(r.profit).toFixed(2) : '0.00';
|
||||
const profitColor = isProfit ? 'var(--success-color)' : (parseFloat(r.profit) < 0 ? 'var(--danger-color)' : 'var(--text-muted)');
|
||||
|
||||
html += `
|
||||
<div class="record-item">
|
||||
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
||||
<span style="font-weight: bold; color: white;">${r.symbol} <span style="font-size: 11px; background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 4px; margin-left: 5px;">${r.trade_type}</span></span>
|
||||
<span style="color: var(--text-muted); font-size: 12px;">${r.created_at}</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="font-size: 13px;">
|
||||
<span style="color: ${r.side === 'buy' ? 'var(--success-color)' : 'var(--danger-color)'}">${r.side === 'buy' ? '买入' : '卖出'}</span>
|
||||
<span style="color: var(--text-muted); margin-left: 10px;">价格: ${parseFloat(r.price).toLocaleString()}</span>
|
||||
<span style="color: var(--text-muted); margin-left: 10px;">数量: ${parseFloat(r.amount).toFixed(4)}</span>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-size: 11px; color: var(--text-muted);">盈亏</div>
|
||||
<div style="font-weight: bold; color: ${profitColor};">${profitText} USDT</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
container.innerHTML = html;
|
||||
} catch (e) {
|
||||
container.innerHTML = '<div style="text-align: center; padding: 40px; color: var(--danger-color);">加载失败</div>';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
95
register.php
Normal file
95
register.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?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 = "Please fill all fields.";
|
||||
} elseif ($password !== $confirm_password) {
|
||||
$error = "Passwords do 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 already taken.";
|
||||
} else {
|
||||
// Generate UID starting from 618120
|
||||
$stmt = $pdo->query("SELECT COUNT(*) FROM users");
|
||||
$count = $stmt->fetchColumn();
|
||||
$uid = 618120 + $count + mt_rand(1, 9); // Add a small random offset to make it look "randomly sorted" but starting from 618120
|
||||
|
||||
// Register and auto-login
|
||||
// Default trading_password is '123456' as requested
|
||||
$stmt = $pdo->prepare("INSERT INTO users (uid, username, password, trading_password, balance) VALUES (?, ?, ?, '123456', 0)");
|
||||
if ($stmt->execute([$uid, $username, password_hash($password, PASSWORD_DEFAULT)])) {
|
||||
$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;">Create Account</h2>
|
||||
<p style="text-align: center; color: var(--text-muted); margin-bottom: 40px;">Join NovaEx - The Leading Crypto Exchange</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;">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="Enter your email or 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;">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="Set your login 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;">Confirm Password</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="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;">I have read and agree to the <a href="privacy.php" style="color: var(--primary-color);">Privacy Policy</a> and <a href="terms.php" style="color: var(--primary-color);">Terms of Service</a>.</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);">Already have an 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
49
request.php
Normal 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
119
security.php
Normal 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'; ?>
|
||||
703
spot.php
Normal file
703
spot.php
Normal file
@ -0,0 +1,703 @@
|
||||
<?php
|
||||
session_start();
|
||||
include 'header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
$balance = 0;
|
||||
if ($user_id) {
|
||||
$stmt = db()->prepare("SELECT balance FROM users WHERE id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
$balance = $user['balance'] ?? 0;
|
||||
}
|
||||
?>
|
||||
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
:root {
|
||||
--bg-color: #0b0e11;
|
||||
--panel-bg: #161a1e;
|
||||
--border-color: #2b3139;
|
||||
--text-primary: #EAECEF;
|
||||
--text-secondary: #848e9c;
|
||||
--accent-color: #f0b90b;
|
||||
--up-color: #00c087;
|
||||
--down-color: #f6465d;
|
||||
--input-bg: #1e2329;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-primary);
|
||||
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||
margin: 0;
|
||||
overflow: hidden; /* Prevent whole page scroll */
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.trading-layout {
|
||||
display: flex;
|
||||
height: calc(100vh - 64px); /* Fixed height excluding navbar */
|
||||
gap: 1px;
|
||||
background: var(--border-color);
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background: var(--panel-bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%; /* Fill the layout height */
|
||||
}
|
||||
|
||||
/* Left: Markets - Scrollable */
|
||||
.market-panel {
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.search-box { padding: 12px; border-bottom: 1px solid var(--border-color); width: 100%; position: sticky; top: 0; background: var(--panel-bg); z-index: 5; }
|
||||
.search-input-wrapper { position: relative; width: 100%; }
|
||||
.search-input-wrapper input { width: 100%; background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 6px 12px 6px 32px; border-radius: 4px; font-size: 13px; outline: none; display: block; }
|
||||
.search-input-wrapper i { position: absolute; left: 10px; top: 9px; color: var(--text-secondary); }
|
||||
.pairs-list-header { display: flex; padding: 8px 12px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); position: sticky; top: 57px; background: var(--panel-bg); z-index: 5; }
|
||||
.pair-item { display: flex; justify-content: space-between; padding: 8px 12px; cursor: pointer; transition: background 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
|
||||
.pair-item:hover { background: rgba(255,255,255,0.05); }
|
||||
.pair-item.active { background: rgba(240, 185, 11, 0.1); }
|
||||
|
||||
/* Center: Chart (Fixed) and scrollable content below */
|
||||
.center-panel {
|
||||
flex: 1;
|
||||
overflow: hidden; /* Internal scroll only */
|
||||
}
|
||||
.info-bar { height: 50px; display: flex; align-items: center; padding: 0 15px; gap: 20px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; background: var(--panel-bg); }
|
||||
.chart-container { height: 350px; background: var(--bg-color); flex-shrink: 0; border-bottom: 1px solid var(--border-color); }
|
||||
|
||||
/* Scrollable content below chart */
|
||||
.center-content-scroll {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.order-placement-panel { display: flex; gap: 20px; padding: 20px; border-bottom: 1px solid var(--border-color); background: var(--panel-bg); }
|
||||
.order-side-column { flex: 1; }
|
||||
.order-type-tabs { display: flex; gap: 15px; margin-bottom: 15px; }
|
||||
.order-type-btn { background: none; border: none; color: var(--text-secondary); font-size: 14px; cursor: pointer; padding: 0; }
|
||||
.order-type-btn.active { color: var(--accent-color); font-weight: bold; }
|
||||
.input-row { background: var(--input-bg); border: 1px solid var(--border-color); border-radius: 4px; display: flex; align-items: center; margin-bottom: 10px; padding: 8px 12px; }
|
||||
.input-label { color: var(--text-secondary); font-size: 13px; width: 50px; }
|
||||
.input-row input { flex: 1; background: transparent; border: none; color: white; text-align: right; outline: none; font-size: 14px; }
|
||||
.input-row input:disabled { color: var(--text-secondary); cursor: not-allowed; }
|
||||
.input-unit { color: var(--text-secondary); font-size: 12px; margin-left: 8px; width: 40px; text-align: right; }
|
||||
|
||||
.slider-container { margin: 15px 0 25px 0; padding: 0 5px; position: relative; }
|
||||
.slider-marks { display: flex; justify-content: space-between; margin-top: -10px; position: relative; padding: 0 8px; pointer-events: none; }
|
||||
.mark-dot { width: 8px; height: 8px; background: var(--border-color); border: 2px solid var(--input-bg); border-radius: 50%; cursor: pointer; z-index: 2; pointer-events: auto; transform: translateY(-2px); }
|
||||
.mark-dot.active { background: var(--accent-color); border-color: var(--accent-color); }
|
||||
.slider-labels { display: flex; justify-content: space-between; margin-top: 8px; padding: 0 2px; }
|
||||
.label-item { color: var(--text-secondary); font-size: 10px; cursor: pointer; user-select: none; width: 20px; text-align: center; }
|
||||
.label-item.active { color: var(--text-primary); }
|
||||
|
||||
.execute-btn { width: 100%; padding: 12px; border: none; border-radius: 4px; font-weight: bold; font-size: 15px; cursor: pointer; color: white; transition: opacity 0.2s; }
|
||||
.execute-btn:active { opacity: 0.8; }
|
||||
.execute-btn.buy { background: var(--up-color); }
|
||||
.execute-btn.sell { background: var(--down-color); }
|
||||
|
||||
.bottom-tabs { min-height: 400px; }
|
||||
.tabs-header { display: flex; border-bottom: 1px solid var(--border-color); padding: 0 15px; position: sticky; top: 0; background: var(--panel-bg); z-index: 9; }
|
||||
.tab-btn { background: none; border: none; color: var(--text-secondary); padding: 12px 15px; font-size: 14px; cursor: pointer; border-bottom: 2px solid transparent; }
|
||||
.tab-btn.active { color: var(--accent-color); border-bottom-color: var(--accent-color); }
|
||||
|
||||
/* Right: Order Book - Scrollable */
|
||||
.order-book-panel {
|
||||
width: 300px;
|
||||
flex-shrink: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.order-book-header { padding: 10px 15px; font-size: 12px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; position: sticky; top: 0; background: var(--panel-bg); z-index: 5; }
|
||||
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; }
|
||||
.ob-bar { position: absolute; right: 0; top: 0; bottom: 0; z-index: 0; }
|
||||
.ob-val { z-index: 1; position: relative; }
|
||||
|
||||
input[type=range] { -webkit-appearance: none; width: 100%; background: transparent; margin: 0; padding: 0; }
|
||||
input[type=range]:focus { outline: none; }
|
||||
input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; background: var(--border-color); border-radius: 2px; }
|
||||
input[type=range]::-webkit-slider-thumb { height: 14px; width: 14px; border-radius: 50%; background: white; cursor: pointer; -webkit-appearance: none; margin-top: -5px; box-shadow: 0 0 2px rgba(0,0,0,0.5); border: 2px solid var(--accent-color); z-index: 3; position: relative; }
|
||||
|
||||
::-webkit-scrollbar { width: 4px; }
|
||||
::-webkit-scrollbar-thumb { background: #333; border-radius: 10px; }
|
||||
|
||||
#pairs-list { }
|
||||
</style>
|
||||
|
||||
<div class="trading-layout">
|
||||
<!-- Left Panel -->
|
||||
<div class="panel market-panel">
|
||||
<div class="search-box">
|
||||
<div class="search-input-wrapper">
|
||||
<i class="fas fa-search"></i>
|
||||
<input type="text" id="market-search" placeholder="搜索币种" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="pairs-list-header">
|
||||
<span style="flex: 1.5;">币对</span>
|
||||
<span style="flex: 1; text-align: right;">价格</span>
|
||||
<span style="flex: 1; text-align: right;">涨跌</span>
|
||||
</div>
|
||||
<div id="pairs-list"></div>
|
||||
</div>
|
||||
|
||||
<!-- Center Panel -->
|
||||
<div class="panel center-panel">
|
||||
<div class="info-bar">
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<img id="current-logo" src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/btc.png" width="24" height="24" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
||||
<span id="current-pair-display" style="font-size: 16px; font-weight: bold;">BTC/USDT</span>
|
||||
</div>
|
||||
<div id="last-price" style="font-size: 16px; font-weight: bold; color: var(--up-color);">--</div>
|
||||
<div id="price-change" style="font-size: 12px; color: var(--up-color);">--</div>
|
||||
<div style="display: flex; gap: 20px; margin-left: auto; font-size: 12px;">
|
||||
<div style="color: var(--text-secondary);">24h高 <span id="high-24h" style="color: white; margin-left: 4px;">--</span></div>
|
||||
<div style="color: var(--text-secondary);">24h低 <span id="low-24h" style="color: white; margin-left: 4px;">--</span></div>
|
||||
<div style="color: var(--text-secondary);">24h量 <span id="vol-24h" style="color: white; margin-left: 4px;">--</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<div id="tv_chart_container" style="height: 100%;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Scrollable content below chart -->
|
||||
<div class="center-content-scroll">
|
||||
<div class="order-placement-panel">
|
||||
<div class="order-side-column" id="buy-column">
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn" id="buy-limit-btn" onclick="setOrderType('buy', 'limit')">限价买入</button>
|
||||
<button class="order-type-btn active" id="buy-market-btn" onclick="setOrderType('buy', 'market')">市价买入</button>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">买入 <span class="asset-name">BTC</span></span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="buy-available" style="color: white;">--</span> USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="buy-price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="buy-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="buy-market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" id="buy-market-price-display" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="buy-amount" placeholder="0.00" step="0.0001">
|
||||
<span class="input-unit asset-name">BTC</span>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input type="range" min="0" max="100" value="0" id="buy-slider" oninput="updateFromSlider('buy', this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider('buy', 0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 100)"></div>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider('buy', 0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 100)">100%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">交易额</span>
|
||||
<span><span id="buy-total">0.00</span> USDT</span>
|
||||
</div>
|
||||
<button class="execute-btn buy" onclick="placeOrder('buy')">买入 BTC</button>
|
||||
</div>
|
||||
|
||||
<div class="order-side-column" id="sell-column">
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn active" id="sell-limit-btn" onclick="setOrderType('sell', 'limit')">限价卖出</button>
|
||||
<button class="order-type-btn" id="sell-market-btn" onclick="setOrderType('sell', 'market')">市价卖出</button>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">卖出 <span class="asset-name">BTC</span></span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="sell-available" style="color: white;">--</span> <span class="asset-name">BTC</span></span>
|
||||
</div>
|
||||
<div class="input-row" id="sell-price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="sell-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="sell-market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" id="sell-market-price-display" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="sell-amount" placeholder="0.00" step="0.0001">
|
||||
<span class="input-unit asset-name">BTC</span>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input type="range" min="0" max="100" value="0" id="sell-slider" oninput="updateFromSlider('sell', this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider('sell', 0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 100)"></div>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider('sell', 0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 100)">100%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">成交总计</span>
|
||||
<span><span id="sell-total">0.00</span> USDT</span>
|
||||
</div>
|
||||
<button class="execute-btn sell" onclick="placeOrder('sell')">卖出 BTC</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bottom-tabs">
|
||||
<div class="tabs-header">
|
||||
<button class="tab-btn active" id="tab-open" onclick="switchTab(this, 'open')">当前委托</button>
|
||||
<button class="tab-btn" id="tab-history" onclick="switchTab(this, 'history')">历史委托</button>
|
||||
<button class="tab-btn" id="tab-assets" onclick="switchTab(this, 'assets')">资产余额</button>
|
||||
</div>
|
||||
<div id="tab-content-area" style="padding: 15px;">
|
||||
<table id="orders-table" style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||
<thead style="color: var(--text-secondary); text-align: left;">
|
||||
<tr id="table-header">
|
||||
<th style="padding: 8px;">时间</th>
|
||||
<th style="padding: 8px;">币对</th>
|
||||
<th style="padding: 8px;">类型</th>
|
||||
<th style="padding: 8px;">方向</th>
|
||||
<th style="padding: 8px;">价格</th>
|
||||
<th style="padding: 8px;">数量</th>
|
||||
<th style="padding: 8px;">状态</th>
|
||||
<th style="padding: 8px; text-align: right;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="orders-tbody">
|
||||
<tr><td colspan="8" style="text-align: center; padding: 40px; color: var(--text-secondary);">暂无记录</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div class="panel order-book-panel">
|
||||
<div class="order-book-header">
|
||||
<span>价格(USDT)</span>
|
||||
<span>数量(BTC)</span>
|
||||
</div>
|
||||
<div id="asks-list" style="display: flex; flex-direction: column-reverse;"></div>
|
||||
<div id="mid-price-container" style="padding: 10px 15px; border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); text-align: center;">
|
||||
<div id="ob-mid-price" style="font-size: 16px; font-weight: bold;">--</div>
|
||||
<div id="ob-index-price" style="font-size: 11px; color: var(--text-secondary);">指数价格 --</div>
|
||||
</div>
|
||||
<div id="bids-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
|
||||
<script>
|
||||
let currentPair = 'BTCUSDT';
|
||||
let currentPrice = 0;
|
||||
let usdtBalance = 0;
|
||||
let userAssets = {};
|
||||
let marketData = {};
|
||||
let orderTypes = { buy: 'market', sell: 'limit' };
|
||||
let activeTab = 'open';
|
||||
|
||||
const pairs = [
|
||||
'BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'AVAXUSDT', 'TRXUSDT', 'DOTUSDT',
|
||||
'LINKUSDT', 'PEPEUSDT', 'SHIBUSDT', 'NEARUSDT', 'LTCUSDT', 'MATICUSDT', 'UNIUSDT', 'ATOMUSDT', 'ETCUSDT', 'FILUSDT',
|
||||
'APTUSDT', 'ARBUSDT', 'OPUSDT', 'TIAUSDT', 'ORDIUSDT', 'SUIUSDT', 'RNDRUSDT', 'FETUSDT', 'AGIXUSDT', 'WLDUSDT',
|
||||
'LDOUSDT', 'AAVEUSDT', 'MKRUSDT', 'GMXUSDT', 'SNXUSDT', 'STXUSDT', 'IMXUSDT', 'KASUSDT', 'INJUSDT', 'RUNEUSDT',
|
||||
'ICPUSDT', 'SEIUSDT', 'BONKUSDT', 'FLOKIUSDT', 'BCHUSDT', 'DYDXUSDT', 'CRVUSDT', 'GRTUSDT', 'FTMUSDT'
|
||||
];
|
||||
|
||||
function initChart(symbol) {
|
||||
new TradingView.widget({
|
||||
"width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "15", "timezone": "Etc/UTC", "theme": "dark", "style": "1", "locale": "zh_CN", "container_id": "tv_chart_container", "backgroundColor": "#0b0e11", "gridColor": "rgba(42, 46, 57, 0.05)", "hide_side_toolbar": true, "allow_symbol_change": false, "save_image": false, "toolbar_bg": "#161a1e"
|
||||
});
|
||||
}
|
||||
initChart(currentPair);
|
||||
|
||||
let ws;
|
||||
function connectWS() {
|
||||
if (ws) ws.close();
|
||||
const streams = pairs.map(p => p.toLowerCase() + '@ticker').join('/');
|
||||
ws = new WebSocket(`wss://stream.binance.com:9443/ws/${streams}`);
|
||||
ws.onmessage = (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
marketData[data.s] = data;
|
||||
renderPairs();
|
||||
if (data.s === currentPair) {
|
||||
updateUIWithData(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
connectWS();
|
||||
|
||||
function updateUIWithData(data) {
|
||||
currentPrice = parseFloat(data.c);
|
||||
document.getElementById('last-price').innerText = currentPrice.toLocaleString();
|
||||
document.getElementById('last-price').style.color = data.P >= 0 ? 'var(--up-color)' : 'var(--down-color)';
|
||||
document.getElementById('ob-mid-price').innerText = currentPrice.toLocaleString();
|
||||
document.getElementById('ob-mid-price').style.color = data.P >= 0 ? 'var(--up-color)' : 'var(--down-color)';
|
||||
document.getElementById('price-change').innerText = (data.P >= 0 ? '+' : '') + data.P + '%';
|
||||
document.getElementById('price-change').style.color = data.P >= 0 ? 'var(--up-color)' : 'var(--down-color)';
|
||||
document.getElementById('high-24h').innerText = parseFloat(data.h).toLocaleString();
|
||||
document.getElementById('low-24h').innerText = parseFloat(data.l).toLocaleString();
|
||||
document.getElementById('vol-24h').innerText = parseFloat(data.v).toLocaleString();
|
||||
|
||||
document.getElementById('buy-market-price-display').value = currentPrice.toFixed(2);
|
||||
document.getElementById('sell-market-price-display').value = currentPrice.toFixed(2);
|
||||
|
||||
updateOrderBook();
|
||||
|
||||
const bp = document.getElementById('buy-price');
|
||||
const sp = document.getElementById('sell-price');
|
||||
if (!bp.value || bp.getAttribute('data-auto') === 'true') {
|
||||
bp.value = currentPrice;
|
||||
bp.setAttribute('data-auto', 'true');
|
||||
}
|
||||
if (!sp.value || sp.getAttribute('data-auto') === 'true') {
|
||||
sp.value = currentPrice;
|
||||
sp.setAttribute('data-auto', 'true');
|
||||
}
|
||||
|
||||
if (orderTypes.buy === 'market') updateFromSlider('buy', document.getElementById('buy-slider').value);
|
||||
if (orderTypes.sell === 'market') updateFromSlider('sell', document.getElementById('sell-slider').value);
|
||||
}
|
||||
|
||||
function renderPairs() {
|
||||
const list = document.getElementById('pairs-list');
|
||||
if (!list) return;
|
||||
const search = document.getElementById('market-search').value.toUpperCase();
|
||||
let html = '';
|
||||
pairs.forEach(p => {
|
||||
if (search && !p.includes(search)) return;
|
||||
const d = marketData[p] || {c: 0, P: 0};
|
||||
const name = p.replace('USDT', '');
|
||||
html += `
|
||||
<div class="pair-item ${currentPair === p ? 'active' : ''}" onclick="switchPair('${p}')">
|
||||
<div style="display: flex; align-items: center; gap: 8px; flex: 1.5;">
|
||||
<img src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png" width="18" height="18" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
||||
<span style="font-weight: 500; font-size: 13px;">${name}/USDT</span>
|
||||
</div>
|
||||
<span style="flex: 1; text-align: right; font-size: 13px;">${parseFloat(d.c).toLocaleString()}</span>
|
||||
<span style="flex: 1; text-align: right; font-size: 13px; color: ${d.P >= 0 ? 'var(--up-color)' : 'var(--down-color)'}">${(d.P >= 0 ? '+' : '') + d.P}%</span>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
list.innerHTML = html;
|
||||
}
|
||||
|
||||
async function fetchAssets() {
|
||||
const resp = await fetch('api/get_assets.php');
|
||||
const res = await resp.json();
|
||||
if (res.success) {
|
||||
userAssets = {};
|
||||
res.data.forEach(a => {
|
||||
userAssets[a.symbol] = parseFloat(a.amount);
|
||||
});
|
||||
usdtBalance = userAssets['USDT'] || 0;
|
||||
updateAvailableDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
function updateAvailableDisplay() {
|
||||
const coin = currentPair.replace('USDT', '');
|
||||
document.getElementById('buy-available').innerText = usdtBalance.toFixed(2);
|
||||
document.getElementById('sell-available').innerText = (userAssets[coin] || 0).toFixed(6);
|
||||
}
|
||||
|
||||
function switchPair(p) {
|
||||
currentPair = p;
|
||||
const name = p.replace('USDT', '');
|
||||
document.getElementById('current-pair-display').innerText = name + '/USDT';
|
||||
document.getElementById('current-logo').src = `https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png`;
|
||||
|
||||
document.querySelectorAll('.asset-name').forEach(el => { el.innerText = name; });
|
||||
document.querySelector('.execute-btn.buy').innerText = '买入 ' + name;
|
||||
document.querySelector('.execute-btn.sell').innerText = '卖出 ' + name;
|
||||
|
||||
updateAvailableDisplay();
|
||||
|
||||
if (marketData[p]) {
|
||||
updateUIWithData(marketData[p]);
|
||||
} else {
|
||||
document.getElementById('last-price').innerText = '--';
|
||||
document.getElementById('buy-price').value = '';
|
||||
document.getElementById('sell-price').value = '';
|
||||
}
|
||||
|
||||
document.getElementById('buy-price').setAttribute('data-auto', 'true');
|
||||
document.getElementById('sell-price').setAttribute('data-auto', 'true');
|
||||
|
||||
document.getElementById('buy-amount').value = '';
|
||||
document.getElementById('sell-amount').value = '';
|
||||
document.getElementById('buy-slider').value = 0;
|
||||
document.getElementById('sell-slider').value = 0;
|
||||
document.getElementById('buy-total').innerText = '0.00';
|
||||
document.getElementById('sell-total').innerText = '0.00';
|
||||
updateSliderMarks('buy', 0);
|
||||
updateSliderMarks('sell', 0);
|
||||
|
||||
initChart(p);
|
||||
renderPairs();
|
||||
}
|
||||
|
||||
function setOrderType(side, type) {
|
||||
orderTypes[side] = type;
|
||||
document.getElementById(`${side}-limit-btn`).classList.toggle('active', type === 'limit');
|
||||
document.getElementById(`${side}-market-btn`).classList.toggle('active', type === 'market');
|
||||
document.getElementById(`${side}-price-row`).style.display = type === 'limit' ? 'flex' : 'none';
|
||||
document.getElementById(`${side}-market-price-row`).style.display = type === 'market' ? 'flex' : 'none';
|
||||
updateFromSlider(side, document.getElementById(side + '-slider').value);
|
||||
}
|
||||
|
||||
function updateOrderBook() {
|
||||
const asks = document.getElementById('asks-list');
|
||||
const bids = document.getElementById('bids-list');
|
||||
if (!asks || !bids) return;
|
||||
let asksHtml = ''; let bidsHtml = '';
|
||||
const step = currentPrice * 0.0002;
|
||||
for(let i=0; i<15; i++) {
|
||||
const askPrice = currentPrice + (i + 1) * step;
|
||||
const bidPrice = currentPrice - (i + 1) * step;
|
||||
asksHtml += `<div class="ob-row"><div class="ob-bar" style="background: rgba(246, 70, 93, 0.1); width: ${Math.random()*100}%;"></div><span class="ob-val" style="color: var(--down-color);">${askPrice.toFixed(2)}</span><span class="ob-val">${(Math.random()*2).toFixed(4)}</span></div>`;
|
||||
bidsHtml += `<div class="ob-row"><div class="ob-bar" style="background: rgba(0, 192, 135, 0.1); width: ${Math.random()*100}%;"></div><span class="ob-val" style="color: var(--up-color);">${bidPrice.toFixed(2)}</span><span class="ob-val">${(Math.random()*2).toFixed(4)}</span></div>`;
|
||||
}
|
||||
asks.innerHTML = asksHtml; bids.innerHTML = bidsHtml;
|
||||
}
|
||||
|
||||
function updateFromSlider(side, val) {
|
||||
val = parseFloat(val);
|
||||
const isBuy = side === 'buy';
|
||||
const isLimit = orderTypes[side] === 'limit';
|
||||
const price = isLimit ? (parseFloat(document.getElementById(side + '-price').value) || currentPrice) : currentPrice;
|
||||
const coin = currentPair.replace('USDT', '');
|
||||
|
||||
if (isBuy) {
|
||||
const totalUSDT = usdtBalance * (val / 100);
|
||||
const amount = price > 0 ? (totalUSDT / price) : 0;
|
||||
document.getElementById('buy-amount').value = amount > 0 ? amount.toFixed(6) : '';
|
||||
document.getElementById('buy-total').innerText = totalUSDT.toFixed(2);
|
||||
} else {
|
||||
const coinBal = userAssets[coin] || 0;
|
||||
const amount = coinBal * (val / 100);
|
||||
const totalUSDT = amount * price;
|
||||
document.getElementById('sell-amount').value = amount > 0 ? amount.toFixed(6) : '';
|
||||
document.getElementById('sell-total').innerText = totalUSDT.toFixed(2);
|
||||
}
|
||||
updateSliderMarks(side, val);
|
||||
}
|
||||
|
||||
function updateFromInputs(side) {
|
||||
const isBuy = side === 'buy';
|
||||
const isLimit = orderTypes[side] === 'limit';
|
||||
const priceInput = document.getElementById(side + '-price');
|
||||
const price = isLimit ? (parseFloat(priceInput.value) || currentPrice) : currentPrice;
|
||||
const amount = parseFloat(document.getElementById(side + '-amount').value) || 0;
|
||||
const coin = currentPair.replace('USDT', '');
|
||||
|
||||
const total = price * amount;
|
||||
if (isBuy) {
|
||||
document.getElementById('buy-total').innerText = total.toFixed(2);
|
||||
} else {
|
||||
document.getElementById('sell-total').innerText = total.toFixed(2);
|
||||
}
|
||||
|
||||
let percentage = 0;
|
||||
if (isBuy) {
|
||||
percentage = usdtBalance > 0 ? (total / usdtBalance) * 100 : 0;
|
||||
} else {
|
||||
const coinBal = userAssets[coin] || 0;
|
||||
percentage = coinBal > 0 ? (amount / coinBal) * 100 : 0;
|
||||
}
|
||||
percentage = Math.min(Math.max(percentage, 0), 100);
|
||||
document.getElementById(side + '-slider').value = percentage;
|
||||
updateSliderMarks(side, percentage);
|
||||
}
|
||||
|
||||
function updateSliderMarks(side, val) {
|
||||
const column = document.getElementById(side + '-column');
|
||||
const marks = column.querySelectorAll('.mark-dot');
|
||||
const labels = column.querySelectorAll('.label-item');
|
||||
marks.forEach((m, i) => { if (i * 25 <= val) m.classList.add('active'); else m.classList.remove('active'); });
|
||||
labels.forEach((l, i) => { if (Math.abs(i * 25 - val) < 5) l.classList.add('active'); else l.classList.remove('active'); });
|
||||
}
|
||||
|
||||
function setSlider(side, val) {
|
||||
document.getElementById(side + '-slider').value = val;
|
||||
updateFromSlider(side, val);
|
||||
}
|
||||
|
||||
['buy', 'sell'].forEach(side => {
|
||||
document.getElementById(side + '-price').addEventListener('input', (e) => {
|
||||
e.target.setAttribute('data-auto', 'false');
|
||||
updateFromInputs(side);
|
||||
});
|
||||
document.getElementById(side + '-amount').addEventListener('input', () => updateFromInputs(side));
|
||||
});
|
||||
|
||||
async function placeOrder(side) {
|
||||
const type = orderTypes[side];
|
||||
const priceInput = document.getElementById(side + '-price').value;
|
||||
const amount = parseFloat(document.getElementById(side + '-amount').value);
|
||||
if (!amount) return alert('请输入数量');
|
||||
const price = type === 'limit' ? (priceInput ? parseFloat(priceInput) : currentPrice) : currentPrice;
|
||||
|
||||
const response = await fetch('api/place_order.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
symbol: currentPair, type: 'spot', side: side,
|
||||
order_type: type,
|
||||
price: price, amount: amount, total: price * amount,
|
||||
tp_price: currentPrice
|
||||
})
|
||||
});
|
||||
const res = await response.json();
|
||||
if (res.success) {
|
||||
alert('下单成功');
|
||||
fetchAssets();
|
||||
fetchOrders();
|
||||
} else {
|
||||
alert('失败: ' + res.error);
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchOrders() {
|
||||
if (activeTab === 'assets') return fetchAssetsList();
|
||||
|
||||
const response = await fetch(`api/get_orders.php?type=spot&status=${activeTab}`);
|
||||
const res = await response.json();
|
||||
const tbody = document.getElementById('orders-tbody');
|
||||
const thead = document.getElementById('table-header');
|
||||
if (!tbody || !thead) return;
|
||||
|
||||
thead.innerHTML = `
|
||||
<th style="padding: 8px;">时间</th>
|
||||
<th style="padding: 8px;">币对</th>
|
||||
<th style="padding: 8px;">类型</th>
|
||||
<th style="padding: 8px;">方向</th>
|
||||
<th style="padding: 8px;">价格</th>
|
||||
<th style="padding: 8px;">数量</th>
|
||||
<th style="padding: 8px;">状态</th>
|
||||
<th style="padding: 8px; text-align: right;">操作</th>
|
||||
`;
|
||||
|
||||
if (res.success && res.data.length > 0) {
|
||||
let html = '';
|
||||
res.data.forEach(o => {
|
||||
let statusText = '';
|
||||
if (o.status === 'open') statusText = '进行中';
|
||||
else if (o.status === 'closed') statusText = '已成交';
|
||||
else statusText = '已取消';
|
||||
|
||||
html += `
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 10px 8px;">${o.created_at}</td>
|
||||
<td style="padding: 10px 8px; font-weight: bold;">${o.symbol}</td>
|
||||
<td style="padding: 10px 8px;">${o.order_type === 'market' ? '市价' : '限价'}</td>
|
||||
<td style="padding: 10px 8px; color: ${o.side === 'buy' ? 'var(--up-color)' : 'var(--down-color)'}">${o.side === 'buy' ? '买入' : '卖出'}</td>
|
||||
<td style="padding: 10px 8px;">${parseFloat(o.price).toLocaleString()}</td>
|
||||
<td style="padding: 10px 8px;">${parseFloat(o.amount).toFixed(6)}</td>
|
||||
<td style="padding: 10px 8px;">${statusText}</td>
|
||||
<td style="padding: 10px 8px; text-align: right;">
|
||||
${o.status === 'open' ? `<button onclick="cancelOrder(${o.id})" style="background: none; border: 1px solid var(--down-color); color: var(--down-color); padding: 2px 8px; border-radius: 4px; cursor: pointer;">取消</button>` : '--'}
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
tbody.innerHTML = html;
|
||||
} else {
|
||||
tbody.innerHTML = '<tr><td colspan="8" style="text-align: center; padding: 40px; color: var(--text-secondary);">暂无记录</td></tr>';
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchAssetsList() {
|
||||
await fetchAssets();
|
||||
const tbody = document.getElementById('orders-tbody');
|
||||
const thead = document.getElementById('table-header');
|
||||
if (!tbody || !thead) return;
|
||||
|
||||
thead.innerHTML = `
|
||||
<th style="padding: 8px;">资产</th>
|
||||
<th style="padding: 8px;">可用</th>
|
||||
<th style="padding: 8px;">冻结</th>
|
||||
<th style="padding: 8px;">折合(USDT)</th>
|
||||
<th style="padding: 8px; text-align: right;">操作</th>
|
||||
`;
|
||||
|
||||
let html = '';
|
||||
const assets = Object.entries(userAssets).filter(([sym, amt]) => amt > 0 || sym === 'USDT');
|
||||
assets.forEach(([sym, amt]) => {
|
||||
let price = 1;
|
||||
if (sym !== 'USDT') {
|
||||
const pair = sym + 'USDT';
|
||||
price = marketData[pair] ? parseFloat(marketData[pair].c) : 0;
|
||||
}
|
||||
html += `
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 10px 8px; font-weight: bold;">${sym}</td>
|
||||
<td style="padding: 10px 8px;">${amt.toFixed(sym === 'USDT' ? 2 : 6)}</td>
|
||||
<td style="padding: 10px 8px;">0.00</td>
|
||||
<td style="padding: 10px 8px;">${(amt * price).toFixed(2)}</td>
|
||||
<td style="padding: 10px 8px; text-align: right;">
|
||||
<button onclick="switchPair('${sym}USDT')" style="background: none; border: 1px solid var(--accent-color); color: var(--accent-color); padding: 2px 8px; border-radius: 4px; cursor: pointer;">去交易</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
tbody.innerHTML = html || '<tr><td colspan="5" style="text-align: center; padding: 40px; color: var(--text-secondary);">暂无资产</td></tr>';
|
||||
}
|
||||
|
||||
function switchTab(btn, tab) {
|
||||
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
activeTab = tab;
|
||||
fetchOrders();
|
||||
}
|
||||
|
||||
async function cancelOrder(id) {
|
||||
if (!confirm('确定取消订单吗?')) return;
|
||||
const resp = await fetch('api/cancel_order.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({order_id: id})
|
||||
});
|
||||
if ((await resp.json()).success) {
|
||||
fetchAssets();
|
||||
fetchOrders();
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('market-search').addEventListener('input', renderPairs);
|
||||
fetchAssets();
|
||||
fetchOrders();
|
||||
setInterval(() => {
|
||||
if (activeTab === 'assets') fetchAssetsList();
|
||||
else fetchOrders();
|
||||
}, 5000);
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
44
status.php
Normal file
44
status.php
Normal 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
44
terms.php
Normal 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'; ?>
|
||||
136
withdraw.php
Normal file
136
withdraw.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?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') {
|
||||
$amount = $_POST['amount'];
|
||||
$address = $_POST['address'];
|
||||
$network = $_POST['network'];
|
||||
$trading_pass = $_POST['trading_password'];
|
||||
|
||||
if ($trading_pass !== $user['trading_password']) {
|
||||
$error = "Incorrect trading password";
|
||||
} elseif ($amount > $user['balance']) {
|
||||
$error = "Insufficient balance";
|
||||
} elseif ($amount < 10) {
|
||||
$error = "Minimum withdrawal amount is 10 USDT";
|
||||
} else {
|
||||
// Process withdrawal (simplified)
|
||||
$db->beginTransaction();
|
||||
try {
|
||||
$stmt = $db->prepare("UPDATE users SET balance = balance - ? WHERE id = ?");
|
||||
$stmt->execute([$amount, $_SESSION['user_id']]);
|
||||
|
||||
// Log as a special type of order or transaction
|
||||
$stmt = $db->prepare("INSERT INTO orders (user_id, type, amount, currency, account_info, status) VALUES (?, 'usdt', ?, 'USDT', ?, 'pending')");
|
||||
$stmt->execute([$_SESSION['user_id'], $amount, "Network: $network, Address: $address"]);
|
||||
|
||||
$db->commit();
|
||||
$message = "Withdrawal request submitted successfully. Please wait for audit.";
|
||||
// Refresh user data
|
||||
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$user = $stmt->fetch();
|
||||
} catch (Exception $e) {
|
||||
$db->rollBack();
|
||||
$error = "System error, please try again later";
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<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> <?php echo __('nav_profile'); ?></a>
|
||||
|
||||
<div style="margin-bottom: 40px;">
|
||||
<h1 style="font-size: 2.5rem; font-weight: bold; margin-bottom: 10px;"><?php echo __('withdraw_assets'); ?></h1>
|
||||
<p style="color: var(--text-muted);"><?php echo __('withdraw_tip'); ?></p>
|
||||
</div>
|
||||
|
||||
<?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);">
|
||||
<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: 15px; border-radius: 8px; margin-bottom: 20px; border: 1px solid var(--danger-color);">
|
||||
<i class="fas fa-exclamation-circle"></i> <?php echo $error; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1.5fr 1fr; gap: 30px;">
|
||||
<div style="background: var(--card-bg); padding: 35px; border-radius: 24px; border: 1px solid var(--border-color);">
|
||||
<form method="POST">
|
||||
<div style="margin-bottom: 25px;">
|
||||
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('select_network'); ?></label>
|
||||
<select name="network" style="width: 100%; padding: 14px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; outline: none;">
|
||||
<option value="TRC20">USDT - TRC20 (Recommended)</option>
|
||||
<option value="ERC20">USDT - ERC20</option>
|
||||
<option value="BEP20">USDT - BEP20 (BSC)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 25px;">
|
||||
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('withdraw_address'); ?></label>
|
||||
<input type="text" name="address" placeholder="Paste your USDT wallet address" required style="width: 100%; padding: 14px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; outline: none;">
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 25px;">
|
||||
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('amount'); ?></label>
|
||||
<div style="position: relative;">
|
||||
<input type="number" name="amount" id="withdraw-amount" placeholder="Min. 10" step="0.01" required style="width: 100%; padding: 14px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; outline: none;">
|
||||
<span onclick="document.getElementById('withdraw-amount').value = '<?php echo $user['balance']; ?>'" style="position: absolute; right: 20px; top: 50%; transform: translateY(-50%); color: var(--primary-color); font-weight: bold; cursor: pointer; font-size: 12px;"><?php echo __('max'); ?></span>
|
||||
</div>
|
||||
<div style="margin-top: 8px; font-size: 12px; color: var(--text-muted);">
|
||||
<?php echo __('available_balance'); ?>: <span style="color: white; font-weight: bold;"><?php echo number_format($user['balance'], 2); ?> USDT</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 30px;">
|
||||
<label style="display: block; margin-bottom: 10px; color: var(--text-muted); font-size: 14px;"><?php echo __('trading_password'); ?></label>
|
||||
<input type="password" name="trading_password" placeholder="Enter 6-digit trading password" required style="width: 100%; padding: 14px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; outline: none;">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn-primary" style="width: 100%; padding: 16px; font-size: 1.1rem; border-radius: 12px; background: var(--danger-color);"><?php echo __('submit_withdrawal'); ?></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div style="background: rgba(240,185,11,0.05); padding: 25px; border-radius: 20px; border: 1px solid rgba(240,185,11,0.1); margin-bottom: 20px;">
|
||||
<h4 style="color: #f0b90b; margin: 0 0 15px; display: flex; align-items: center; gap: 10px;"><i class="fas fa-exclamation-triangle"></i> <?php echo __('withdrawal_tips'); ?></h4>
|
||||
<ul style="color: var(--text-muted); font-size: 13px; line-height: 1.8; padding-left: 20px; margin: 0;">
|
||||
<li><?php echo __('withdrawal_tip_1'); ?></li>
|
||||
<li><?php echo __('withdrawal_tip_2'); ?></li>
|
||||
<li><?php echo __('withdrawal_tip_3'); ?></li>
|
||||
<li><?php echo __('withdrawal_tip_4'); ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div style="background: var(--card-bg); padding: 25px; border-radius: 20px; border: 1px solid var(--border-color);">
|
||||
<h4 style="margin: 0 0 15px;"><?php echo __('recent_history'); ?></h4>
|
||||
<div style="color: var(--text-muted); font-size: 13px; text-align: center; padding: 20px 0;">
|
||||
<?php echo __('no_records'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
Loading…
x
Reference in New Issue
Block a user