Autosave: 20260213-120315

This commit is contained in:
Flatlogic Bot 2026-02-13 12:03:16 +00:00
parent 32423d4989
commit 01edcfe23d
21 changed files with 1206 additions and 901 deletions

View File

@ -25,14 +25,33 @@ if (isset($_POST['action'])) {
$order = $orderStmt->fetch();
if ($order) {
$credit_amount = $order['usdt_amount'] > 0 ? $order['usdt_amount'] : $order['amount'];
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$credit_amount, $order['user_id']]);
$pdo->prepare("UPDATE $table SET status = 'completed' WHERE id = ?")->execute([$id]);
$msg = "您的充值 " . $credit_amount . " USDT 已确认到账。";
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
$pdo->beginTransaction();
try {
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$credit_amount, $order['user_id']]);
$pdo->prepare("UPDATE $table SET status = 'completed' WHERE id = ?")->execute([$id]);
// Update transaction status
$pdo->prepare("UPDATE transactions SET status = 'completed' WHERE user_id = ? AND type = 'deposit' AND description LIKE ?")->execute([$order['user_id'], "%#$id%"]);
$msg = "您的充值 " . $credit_amount . " USDT 已确认到账。";
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
}
}
} elseif ($_POST['action'] == 'reject') {
$pdo->prepare("UPDATE $table SET status = 'rejected' WHERE id = ?")->execute([$id]);
$orderStmt = $pdo->prepare("SELECT user_id FROM $table WHERE id = ?");
$orderStmt->execute([$id]);
$order = $orderStmt->fetch();
if ($order) {
// Update transaction status
$pdo->prepare("UPDATE transactions SET status = 'rejected' WHERE user_id = ? AND type = 'deposit' AND description LIKE ?")->execute([$order['user_id'], "%#$id%"]);
}
}
}
@ -54,30 +73,30 @@ $pending_orders_count = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE stat
<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>
:root { --primary: #f0b90b; --bg: #ffffff; --text: #1e2329; --border: #eaecef; }
body { background: #f4f6f9; color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; }
.admin-layout { display: flex; min-height: 100vh; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid #eaecef; padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; color: #1e2329; overflow-x: auto; }
.sidebar { width: 250px; background: #ffffff; border-right: 1px solid var(--border); padding: 1.5rem; }
.main-content { flex: 1; padding: 2rem; background: #ffffff; }
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: #f0b90b; font-weight: bold; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; margin-bottom: 3rem; }
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #eaecef; font-size: 0.85rem; }
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid var(--border); font-size: 0.85rem; }
.status-badge { padding: 3px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: bold; }
.matching { background: rgba(255, 60, 0, 0.2); color: #ff3c00; border: 1px solid #ff3c00; }
.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; }
.back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
.btn-primary { background: #f0b90b; color: black; border: none; padding: 8px 15px; border-radius: 6px; font-weight: bold; cursor: pointer; }
.btn-primary { background: var(--primary); color: black; border: none; padding: 8px 15px; border-radius: 6px; font-weight: bold; cursor: pointer; }
</style>
</head>
<body>
<div class="admin-layout">
<div class="sidebar">
<h2 style="color: #f0b90b; margin-bottom: 2rem;">NovaEx Admin</h2>
<h2 style="color: var(--primary); margin-bottom: 2rem;">NovaEx Admin</h2>
<a href="index.php" class="menu-item"><i class="fas fa-home"></i> 仪表盘</a>
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
<a href="agents.php" class="menu-item"><i class="fas fa-user-shield"></i> 代理管理</a>
@ -94,8 +113,7 @@ $pending_orders_count = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE stat
<a href="logout.php" class="menu-item"><i class="fas fa-sign-out-alt"></i> 退出登录</a>
</div>
<div class="main-content">
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
<h2>充值申请管理</h2>
<h1>充值申请管理</h1>
<table class="table">
<thead>
@ -124,7 +142,7 @@ $pending_orders_count = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE stat
<form method="POST" style="display: flex; gap: 5px;">
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
<input type="hidden" name="action" value="match">
<input type="text" name="account_info" placeholder="收款账户信息" required style="padding: 8px; background: #f9fafb; border: 1px solid #eaecef; border-radius: 4px;">
<input type="text" name="account_info" placeholder="收款账户信息" required style="padding: 8px; border: 1px solid var(--border); border-radius: 4px;">
<button type="submit" class="btn-primary" style="background: #ff3c00; color: white;">分配账户</button>
</form>
<?php elseif($o['status'] == 'submitting' || $o['status'] == 'matched'): ?>

View File

@ -19,27 +19,45 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) {
} elseif ($action == 'update_user') {
$id = $_POST['id'];
$username = $_POST['username'];
$balance = $_POST['balance'];
$new_balance = (float)$_POST['balance'];
$credit_score = $_POST['credit_score'];
$win_loss = $_POST['win_loss_control'];
$status = $_POST['status'];
// Fetch old balance to log if changed
$old_user = $pdo->prepare("SELECT balance FROM users WHERE id = ?");
$old_user->execute([$id]);
$old_balance = (float)$old_user->fetchColumn();
$sql = "UPDATE users SET username = ?, balance = ?, credit_score = ?, win_loss_control = ?, status = ? WHERE id = ?";
$params = [$username, $balance, $credit_score, $win_loss, $status, $id];
$params = [$username, $new_balance, $credit_score, $win_loss, $status, $id];
if (!empty($_POST['password'])) {
$sql = "UPDATE users SET username = ?, balance = ?, credit_score = ?, win_loss_control = ?, status = ?, password = ? WHERE id = ?";
$params = [$username, $balance, $credit_score, $win_loss, $status, password_hash($_POST['password'], PASSWORD_DEFAULT), $id];
$params = [$username, $new_balance, $credit_score, $win_loss, $status, password_hash($_POST['password'], PASSWORD_DEFAULT), $id];
}
$pdo->prepare($sql)->execute($params);
if ($new_balance != $old_balance) {
$diff = $new_balance - $old_balance;
$pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'admin_adjust', ?, 'USDT', 'completed', ?)")->execute([
$id, $diff, "管理员手动修改余额 (Balance adjusted by admin)"
]);
}
} elseif ($action == 'adjust_balance') {
$id = $_POST['id'];
$type = $_POST['adjustment_type'];
$amount = (float)$_POST['amount'];
if ($type == 'up') {
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$amount, $id]);
$pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'admin_adjust', ?, 'USDT', 'completed', ?)")->execute([
$id, $amount, "管理员增加余额 (Credit by admin)"
]);
} else {
$pdo->prepare("UPDATE users SET balance = balance - ? WHERE id = ?")->execute([$amount, $id]);
$pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'admin_adjust', ?, 'USDT', 'completed', ?)")->execute([
$id, -$amount, "管理员扣除余额 (Debit by admin)"
]);
}
} elseif ($action == 'toggle_status') {
$id = $_POST['id'];
@ -72,22 +90,18 @@ $pending_kyc = $pdo->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->f
.menu-item { padding: 12px 15px; color: #474d57; text-decoration: none; display: flex; align-items: center; gap: 12px; border-radius: 8px; margin-bottom: 8px; transition: 0.2s; }
.menu-item:hover, .menu-item.active { background: #f5f5f5; color: var(--primary); font-weight: bold; }
.badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
.card { background: white; border-radius: 12px; border: 1px solid var(--border); padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
.table { width: 100%; border-collapse: collapse; margin-top: 1.5rem; }
.table th, .table td { padding: 15px; text-align: left; border-bottom: 1px solid var(--border); font-size: 0.9rem; }
.table th { background: #f9fafb; color: #707a8a; font-weight: 600; text-transform: uppercase; font-size: 0.75rem; }
.btn { padding: 8px 16px; border-radius: 6px; font-size: 0.85rem; border: none; cursor: pointer; font-weight: 500; transition: 0.2s; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
.btn-primary { background: var(--primary); color: black; }
.btn-danger { background: #f6465d; color: white; }
.btn-info { background: #2f80ed; color: white; }
.btn-success { background: #00c087; color: white; }
.status-badge { padding: 4px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: bold; }
.status-active { background: #e6fcf5; color: #00c087; }
.status-disabled { background: #fff5f5; color: #f6465d; }
.modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-content { background: white; width: 550px; padding: 30px; border-radius: 16px; box-shadow: 0 20px 40px rgba(0,0,0,0.2); }
.form-group { margin-bottom: 20px; }
@ -286,7 +300,6 @@ $pending_kyc = $pdo->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->f
<script>
function showModal(id) { document.getElementById(id).style.display = 'flex'; }
function hideModal(id) { document.getElementById(id).style.display = 'none'; }
function editUser(user) {
document.getElementById('edit-id').value = user.id;
document.getElementById('edit-username').value = user.username;
@ -296,18 +309,12 @@ $pending_kyc = $pdo->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->f
document.getElementById('edit-status').value = user.status;
showModal('editModal');
}
function adjustBalance(id, name) {
document.getElementById('adj-id').value = id;
document.getElementById('adj-name').innerText = name;
showModal('balanceModal');
}
window.onclick = function(event) {
if (event.target.className === 'modal') {
event.target.style.display = "none";
}
}
window.onclick = function(event) { if (event.target.className === 'modal') { event.target.style.display = "none"; } }
</script>
</body>
</html>

View File

@ -13,26 +13,47 @@ if (isset($_POST['action'])) {
if ($_POST['action'] == 'complete') {
$pdo->prepare("UPDATE orders SET status = 'completed' WHERE id = ?")->execute([$id]);
$orderStmt = $pdo->prepare("SELECT user_id, amount, currency FROM orders WHERE id = ?");
$orderStmt = $pdo->prepare("SELECT user_id, amount, currency, type FROM orders WHERE id = ?");
$orderStmt->execute([$id]);
$order = $orderStmt->fetch();
if ($order) {
$msg = "您的提现 " . $order['amount'] . " " . ($order['currency'] ?? 'USDT') . " 已汇出,请查收。";
// Update transaction status
$pdo->prepare("UPDATE transactions SET status = 'completed' WHERE user_id = ? AND type = 'withdraw' AND description LIKE ?")->execute([$order['user_id'], "%#$id%"]);
$msg = "您的提现 " . $order['amount'] . " USDT 已汇出,请查收。";
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
}
$success_msg = "确认成功,提现已处理。";
} elseif ($_POST['action'] == 'reject') {
$remark = !empty($_POST['remark']) ? $_POST['remark'] : '违反规定';
$orderStmt = $pdo->prepare("SELECT user_id, amount FROM orders 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 orders SET status = 'rejected' WHERE id = ?")->execute([$id]);
$remark = !empty($_POST['remark']) ? $_POST['remark'] : '违反规定';
$msg = "您的提现申请 #$id 已被拒绝,资金已退回您的余额。原因: " . $remark;
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
$success_msg = "拒绝成功";
$pdo->beginTransaction();
try {
// Return balance
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['amount'], $order['user_id']]);
$pdo->prepare("UPDATE orders SET status = 'rejected' WHERE id = ?")->execute([$id]);
// Log return to transactions
$pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'withdraw_return', ?, 'USDT', 'completed', ?)")->execute([
$order['user_id'], $order['amount'], "Withdrawal #$id Rejected: $remark"
]);
// Update original transaction status
$pdo->prepare("UPDATE transactions SET status = 'rejected' WHERE user_id = ? AND type = 'withdraw' AND description LIKE ?")->execute([$order['user_id'], "%#$id%"]);
$msg = "您的提现申请 #$id 已被拒绝,资金已退回您的余额。原因: " . $remark;
$pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$order['user_id'], $msg]);
$pdo->commit();
$success_msg = "拒绝成功";
} catch (Exception $e) {
$pdo->rollBack();
$error_msg = "操作失败: " . $e->getMessage();
}
} else {
$error_msg = "订单不存在。";
}
@ -48,7 +69,7 @@ if (isset($_POST['action'])) {
}
}
$withdrawals = $pdo->query("SELECT o.*, u.username, u.uid FROM orders o JOIN users u ON o.user_id = u.id WHERE o.type = 'usdt' ORDER BY o.id DESC")->fetchAll();
$withdrawals = $pdo->query("SELECT o.*, u.username, u.uid FROM orders o JOIN users u ON o.user_id = u.id WHERE o.type IN ('usdt', 'fiat') ORDER BY o.id DESC")->fetchAll();
$unread_msgs = $pdo->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn();
$pending_orders_count = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn();
@ -121,26 +142,30 @@ $pending_kyc = $pdo->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->f
<?php if($success_msg): ?>
<div class="alert alert-success"><i class="fas fa-check-circle"></i> <?php echo $success_msg; ?></div>
<?php endif; ?>
<?php if($error_msg): ?>
<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> <?php echo $error_msg; ?></div>
<?php endif; ?>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>用户</th>
<th>金额</th>
<th>币种</th>
<th>金额 (USDT)</th>
<th>类型</th>
<th>详情</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach($withdrawals as $o): ?>
<?php foreach($withdrawals as $o):
?>
<tr>
<td>#<?php echo $o['id']; ?></td>
<td><b><?php echo htmlspecialchars($o['username']); ?></b> (<?php echo $o['uid']; ?>)</td>
<td><?php echo number_format($o['amount'], 2); ?></td>
<td><?php echo strtoupper($o['currency'] ?? 'USDT'); ?></td>
<td><?php echo strtoupper($o['type']); ?></td>
<td><small><?php echo htmlspecialchars($o['account_info'] ?? ''); ?></small></td>
<td><span class="status-badge <?php echo $o['status']; ?>"><?php echo strtoupper($o['status']); ?></span></td>
<td>
@ -163,15 +188,18 @@ $pending_kyc = $pdo->query("SELECT COUNT(*) FROM users WHERE kyc_status = 1")->f
<button type="submit" class="btn btn-danger">驳回</button>
</form>
</div>
<?php else: ?>
--
<?php endif; ?>
<?php else:
?>
--
<?php endif;
?>
</td>
</tr>
<?php endforeach; ?>
<?php endforeach;
?>
</tbody>
</table>
</div>
</div>
</body>
</html>
</html>

30
api/get_transactions.php Normal file
View File

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

View File

@ -14,7 +14,7 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
line-height: 1.5;
@ -50,7 +50,7 @@ body {
color: var(--text-color);
text-decoration: none;
font-size: 14px;
font-weight: 500;
font-weight: 600;
transition: color 0.2s;
display: flex;
align-items: center;
@ -60,19 +60,17 @@ body {
color: var(--primary-color);
}
.nav-link-icon {
margin-right: 6px;
font-size: 16px;
}
/* Colorful Menu Icons */
/* Colorful Icons */
.fa-home { color: #5d5dff; }
.fa-chart-line { color: #00e676; }
.fa-coins { color: #ffd600; }
.fa-file-contract { color: #ff3d00; }
.fa-bolt { color: #fbc02d; }
.fa-pickaxe { color: #8e24aa; }
.fa-hammer { color: #8e24aa !important; }
.fa-wallet { color: #03a9f4; }
.fa-clock { color: #fbc02d; }
.fa-mobile-alt { color: #4facfe; }
.fa-exchange-alt { color: #00e676; }
.dropdown {
position: relative;
@ -151,8 +149,9 @@ body {
gap: 4px;
}
.mobile-nav-item i { font-size: 20px; }
.mobile-nav-item i { font-size: 22px; }
.mobile-nav-item.active { color: var(--primary-color); }
.mobile-nav-item.active i { color: var(--primary-color); }
/* Sidebar Drawer */
.mobile-sidebar {
@ -237,4 +236,4 @@ body {
padding: 2px 8px;
border-radius: 4px;
margin-top: 5px;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,87 +1,40 @@
<?php
include 'header.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
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: chat.php");
exit;
}
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
if ($stmt->fetch()) { header("Location: chat.php"); exit; }
$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',
'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>
<h1 style="font-size: 2.5rem; font-weight: bold; margin-bottom: 10px;"><?php echo __('nav_deposit'); ?></h1>
<p style="color: var(--text-muted);"><?php echo __('deposit_method_tip', 'Select your preferred deposit method'); ?></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 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', 'Fiat Deposit'); ?></h3><p style="margin: 5px 0 0; color: var(--text-muted); font-size: 14px;"><?php echo __('bank_transfer', 'Bank Transfer / OTC'); ?></p></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 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', 'Crypto Deposit'); ?></h3><p style="margin: 5px 0 0; color: var(--text-muted); font-size: 14px;">USDT</p></div>
</div>
</div>
</div>
@ -90,129 +43,47 @@ $fiat_currencies_info = [
<form action="matching.php" method="POST" id="fiat-form">
<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>
<div><label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('select_currency', '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>
<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>
<div><label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('buy_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;">Order Confirmation / 订单确认</button>
<button type="submit" class="btn-primary" style="width: 100%; padding: 18px; font-size: 1.1rem; border-radius: 12px;"><?php echo __('confirm'); ?></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">
<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="margin-bottom: 30px;"><label style="display: block; margin-bottom: 15px; color: var(--text-muted); font-size: 14px;"><?php echo __('type'); ?></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>
<label class="network-label active"><input type="radio" name="network" value="TRC20" checked style="display: none;"><div style="font-weight: bold;">TRC20</div></label>
<label class="network-label"><input type="radio" name="network" value="ERC20" style="display: none;"><div style="font-weight: bold;">ERC20</div></label>
<label class="network-label"><input type="radio" name="network" value="BEP20" style="display: none;"><div style="font-weight: bold;">BEP20</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>
<div style="margin-bottom: 35px;"><label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('buy_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);">Order Confirmation / 订单确认</button>
<button type="submit" class="btn-primary" style="width: 100%; padding: 18px; font-size: 1.1rem; border-radius: 12px; background: var(--success-color);"><?php echo __('confirm'); ?></button>
</form>
</div>
</div>
</main>
<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); }
</style>
<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); } </style>
<script>
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)';
}
document.getElementById('fiat-section').style.display = method === 'fiat' ? 'block' : 'none';
document.getElementById('usdt-section').style.display = method === 'usdt' ? 'block' : 'none';
document.getElementById('card-fiat').style.borderColor = method === 'fiat' ? 'var(--primary-color)' : 'transparent';
document.getElementById('card-usdt').style.borderColor = method === 'usdt' ? 'var(--success-color)' : 'transparent';
}
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;
};
});
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'; ?>

View File

@ -12,7 +12,7 @@
</linearGradient>
</defs>
</svg>
NovaEx
<?php echo __('site_name'); ?>
</div>
<p style="color: var(--text-muted); font-size: 14px; line-height: 1.6; margin-bottom: 1.5rem;"><?php echo __('footer_desc'); ?></p>
<div style="display: flex; gap: 1.2rem; font-size: 1.2rem;">
@ -58,7 +58,7 @@
<div class="footer-bottom" style="max-width: 1200px; margin: 40px auto 0; padding-top: 30px; border-top: 1px solid #1e2329; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
<div style="color: var(--text-muted); font-size: 12px;">
&copy; 2017-2026 NOVAEX.COM <?php echo __('all_rights_reserved'); ?>
&copy; 2017-2026 <?php echo strtoupper(__('site_name')); ?>.COM <?php echo __('all_rights_reserved'); ?>
</div>
<div style="display: flex; gap: 15px; color: var(--text-muted); font-size: 12px; flex-wrap: wrap;">
<div style="display: flex; align-items: center; gap: 5px; color: var(--success-color);">

View File

@ -6,143 +6,174 @@ $user_id = $_SESSION['user_id'] ?? null;
?>
<style>
/* Layout Fixes */
/* Global layout enforcement */
html, body {
background: #0b0e11;
min-width: 1280px;
max-width: 1920px;
margin: 0 auto;
overflow-x: auto;
}
@media (max-width: 991px) {
html, body {
min-width: 100%;
max-width: 100%;
overflow-x: hidden;
}
.navbar, footer { display: none !important; }
body { padding-bottom: 65px !important; margin: 0 !important; max-width: 100% !important; }
body { padding-bottom: 0 !important; }
}
.trading-container {
display: flex;
background: #0b0e11;
min-height: calc(100vh - 64px);
max-width: 100%;
margin: 0;
overflow: hidden;
width: 100%;
}
@media (max-width: 991px) {
.trading-container { min-height: 100vh; flex-direction: column; }
.trading-container { min-height: calc(100vh - 50px); flex-direction: column; }
}
.left-col { width: 280px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.center-col { flex: 1; min-width: 0; background: #0b0e11; display: flex; flex-direction: column; overflow: hidden; }
.right-col { width: 320px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-left: 1px solid #2b3139; }
.left-col { width: 260px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.center-col { flex: 1; min-width: 600px; background: #0b0e11; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.right-col { width: 320px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; }
@media (max-width: 991px) {
.left-col, .right-col { display: none !important; }
.center-col { min-width: 100%; }
}
/* Category Tabs above Search */
.category-tabs { display: flex; padding: 15px 15px 5px; gap: 8px; }
.category-tab { flex: 1; text-align: center; padding: 6px 0; background: #2b3139; border-radius: 4px; font-size: 11px; color: #848e9c; cursor: pointer; transition: all 0.2s; white-space: nowrap; border: 1px solid transparent; }
.category-tab.active { background: rgba(0, 82, 255, 0.1); border-color: var(--primary-color); color: var(--primary-color); font-weight: bold; }
/* Search Box */
.search-box { padding: 5px 15px 10px; position: relative; }
.search-box i { position: absolute; left: 25px; top: 50%; transform: translateY(-50%); color: #848e9c; font-size: 12px; }
.search-box input { width: 100%; background: #2b3139; border: 1px solid transparent; border-radius: 4px; padding: 8px 10px 8px 30px; color: white; font-size: 13px; outline: none; }
.search-box input:focus { border-color: var(--primary-color); }
/* Pairs List */
#pairs-list { flex: 1; overflow-y: auto; }
.pair-item { display: flex; align-items: center; padding: 12px 15px; cursor: pointer; border-bottom: 1px solid rgba(255,255,255,0.02); transition: all 0.2s; }
.pair-item { display: flex; align-items: center; padding: 10px 15px; cursor: pointer; transition: all 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
.pair-item:hover { background: #1e2329; }
.pair-item.active { background: #1e2329; border-left: 3px solid var(--primary-color); }
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; }
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; flex-shrink: 0; background: #2b3139; }
/* Chart Area */
.chart-header { padding: 12px 20px; display: flex; align-items: center; gap: 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
.chart-box { height: 400px; background: #0b0e11; }
@media (max-width: 991px) { .chart-box { height: 350px; } }
.chart-header { padding: 8px 20px; display: flex; align-items: center; background: #161a1e; border-bottom: 1px solid #2b3139; flex-wrap: nowrap; gap: 20px; height: 50px; }
.chart-box { flex: 1; min-height: 400px; height: 400px; background: #0b0e11; border-bottom: 1px solid #2b3139; }
@media (max-width: 991px) { .chart-box { min-height: 320px; height: 320px; } }
/* Order Panel */
.order-box { padding: 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
.futures-config { display: flex; gap: 10px; margin-bottom: 15px; }
.config-btn { flex: 1; background: #2b3139; color: white; padding: 10px; border-radius: 4px; border: 1px solid transparent; cursor: pointer; font-size: 13px; text-align: center; font-weight: 600; }
.order-box { padding: 12px 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
.futures-config { display: flex; gap: 10px; margin-bottom: 10px; }
.config-btn { flex: 1; background: #2b3139; color: white; padding: 6px; border-radius: 4px; border: 1px solid transparent; cursor: pointer; font-size: 12px; text-align: center; font-weight: 600; }
.config-btn:hover { border-color: var(--primary-color); }
.input-group { background: #2b3139; border-radius: 4px; padding: 10px 12px; display: flex; align-items: center; margin-bottom: 10px; border: 1px solid transparent; }
.input-group { background: #2b3139; border-radius: 4px; padding: 6px 12px; display: flex; align-items: center; margin-bottom: 6px; border: 1px solid transparent; }
.input-group:focus-within { border-color: var(--primary-color); }
.input-group input { background: transparent; border: none; color: white; flex: 1; text-align: right; outline: none; font-size: 14px; width: 100%; }
.input-group .label { color: #848e9c; font-size: 12px; }
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 12px; }
.input-group input { background: transparent; border: none; color: white; flex: 1; text-align: left; outline: none; font-size: 13px; width: 100%; }
.input-group .label { color: #848e9c; font-size: 11px; margin-right: 10px; }
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 11px; }
/* Slider Style */
.slider-container { margin: 15px 0 25px; padding: 0 5px; }
.slider-labels { display: flex; justify-content: space-between; margin-top: 8px; font-size: 10px; color: #848e9c; }
input[type=range] { -webkit-appearance: none; width: 100%; height: 4px; background: #2b3139; border-radius: 2px; outline: none; }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; background: var(--primary-color); border-radius: 50%; cursor: pointer; border: 3px solid #161a1e; }
.slider-container { margin: 8px 0 15px; padding: 0 5px; }
.slider-labels { display: flex; justify-content: space-between; margin-top: 4px; font-size: 10px; color: #848e9c; }
input[type=range] { -webkit-appearance: none; width: 100%; height: 3px; background: #2b3139; border-radius: 2px; outline: none; }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; background: var(--primary-color); border-radius: 50%; cursor: pointer; border: 2px solid #161a1e; }
.trade-actions { display: flex; gap: 12px; margin-top: 15px; }
.trade-btn { flex: 1; padding: 14px; border-radius: 4px; font-weight: bold; font-size: 15px; border: none; cursor: pointer; transition: opacity 0.2s; }
.trade-actions { display: flex; gap: 12px; margin-top: 8px; }
.trade-btn { flex: 1; padding: 10px; border-radius: 4px; font-weight: bold; font-size: 14px; border: none; cursor: pointer; transition: opacity 0.2s; }
.btn-long { background: #0ecb81; color: white; }
.btn-short { background: #f6465d; color: white; }
/* Records */
.record-tabs { display: flex; background: #161a1e; border-bottom: 1px solid #2b3139; padding: 0 20px; }
.record-tab { padding: 15px 0; margin-right: 30px; font-size: 13px; color: #848e9c; cursor: pointer; position: relative; }
.record-tab { padding: 10px 0; margin-right: 25px; font-size: 13px; color: #848e9c; cursor: pointer; position: relative; }
.record-tab.active { color: white; border-bottom: 2px solid var(--primary-color); font-weight:bold; }
.records-content { min-height: 300px; background: #161a1e; }
@media (max-width: 991px) { .records-content { padding-bottom: 80px; } }
.records-content { min-height: 200px; background: #161a1e; overflow-y: auto; }
/* Order Book */
.ob-header { padding: 10px 15px; font-size: 11px; color: #848e9c; display: flex; justify-content: space-between; border-bottom: 1px solid #2b3139; }
.ob-row { display: flex; justify-content: space-between; padding: 4px 15px; font-size: 12px; font-family: monospace; position: relative; cursor: pointer; }
/* Order Book Styles */
.ob-header { padding: 10px 15px; font-size: 11px; color: #848e9c; display: flex; justify-content: space-between; border-bottom: 1px solid #2b3139; background: #161a1e; }
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; cursor: pointer; height: 20px; align-items: center; }
.ob-bar { position: absolute; right: 0; top: 0; bottom: 0; opacity: 0.1; z-index: 0; }
#mid-price { padding: 12px 15px; font-size: 18px; font-weight: 800; text-align: center; border-top: 1px solid #2b3139; border-bottom: 1px solid #2b3139; }
#mid-price { padding: 8px 15px; font-size: 16px; font-weight: 800; text-align: center; border-top: 1px solid #2b3139; border-bottom: 1px solid #2b3139; background: #161a1e; }
/* Stats Item */
.stats-item { display: flex; flex-direction: column; justify-content: center; }
.stats-label { font-size: 10px; color: #848e9c; margin-bottom: 1px; white-space: nowrap; }
.stats-value { font-size: 12px; font-weight: 600; color: white; white-space: nowrap; }
/* Mobile Nav */
.m-trade-nav { display: none; background: #161a1e; border-bottom: 1px solid #2b3139; position: sticky; top: 0; z-index: 100; }
.m-trade-nav a { flex: 1; text-align: center; padding: 14px; font-size: 14px; color: #848e9c; text-decoration: none; border-bottom: 2px solid transparent; }
.m-trade-nav a.active { color: var(--primary-color); border-bottom-color: var(--primary-color); font-weight: bold; }
/* Mobile Headers */
.m-trading-header { display: none; background: #161a1e; padding: 12px 15px; border-bottom: 1px solid #2b3139; }
.m-currency-bar { display: none; overflow-x: auto; background: #161a1e; padding: 10px; gap: 10px; border-bottom: 1px solid #2b3139; scrollbar-width: none; }
.m-nav-tabs { display: none; background: #161a1e; border-bottom: 1px solid #2b3139; }
@media (max-width: 991px) { .m-trading-header, .m-currency-bar, .m-nav-tabs { display: flex; } .m-trading-header { flex-direction: column; } }
.m-currency-bar::-webkit-scrollbar { display: none; }
.m-coin-item { flex-shrink: 0; background: #2b3139; padding: 6px 12px; border-radius: 4px; display: flex; align-items: center; gap: 6px; border: 1px solid transparent; }
.m-coin-item.active { border-color: var(--primary-color); background: rgba(0, 82, 255, 0.1); }
.m-coin-item img { width: 16px; height: 16px; border-radius: 50%; }
.m-nav-tab { flex:1; text-align:center; padding:12px; font-size:14px; color:#848e9c; border-bottom:2px solid transparent; }
.m-nav-tab.active { color:white; border-bottom-color:var(--primary-color); font-weight:bold; }
/* Modal */
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 2000; display: none; align-items: center; justify-content: center; }
.modal-content { background: #1e2329; width: 90%; max-width: 400px; padding: 25px; border-radius: 12px; }
@media (max-width: 991px) {
.m-trade-nav { display: flex; }
.m-currency-bar { display: flex; }
.chart-header { gap: 10px; padding: 10px 15px; overflow-x: auto; scrollbar-width: none; }
.chart-header::-webkit-scrollbar { display: none; }
}
</style>
<!-- Mobile Trading Header -->
<div class="m-trading-header">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="display: flex; align-items: center; gap: 10px;" onclick="toggleSidebar()">
<i class="fas fa-bars" style="font-size: 18px;"></i>
<div style="font-size: 18px; font-weight: 800; display: flex; align-items: center; gap: 6px;">
<img id="m-curr-icon" src="" style="width:24px; height:24px; border-radius:50%">
<span id="m-curr-pair">BTCUSDT Perp</span>
<i class="fas fa-chevron-down" style="font-size: 10px; opacity: 0.5;"></i>
</div>
</div>
<div style="text-align: right">
<div id="m-curr-price" style="font-size: 22px; font-weight: 800; color: #0ecb81; line-height: 1">--</div>
<div id="m-curr-change" style="font-size: 12px; font-weight: 600; margin-top: 4px">--</div>
</div>
</div>
<div style="display: flex; gap: 15px; margin-top: 10px; font-size: 11px; color: #848e9c;">
<span id="m-24h-high">H: --</span><span id="m-24h-low">L: --</span><span id="m-24h-vol">V: --</span>
</div>
<div class="m-trade-nav">
<a href="spot.php"><?php echo __('nav_spot'); ?></a>
<a href="futures.php" class="active"><?php echo __('nav_futures'); ?></a>
<a href="options.php"><?php echo __('nav_options'); ?></a>
</div>
<div class="m-currency-bar" id="m-coin-list"></div>
<div class="m-nav-tabs">
<div class="m-nav-tab active" onclick="switchMobileView('trade')"><?php echo __('nav_trade'); ?></div>
<div class="m-nav-tab" onclick="switchMobileView('chart')"><?php echo __('chart'); ?></div>
<div class="m-nav-tab" onclick="switchMobileView('orders')"><?php echo __('positions'); ?></div>
</div>
<div class="trading-container">
<div class="left-col d-none d-lg-flex">
<div class="market-header" style="padding:15px; font-weight:bold; border-bottom:1px solid #2b3139"><?php echo __('nav_market'); ?></div>
<div class="category-tabs">
<div class="category-tab" onclick="location.href='options.php'"><?php echo $lang == 'zh' ? '秒合约' : 'Options'; ?></div>
<div class="category-tab" onclick="location.href='spot.php'"><?php echo $lang == 'zh' ? '现货交易' : 'Spot'; ?></div>
<div class="category-tab active" onclick="location.href='futures.php'"><?php echo $lang == 'zh' ? '合约交易' : 'Futures'; ?></div>
</div>
<div class="search-box">
<i class="fas fa-search"></i>
<input type="text" id="pair-search" placeholder="<?php echo __('search_currency'); ?>" oninput="filterPairs()">
</div>
<div id="pairs-list"></div>
</div>
<div class="center-col m-view active" id="view-trade">
<div class="chart-header d-none d-lg-flex">
<div style="display: flex; align-items: center; gap: 12px;">
<div class="center-col">
<div class="chart-header">
<div style="display: flex; align-items: center; gap: 10px; padding-right: 15px; border-right: 1px solid #2b3139;">
<img id="curr-icon" src="" class="coin-icon" style="margin:0; width:28px; height:28px;">
<span id="curr-pair" style="font-weight: 800; font-size: 18px;">BTCUSDT Perpetual</span>
<span id="curr-pair" style="font-weight: 800; font-size: 16px;">BTC/USDT Perpetual</span>
</div>
<div style="flex:1"></div>
<div style="text-align: right">
<div id="curr-price" style="font-size: 20px; font-weight: 800; color: #0ecb81;">--</div>
<div id="curr-change" style="font-size: 12px; font-weight: 600; color: #0ecb81;">--</div>
<div class="stats-item">
<div id="curr-price" style="font-size: 18px; font-weight: 800; color: #0ecb81; line-height: 1.2;">--</div>
<div id="curr-change" style="font-size: 11px; font-weight: 600;">--</div>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_high'); ?></span>
<span class="stats-value" id="h-high">--</span>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_low'); ?></span>
<span class="stats-value" id="h-low">--</span>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_vol'); ?></span>
<span class="stats-value" id="h-vol">--</span>
</div>
</div>
<div class="chart-box d-none d-lg-block">
<div id="tv_chart_container_desk" style="height: 100%;"></div>
</div>
<div class="chart-box"><div id="tv_chart_container" style="height: 100%;"></div></div>
<div class="order-box">
<div class="futures-config">
@ -151,7 +182,7 @@ $user_id = $_SESSION['user_id'] ?? null;
</div>
<div class="input-group">
<span class="label"><?php echo __('price'); ?></span>
<input type="number" id="futures-price" placeholder="Market Price">
<input type="number" id="futures-price" placeholder="<?php echo __('market'); ?>">
<span class="unit">USDT</span>
</div>
<div class="input-group">
@ -164,11 +195,11 @@ $user_id = $_SESSION['user_id'] ?? null;
<div class="slider-labels"><span>0%</span><span>25%</span><span>50%</span><span>75%</span><span>100%</span></div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<div class="input-group"><span class="label">TP</span><input type="number" id="futures-tp" placeholder="Price"></div>
<div class="input-group"><span class="label">SL</span><input type="number" id="futures-sl" placeholder="Price"></div>
<div class="input-group"><span class="label">TP</span><input type="number" id="futures-tp" placeholder="<?php echo __('price'); ?>"></div>
<div class="input-group"><span class="label">SL</span><input type="number" id="futures-sl" placeholder="<?php echo __('price'); ?>"></div>
</div>
<div style="display: flex; justify-content: space-between; font-size: 12px; color: #848e9c; margin-bottom: 12px;">
<span>Available</span><span id="futures-avail" style="color:white; font-weight:600">0.00 USDT</span>
<div style="display: flex; justify-content: space-between; font-size: 11px; color: #848e9c; margin-bottom: 8px;">
<span><?php echo __('available'); ?></span><span id="futures-avail" style="color:white; font-weight:600">0.00 USDT</span>
</div>
<div class="trade-actions">
<button onclick="placeOrder('buy')" class="trade-btn btn-long"><?php echo __('buy_long'); ?></button>
@ -184,46 +215,39 @@ $user_id = $_SESSION['user_id'] ?? null;
<div id="records-list" class="records-content"></div>
</div>
<div class="center-col m-view" id="view-chart" style="display:none">
<div class="chart-box"><div id="tv_chart_container_mob" style="height: 100%;"></div></div>
</div>
<div class="center-col m-view" id="view-orders" style="display:none">
<div class="record-tabs">
<div class="record-tab active" onclick="switchRecords('positions')"><?php echo __('positions'); ?></div>
<div class="record-tab" onclick="switchRecords('history')"><?php echo __('history_orders'); ?></div>
<div class="record-tab" onclick="switchRecords('trades')"><?php echo __('settled'); ?></div>
</div>
<div id="m-records-list" class="records-content"></div>
</div>
<div class="right-col d-none d-lg-flex">
<div class="ob-header"><span>Price</span><span>Amount</span></div>
<div id="asks-list" style="flex: 1; display: flex; flex-direction: column-reverse; overflow: hidden;"></div>
<div class="ob-header"><span><?php echo __('price'); ?></span><span><?php echo __('amount'); ?></span></div>
<div id="asks-list" style="flex: 1; display: flex; flex-direction: column; overflow: hidden; justify-content: flex-start;"></div>
<div id="mid-price">--</div>
<div id="bids-list" style="flex: 1; overflow: hidden;"></div>
<div id="bids-list" style="flex: 1; display: flex; flex-direction: column; overflow: hidden; justify-content: flex-start;"></div>
</div>
</div>
<div class="modal-overlay" id="leverage-modal">
<div class="modal-content">
<div style="display:flex; justify-content:space-between; margin-bottom:20px;"><span style="font-weight:bold; font-size:16px;">Adjust Leverage</span><i class="fas fa-times" onclick="toggleLeverageModal()" style="cursor:pointer; color:#848e9c"></i></div>
<div style="display:flex; justify-content:space-between; margin-bottom:20px;"><span style="font-weight:bold; font-size:16px;"><?php echo __('adjust_leverage'); ?></span><i class="fas fa-times" onclick="toggleLeverageModal()" style="cursor:pointer; color:#848e9c"></i></div>
<div style="text-align:center; font-size:32px; font-weight:800; color:var(--primary-color); margin-bottom:10px;" id="slider-val">20x</div>
<div class="slider-container">
<input type="range" id="leverage-range" min="20" max="100" value="20" oninput="updateSliderVal(this.value)">
<div style="display:flex; justify-content:space-between; font-size:12px; color:#848e9c; margin-top:10px;"><span>20x</span><span>100x</span></div>
</div>
<button class="trade-btn btn-long" style="width:100%;" onclick="confirmLeverage()">Confirm</button>
<button class="trade-btn btn-long" style="width:100%;" onclick="confirmLeverage()"><?php echo __('confirm'); ?></button>
</div>
</div>
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script>
let currentPair = 'BTCUSDT'; let currentPrice = 0; let currentLeverage = 20; let marginMode = 'cross'; let currentStatus = 'positions';
let currentPair = 'BTCUSDT'; let currentPrice = 0; let currentLeverage = 20; let marginMode = 'cross'; let currentStatus = 'positions'; let searchQuery = '';
const pairs = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'MATICUSDT', 'LTCUSDT', 'SHIBUSDT', 'TRXUSDT', 'AVAXUSDT', 'LINKUSDT', 'BCHUSDT', 'UNIUSDT', 'ETCUSDT', 'NEARUSDT', 'FILUSDT', 'ALGOUSDT', 'FTMUSDT', 'SANDUSDT', 'MANAUSDT', 'AXSUSDT', 'ATOMUSDT', 'HBARUSDT', 'ICPUSDT', 'VETUSDT'];
const marketData = {}; let balances = {usdt: 0};
function getIcon(s) { return `https://cdn.jsdelivr.net/gh/atomiclabs/cryptocurrency-icons@1a72df150d6d8481e2345e691456c6c7d1e84a22/32/color/${s.replace('USDT', '').toLowerCase()}.png`; }
function initChart(symbol, container) { new TradingView.widget({ "width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "15", "theme": "dark", "style": "1", "locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>", "container_id": container, "backgroundColor": "#0b0e11", "hide_side_toolbar": true }); }
function getIcon(s) {
const symbol = s.replace('USDT', '').toLowerCase();
return `https://assets.coincap.io/assets/icons/${symbol}@2x.png`;
}
function initChart(symbol) { new TradingView.widget({ "width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "15", "theme": "dark", "style": "1", "locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>", "container_id": "tv_chart_container", "backgroundColor": "#0b0e11", "hide_side_toolbar": true }); }
initChart(currentPair);
const ws = new WebSocket('wss://stream.binance.com:9443/ws/' + pairs.map(p => p.toLowerCase() + '@ticker').join('/'));
ws.onmessage = (e) => {
@ -234,17 +258,14 @@ $user_id = $_SESSION['user_id'] ?? null;
function updatePriceUI(d) {
const color = d.P>=0 ? '#0ecb81' : '#f6465d';
document.getElementById('curr-price').innerText = currentPrice.toLocaleString();
document.getElementById('m-curr-price').innerText = currentPrice.toLocaleString();
document.getElementById('curr-price').innerText = currentPrice.toLocaleString(undefined, {minimumFractionDigits: 2});
document.getElementById('curr-price').style.color = color;
document.getElementById('m-curr-price').style.color = color;
document.getElementById('curr-change').innerText = (d.P>=0?'+':'')+d.P+'%';
document.getElementById('m-curr-change').innerText = (d.P>=0?'+':'')+d.P+'%';
document.getElementById('m-24h-high').innerText = 'H: ' + parseFloat(d.h).toLocaleString();
document.getElementById('m-24h-low').innerText = 'L: ' + parseFloat(d.l).toLocaleString();
document.getElementById('m-24h-vol').innerText = 'V: ' + (parseFloat(d.v)/1000).toFixed(1) + 'K';
document.getElementById('mid-price').innerText = currentPrice.toLocaleString();
document.getElementById('mid-price').style.color = color;
document.getElementById('curr-change').style.color = color;
const hHigh = document.getElementById('h-high'); if(hHigh) hHigh.innerText = parseFloat(d.h).toLocaleString();
const hLow = document.getElementById('h-low'); if(hLow) hLow.innerText = parseFloat(d.l).toLocaleString();
const hVol = document.getElementById('h-vol'); if(hVol) hVol.innerText = (parseFloat(d.v)/1000).toFixed(1) + 'K';
const mid = document.getElementById('mid-price'); if(mid) { mid.innerText = currentPrice.toLocaleString(undefined, {minimumFractionDigits: 2}); mid.style.color = color; }
}
function renderPairs() {
@ -252,21 +273,28 @@ $user_id = $_SESSION['user_id'] ?? null;
let lH = ''; let mH = '';
pairs.forEach(p => {
const d = marketData[p]||{c:0,P:0}; const icon = getIcon(p); const active = p === currentPair; const color = d.P >= 0 ? '#0ecb81' : '#f6465d';
lH += `<div class="pair-item ${active?'active':''}" onclick="switchPair('${p}')"><img src="${icon}" class="coin-icon"> <div style="flex:1"><div style="font-weight:700; font-size:13px">${p}</div></div> <div style="text-align:right"><div style="font-size:13px; font-weight:bold">${parseFloat(d.c).toLocaleString()}</div><div style="font-size:11px; color:${color}">${(d.P>=0?'+':'')+d.P}%</div></div></div>`;
mH += `<div class="m-coin-item ${active?'active':''}" onclick="switchPair('${p}')"><img src="${icon}"><span>${p.replace('USDT','')}</span></div>`;
const disp = p.replace('USDT','') + '/USDT';
if (searchQuery === '' || disp.includes(searchQuery)) {
lH += `<div class="pair-item ${active?'active':''}" onclick="switchPair('${p}')"><img src="${icon}" class="coin-icon" onerror="this.src='https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff'"> <div style="flex:1"><div style="font-weight:700; font-size:13px">${disp}</div></div> <div style="text-align:right"><div style="font-size:13px; font-weight:bold">${parseFloat(d.c).toLocaleString()}</div><div style="font-size:11px; color:${color}">${(d.P>=0?'+':'')+d.P}%</div></div></div>`;
}
mH += `<div class="m-coin-item ${active?'active':''}" onclick="switchPair('${p}')"><img src="${icon}" onerror="this.src='https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff'"><span>${p.replace('USDT','')}</span></div>`;
});
if(list) list.innerHTML = lH; if(mBar) mBar.innerHTML = mH;
}
function filterPairs() { searchQuery = document.getElementById('pair-search').value.toUpperCase(); renderPairs(); }
function switchPair(p) {
currentPair = p; const icon = getIcon(p);
document.getElementById('curr-pair').innerText = p + ' Perpetual'; document.getElementById('m-curr-pair').innerText = p + ' Perp';
document.getElementById('curr-icon').src = icon; document.getElementById('m-curr-icon').src = icon;
currentPair = p; const icon = getIcon(p);
document.getElementById('curr-pair').innerText = p.replace('USDT','')+'/USDT';
const iconEl = document.getElementById('curr-icon');
iconEl.src = icon;
iconEl.onerror = function() { this.src = `https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff`; };
document.querySelectorAll('.coin-name').forEach(el => el.innerText = p.replace('USDT',''));
initChart(p, "tv_chart_container_desk"); initChart(p, "tv_chart_container_mob"); updateBalance();
initChart(p); updateBalance();
}
function toggleMarginMode() { marginMode = marginMode === 'cross' ? 'isolated' : 'cross'; document.getElementById('margin-mode').innerText = marginMode.toUpperCase(); }
function toggleMarginMode() { marginMode = marginMode === 'cross' ? 'isolated' : 'cross'; document.getElementById('margin-mode').innerText = marginMode === 'cross' ? '<?php echo __('cross'); ?>' : '<?php echo __('isolated'); ?>'; }
function toggleLeverageModal() { const modal = document.getElementById('leverage-modal'); modal.style.display = modal.style.display === 'flex' ? 'none' : 'flex'; }
function updateSliderVal(v) { document.getElementById('slider-val').innerText = v + 'x'; }
function confirmLeverage() { currentLeverage = document.getElementById('leverage-range').value; document.getElementById('leverage-val').innerText = currentLeverage + 'x'; toggleLeverageModal(); }
@ -274,17 +302,18 @@ $user_id = $_SESSION['user_id'] ?? null;
async function placeOrder(side) {
const p = parseFloat(document.getElementById('futures-price').value) || currentPrice; const a = parseFloat(document.getElementById('futures-amount').value);
if(!a || a<=0) return alert('Invalid amount');
if(!a || a<=0) return alert('<?php echo __('amount'); ?> Error');
const resp = await fetch('api/place_order.php', { method:'POST', body:JSON.stringify({ symbol:currentPair, type:'futures', side:side, order_type:'market', price:p, amount:a, total:p*a, leverage:currentLeverage, tp_price:document.getElementById('futures-tp').value, sl_price:document.getElementById('futures-sl').value }) });
const res = await resp.json();
if(res.success) { alert('Order placed'); updateBalance(); fetchOrders(); } else alert(res.error);
if(res.success) { alert('<?php echo __('order_placed'); ?>'); updateBalance(); fetchOrders(); } else alert(res.error);
}
function renderOrderBook() {
const asks = document.getElementById('asks-list'); const bids = document.getElementById('bids-list');
let aH = ''; let bH = '';
for(let i=8; i>0; i--) { const p = currentPrice * (1+i*0.0001); const amt = Math.random()*2; aH += `<div class="ob-row"><div class="ob-bar" style="width:${amt*25}%; background:#f6465d"></div><span style="color:#f6465d">${p.toFixed(1)}</span><span>${amt.toFixed(3)}</span></div>`; }
for(let i=1; i<=8; i++) { const p = currentPrice * (1-i*0.0001); const amt = Math.random()*2; bH += `<div class="ob-row"><div class="ob-bar" style="width:${amt*25}%; background:#0ecb81"></div><span style="color:#0ecb81">${p.toFixed(1)}</span><span>${amt.toFixed(3)}</span></div>`; }
const rowCount = 20;
for(let i=rowCount; i>0; i--) { const p = currentPrice * (1+i*0.0001); const amt = Math.random()*2; aH += `<div class="ob-row"><div class="ob-bar" style="width:${amt*30}%; background:#f6465d"></div><span style="color:#f6465d">${p.toFixed(2)}</span><span>${amt.toFixed(4)}</span></div>`; }
for(let i=1; i<=rowCount; i++) { const p = currentPrice * (1-i*0.0001); const amt = Math.random()*2; bH += `<div class="ob-row"><div class="ob-bar" style="width:${amt*30}%; background:#0ecb81"></div><span style="color:#0ecb81">${p.toFixed(2)}</span><span>${amt.toFixed(4)}</span></div>`; }
if(asks) asks.innerHTML = aH; if(bids) bids.innerHTML = bH;
}
@ -295,14 +324,12 @@ $user_id = $_SESSION['user_id'] ?? null;
async function fetchOrders() {
const resp = await fetch(`api/get_orders.php?type=futures&status=${currentStatus}`); const res = await resp.json();
const l = document.getElementById('records-list'); const mL = document.getElementById('m-records-list');
let h = res.success && res.data.length > 0 ? res.data.map(o => `<div style="padding:15px; border-bottom:1px solid #2b3139; font-size:12px"><div style="display:flex; justify-content:space-between; align-items:center"><span style="color:${o.side==='buy'?'#0ecb81':'#f6465d'}; font-weight:bold; font-size:14px">${o.side==='buy'?'Long':'Short'} ${o.symbol} ${o.leverage}x</span><span style="color:#848e9c">${o.created_at}</span></div><div style="display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; color:#848e9c; margin-top:10px"><div>Size<br><span style="color:white; font-weight:bold">${o.amount}</span></div><div>Price<br><span style="color:white; font-weight:bold">${parseFloat(o.price).toFixed(2)}</span></div><div>TP/SL<br><span style="color:white; font-weight:bold">${o.tp_price||'--'}/${o.sl_price||'--'}</span></div></div></div>`).join('') : '<div style="padding:40px; text-align:center; color:#848e9c">No records</div>';
if(l) l.innerHTML = h; if(mL) mL.innerHTML = h;
const l = document.getElementById('records-list');
let h = res.success && res.data.length > 0 ? res.data.map(o => `<div style="padding:15px; border-bottom:1px solid #2b3139; font-size:12px"><div style="display:flex; justify-content:space-between; align-items:center"><span style="color:${o.side==='buy'?'#0ecb81':'#f6465d'}; font-weight:bold; font-size:14px">${o.side==='buy'?'Long':'Short'} ${o.symbol} ${o.leverage}x</span><span style="color:#848e9c">${o.created_at}</span></div><div style="display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; color:#848e9c; margin-top:10px"><div><?php echo __('size'); ?><br><span style="color:white; font-weight:bold">${o.amount}</span></div><div><?php echo __('price'); ?><br><span style="color:white; font-weight:bold">${parseFloat(o.price).toFixed(2)}</span></div><div>TP/SL<br><span style="color:white; font-weight:bold">${o.tp_price||'--'}/${o.sl_price||'--'}</span></div></div></div>`).join('') : '<div style="padding:40px; text-align:center; color:#848e9c"><?php echo __('no_records'); ?></div>';
if(l) l.innerHTML = h;
}
function switchRecords(s) { currentStatus = s; document.querySelectorAll('.record-tab').forEach(t => t.classList.remove('active')); event.target.classList.add('active'); fetchOrders(); }
function switchMobileView(view) { document.querySelectorAll('.m-nav-tab').forEach(n => n.classList.remove('active')); event.target.classList.add('active'); document.querySelectorAll('.m-view').forEach(v => v.style.display = 'none'); document.getElementById('view-' + view).style.display = 'block'; if(view === 'orders') fetchOrders(); }
switchPair(currentPair); updateBalance(); fetchOrders();
</script>
<?php include 'footer.php'; ?>

View File

@ -12,7 +12,7 @@ $site_logo = $settings['site_logo'] ?? null;
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>NovaEx | Leading Crypto Exchange</title>
<title><?php echo __('site_title'); ?></title>
<?php if($site_logo): ?>
<link rel="icon" href="<?php echo $site_logo; ?>" type="image/x-icon">
<?php endif; ?>
@ -125,7 +125,7 @@ $site_logo = $settings['site_logo'] ?? null;
<?php if($site_logo): ?>
<img src="<?php echo $site_logo; ?>" class="site-logo-img" alt="Logo">
<?php else: ?>
<span style="font-size: 1.5rem; color: var(--primary-color);">NovaEx</span>
<span style="font-size: 1.5rem; color: var(--primary-color);"><?php echo __('site_name'); ?></span>
<?php endif; ?>
</div>
<i class="fas fa-times" style="font-size: 1.4rem; color: var(--text-muted); cursor: pointer;" onclick="toggleSidebar()"></i>
@ -137,7 +137,7 @@ $site_logo = $settings['site_logo'] ?? null;
<a href="options.php"><i class="fas fa-clock" style="color: #fbc02d;"></i> <?php echo __('nav_options'); ?></a>
<a href="spot.php"><i class="fas fa-coins" style="color: #ffd600;"></i> <?php echo __('nav_spot'); ?></a>
<a href="futures.php"><i class="fas fa-file-contract" style="color: #ff3d00;"></i> <?php echo __('nav_futures'); ?></a>
<a href="mining.php"><i class="fas fa-pickaxe" style="color: #8e24aa;"></i> <?php echo __('nav_mining'); ?></a>
<a href="mining.php"><i class="fas fa-hammer" style="color: #8e24aa;"></i> <?php echo __('nav_mining'); ?></a>
<a href="app.php"><i class="fas fa-mobile-alt" style="color: #4facfe;"></i> <?php echo __('nav_app_download'); ?></a>
<div style="margin: 20px 24px; padding: 20px; background: var(--card-bg); border-radius: 16px;">
@ -160,7 +160,7 @@ $site_logo = $settings['site_logo'] ?? null;
<div id="cs-chat-window">
<div class="chat-header">
<span>NovaEx Support</span>
<span><?php echo __('site_name'); ?> Support</span>
<i class="fas fa-times" onclick="toggleCSChat()" style="cursor: pointer;"></i>
</div>
<iframe src="chat_iframe.php"></iframe>
@ -179,7 +179,7 @@ $site_logo = $settings['site_logo'] ?? null;
<rect x="10" y="10" width="80" height="80" rx="20" fill="var(--primary-color)"/>
<path d="M30 30 L70 70 M70 30 L30 70" stroke="white" stroke-width="12" stroke-linecap="round"/>
</svg>
<span class="logo-name">NovaEx</span>
<span class="logo-name"><?php echo __('site_name'); ?></span>
<?php endif; ?>
</div>
</a>
@ -243,7 +243,7 @@ $site_logo = $settings['site_logo'] ?? null;
<span><?php echo __('nav_trade'); ?></span>
</a>
<a href="mining.php" class="mobile-nav-item <?php echo basename($_SERVER['PHP_SELF']) == 'mining.php' ? 'active' : ''; ?>">
<i class="fas fa-pickaxe"></i>
<i class="fas fa-hammer"></i>
<span><?php echo __('nav_mining'); ?></span>
</a>
<a href="profile.php" class="mobile-nav-item <?php echo basename($_SERVER['PHP_SELF']) == 'profile.php' ? 'active' : ''; ?>">
@ -284,4 +284,4 @@ $site_logo = $settings['site_logo'] ?? null;
} catch (e) {}
}, 5000);
<?php endif; ?>
</script>
</script>

View File

@ -5,8 +5,11 @@ if (session_status() === PHP_SESSION_NONE) {
$translations = [
'en' => [
'site_name' => 'NovaEx',
'site_title' => 'NovaEx | Leading Crypto Exchange',
'nav_home' => 'Home',
'nav_market' => 'Markets',
'search_currency' => 'Search Currency',
'nav_trade' => 'Trade',
'nav_spot' => 'Spot',
'nav_futures' => 'Futures',
@ -24,6 +27,7 @@ $translations = [
'nav_security' => 'Security',
'nav_app_download' => 'APP Download',
'nav_help' => 'Help',
'language' => 'Language',
'hero_title' => 'Buy, trade, and hold 350+ cryptocurrencies on NovaEx',
'hero_subtitle' => 'Join the world\'s largest crypto exchange with the lowest fees and best security.',
@ -41,6 +45,9 @@ $translations = [
'last_price' => 'Last Price',
'24h_change' => '24h Change',
'market_cap' => 'Market Cap',
'24h_high' => '24h High',
'24h_low' => '24h Low',
'24h_vol' => '24h Vol',
'why_choose_us' => 'Why Choose NovaEx?',
'secure_storage' => 'Secure Storage',
@ -82,6 +89,7 @@ $translations = [
'search_contract' => 'Search Contracts',
'price' => 'Price',
'amount' => 'Amount',
'size' => 'Size',
'total' => 'Total',
'available' => 'Available',
'limit' => 'Limit',
@ -131,6 +139,8 @@ $translations = [
'trading_executing' => 'Trading Executing',
'waiting_settlement' => 'Waiting for Settlement',
'system_matching_engine' => 'System matching engine',
'options_instruction' => 'Trading Instruction',
'options_wait_settle' => 'The system matching engine is executing. Please wait for the countdown to end for settlement.',
'kyc_status' => 'KYC Verification',
'kyc_none' => 'Unverified',
@ -152,10 +162,53 @@ $translations = [
'withdraw_submit' => 'Confirm Withdrawal',
'withdraw_tip' => 'Please jump to customer service to confirm withdrawal after submission.',
'payout_format_received' => 'Payout Format Received',
'chart' => 'Chart',
'orders' => 'Orders',
'order_placed' => 'Order Placed',
'min_amount' => 'Min Amount',
'home_slide1_title' => 'NovaEx Global Launch',
'home_slide1_desc' => 'Experience the next generation of digital asset trading with ultra-low latency and bank-grade security.',
'home_slide2_title' => 'Trade Futures with 100x Leverage',
'home_slide2_desc' => 'Maximize your capital efficiency with our professional perpetual futures contracts.',
'home_slide3_title' => 'Secure Crypto Staking',
'home_slide3_desc' => 'Earn passive income on your idle assets with our high-yield staking pools.',
'home_download_title' => 'Trade Anywhere, Anytime',
'home_download_desc' => 'Stay connected to the markets with the NovaEx mobile app. Experience professional trading features in the palm of your hand.',
'fast_secure' => 'Fast & Secure',
'fast_secure_desc' => 'Military-grade encryption for all your data.',
'real_time' => 'Real-time',
'real_time_desc' => 'Low-latency updates and market depth.',
'scan_download' => 'Scan to Download',
'ios_android' => 'Support for iOS & Android',
'mining_staking' => 'Staking & Mining',
'mining_hero_subtitle' => 'Participate in proof-of-stake and decentralized finance to earn rewards on your digital assets.',
'liquidity_mining' => 'Liquidity Mining',
'liquidity_mining_desc' => 'Provide liquidity to automated market makers and earn a portion of the trading fees plus governance tokens.',
'pos_staking' => 'PoS Staking',
'pos_staking_desc' => 'Stake your proof-of-stake assets to help secure the network and receive inflation rewards directly in your wallet.',
'launchpad' => 'Launchpad',
'launchpad_desc' => 'Gain exclusive access to high-quality blockchain projects before they list on our exchange.',
'est_apr' => 'Est. APR',
'stake_now' => 'Stake Now',
'view_details' => 'View Details',
'yield_rankings' => 'Yield Rankings',
'all' => 'All',
'asset' => 'Asset',
'duration' => 'Duration',
'flexible' => 'Flexible',
'subscribe' => 'Subscribe',
'days' => 'Days',
'coming_soon' => 'Coming Soon',
'next_project' => 'Next Project',
],
'zh' => [
'site_name' => 'NovaEx',
'site_title' => 'NovaEx | 全球领先的数字资产交易所',
'nav_home' => '首页',
'nav_market' => '行情',
'search_currency' => '搜索币种',
'nav_trade' => '交易',
'nav_spot' => '现货交易',
'nav_futures' => '合约交易',
@ -173,6 +226,7 @@ $translations = [
'nav_security' => '安全中心',
'nav_app_download' => 'APP 下载',
'nav_help' => '帮助中心',
'language' => '语言',
'hero_title' => '在 NovaEx 购买、交易和持有 350 多种加密货币',
'hero_subtitle' => '加入全球最大的加密货币交易所,享受最低的费用和最好的安全性。',
@ -190,6 +244,9 @@ $translations = [
'last_price' => '最新价',
'24h_change' => '24h 涨跌',
'market_cap' => '市值',
'24h_high' => '24h 最高',
'24h_low' => '24h 最低',
'24h_vol' => '24h 成交额',
'why_choose_us' => '为什么选择 NovaEx?',
'secure_storage' => '安全存储',
@ -203,7 +260,7 @@ $translations = [
'global_partners' => '全球合作伙伴',
'partners_subtitle' => '深受全球领先组织和金融机构的信任。',
'footer_desc' => 'NovaEx 是全球领先的数字资产交易平台,为全球用户提供安全稳定的交易服务。',
'footer_desc' => 'NovaEx 是全球领先的数字资产 trading 平台,为全球用户提供安全稳定的交易服务。',
'about' => '关于',
'about_us' => '关于我们',
'careers' => '职业介绍',
@ -231,6 +288,7 @@ $translations = [
'search_contract' => '搜索合约',
'price' => '价格',
'amount' => '数量',
'size' => '数量',
'total' => '总额',
'available' => '可用',
'limit' => '限价',
@ -280,6 +338,8 @@ $translations = [
'trading_executing' => '交易执行中',
'waiting_settlement' => '等待结算',
'system_matching_engine' => '系统撮合引擎',
'options_instruction' => '交易说明',
'options_wait_settle' => '系统撮合引擎正在执行中,请等待倒计时结束进行结算。',
'kyc_status' => '实名认证',
'kyc_none' => '未认证',
@ -301,6 +361,46 @@ $translations = [
'withdraw_submit' => '确认订单',
'withdraw_tip' => '提交后请跳转客服对话窗确认。',
'payout_format_received' => '收到出款格式',
'chart' => '图表',
'orders' => '订单',
'order_placed' => '下单成功',
'min_amount' => '最小金额',
'home_slide1_title' => 'NovaEx 全球发布',
'home_slide1_desc' => '体验超低延迟和银行级安全的新一代数字资产交易。',
'home_slide2_title' => '100倍杠杆合约交易',
'home_slide2_desc' => '通过我们的专业永续合约最大限度地提高您的资金效率。',
'home_slide3_title' => '安全数字资产质押',
'home_slide3_desc' => '通过我们的高收益质押池赚取被动收入。',
'home_download_title' => '随时随地,随心交易',
'home_download_desc' => '通过 NovaEx 移动应用保持与市场的连接。在掌中体验专业的交易功能。',
'fast_secure' => '快速且安全',
'fast_secure_desc' => '为您的所有数据提供军用级加密。',
'real_time' => '实时行情',
'real_time_desc' => '低延迟更新和市场深度。',
'scan_download' => '扫描下载',
'ios_android' => '支持 iOS 和 Android',
'mining_staking' => '质押与挖矿',
'mining_hero_subtitle' => '参与权益证明和去中心化金融,从您的数字资产中赚取奖励。',
'liquidity_mining' => '流动性挖矿',
'liquidity_mining_desc' => '向自动做市商提供流动性,赚取部分交易费用及治理代币奖励。',
'pos_staking' => 'PoS 质押',
'pos_staking_desc' => '质押您的权益证明资产,协助维护网络安全,并直接在钱包中获取通胀奖励。',
'launchpad' => '打新平台',
'launchpad_desc' => '在优质区块链项目上线交易所前,获得独家参与机会。',
'est_apr' => '预估年化收益率',
'stake_now' => '立即质押',
'view_details' => '查看详情',
'yield_rankings' => '收益排行榜',
'all' => '全部',
'asset' => '资产',
'duration' => '期限',
'flexible' => '活期',
'subscribe' => '立即申购',
'days' => '天',
'coming_soon' => '即将到来',
'next_project' => '下一个项目',
]
];
@ -317,4 +417,4 @@ $lang = $_SESSION['lang'];
function __($key, $default = '') {
global $translations, $lang;
return $translations[$lang][$key] ?? ($translations['en'][$key] ?? ($default ?: $key));
}
}

View File

@ -15,24 +15,24 @@ $trending_pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'];
<div class="carousel-slide" style="min-width: 100%; position: relative;">
<img src="https://images.pexels.com/photos/6771574/pexels-photo-6771574.jpeg?auto=compress&cs=tinysrgb&w=1920" style="width: 100%; height: 100%; object-fit: cover; opacity: 0.6;">
<div class="carousel-content" style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 650px;">
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);">NovaEx Global Launch</h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;">Experience the next generation of digital asset trading with ultra-low latency and bank-grade security.</p>
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);"><?php echo __('home_slide1_title'); ?></h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;"><?php echo __('home_slide1_desc'); ?></p>
<a href="register.php" class="btn-primary" style="padding: 15px 45px; border-radius: 12px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white; font-size: 1.1rem; box-shadow: 0 10px 20px rgba(79, 172, 254, 0.3);"><?php echo __('join_now'); ?></a>
</div>
</div>
<div class="carousel-slide" style="min-width: 100%; position: relative;">
<img src="https://images.pexels.com/photos/844124/pexels-photo-844124.jpeg?auto=compress&cs=tinysrgb&w=1920" style="width: 100%; height: 100%; object-fit: cover; opacity: 0.6;">
<div class="carousel-content" style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 650px;">
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);">Trade Futures with 100x Leverage</h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;">Maximize your capital efficiency with our professional perpetual futures contracts.</p>
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);"><?php echo __('home_slide2_title'); ?></h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;"><?php echo __('home_slide2_desc'); ?></p>
<a href="futures.php" class="btn-primary" style="padding: 15px 45px; border-radius: 12px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white; font-size: 1.1rem;"><?php echo __('start_trading'); ?></a>
</div>
</div>
<div class="carousel-slide" style="min-width: 100%; position: relative;">
<img src="https://images.pexels.com/photos/6771178/pexels-photo-6771178.jpeg?auto=compress&cs=tinysrgb&w=1920" style="width: 100%; height: 100%; object-fit: cover; opacity: 0.6;">
<div class="carousel-content" style="position: absolute; top: 50%; left: 8%; transform: translateY(-50%); color: white; max-width: 650px;">
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);">Secure Crypto Staking</h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;">Earn passive income on your idle assets with our high-yield staking pools.</p>
<h2 class="carousel-title" style="font-size: 3.5rem; font-weight: 800; margin-bottom: 25px; line-height: 1.1; text-shadow: 0 10px 20px rgba(0,0,0,0.5);"><?php echo __('home_slide3_title'); ?></h2>
<p class="carousel-desc" style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 35px; line-height: 1.6;"><?php echo __('home_slide3_desc'); ?></p>
<a href="mining.php" class="btn-primary" style="padding: 15px 45px; border-radius: 12px; font-weight: bold; text-decoration: none; display: inline-block; background: var(--primary-color); color: white; font-size: 1.1rem;"><?php echo __('earn_now'); ?></a>
</div>
</div>
@ -128,8 +128,8 @@ $trending_pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'];
<div class="container">
<div class="download-grid" style="display: flex; align-items: center; justify-content: space-between; gap: 60px; flex-wrap: wrap;">
<div style="flex: 1.2; min-width: 300px;">
<h2 class="section-title-small" style="font-size: 3rem; font-weight: 800; margin-bottom: 25px; background: linear-gradient(135deg, #fff 0%, #848e9c 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; line-height: 1.2;">Trade Anywhere, Anytime</h2>
<p style="color: var(--text-muted); font-size: 1.2rem; line-height: 1.8; margin-bottom: 40px;">Stay connected to the markets with the NovaEx mobile app. Experience professional trading features in the palm of your hand.</p>
<h2 class="section-title-small" style="font-size: 3rem; font-weight: 800; margin-bottom: 25px; background: linear-gradient(135deg, #fff 0%, #848e9c 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; line-height: 1.2;"><?php echo __('home_download_title'); ?></h2>
<p style="color: var(--text-muted); font-size: 1.2rem; line-height: 1.8; margin-bottom: 40px;"><?php echo __('home_download_desc'); ?></p>
<div class="features-mini-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-top: 40px;">
<div style="display: flex; gap: 15px; align-items: flex-start;">
@ -137,8 +137,8 @@ $trending_pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'];
<i class="fas fa-bolt" style="font-size: 18px;"></i>
</div>
<div>
<h4 style="margin: 0 0 5px; font-weight: 700; font-size: 1.1rem; color: white;">Fast & Secure</h4>
<p style="font-size: 0.95rem; color: #848e9c; margin: 0; line-height: 1.4;">Military-grade encryption for all your data.</p>
<h4 style="margin: 0 0 5px; font-weight: 700; font-size: 1.1rem; color: white;"><?php echo __('fast_secure'); ?></h4>
<p style="font-size: 0.95rem; color: #848e9c; margin: 0; line-height: 1.4;"><?php echo __('fast_secure_desc'); ?></p>
</div>
</div>
<div style="display: flex; gap: 15px; align-items: flex-start;">
@ -146,8 +146,8 @@ $trending_pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'];
<i class="fas fa-chart-line" style="font-size: 18px;"></i>
</div>
<div>
<h4 style="margin: 0 0 5px; font-weight: 700; font-size: 1.1rem; color: white;">Real-time</h4>
<p style="font-size: 0.95rem; color: #848e9c; margin: 0; line-height: 1.4;">Low-latency updates and market depth.</p>
<h4 style="margin: 0 0 5px; font-weight: 700; font-size: 1.1rem; color: white;"><?php echo __('real_time'); ?></h4>
<p style="font-size: 0.95rem; color: #848e9c; margin: 0; line-height: 1.4;"><?php echo __('real_time_desc'); ?></p>
</div>
</div>
</div>
@ -185,8 +185,8 @@ $trending_pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'];
<i class="fas fa-qrcode" style="font-size: 2.5rem; color: #000;"></i>
</div>
<div>
<div style="font-weight: 800; color: white; font-size: 1.1rem; margin-bottom: 4px;">Scan to Download</div>
<div style="font-size: 0.9rem; color: #848e9c;">Support for iOS & Android</div>
<div style="font-weight: 800; color: white; font-size: 1.1rem; margin-bottom: 4px;"><?php echo __('scan_download'); ?></div>
<div style="font-size: 0.9rem; color: #848e9c;"><?php echo __('ios_android'); ?></div>
</div>
</div>
</div>

View File

@ -55,7 +55,7 @@
</style>
<script>
const pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'LINKUSDT', 'AVAXUSDT', 'MATICUSDT', 'SHIBUSDT'];
const pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'LINKUSDT', 'AVAXUSDT', 'MATICUSDT', 'SHIBUSDT', 'TRXUSDT', 'LTCUSDT', 'BCHUSDT', 'UNIUSDT', 'FTMUSDT', 'NEARUSDT'];
const ws = new WebSocket('wss://stream.binance.com:9443/ws/' + pairs.map(p => p.toLowerCase() + '@ticker').join('/'));
const marketData = {};
@ -75,16 +75,17 @@
const price = parseFloat(d.c).toLocaleString(undefined, {minimumFractionDigits: 2});
const change = parseFloat(d.P).toFixed(2);
const color = change >= 0 ? 'var(--success-color)' : 'var(--danger-color)';
const color = change >= 0 ? '#0ecb81' : '#f6465d';
const name = p.replace('USDT', '');
const icon = `https://assets.coincap.io/assets/icons/${name.toLowerCase()}@2x.png`;
html += `
<tr style="border-bottom: 1px solid #2b3139; cursor: pointer;" onclick="location.href='spot.php?symbol=${p}'">
<td style="padding: 15px 20px; display: flex; align-items: center; gap: 12px;">
<img src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png" width="28" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
<img src="${icon}" width="28" height="28" style="border-radius:50%; background:#2b3139" onerror="this.src='https://ui-avatars.com/api/?name=${name}&background=2b3139&color=fff'">
<div>
<div style="color: white; font-weight: bold; font-size: 0.95rem;">${name}</div>
<div style="color: #666; font-size: 0.75rem;">${name}/USDT</div>
<div style="color: #848e9c; font-size: 0.75rem;">${name}/USDT</div>
</div>
</td>
<td style="padding: 15px 20px; text-align: right; color: white; font-weight: bold; font-family: monospace; font-size: 0.95rem;">$ ${price}</td>

View File

@ -23,28 +23,32 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['amount'])) {
$expires_at = date('Y-m-d H:i:s', strtotime('+30 minutes'));
// Create order with status 'matching'
$stmt = $pdo->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 = $pdo->lastInsertId();
// Get user IP
$user_ip = $_SERVER['REMOTE_ADDR'];
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$user_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
$pdo->beginTransaction();
try {
// Create order with status 'matching'
$stmt = $pdo->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 = $pdo->lastInsertId();
// Log to transactions table
$stmt = $pdo->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'deposit', ?, 'USDT', 'pending', ?)");
$stmt->execute([$user_id, $usdt_amount, "Deposit Request #$order_id ($amount $currency)"]);
// Explicit notification message for admin/chat
$method_info = ($type === 'usdt') ? "USDT ($network)" : "法币 ($currency)";
$msg = "👉 用户发起充值,金额 $amount $currency\n订单号: #$order_id\n方式: $method_info";
$stmt = $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
$stmt->execute([$user_id, $msg]);
// Redirect to chat
header("Location: chat.php");
exit;
// Explicit notification message for admin/chat
$method_info = ($type === 'usdt') ? "USDT ($network)" : "法币 ($currency)";
$msg = "升匆 用户发起充值,金额 $amount $currency\n订单号: #$order_id\n方式: $method_info";
$stmt = $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'user', ?)");
$stmt->execute([$user_id, $msg]);
$pdo->commit();
header("Location: chat.php");
exit;
} catch (Exception $e) {
$pdo->rollBack();
die("Error: " . $e->getMessage());
}
} else {
header("Location: deposit.php");
exit;
}
}

View File

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

View File

@ -6,152 +6,239 @@ $user_id = $_SESSION['user_id'] ?? null;
?>
<style>
/* Layout Fixes */
/* Global layout enforcement */
html, body {
background: #0b0e11;
min-width: 1280px;
max-width: 1920px;
margin: 0 auto;
overflow-x: auto;
}
@media (max-width: 991px) {
html, body {
min-width: 100%;
max-width: 100%;
overflow-x: hidden;
}
.navbar, footer { display: none !important; }
body { padding-bottom: 65px !important; margin: 0 !important; max-width: 100% !important; }
body { padding-bottom: 0 !important; }
}
.trading-container {
display: flex;
background: #0b0e11;
min-height: calc(100vh - 64px);
max-width: 100%;
margin: 0;
overflow: hidden;
width: 100%;
}
@media (max-width: 991px) {
.trading-container { min-height: 100vh; flex-direction: column; }
.trading-container { min-height: calc(100vh - 50px); flex-direction: column; }
}
.left-col { width: 280px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.center-col { flex: 1; min-width: 0; background: #0b0e11; display: flex; flex-direction: column; overflow: hidden; }
.right-col { width: 320px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-left: 1px solid #2b3139; }
.left-col { width: 260px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.center-col { flex: 1; min-width: 600px; background: #0b0e11; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.right-col { width: 320px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; }
@media (max-width: 991px) {
.left-col, .right-col { display: none !important; }
.center-col { min-width: 100%; }
}
/* Category Tabs above Search */
.category-tabs { display: flex; padding: 15px 15px 5px; gap: 8px; }
.category-tab { flex: 1; text-align: center; padding: 6px 0; background: #2b3139; border-radius: 4px; font-size: 11px; color: #848e9c; cursor: pointer; transition: all 0.2s; white-space: nowrap; border: 1px solid transparent; }
.category-tab.active { background: rgba(0, 82, 255, 0.1); border-color: var(--primary-color); color: var(--primary-color); font-weight: bold; }
/* Search Box */
.search-box { padding: 5px 15px 10px; position: relative; }
.search-box i { position: absolute; left: 25px; top: 50%; transform: translateY(-50%); color: #848e9c; font-size: 12px; }
.search-box input { width: 100%; background: #2b3139; border: 1px solid transparent; border-radius: 4px; padding: 8px 10px 8px 30px; color: white; font-size: 13px; outline: none; }
.search-box input:focus { border-color: var(--primary-color); }
/* Pairs List */
#pairs-list { flex: 1; overflow-y: auto; }
.pair-item { display: flex; align-items: center; padding: 12px 15px; cursor: pointer; transition: all 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
.pair-item { display: flex; align-items: center; padding: 10px 15px; cursor: pointer; transition: all 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
.pair-item:hover { background: #1e2329; }
.pair-item.active { background: #1e2329; border-left: 3px solid var(--primary-color); }
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; }
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; flex-shrink: 0; background: #2b3139; }
/* Chart Area */
.chart-header { padding: 12px 20px; display: flex; align-items: center; gap: 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
.chart-box { flex: 1; min-height: 400px; background: #0b0e11; }
.chart-header { padding: 8px 20px; display: flex; align-items: center; background: #161a1e; border-bottom: 1px solid #2b3139; flex-wrap: nowrap; gap: 20px; height: 50px; }
.chart-box { flex: 1; min-height: 400px; height: 400px; background: #0b0e11; border-bottom: 1px solid #2b3139; }
/* Order Records */
.record-tabs { display: flex; background: #161a1e; border-bottom: 1px solid #2b3139; padding: 0 15px; }
.record-tab { padding: 12px 0; margin-right: 25px; font-size: 13px; color: var(--text-muted); cursor: pointer; position: relative; }
.record-tab.active { color: var(--text-color); font-weight: 600; }
.record-tab { padding: 10px 0; margin-right: 25px; font-size: 13px; color: #848e9c; cursor: pointer; position: relative; }
.record-tab.active { color: white; font-weight: 600; }
.record-tab.active::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 2px; background: var(--primary-color); }
.records-content { height: 300px; overflow-y: auto; background: #161a1e; }
.records-content { min-height: 200px; height: 220px; overflow-y: auto; background: #161a1e; }
@media (max-width: 991px) {
.records-content { min-height: 350px; padding-bottom: 100px; height: auto; }
@media (max-width: 991px) {
.records-content { min-height: 200px; padding-bottom: 20px; height: auto; }
.chart-box { min-height: 320px; height: 320px; }
}
/* Right Order Panel */
.order-panel { padding: 20px; }
.panel-label { color: #848e9c; font-size: 12px; margin-bottom: 8px; }
.duration-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 20px; }
.time-btn { background: #2b3139; border: 1px solid transparent; color: #eaecef; padding: 8px 4px; border-radius: 4px; font-size: 11px; cursor: pointer; text-align: center; display: flex; flex-direction: column; align-items: center; }
.time-btn.active { background: rgba(0, 82, 255, 0.1); border-color: var(--primary-color); color: var(--primary-color); }
.time-btn .rate { font-size: 10px; font-weight: bold; margin-top: 2px; }
.order-panel { padding: 12px 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
.panel-label { color: #848e9c; font-size: 11px; margin-bottom: 6px; font-weight: 500; }
.duration-grid { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 5px; scrollbar-width: none; }
.duration-grid::-webkit-scrollbar { display: none; }
.time-btn { flex: 1; min-width: 70px; background: #2b3139; border: 1px solid transparent; color: #eaecef; padding: 6px 4px; border-radius: 4px; font-size: 11px; cursor: pointer; text-align: center; display: flex; flex-direction: column; align-items: center; transition: all 0.2s; }
.time-btn.active { background: rgba(0, 82, 255, 0.1); border-color: var(--primary-color); color: var(--primary-color); font-weight: bold; }
.time-btn .rate { font-size: 9px; font-weight: bold; margin-top: 2px; }
.input-group { background: #2b3139; border-radius: 4px; padding: 10px 12px; display: flex; align-items: center; margin-bottom: 10px; border: 1px solid transparent; }
.input-group { background: #2b3139; border-radius: 4px; padding: 6px 12px; display: flex; align-items: center; border: 1px solid transparent; transition: border-color 0.2s; }
.input-group:focus-within { border-color: var(--primary-color); }
.input-group input { background: transparent; border: none; color: white; flex: 1; text-align: right; outline: none; font-size: 14px; width: 100%; }
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 12px; }
.input-group input { background: transparent; border: none; color: white; flex: 1; text-align: left; outline: none; font-size: 13px; width: 100%; }
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 11px; }
.balance-info { display: flex; justify-content: space-between; font-size: 12px; color: #848e9c; margin: 15px 0; }
.trade-btn { width: 100%; padding: 14px; border-radius: 4px; font-weight: bold; font-size: 15px; border: none; cursor: pointer; margin-top: 10px; }
.balance-info { display: flex; justify-content: space-between; font-size: 10px; color: #848e9c; margin-top: 4px; }
.trade-btn { flex: 1; padding: 10px; border-radius: 4px; font-weight: bold; font-size: 14px; border: none; cursor: pointer; transition: transform 0.1s; }
.trade-btn:active { transform: scale(0.98); }
.btn-up { background: #0ecb81; color: white; }
.btn-down { background: #f6465d; color: white; }
/* Mobile Components */
.m-trading-header { display: none; background: #161a1e; padding: 12px 15px; border-bottom: 1px solid #2b3139; }
.m-nav-tabs { display: none; background: #161a1e; border-bottom: 1px solid #2b3139; }
/* Order Book Styles */
.order-book-header { padding: 10px 15px; font-size: 12px; font-weight: 600; border-bottom: 1px solid #2b3139; color: white; background: #161a1e; }
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; height: 20px; align-items: center; }
.ob-price { flex: 1; font-weight: 500; }
.ob-amount { flex: 1; text-align: right; color: #eaecef; }
.ob-total { flex: 1; text-align: right; color: #848e9c; }
.ob-bg-sell { position: absolute; right: 0; top: 0; bottom: 0; background: rgba(246, 70, 93, 0.1); z-index: 0; }
.ob-bg-buy { position: absolute; right: 0; top: 0; bottom: 0; background: rgba(14, 203, 129, 0.1); z-index: 0; }
/* Mobile Nav */
.m-trade-nav { display: none; background: #161a1e; border-bottom: 1px solid #2b3139; position: sticky; top: 0; z-index: 100; }
.m-trade-nav a { flex: 1; text-align: center; padding: 14px; font-size: 14px; color: #848e9c; text-decoration: none; border-bottom: 2px solid transparent; }
.m-trade-nav a.active { color: var(--primary-color); border-bottom-color: var(--primary-color); font-weight: bold; }
.m-currency-bar { display: none; overflow-x: auto; background: #161a1e; padding: 10px; gap: 10px; border-bottom: 1px solid #2b3139; scrollbar-width: none; }
@media (max-width: 991px) {
.m-trading-header, .m-nav-tabs, .m-currency-bar { display: flex; }
.m-trading-header { flex-direction: column; }
}
.m-currency-bar::-webkit-scrollbar { display: none; }
.m-coin-item { flex-shrink: 0; background: #2b3139; padding: 6px 12px; border-radius: 4px; display: flex; align-items: center; gap: 6px; border: 1px solid transparent; }
.m-coin-item.active { border-color: var(--primary-color); background: rgba(0, 82, 255, 0.1); }
.m-coin-item img { width: 16px; height: 16px; border-radius: 50%; }
.mobile-footer-actions { display: none; position: fixed; bottom: 65px; left: 0; width: 100%; background: #161a1e; padding: 12px 15px; border-top: 1px solid #2b3139; gap: 12px; z-index: 1000; }
@media (max-width: 991px) { .mobile-footer-actions { display: flex; } }
.m-order-sheet { position: fixed; bottom: -100%; left: 0; width: 100%; background: #1e2329; border-top-left-radius: 20px; border-top-right-radius: 20px; z-index: 2000; padding: 25px 20px; transition: bottom 0.3s ease; }
.m-order-sheet.show { bottom: 65px; }
.m-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 1999; display: none; }
.m-overlay.show { display: block; }
@media (max-width: 991px) {
.m-trade-nav { display: flex; }
.m-currency-bar { display: flex; }
.chart-header { gap: 10px; padding: 10px 15px; overflow-x: auto; scrollbar-width: none; }
.chart-header::-webkit-scrollbar { display: none; }
.stats-item { flex-shrink: 0; }
}
.progress-bar-container { width: 100%; height: 3px; background: #2b3139; border-radius: 2px; margin-top: 8px; overflow: hidden; }
.progress-bar-fill { height: 100%; background: var(--primary-color); width: 0%; transition: width 1s linear; }
.stats-item { display: flex; flex-direction: column; justify-content: center; }
.stats-label { font-size: 10px; color: #848e9c; margin-bottom: 1px; white-space: nowrap; }
.stats-value { font-size: 12px; font-weight: 600; color: white; white-space: nowrap; }
/* Countdown Modal (Beautiful Square with Circular Timer) */
.option-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.85); z-index: 3000; display: none; align-items: center; justify-content: center; backdrop-filter: blur(8px); }
.option-modal-content { background: #1e2329; width: 420px; height: 420px; border-radius: 24px; padding: 30px; border: 1px solid #2b3139; position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: center; justify-content: space-between; box-shadow: 0 20px 50px rgba(0,0,0,0.5); }
.circular-timer-box { position: relative; width: 120px; height: 120px; margin-bottom: 10px; }
.circular-timer-svg { transform: rotate(-90deg); width: 120px; height: 120px; }
.circular-timer-bg { fill: none; stroke: #2b3139; stroke-width: 8; }
.circular-timer-progress { fill: none; stroke: var(--primary-color); stroke-width: 8; stroke-linecap: round; stroke-dasharray: 351.85; stroke-dashoffset: 0; transition: stroke-dashoffset 1s linear; }
.timer-text { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 28px; font-weight: 800; color: white; font-family: 'Courier New', monospace; }
.modal-symbol { font-size: 20px; font-weight: 800; color: white; margin-bottom: 2px; }
.modal-dir { font-size: 13px; font-weight: 700; padding: 4px 16px; border-radius: 20px; margin-bottom: 15px; }
.modal-info-grid { width: 100%; display: grid; grid-template-columns: 1fr 1fr; gap: 15px; background: rgba(255,255,255,0.03); padding: 15px; border-radius: 16px; margin-bottom: 15px; }
.info-item { display: flex; flex-direction: column; gap: 4px; }
.info-label { color: #848e9c; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; }
.info-value { color: white; font-size: 14px; font-weight: 700; }
.modal-live-box { text-align: center; width: 100%; }
.live-label { color: #848e9c; font-size: 12px; margin-bottom: 5px; }
.live-price { font-size: 24px; font-weight: 800; transition: color 0.3s; }
.profit-estimate { font-size: 14px; font-weight: 700; margin-top: 4px; }
.modal-footer-note { font-size: 11px; color: #5e6673; text-align: center; line-height: 1.4; }
</style>
<!-- Mobile Trading Header -->
<div class="m-trading-header">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="display: flex; align-items: center; gap: 10px;" onclick="toggleSidebar()">
<i class="fas fa-bars" style="font-size: 18px;"></i>
<div style="font-size: 18px; font-weight: 800; display: flex; align-items: center; gap: 6px;">
<img id="m-curr-icon" src="" style="width:24px; height:24px; border-radius:50%">
<span id="m-curr-pair">BTC/USDT</span>
<i class="fas fa-chevron-down" style="font-size: 10px; opacity: 0.5;"></i>
</div>
</div>
<div style="text-align: right">
<div id="m-curr-price" style="font-size: 22px; font-weight: 800; color: #0ecb81; line-height: 1;">--</div>
<div id="m-curr-change" style="font-size: 12px; font-weight: 600; margin-top: 4px;">--</div>
</div>
</div>
<div style="display: flex; gap: 15px; margin-top: 10px; font-size: 11px; color: #848e9c;">
<span id="m-24h-high">H: --</span>
<span id="m-24h-low">L: --</span>
<span id="m-24h-vol">V: --</span>
</div>
<div class="m-trade-nav">
<a href="spot.php"><?php echo __('nav_spot'); ?></a>
<a href="futures.php"><?php echo __('nav_futures'); ?></a>
<a href="options.php" class="active"><?php echo __('nav_options'); ?></a>
</div>
<!-- Mobile Currency Bar -->
<div class="m-currency-bar" id="m-coin-list"></div>
<!-- Mobile Nav Tabs -->
<div class="m-nav-tabs">
<div class="m-nav-tab active" data-view="chart" onclick="switchMobileView('chart')"><?php echo __('chart'); ?></div>
<div class="m-nav-tab" data-view="orders" onclick="switchMobileView('orders')"><?php echo __('positions'); ?></div>
</div>
<div class="trading-container">
<div class="left-col d-none d-lg-flex">
<div class="market-header" style="padding:15px; font-weight:bold; border-bottom:1px solid #2b3139"><?php echo __('nav_market'); ?></div>
<div class="category-tabs">
<div class="category-tab active" onclick="location.href='options.php'"><?php echo $lang == 'zh' ? '秒合约' : 'Options'; ?></div>
<div class="category-tab" onclick="location.href='spot.php'"><?php echo $lang == 'zh' ? '现货交易' : 'Spot'; ?></div>
<div class="category-tab" onclick="location.href='futures.php'"><?php echo $lang == 'zh' ? '合约交易' : 'Futures'; ?></div>
</div>
<div class="search-box">
<i class="fas fa-search"></i>
<input type="text" id="pair-search" placeholder="<?php echo __('search_currency'); ?>" oninput="filterPairs()">
</div>
<div id="pairs-list"></div>
</div>
<div class="center-col">
<div class="chart-header d-none d-lg-flex">
<div style="display: flex; align-items: center; gap: 12px;">
<img id="curr-icon" src="" class="coin-icon" style="margin:0; width:32px; height:32px;">
<div class="chart-header">
<div style="display: flex; align-items: center; gap: 10px; padding-right: 15px; border-right: 1px solid #2b3139;">
<img id="curr-icon" src="" class="coin-icon" style="margin:0; width:28px; height:28px;">
<div>
<div style="font-weight: 800; font-size: 20px; line-height: 1.2;">
<span id="curr-pair">BTC/USDT</span>
</div>
<div style="font-size: 11px; color: var(--primary-color); font-weight: 600;"><?php echo __('nav_options'); ?></div>
<div style="font-weight: 800; font-size: 16px; line-height: 1.2;"><span id="curr-pair">BTC/USDT</span></div>
<div style="font-size: 10px; color: var(--primary-color); font-weight: 600;"><?php echo __('nav_options'); ?></div>
</div>
</div>
<div style="flex:1"></div>
<div style="text-align: right">
<div id="curr-price" style="font-size: 24px; font-weight: 800; color: #0ecb81;">--</div>
<div id="curr-change" style="font-size: 13px; font-weight: 600;">--</div>
<div class="stats-item">
<div id="curr-price" style="font-size: 18px; font-weight: 800; color: #0ecb81; line-height: 1.2;">--</div>
<div id="curr-change" style="font-size: 11px; font-weight: 600;">--</div>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_high'); ?></span>
<span class="stats-value" id="h-high">--</span>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_low'); ?></span>
<span class="stats-value" id="h-low">--</span>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_vol'); ?></span>
<span class="stats-value" id="h-vol">--</span>
</div>
</div>
<div class="chart-box" id="chart-section">
<div id="tv_chart_container" style="height: 100%;"></div>
<div class="chart-box"><div id="tv_chart_container" style="height: 100%;"></div></div>
<div class="order-panel">
<div style="display: grid; grid-template-columns: 1.2fr 0.8fr 1fr; gap: 15px; align-items: end;">
<div>
<div class="panel-label"><?php echo __('settlement_time'); ?></div>
<div class="duration-grid">
<div class="time-btn active" data-duration="60" data-rate="8" data-min="100">60S <span class="rate">8%</span></div>
<div class="time-btn" data-duration="90" data-rate="12" data-min="5000">90S <span class="rate">12%</span></div>
<div class="time-btn" data-duration="120" data-rate="15" data-min="30000">120S <span class="rate">15%</span></div>
<div class="time-btn" data-duration="180" data-rate="20" data-min="100000">180S <span class="rate">20%</span></div>
<div class="time-btn" data-duration="300" data-rate="32" data-min="300000">300S <span class="rate">32%</span></div>
</div>
</div>
<div>
<div class="panel-label"><?php echo __('buy_amount'); ?></div>
<div class="input-group">
<input type="number" id="option-amount" placeholder="<?php echo __('min_order'); ?> 100">
<span class="unit">USDT</span>
</div>
<div class="balance-info">
<span><?php echo __('available'); ?>: <span id="usdt-balance" style="color:white">0.00</span></span>
<span id="potential-profit" style="color: #0ecb81; font-weight: bold;">+0.00</span>
</div>
</div>
<div style="display:flex; gap:8px;">
<button class="trade-btn btn-up" onclick="placeOptionOrder('up')"><?php echo __('buy_up'); ?></button>
<button class="trade-btn btn-down" onclick="placeOptionOrder('down')"><?php echo __('buy_down'); ?></button>
</div>
</div>
</div>
<div id="records-section">
@ -164,196 +251,221 @@ $user_id = $_SESSION['user_id'] ?? null;
</div>
<div class="right-col d-none d-lg-flex">
<div class="order-panel">
<div class="panel-label"><?php echo __('settlement_time'); ?></div>
<div class="duration-grid">
<div class="time-btn active" data-duration="60" data-rate="8" data-min="100">60S <span class="rate">8%</span></div>
<div class="time-btn" data-duration="90" data-rate="12" data-min="5000">90S <span class="rate">12%</span></div>
<div class="time-btn" data-duration="120" data-rate="15" data-min="30000">120S <span class="rate">15%</span></div>
<div class="time-btn" data-duration="180" data-rate="20" data-min="100000">180S <span class="rate">20%</span></div>
<div class="time-btn" data-duration="300" data-rate="32" data-min="300000">300S <span class="rate">32%</span></div>
</div>
<div class="panel-label"><?php echo __('buy_amount'); ?></div>
<div class="input-group">
<input type="number" id="option-amount" placeholder="60S 最小 100 USDT">
<span class="unit">USDT</span>
</div>
<div class="balance-info">
<span><?php echo __('profit'); ?></span>
<span style="color: #0ecb81; font-weight: 800;" id="potential-profit">+0.00 USDT</span>
</div>
<button class="trade-btn btn-up" onclick="placeOptionOrder('up')"><?php echo __('buy_up'); ?></button>
<button class="trade-btn btn-down" onclick="placeOptionOrder('down')"><?php echo __('buy_down'); ?></button>
<div style="margin-top: 30px;">
<div class="balance-info">
<span><?php echo __('available'); ?></span>
<span id="usdt-balance" style="color: white; font-weight: 600;">0.00 USDT</span>
</div>
<div class="order-book-header"><?php echo __('order_book'); ?></div>
<div style="padding: 10px 0; display: flex; flex-direction: column; flex: 1;">
<div id="ob-asks" style="display: flex; flex-direction: column; justify-content: flex-start; flex: 1;"></div>
<div style="padding: 10px; border-top: 1px solid #2b3139; border-bottom: 1px solid #2b3139; margin: 5px 0; text-align: center; background: #161a1e;">
<span id="ob-mid-price" style="font-size: 16px; font-weight: 800; color: #0ecb81;">--</span>
</div>
<div id="ob-bids" style="display: flex; flex-direction: column; justify-content: flex-start; flex: 1;"></div>
</div>
</div>
</div>
<div class="mobile-footer-actions">
<button class="trade-btn btn-up" style="margin:0; flex:1" onclick="openOrderSheet('up')"><?php echo __('buy_up'); ?></button>
<button class="trade-btn btn-down" style="margin:0; flex:1" onclick="openOrderSheet('down')"><?php echo __('buy_down'); ?></button>
</div>
<div class="option-modal" id="order-modal">
<div class="option-modal-content">
<div class="modal-symbol" id="modal-symbol">BTC/USDT</div>
<div class="modal-dir" id="modal-dir">BUY UP</div>
<div class="circular-timer-box">
<svg class="circular-timer-svg">
<circle class="circular-timer-bg" cx="60" cy="60" r="56"></circle>
<circle class="circular-timer-progress" id="circular-progress" cx="60" cy="60" r="56"></circle>
</svg>
<div class="timer-text" id="modal-timer">00</div>
</div>
<div class="m-overlay" id="sheet-overlay" onclick="closeOrderSheet()"></div>
<div class="m-order-sheet" id="m-order-sheet">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px;">
<span style="font-weight: 800; font-size: 22px;" id="m-sheet-title"><?php echo __('buy_up'); ?></span>
<i class="fas fa-times" onclick="closeOrderSheet()" style="font-size: 20px; color: #848e9c"></i>
<div class="modal-live-box">
<div class="live-label"><?php echo __('current_price'); ?></div>
<div class="live-price" id="modal-price-live">--</div>
<div class="profit-estimate" id="modal-profit-estimate">--</div>
</div>
<div class="modal-info-grid">
<div class="info-item">
<div class="info-label"><?php echo __('opening_price'); ?></div>
<div class="info-value" id="modal-open-price">--</div>
</div>
<div class="info-item" style="text-align: right;">
<div class="info-label"><?php echo __('buy_amount'); ?></div>
<div class="info-value" id="modal-amount">--</div>
</div>
</div>
<div class="modal-footer-note">
<?php echo __('options_instruction'); ?>: <?php echo __('options_wait_settle'); ?>
</div>
</div>
<div class="panel-label"><?php echo __('settlement_time'); ?></div>
<div class="duration-grid">
<div class="time-btn active" data-duration="60" data-rate="8" data-min="100">60S <span class="rate">8%</span></div>
<div class="time-btn" data-duration="90" data-rate="12" data-min="5000">90S <span class="rate">12%</span></div>
<div class="time-btn" data-duration="120" data-rate="15" data-min="30000">120S <span class="rate">15%</span></div>
<div class="time-btn" data-duration="180" data-rate="20" data-min="100000">180S <span class="rate">20%</span></div>
<div class="time-btn" data-duration="300" data-rate="32" data-min="300000">300S <span class="rate">32%</span></div>
</div>
<div class="panel-label"><?php echo __('buy_amount'); ?></div>
<div class="input-group">
<input type="number" id="m-option-amount" placeholder="60S 最小 100 USDT">
<span class="unit">USDT</span>
</div>
<div class="balance-info" style="margin-bottom: 25px;">
<span><?php echo __('available'); ?>: <span id="m-usdt-balance" style="color:white; font-weight:bold">0.00</span> USDT</span>
<span style="color: #0ecb81; font-weight:800" id="m-potential-profit">+0 USDT</span>
</div>
<button class="trade-btn" id="m-confirm-btn" style="background: #0ecb81; color: white;" onclick="confirmMobileOrder()"><?php echo __('confirm'); ?></button>
</div>
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script>
let currentPair = 'BTCUSDT';
let currentPrice = 0;
let currentDuration = 60;
let currentRate = 0.08;
let currentMin = 100;
let currentStatus = 'pending';
let mobileDirection = 'up';
let currentPair = 'BTCUSDT'; let currentPrice = 0; let currentDuration = 60; let currentRate = 0.08; let currentMin = 100; let currentStatus = 'pending'; let searchQuery = '';
const pairs = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'MATICUSDT', 'LTCUSDT', 'SHIBUSDT', 'TRXUSDT', 'AVAXUSDT', 'LINKUSDT', 'BCHUSDT', 'UNIUSDT', 'ETCUSDT', 'NEARUSDT', 'FILUSDT', 'ALGOUSDT', 'FTMUSDT', 'SANDUSDT', 'MANAUSDT', 'AXSUSDT', 'ATOMUSDT', 'HBARUSDT', 'ICPUSDT', 'VETUSDT'];
const marketData = {};
function getIcon(s) {
let sym = s.replace('USDT', '').toLowerCase();
return `https://cdn.jsdelivr.net/gh/atomiclabs/cryptocurrency-icons@1a72df150d6d8481e2345e691456c6c7d1e84a22/32/color/${sym}.png`;
}
function initChart(symbol) {
new TradingView.widget({
"width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol,
"interval": "1", "theme": "dark", "style": "1", "locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>",
"container_id": "tv_chart_container", "backgroundColor": "#0b0e11", "hide_side_toolbar": true
});
function getIcon(s) {
const symbol = s.replace('USDT', '').toLowerCase();
return `https://assets.coincap.io/assets/icons/${symbol}@2x.png`;
}
function initChart(symbol) { new TradingView.widget({ "width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "1", "theme": "dark", "style": "1", "locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>", "container_id": "tv_chart_container", "backgroundColor": "#0b0e11", "hide_side_toolbar": true }); }
initChart(currentPair);
const ws = new WebSocket('wss://stream.binance.com:9443/ws/' + pairs.map(p => p.toLowerCase() + '@ticker').join('/'));
ws.onmessage = (e) => {
const d = JSON.parse(e.data);
if (d.s === currentPair) {
currentPrice = parseFloat(d.c);
updatePriceUI(d);
}
marketData[d.s] = d;
renderPairs();
if (d.s === currentPair) { currentPrice = parseFloat(d.c); updatePriceUI(d); updateOrderBook(); updateModalLive(); }
marketData[d.s] = d; renderPairs();
};
function updatePriceUI(d) {
const pStr = currentPrice.toLocaleString(undefined, {minimumFractionDigits: 2});
document.getElementById('curr-price').innerText = pStr;
document.getElementById('m-curr-price').innerText = pStr;
document.getElementById('ob-mid-price').innerText = pStr;
const color = d.P >= 0 ? '#0ecb81' : '#f6465d';
document.getElementById('curr-price').style.color = color;
document.getElementById('m-curr-price').style.color = color;
document.getElementById('ob-mid-price').style.color = color;
document.getElementById('curr-change').innerText = (d.P >= 0 ? '+' : '') + d.P + '%';
document.getElementById('m-curr-change').innerText = (d.P >= 0 ? '+' : '') + d.P + '%';
document.getElementById('curr-change').style.color = color;
document.getElementById('m-curr-change').style.color = color;
document.getElementById('m-24h-high').innerText = 'H: ' + parseFloat(d.h).toLocaleString();
document.getElementById('m-24h-low').innerText = 'L: ' + parseFloat(d.l).toLocaleString();
document.getElementById('m-24h-vol').innerText = 'V: ' + (parseFloat(d.v)/1000).toFixed(1) + 'K';
const hHigh = document.getElementById('h-high'); if (hHigh) hHigh.innerText = parseFloat(d.h).toLocaleString();
const hLow = document.getElementById('h-low'); if (hLow) hLow.innerText = parseFloat(d.l).toLocaleString();
const hVol = document.getElementById('h-vol'); if (hVol) hVol.innerText = (parseFloat(d.v)/1000).toFixed(1) + 'K';
}
function updateOrderBook() {
const asks = document.getElementById('ob-asks'); const bids = document.getElementById('ob-bids');
let aHtml = ''; let bHtml = ''; const rowCount = 20;
for (let i = 0; i < rowCount; i++) {
const aPrice = currentPrice * (1 + (rowCount - i) * 0.0001);
const aAmt = (Math.random() * 2).toFixed(4);
aHtml += `<div class="ob-row"><div class="ob-bg-sell" style="width:${Math.random()*80}%"></div><span class="ob-price" style="color:#f6465d">${aPrice.toFixed(2)}</span><span class="ob-amount">${aAmt}</span><span class="ob-total">${(aPrice*aAmt).toFixed(2)}</span></div>`;
const bPrice = currentPrice * (1 - (i + 1) * 0.0001);
const bAmt = (Math.random() * 2).toFixed(4);
bHtml += `<div class="ob-row"><div class="ob-bg-buy" style="width:${Math.random()*80}%"></div><span class="ob-price" style="color:#0ecb81">${bPrice.toFixed(2)}</span><span class="ob-amount">${bAmt}</span><span class="ob-total">${(bPrice*bAmt).toFixed(2)}</span></div>`;
}
asks.innerHTML = aHtml; bids.innerHTML = bHtml;
}
function renderPairs() {
const list = document.getElementById('pairs-list');
const mBar = document.getElementById('m-coin-list');
const list = document.getElementById('pairs-list'); const mBar = document.getElementById('m-coin-list');
let lHtml = ''; let mHtml = '';
pairs.forEach(p => {
const d = marketData[p] || {c: 0, P: 0}; const icon = getIcon(p); const active = p === currentPair; const color = d.P >= 0 ? '#0ecb81' : '#f6465d';
lHtml += `<div class="pair-item ${active ? 'active' : ''}" onclick="switchPair('${p}')"><img src="${icon}" class="coin-icon"> <div style="flex:1"><div style="font-weight:700; font-size:13px">${p.replace('USDT', '')}/USDT</div></div> <div style="text-align:right"><div style="font-size:13px; font-weight:bold">${parseFloat(d.c).toLocaleString()}</div><div style="font-size:11px; color:${color}">${(d.P >= 0 ? '+' : '') + d.P}%</div></div></div>`;
mHtml += `<div class="m-coin-item ${active ? 'active' : ''}" onclick="switchPair('${p}')"><img src="${icon}"><span>${p.replace('USDT', '')}</span></div>`;
const disp = p.replace('USDT', '') + '/USDT';
if (searchQuery === '' || disp.includes(searchQuery)) {
lHtml += `<div class="pair-item ${active ? 'active' : ''}" onclick="switchPair('${p}')"><img src="${icon}" class="coin-icon" onerror="this.src='https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff'"> <div style="flex:1"><div style="font-weight:700; font-size:13px">${disp}</div></div> <div style="text-align:right"><div style="font-size:13px; font-weight:bold">${parseFloat(d.c).toLocaleString()}</div><div style="font-size:11px; color:${color}">${(d.P >= 0 ? '+' : '') + d.P}%</div></div></div>`;
}
mHtml += `<div class="m-coin-item ${active ? 'active' : ''}" onclick="switchPair('${p}')"><img src="${icon}" onerror="this.src='https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff'"><span>${p.replace('USDT', '')}</span></div>`;
});
if(list) list.innerHTML = lHtml;
if(mBar) mBar.innerHTML = mHtml;
if(list) list.innerHTML = lHtml; if(mBar) mBar.innerHTML = mHtml;
}
function switchPair(p) {
currentPair = p; const icon = getIcon(p);
document.getElementById('curr-pair').innerText = p.replace('USDT', '') + '/USDT';
document.getElementById('m-curr-pair').innerText = p.replace('USDT', '') + '/USDT';
document.getElementById('curr-icon').src = icon; document.getElementById('m-curr-icon').src = icon;
initChart(p); renderPairs();
function filterPairs() { searchQuery = document.getElementById('pair-search').value.toUpperCase(); renderPairs(); }
function switchPair(p) {
currentPair = p; const icon = getIcon(p);
document.getElementById('curr-pair').innerText = p.replace('USDT', '') + '/USDT';
const iconEl = document.getElementById('curr-icon');
iconEl.src = icon;
iconEl.onerror = function() { this.src = `https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff`; };
initChart(p); renderPairs();
}
document.querySelectorAll('.time-btn').forEach(btn => {
btn.addEventListener('click', function() {
currentDuration = parseInt(this.dataset.duration);
currentRate = parseInt(this.dataset.rate) / 100;
currentMin = parseInt(this.dataset.min);
currentDuration = parseInt(this.dataset.duration); currentRate = parseInt(this.dataset.rate) / 100; currentMin = parseInt(this.dataset.min);
document.querySelectorAll('.time-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll(`.time-btn[data-duration="${currentDuration}"]`).forEach(b => b.classList.add('active'));
const ph = `${currentDuration}S 最小 ${currentMin} USDT`;
document.getElementById('option-amount').placeholder = ph;
document.getElementById('m-option-amount').placeholder = ph;
this.classList.add('active');
document.getElementById('option-amount').placeholder = `<?php echo __('min_order'); ?> ${currentMin}`;
updatePotentialProfit();
});
});
function updatePotentialProfit() {
const amt = parseFloat(document.getElementById('option-amount').value) || parseFloat(document.getElementById('m-option-amount').value) || 0;
const amt = parseFloat(document.getElementById('option-amount').value) || 0;
const profit = (amt * currentRate).toFixed(2);
document.getElementById('potential-profit').innerText = '+' + profit + ' USDT';
document.getElementById('m-potential-profit').innerText = '+' + profit + ' USDT (+' + (currentRate * 100) + '%)';
document.getElementById('potential-profit').innerText = '+' + profit;
}
document.getElementById('option-amount').addEventListener('input', updatePotentialProfit);
document.getElementById('m-option-amount').addEventListener('input', updatePotentialProfit);
async function placeOptionOrder(dir) {
const amt = parseFloat(document.getElementById('option-amount').value);
if (!amt || amt < currentMin) return alert('<?php echo __('min_amount'); ?>: ' + currentMin + ' USDT');
const resp = await fetch('api/place_option_order.php', { method: 'POST', body: JSON.stringify({ symbol: currentPair, amount: amt, direction: dir, duration: currentDuration, opening_price: currentPrice }) });
const res = await resp.json();
if (res.success) { alert('<?php echo __('order_placed'); ?>'); document.getElementById('option-amount').value = ''; updateBalance(); fetchOrders(); } else alert(res.error);
if (res.success) {
showCountdownModal(dir, amt, currentPrice, currentDuration, currentRate);
document.getElementById('option-amount').value = ''; updateBalance(); fetchOrders();
} else alert(res.error);
}
function openOrderSheet(dir) {
mobileDirection = dir;
document.getElementById('m-sheet-title').innerText = dir === 'up' ? '<?php echo __('buy_up'); ?>' : '<?php echo __('buy_down'); ?>';
document.getElementById('m-confirm-btn').style.background = dir === 'up' ? '#0ecb81' : '#f6465d';
document.getElementById('sheet-overlay').classList.add('show');
document.getElementById('m-order-sheet').classList.add('show');
let modalInterval = null;
let modalActiveRate = 0;
function showCountdownModal(dir, amount, openPrice, duration, rate) {
const modal = document.getElementById('order-modal');
const timer = document.getElementById('modal-timer');
const dirEl = document.getElementById('modal-dir');
const progress = document.getElementById('circular-progress');
modalActiveRate = rate;
document.getElementById('modal-symbol').innerText = currentPair.replace('USDT','') + '/USDT';
document.getElementById('modal-open-price').innerText = openPrice.toLocaleString();
document.getElementById('modal-amount').innerText = amount + ' USDT';
dirEl.innerText = dir === 'up' ? '<?php echo __('buy_up'); ?>' : '<?php echo __('buy_down'); ?>';
dirEl.style.background = dir === 'up' ? 'rgba(14, 203, 129, 0.2)' : 'rgba(246, 70, 93, 0.2)';
dirEl.style.color = dir === 'up' ? '#0ecb81' : '#f6465d';
let remaining = duration;
const total = duration;
timer.innerText = remaining;
modal.style.display = 'flex';
const circumference = 2 * Math.PI * 56;
progress.style.strokeDasharray = circumference;
if(modalInterval) clearInterval(modalInterval);
modalInterval = setInterval(() => {
remaining--;
timer.innerText = remaining < 10 ? '0' + remaining : remaining;
const offset = circumference - (remaining / total) * circumference;
progress.style.strokeDashoffset = offset;
if(remaining <= 0) {
clearInterval(modalInterval);
setTimeout(() => { modal.style.display = 'none'; fetchOrders(); }, 2000);
}
}, 1000);
}
function closeOrderSheet() { document.getElementById('sheet-overlay').classList.remove('show'); document.getElementById('m-order-sheet').classList.remove('show'); }
async function confirmMobileOrder() {
const amt = parseFloat(document.getElementById('m-option-amount').value);
if (!amt || amt < currentMin) return alert('<?php echo __('min_amount'); ?>: ' + currentMin + ' USDT');
const resp = await fetch('api/place_option_order.php', { method: 'POST', body: JSON.stringify({ symbol: currentPair, amount: amt, direction: mobileDirection, duration: currentDuration, opening_price: currentPrice }) });
const res = await resp.json();
if (res.success) { alert('<?php echo __('order_placed'); ?>'); closeOrderSheet(); updateBalance(); fetchOrders(); } else alert(res.error);
function updateModalLive() {
const modal = document.getElementById('order-modal');
const priceEl = document.getElementById('modal-price-live');
const profitEl = document.getElementById('modal-profit-estimate');
if(modal.style.display === 'flex') {
const openPrice = parseFloat(document.getElementById('modal-open-price').innerText.replace(/,/g, ''));
const dir = document.getElementById('modal-dir').innerText.includes('UP') || document.getElementById('modal-dir').innerText.includes('涨') ? 'up' : 'down';
const amount = parseFloat(document.getElementById('modal-amount').innerText);
const isProfit = dir === 'up' ? currentPrice >= openPrice : currentPrice <= openPrice;
const color = isProfit ? '#0ecb81' : '#f6465d';
priceEl.innerText = currentPrice.toLocaleString(undefined, {minimumFractionDigits: 2});
priceEl.style.color = color;
const profitVal = isProfit ? (amount * modalActiveRate).toFixed(2) : '-' + amount.toFixed(2);
profitEl.innerText = '<?php echo __('estimated_profit'); ?>: ' + (isProfit ? '+' : '') + profitVal + ' USDT';
profitEl.style.color = color;
}
}
function switchRecords(s) { currentStatus = s; document.querySelectorAll('.record-tab').forEach(t => t.classList.remove('active')); event.target.classList.add('active'); fetchOrders(); }
async function fetchOrders() {
const resp = await fetch('api/get_option_orders.php?status=' + currentStatus);
const res = await resp.json();
const resp = await fetch('api/get_option_orders.php?status=' + currentStatus); const res = await resp.json();
const list = document.getElementById('records-list');
if (res.success && res.data.length > 0) {
list.innerHTML = res.data.map(o => `
@ -363,9 +475,9 @@ $user_id = $_SESSION['user_id'] ?? null;
<div style="font-weight:800; color:${parseFloat(o.profit)>=0?'#0ecb81':'#f6465d'}; font-size:15px">${currentStatus==='pending'?'--':(parseFloat(o.profit)>=0?'+':'')+parseFloat(o.profit).toFixed(2)}</div>
</div>
<div style="display:grid; grid-template-columns:repeat(3, 1fr); gap:10px; color:#848e9c; font-size:11px">
<div>Amount<br><span style="color:white; font-weight:bold">${parseFloat(o.amount).toFixed(2)}</span></div>
<div>Open Price<br><span style="color:white; font-weight:bold">${parseFloat(o.opening_price).toLocaleString()}</span></div>
<div>${currentStatus==='pending'?'Time':'Close Price'}<br><span style="color:white; font-weight:bold">${currentStatus==='pending'?o.duration+'s':parseFloat(o.closing_price).toLocaleString()}</span></div>
<div><?php echo __('amount'); ?><br><span style="color:white; font-weight:bold">${parseFloat(o.amount).toFixed(2)}</span></div>
<div><?php echo __('opening_price'); ?><br><span style="color:white; font-weight:bold">${parseFloat(o.opening_price).toLocaleString()}</span></div>
<div>${currentStatus==='pending'?'<?php echo __('time'); ?>':'<?php echo __('closing_price'); ?>'}<br><span style="color:white; font-weight:bold">${currentStatus==='pending'?o.duration+'s':parseFloat(o.closing_price).toLocaleString()}</span></div>
</div>
${currentStatus==='pending'?`<div class="progress-bar-container"><div class="progress-bar-fill" id="pb-${o.id}" data-start="${new Date(o.created_at).getTime()}" data-duration="${o.duration}"></div></div>`:''}
</div>
@ -375,34 +487,18 @@ $user_id = $_SESSION['user_id'] ?? null;
}
function updateProgressBars() {
const bars = document.querySelectorAll('.progress-bar-fill');
const now = Date.now();
bars.forEach(bar => {
const start = parseInt(bar.dataset.start); const dur = parseInt(bar.dataset.duration) * 1000; const elapsed = now - start;
bar.style.width = Math.min(100, (elapsed / dur) * 100) + '%';
});
const bars = document.querySelectorAll('.progress-bar-fill'); const now = Date.now();
bars.forEach(bar => { const start = parseInt(bar.dataset.start); const dur = parseInt(bar.dataset.duration) * 1000; const elapsed = now - start; bar.style.width = Math.min(100, (elapsed / dur) * 100) + '%'; });
if (currentStatus === 'pending' && bars.length > 0) setTimeout(updateProgressBars, 1000);
}
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');
const bal = usdt ? parseFloat(usdt.amount).toFixed(2) : '0.00';
document.getElementById('usdt-balance').innerText = bal + ' USDT';
document.getElementById('m-usdt-balance').innerText = bal;
const usdt = res.data.find(a => a.symbol === 'USDT'); const bal = usdt ? parseFloat(usdt.amount).toFixed(2) : '0.00';
document.getElementById('usdt-balance').innerText = bal;
}
}
function switchMobileView(view) {
document.querySelectorAll('.m-nav-tab').forEach(t => t.classList.remove('active'));
document.querySelector(`.m-nav-tab[data-view="${view}"]`).classList.add('active');
document.getElementById('chart-section').style.display = view === 'chart' ? 'block' : 'none';
document.getElementById('records-section').style.display = view === 'orders' ? 'block' : 'none';
if (view === 'orders') fetchOrders();
}
if (window.innerWidth < 992) switchMobileView('chart');
setInterval(fetchOrders, 3000); updateBalance(); switchPair(currentPair);
</script>
<?php include 'footer.php'; ?>

View File

@ -193,19 +193,35 @@ $kyc_colors = [0 => '#888', 1 => '#f0b90b', 2 => 'var(--success-color)', 3 => 'v
async function loadTransactionRecords() {
const container = document.getElementById('records-list');
try {
const [spotResp, futuresResp] = await Promise.all([
const [spotResp, futuresResp, transResp] = await Promise.all([
fetch('api/get_orders.php?type=spot&status=history'),
fetch('api/get_orders.php?type=futures&status=history')
fetch('api/get_orders.php?type=futures&status=history'),
fetch('api/get_transactions.php')
]);
const spotRes = await spotResp.json();
const futuresRes = await futuresResp.json();
const transRes = await transResp.json();
let allRecords = [];
if (spotRes.success) {
spotRes.data.forEach(r => { r.trade_type = '现货'; allRecords.push(r); });
spotRes.data.forEach(r => {
r.display_type = 'trade';
r.trade_type = '现货';
allRecords.push(r);
});
}
if (futuresRes.success) {
futuresRes.data.forEach(r => { r.trade_type = '合约'; allRecords.push(r); });
futuresRes.data.forEach(r => {
r.display_type = 'trade';
r.trade_type = '合约';
allRecords.push(r);
});
}
if (transRes.success) {
transRes.data.forEach(t => {
t.display_type = 'transaction';
allRecords.push(t);
});
}
allRecords.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
@ -217,29 +233,56 @@ $kyc_colors = [0 => '#888', 1 => '#f0b90b', 2 => 'var(--success-color)', 3 => 'v
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: 10px; background: rgba(255,255,255,0.1); padding: 1px 4px; border-radius: 4px; margin-left: 5px;">${r.trade_type}</span></span>
<span style="color: var(--text-muted); font-size: 11px;">${r.created_at}</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="font-size: 12px;">
<span style="color: ${r.side === 'buy' ? 'var(--success-color)' : 'var(--danger-color)'}">${r.side === 'buy' ? '买入' : '卖出'}</span>
<span style="color: var(--text-muted); margin-left: 8px;">价格: ${parseFloat(r.price).toLocaleString()}</span>
<span style="color: var(--text-muted); margin-left: 8px;">数量: ${parseFloat(r.amount).toFixed(4)}</span>
if (r.display_type === 'trade') {
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: 10px; background: rgba(255,255,255,0.1); padding: 1px 4px; border-radius: 4px; margin-left: 5px;">${r.trade_type}</span></span>
<span style="color: var(--text-muted); font-size: 11px;">${r.created_at}</span>
</div>
<div style="text-align: right;">
<div style="font-size: 10px; color: var(--text-muted);">盈亏</div>
<div style="font-weight: bold; color: ${profitColor}; font-size: 12px;">${profitText} USDT</div>
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="font-size: 12px;">
<span style="color: ${r.side === 'buy' ? 'var(--success-color)' : 'var(--danger-color)'}">${r.side === 'buy' ? '买入' : '卖出'}</span>
<span style="color: var(--text-muted); margin-left: 8px;">价格: ${parseFloat(r.price).toLocaleString()}</span>
<span style="color: var(--text-muted); margin-left: 8px;">数量: ${parseFloat(r.amount).toFixed(4)}</span>
</div>
<div style="text-align: right;">
<div style="font-size: 10px; color: var(--text-muted);">盈亏</div>
<div style="font-weight: bold; color: ${profitColor}; font-size: 12px;">${profitText} USDT</div>
</div>
</div>
</div>
</div>
`;
`;
} else {
// Transaction (Deposit/Withdraw)
const isPositive = parseFloat(r.amount) > 0;
const amountText = (isPositive ? '+' : '') + parseFloat(r.amount).toFixed(2);
const amountColor = isPositive ? 'var(--success-color)' : 'var(--danger-color)';
let typeLabel = r.type === 'deposit' ? '充值' : (r.type === 'withdraw' ? '提现' : (r.type === 'withdraw_return' ? '提现驳回' : r.type));
let statusLabel = r.status === 'completed' ? '已完成' : (r.status === 'pending' ? '处理中' : (r.status === 'rejected' ? '已拒绝' : r.status));
let statusColor = r.status === 'completed' ? 'var(--success-color)' : (r.status === 'pending' ? '#f0b90b' : 'var(--danger-color)');
html += `
<div class="record-item">
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
<span style="font-weight: bold; color: white;">${typeLabel} <span style="font-size: 10px; background: rgba(255,255,255,0.1); padding: 1px 4px; border-radius: 4px; margin-left: 5px; color: ${statusColor}">${statusLabel}</span></span>
<span style="color: var(--text-muted); font-size: 11px;">${r.created_at}</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="font-size: 12px; color: var(--text-muted);">
${r.description || ''}
</div>
<div style="text-align: right;">
<div style="font-weight: bold; color: ${amountColor}; font-size: 14px;">${amountText} USDT</div>
</div>
</div>
</div>
`;
}
});
container.innerHTML = html;
} catch (e) {

370
spot.php
View File

@ -6,185 +6,221 @@ $user_id = $_SESSION['user_id'] ?? null;
?>
<style>
/* Layout Fixes */
/* Global layout enforcement */
html, body {
background: #0b0e11;
min-width: 1280px;
max-width: 1920px;
margin: 0 auto;
overflow-x: auto;
}
@media (max-width: 991px) {
html, body {
min-width: 100%;
max-width: 100%;
overflow-x: hidden;
}
.navbar, footer { display: none !important; }
body { padding-bottom: 65px !important; margin: 0 !important; max-width: 100% !important; }
body { padding-bottom: 0 !important; }
}
.trading-container {
display: flex;
background: #0b0e11;
min-height: calc(100vh - 64px);
max-width: 100%;
margin: 0;
overflow: hidden;
width: 100%;
}
@media (max-width: 991px) {
.trading-container { min-height: 100vh; flex-direction: column; }
.trading-container { min-height: calc(100vh - 50px); flex-direction: column; }
}
.left-col { width: 280px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.center-col { flex: 1; min-width: 0; background: #0b0e11; display: flex; flex-direction: column; overflow: hidden; }
.right-col { width: 320px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-left: 1px solid #2b3139; }
.left-col { width: 260px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.center-col { flex: 1; min-width: 600px; background: #0b0e11; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
.right-col { width: 320px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; }
@media (max-width: 991px) {
.left-col, .right-col { display: none !important; }
.center-col { min-width: 100%; }
}
/* Category Tabs above Search */
.category-tabs { display: flex; padding: 15px 15px 5px; gap: 8px; }
.category-tab { flex: 1; text-align: center; padding: 6px 0; background: #2b3139; border-radius: 4px; font-size: 11px; color: #848e9c; cursor: pointer; transition: all 0.2s; white-space: nowrap; border: 1px solid transparent; }
.category-tab.active { background: rgba(0, 82, 255, 0.1); border-color: var(--primary-color); color: var(--primary-color); font-weight: bold; }
/* Search Box */
.search-box { padding: 5px 15px 10px; position: relative; }
.search-box i { position: absolute; left: 25px; top: 50%; transform: translateY(-50%); color: #848e9c; font-size: 12px; }
.search-box input { width: 100%; background: #2b3139; border: 1px solid transparent; border-radius: 4px; padding: 8px 10px 8px 30px; color: white; font-size: 13px; outline: none; }
.search-box input:focus { border-color: var(--primary-color); }
/* Pairs List */
#pairs-list { flex: 1; overflow-y: auto; }
.pair-item { display: flex; align-items: center; padding: 12px 15px; cursor: pointer; transition: all 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
.pair-item { display: flex; align-items: center; padding: 10px 15px; cursor: pointer; transition: all 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
.pair-item:hover { background: #1e2329; }
.pair-item.active { background: #1e2329; border-left: 3px solid var(--primary-color); }
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; }
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; flex-shrink: 0; background: #2b3139; }
/* Chart Area */
.chart-header { padding: 12px 20px; display: flex; align-items: center; gap: 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
.chart-box { height: 400px; background: #0b0e11; position: relative; }
@media (max-width: 991px) { .chart-box { height: 350px; } }
.chart-header { padding: 8px 20px; display: flex; align-items: center; background: #161a1e; border-bottom: 1px solid #2b3139; flex-wrap: nowrap; gap: 20px; height: 50px; }
.chart-box { flex: 1; min-height: 400px; height: 400px; background: #0b0e11; border-bottom: 1px solid #2b3139; }
@media (max-width: 991px) { .chart-box { min-height: 320px; height: 320px; } }
/* Order Placement */
.order-box { padding: 20px; display: grid; grid-template-columns: 1fr 1fr; gap: 30px; background: #161a1e; border-bottom: 1px solid #2b3139; }
@media (max-width: 991px) { .order-box { grid-template-columns: 1fr; gap: 20px; padding: 15px; } }
.order-type-tabs { display: flex; gap: 20px; margin-bottom: 15px; }
.order-type-tab { font-size: 13px; color: #848e9c; cursor: pointer; padding-bottom: 5px; border-bottom: 2px solid transparent; }
.order-box { padding: 12px 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
.order-type-tabs { display: flex; gap: 20px; margin-bottom: 10px; }
.order-type-tab { font-size: 13px; color: #848e9c; cursor: pointer; padding-bottom: 4px; border-bottom: 2px solid transparent; }
.order-type-tab.active { color: white; border-bottom-color: var(--primary-color); font-weight: bold; }
.input-group { background: #2b3139; border-radius: 4px; padding: 10px 12px; display: flex; align-items: center; margin-bottom: 10px; border: 1px solid transparent; }
.input-group { background: #2b3139; border-radius: 4px; padding: 6px 12px; display: flex; align-items: center; margin-bottom: 6px; border: 1px solid transparent; }
.input-group:focus-within { border-color: var(--primary-color); }
.input-group input { background: transparent; border: none; color: white; flex: 1; text-align: right; outline: none; font-size: 14px; width: 100%; }
.input-group .label { color: #848e9c; font-size: 12px; }
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 12px; }
.input-group input { background: transparent; border: none; color: white; flex: 1; text-align: left; outline: none; font-size: 13px; width: 100%; }
.input-group .label { color: #848e9c; font-size: 11px; margin-right: 10px; }
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 11px; }
/* Slider Style */
.slider-container { margin: 15px 0 25px; padding: 0 5px; }
.slider-labels { display: flex; justify-content: space-between; margin-top: 8px; font-size: 10px; color: #848e9c; }
input[type=range] { -webkit-appearance: none; width: 100%; height: 4px; background: #2b3139; border-radius: 2px; outline: none; }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; background: var(--primary-color); border-radius: 50%; cursor: pointer; border: 3px solid #161a1e; }
.slider-container { margin: 8px 0 15px; padding: 0 5px; }
.slider-labels { display: flex; justify-content: space-between; margin-top: 4px; font-size: 10px; color: #848e9c; }
input[type=range] { -webkit-appearance: none; width: 100%; height: 3px; background: #2b3139; border-radius: 2px; outline: none; }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; background: var(--primary-color); border-radius: 50%; cursor: pointer; border: 2px solid #161a1e; }
.trade-btn { width: 100%; padding: 14px; border-radius: 4px; font-weight: bold; font-size: 15px; border: none; cursor: pointer; margin-top: 10px; }
.trade-btn { width: 100%; padding: 10px; border-radius: 4px; font-weight: bold; font-size: 14px; border: none; cursor: pointer; margin-top: 5px; }
.btn-buy { background: #0ecb81; color: white; }
.btn-sell { background: #f6465d; color: white; }
/* Records */
.record-tabs { display: flex; background: #161a1e; border-bottom: 1px solid #2b3139; padding: 0 20px; }
.record-tab { padding: 15px 0; margin-right: 30px; font-size: 13px; color: #848e9c; cursor: pointer; position: relative; }
.record-tab { padding: 10px 0; margin-right: 25px; font-size: 13px; color: #848e9c; cursor: pointer; position: relative; }
.record-tab.active { color: white; border-bottom: 2px solid var(--primary-color); font-weight: bold; }
.records-content { min-height: 300px; background: #161a1e; }
@media (max-width: 991px) { .records-content { padding-bottom: 80px; } }
.records-content { min-height: 200px; background: #161a1e; overflow-y: auto; }
/* Order Book Styles */
.ob-header { padding: 10px 15px; font-size: 11px; color: #848e9c; display: flex; justify-content: space-between; border-bottom: 1px solid #2b3139; background: #161a1e; }
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; cursor: pointer; height: 20px; align-items: center; }
.ob-bar { position: absolute; right: 0; top: 0; bottom: 0; opacity: 0.1; z-index: 0; }
#mid-price { padding: 8px 15px; font-size: 16px; font-weight: 800; text-align: center; border-top: 1px solid #2b3139; border-bottom: 1px solid #2b3139; background: #161a1e; }
/* Stats Item */
.stats-item { display: flex; flex-direction: column; justify-content: center; }
.stats-label { font-size: 10px; color: #848e9c; margin-bottom: 1px; white-space: nowrap; }
.stats-value { font-size: 12px; font-weight: 600; color: white; white-space: nowrap; }
/* Mobile Nav */
.m-trade-nav { display: none; background: #161a1e; border-bottom: 1px solid #2b3139; position: sticky; top: 0; z-index: 100; }
.m-trade-nav a { flex: 1; text-align: center; padding: 14px; font-size: 14px; color: #848e9c; text-decoration: none; border-bottom: 2px solid transparent; }
.m-trade-nav a.active { color: var(--primary-color); border-bottom-color: var(--primary-color); font-weight: bold; }
/* Mobile Headers */
.m-trading-header { display: none; background: #161a1e; padding: 12px 15px; border-bottom: 1px solid #2b3139; }
.m-currency-bar { display: none; overflow-x: auto; background: #161a1e; padding: 10px; gap: 10px; border-bottom: 1px solid #2b3139; scrollbar-width: none; }
.m-nav-tabs { display: none; background: #161a1e; border-bottom: 1px solid #2b3139; }
@media (max-width: 991px) { .m-trading-header, .m-currency-bar, .m-nav-tabs { display: flex; } .m-trading-header { flex-direction: column; } }
.m-currency-bar::-webkit-scrollbar { display: none; }
.m-coin-item { flex-shrink: 0; background: #2b3139; padding: 6px 12px; border-radius: 4px; display: flex; align-items: center; gap: 6px; border: 1px solid transparent; }
.m-coin-item.active { border-color: var(--primary-color); background: rgba(0, 82, 255, 0.1); }
.m-coin-item img { width: 16px; height: 16px; border-radius: 50%; }
.m-nav-tab { flex:1; text-align:center; padding:12px; font-size:14px; color:#848e9c; border-bottom:2px solid transparent; }
.m-nav-tab.active { color:white; border-bottom-color:var(--primary-color); font-weight:bold; }
@media (max-width: 991px) {
.m-trade-nav { display: flex; }
.m-currency-bar { display: flex; }
.chart-header { gap: 10px; padding: 10px 15px; overflow-x: auto; scrollbar-width: none; }
.chart-header::-webkit-scrollbar { display: none; }
}
</style>
<!-- Mobile Trading Header -->
<div class="m-trading-header">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="display: flex; align-items: center; gap: 10px;" onclick="toggleSidebar()">
<i class="fas fa-bars" style="font-size: 18px;"></i>
<div style="font-size: 18px; font-weight: 800; display: flex; align-items: center; gap: 6px;">
<img id="m-curr-icon" src="" style="width:24px; height:24px; border-radius:50%">
<span id="m-curr-pair">BTC/USDT</span>
<i class="fas fa-chevron-down" style="font-size: 10px; opacity: 0.5;"></i>
</div>
</div>
<div style="text-align: right">
<div id="m-curr-price" style="font-size: 22px; font-weight: 800; color: #0ecb81; line-height:1">--</div>
<div id="m-curr-change" style="font-size: 12px; font-weight: 600; margin-top:4px">--</div>
</div>
</div>
<div style="display: flex; gap: 15px; margin-top: 10px; font-size: 11px; color: #848e9c;">
<span id="m-24h-high">H: --</span><span id="m-24h-low">L: --</span><span id="m-24h-vol">V: --</span>
</div>
<div class="m-trade-nav">
<a href="spot.php" class="active"><?php echo __('nav_spot'); ?></a>
<a href="futures.php"><?php echo __('nav_futures'); ?></a>
<a href="options.php"><?php echo __('nav_options'); ?></a>
</div>
<div class="m-currency-bar" id="m-coin-list"></div>
<div class="m-nav-tabs">
<div class="m-nav-tab active" onclick="switchMobileView('trade')"><?php echo __('nav_trade'); ?></div>
<div class="m-nav-tab" onclick="switchMobileView('chart')"><?php echo __('chart'); ?></div>
<div class="m-nav-tab" onclick="switchMobileView('orders')"><?php echo __('orders'); ?></div>
</div>
<div class="trading-container">
<div class="left-col d-none d-lg-flex">
<div class="market-header" style="padding:15px; font-weight:bold; border-bottom:1px solid #2b3139"><?php echo __('nav_market'); ?></div>
<div class="category-tabs">
<div class="category-tab" onclick="location.href='options.php'"><?php echo $lang == 'zh' ? '秒合约' : 'Options'; ?></div>
<div class="category-tab active" onclick="location.href='spot.php'"><?php echo $lang == 'zh' ? '现货交易' : 'Spot'; ?></div>
<div class="category-tab" onclick="location.href='futures.php'"><?php echo $lang == 'zh' ? '合约交易' : 'Futures'; ?></div>
</div>
<div class="search-box">
<i class="fas fa-search"></i>
<input type="text" id="pair-search" placeholder="<?php echo __('search_currency'); ?>" oninput="filterPairs()">
</div>
<div id="pairs-list"></div>
</div>
<div class="center-col m-view active" id="view-trade">
<div class="chart-header d-none d-lg-flex">
<div style="display: flex; align-items: center; gap: 12px;">
<img id="curr-icon" src="" class="coin-icon" style="margin:0; width:32px; height:32px;">
<span id="curr-pair" style="font-weight: 800; font-size: 20px;">BTC/USDT</span>
<div class="center-col">
<div class="chart-header">
<div style="display: flex; align-items: center; gap: 10px; padding-right: 15px; border-right: 1px solid #2b3139;">
<img id="curr-icon" src="" class="coin-icon" style="margin:0; width:28px; height:28px;">
<span id="curr-pair" style="font-weight: 800; font-size: 16px;">BTC/USDT</span>
</div>
<div style="flex:1"></div>
<div style="text-align: right">
<div id="curr-price" style="font-size: 24px; font-weight: 800; color: #0ecb81;">--</div>
<div id="curr-change" style="font-size: 13px; font-weight: 600;">--</div>
<div class="stats-item">
<div id="curr-price" style="font-size: 18px; font-weight: 800; color: #0ecb81; line-height: 1.2;">--</div>
<div id="curr-change" style="font-size: 11px; font-weight: 600;">--</div>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_high'); ?></span>
<span class="stats-value" id="h-high">--</span>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_low'); ?></span>
<span class="stats-value" id="h-low">--</span>
</div>
<div class="stats-item">
<span class="stats-label"><?php echo __('24h_vol'); ?></span>
<span class="stats-value" id="h-vol">--</span>
</div>
</div>
<div class="chart-box d-none d-lg-block">
<div id="tv_chart_container_desk" style="height: 100%;"></div>
</div>
<div class="chart-box"><div id="tv_chart_container" style="height: 100%;"></div></div>
<div class="order-box">
<!-- Buy -->
<div>
<div class="order-type-tabs">
<div class="order-type-tab active" onclick="switchOrderType('buy', 'limit')"><?php echo __('limit_order'); ?></div>
<div class="order-type-tab" onclick="switchOrderType('buy', 'market')"><?php echo __('market_order'); ?></div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 25px;">
<div>
<div class="order-type-tabs">
<div class="order-type-tab active" onclick="switchOrderType('buy', 'limit')"><?php echo __('limit'); ?></div>
<div class="order-type-tab" onclick="switchOrderType('buy', 'market')"><?php echo __('market'); ?></div>
</div>
<div class="input-group">
<span class="label"><?php echo __('price'); ?></span>
<input type="number" id="buy-price" placeholder="0.00">
<span class="unit">USDT</span>
</div>
<div class="input-group">
<span class="label"><?php echo __('amount'); ?></span>
<input type="number" id="buy-amount" placeholder="0.00">
<span class="unit coin-name">BTC</span>
</div>
<div class="slider-container">
<input type="range" min="0" max="100" value="0" step="1" oninput="setSlider('buy', this.value)">
<div class="slider-labels"><span>0%</span><span>25%</span><span>50%</span><span>75%</span><span>100%</span></div>
</div>
<div style="font-size:11px; color:#848e9c; margin-bottom:8px; display:flex; justify-content:space-between">
<span><?php echo __('available'); ?></span><span id="avail-usdt">0.00 USDT</span>
</div>
<button onclick="placeOrder('buy')" class="trade-btn btn-buy"><?php echo __('buy'); ?> <span class="coin-name">BTC</span></button>
</div>
<div class="input-group">
<span class="label"><?php echo __('price'); ?></span>
<input type="number" id="buy-price" placeholder="0.00">
<span class="unit">USDT</span>
<div>
<div class="order-type-tabs">
<div class="order-type-tab active" onclick="switchOrderType('sell', 'limit')"><?php echo __('limit'); ?></div>
<div class="order-type-tab" onclick="switchOrderType('sell', 'market')"><?php echo __('market'); ?></div>
</div>
<div class="input-group">
<span class="label"><?php echo __('price'); ?></span>
<input type="number" id="sell-price" placeholder="0.00">
<span class="unit">USDT</span>
</div>
<div class="input-group">
<span class="label"><?php echo __('amount'); ?></span>
<input type="number" id="sell-amount" placeholder="0.00">
<span class="unit coin-name">BTC</span>
</div>
<div class="slider-container">
<input type="range" min="0" max="100" value="0" step="1" oninput="setSlider('sell', this.value)">
<div class="slider-labels"><span>0%</span><span>25%</span><span>50%</span><span>75%</span><span>100%</span></div>
</div>
<div style="font-size:11px; color:#848e9c; margin-bottom:8px; display:flex; justify-content:space-between">
<span><?php echo __('available'); ?></span><span id="avail-coin">0.00 BTC</span>
</div>
<button onclick="placeOrder('sell')" class="trade-btn btn-sell"><?php echo __('sell'); ?> <span class="coin-name">BTC</span></button>
</div>
<div class="input-group">
<span class="label"><?php echo __('amount'); ?></span>
<input type="number" id="buy-amount" placeholder="0.00">
<span class="unit coin-name">BTC</span>
</div>
<div class="slider-container">
<input type="range" min="0" max="100" value="0" step="1" oninput="setSlider('buy', this.value)">
<div class="slider-labels"><span>0%</span><span>25%</span><span>50%</span><span>75%</span><span>100%</span></div>
</div>
<div style="font-size:12px; color:#848e9c; margin-bottom:10px; display:flex; justify-content:space-between">
<span>Available</span><span id="avail-usdt">0.00 USDT</span>
</div>
<button onclick="placeOrder('buy')" class="trade-btn btn-buy"><?php echo __('buy'); ?> <span class="coin-name">BTC</span></button>
</div>
<!-- Sell -->
<div>
<div class="order-type-tabs">
<div class="order-type-tab active" onclick="switchOrderType('sell', 'limit')"><?php echo __('limit_order'); ?></div>
<div class="order-type-tab" onclick="switchOrderType('sell', 'market')"><?php echo __('market_order'); ?></div>
</div>
<div class="input-group">
<span class="label"><?php echo __('price'); ?></span>
<input type="number" id="sell-price" placeholder="0.00">
<span class="unit">USDT</span>
</div>
<div class="input-group">
<span class="label"><?php echo __('amount'); ?></span>
<input type="number" id="sell-amount" placeholder="0.00">
<span class="unit coin-name">BTC</span>
</div>
<div class="slider-container">
<input type="range" min="0" max="100" value="0" step="1" oninput="setSlider('sell', this.value)">
<div class="slider-labels"><span>0%</span><span>25%</span><span>50%</span><span>75%</span><span>100%</span></div>
</div>
<div style="font-size:12px; color:#848e9c; margin-bottom:10px; display:flex; justify-content:space-between">
<span>Available</span><span id="avail-coin">0.00 BTC</span>
</div>
<button onclick="placeOrder('sell')" class="trade-btn btn-sell"><?php echo __('sell'); ?> <span class="coin-name">BTC</span></button>
</div>
</div>
@ -196,34 +232,27 @@ $user_id = $_SESSION['user_id'] ?? null;
<div id="records-list" class="records-content"></div>
</div>
<div class="center-col m-view" id="view-chart" style="display:none">
<div class="chart-box"><div id="tv_chart_container_mob" style="height: 100%;"></div></div>
</div>
<div class="center-col m-view" id="view-orders" style="display:none">
<div class="record-tabs">
<div class="record-tab active" onclick="switchRecords('open')"><?php echo __('current_orders'); ?></div>
<div class="record-tab" onclick="switchRecords('history')"><?php echo __('history_orders'); ?></div>
<div class="record-tab" onclick="switchRecords('trades')"><?php echo __('settled'); ?></div>
</div>
<div id="m-records-list" class="records-content"></div>
</div>
<div class="right-col d-none d-lg-flex">
<div class="ob-header"><span>Price</span><span>Amount</span></div>
<div id="asks-list" style="flex: 1; display: flex; flex-direction: column-reverse; overflow: hidden;"></div>
<div class="ob-header"><span><?php echo __('price'); ?>(USDT)</span><span><?php echo __('amount'); ?>(BTC)</span></div>
<div id="asks-list" style="flex: 1; display: flex; flex-direction: column; overflow: hidden; justify-content: flex-start;"></div>
<div id="mid-price">--</div>
<div id="bids-list" style="flex: 1; overflow: hidden;"></div>
<div id="bids-list" style="flex: 1; display: flex; flex-direction: column; overflow: hidden; justify-content: flex-start;"></div>
</div>
</div>
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script>
let currentPair = 'BTCUSDT'; let currentPrice = 0; let orderTypes = {buy:'limit', sell:'limit'}; let currentStatus = 'open';
let currentPair = 'BTCUSDT'; let currentPrice = 0; let orderTypes = {buy:'limit', sell:'limit'}; let currentStatus = 'open'; let searchQuery = '';
const pairs = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'MATICUSDT', 'LTCUSDT', 'SHIBUSDT', 'TRXUSDT', 'AVAXUSDT', 'LINKUSDT', 'BCHUSDT', 'UNIUSDT', 'ETCUSDT', 'NEARUSDT', 'FILUSDT', 'ALGOUSDT', 'FTMUSDT', 'SANDUSDT', 'MANAUSDT', 'AXSUSDT', 'ATOMUSDT', 'HBARUSDT', 'ICPUSDT', 'VETUSDT'];
const marketData = {}; let balances = {usdt:0, coin:0};
function getIcon(s) { return `https://cdn.jsdelivr.net/gh/atomiclabs/cryptocurrency-icons@1a72df150d6d8481e2345e691456c6c7d1e84a22/32/color/${s.replace('USDT', '').toLowerCase()}.png`; }
function initChart(symbol, container) { new TradingView.widget({ "width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "15", "theme": "dark", "style": "1", "locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>", "container_id": container, "backgroundColor": "#0b0e11", "hide_side_toolbar": true }); }
function getIcon(s) {
const symbol = s.replace('USDT', '').toLowerCase();
return `https://assets.coincap.io/assets/icons/${symbol}@2x.png`;
}
function initChart(symbol) { new TradingView.widget({ "width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "15", "theme": "dark", "style": "1", "locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>", "container_id": "tv_chart_container", "backgroundColor": "#0b0e11", "hide_side_toolbar": true }); }
initChart(currentPair);
const ws = new WebSocket('wss://stream.binance.com:9443/ws/' + pairs.map(p => p.toLowerCase() + '@ticker').join('/'));
ws.onmessage = (e) => {
@ -234,17 +263,14 @@ $user_id = $_SESSION['user_id'] ?? null;
function updatePriceUI(d) {
const color = d.P >= 0 ? '#0ecb81' : '#f6465d';
document.getElementById('curr-price').innerText = currentPrice.toLocaleString();
document.getElementById('m-curr-price').innerText = currentPrice.toLocaleString();
document.getElementById('curr-price').innerText = currentPrice.toLocaleString(undefined, {minimumFractionDigits: 2});
document.getElementById('curr-price').style.color = color;
document.getElementById('m-curr-price').style.color = color;
document.getElementById('curr-change').innerText = (d.P>=0?'+':'')+d.P+'%';
document.getElementById('m-curr-change').innerText = (d.P>=0?'+':'')+d.P+'%';
document.getElementById('m-24h-high').innerText = 'H: ' + parseFloat(d.h).toLocaleString();
document.getElementById('m-24h-low').innerText = 'L: ' + parseFloat(d.l).toLocaleString();
document.getElementById('m-24h-vol').innerText = 'V: ' + (parseFloat(d.v)/1000).toFixed(1) + 'K';
document.getElementById('mid-price').innerText = currentPrice.toLocaleString();
document.getElementById('mid-price').style.color = color;
document.getElementById('curr-change').style.color = color;
const hHigh = document.getElementById('h-high'); if(hHigh) hHigh.innerText = parseFloat(d.h).toLocaleString();
const hLow = document.getElementById('h-low'); if(hLow) hLow.innerText = parseFloat(d.l).toLocaleString();
const hVol = document.getElementById('h-vol'); if(hVol) hVol.innerText = (parseFloat(d.v)/1000).toFixed(1) + 'K';
const mid = document.getElementById('mid-price'); if(mid) { mid.innerText = currentPrice.toLocaleString(undefined, {minimumFractionDigits: 2}); mid.style.color = color; }
}
function renderPairs() {
@ -252,18 +278,25 @@ $user_id = $_SESSION['user_id'] ?? null;
let lH = ''; let mH = '';
pairs.forEach(p => {
const d = marketData[p]||{c:0,P:0}; const icon = getIcon(p); const active = p === currentPair; const color = d.P >= 0 ? '#0ecb81' : '#f6465d';
lH += `<div class="pair-item ${active?'active':''}" onclick="switchPair('${p}')"><img src="${icon}" class="coin-icon"> <div style="flex:1"><div style="font-weight:700; font-size:13px">${p.replace('USDT','')}/USDT</div></div> <div style="text-align:right"><div style="font-size:13px; font-weight:bold">${parseFloat(d.c).toLocaleString()}</div><div style="font-size:11px; color:${color}">${(d.P>=0?'+':'')+d.P}%</div></div></div>`;
mH += `<div class="m-coin-item ${active?'active':''}" onclick="switchPair('${p}')"><img src="${icon}"><span>${p.replace('USDT','')}</span></div>`;
const disp = p.replace('USDT','') + '/USDT';
if (searchQuery === '' || disp.includes(searchQuery)) {
lH += `<div class="pair-item ${active?'active':''}" onclick="switchPair('${p}')"><img src="${icon}" class="coin-icon" onerror="this.src='https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff'"> <div style="flex:1"><div style="font-weight:700; font-size:13px">${disp}</div></div> <div style="text-align:right"><div style="font-size:13px; font-weight:bold">${parseFloat(d.c).toLocaleString()}</div><div style="font-size:11px; color:${color}">${(d.P>=0?'+':'')+d.P}%</div></div></div>`;
}
mH += `<div class="m-coin-item ${active?'active':''}" onclick="switchPair('${p}')"><img src="${icon}" onerror="this.src='https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff'"><span>${p.replace('USDT','')}</span></div>`;
});
if(list) list.innerHTML = lH; if(mBar) mBar.innerHTML = mH;
}
function filterPairs() { searchQuery = document.getElementById('pair-search').value.toUpperCase(); renderPairs(); }
function switchPair(p) {
currentPair = p; const icon = getIcon(p);
document.getElementById('curr-pair').innerText = p.replace('USDT','')+'/USDT'; document.getElementById('m-curr-pair').innerText = p.replace('USDT','')+'/USDT';
document.getElementById('curr-icon').src = icon; document.getElementById('m-curr-icon').src = icon;
currentPair = p; const icon = getIcon(p);
document.getElementById('curr-pair').innerText = p.replace('USDT','')+'/USDT';
const iconEl = document.getElementById('curr-icon');
iconEl.src = icon;
iconEl.onerror = function() { this.src = `https://ui-avatars.com/api/?name=${p.replace('USDT','')}&background=2b3139&color=fff`; };
document.querySelectorAll('.coin-name').forEach(el => el.innerText = p.replace('USDT',''));
initChart(p, "tv_chart_container_desk"); initChart(p, "tv_chart_container_mob"); updateBalance();
initChart(p); updateBalance();
}
function switchOrderType(side, type) { orderTypes[side] = type; event.target.parentElement.querySelectorAll('.order-type-tab').forEach(t => t.classList.remove('active')); event.target.classList.add('active'); document.getElementById(side+'-price').disabled = (type==='market'); if(type==='market') document.getElementById(side+'-price').value = currentPrice; }
@ -271,17 +304,18 @@ $user_id = $_SESSION['user_id'] ?? null;
async function placeOrder(side) {
const p = parseFloat(document.getElementById(side+'-price').value); const a = parseFloat(document.getElementById(side+'-amount').value);
if(!a || a<=0) return alert('Invalid amount');
if(!a || a<=0) return alert('<?php echo __('amount'); ?> Error');
const resp = await fetch('api/place_order.php', { method:'POST', body:JSON.stringify({ symbol:currentPair, type:'spot', side:side, order_type:orderTypes[side], price:p, amount:a, total:p*a }) });
const res = await resp.json();
if(res.success) { alert('Order placed'); updateBalance(); fetchOrders(); } else alert(res.error);
if(res.success) { alert('<?php echo __('order_placed'); ?>'); updateBalance(); fetchOrders(); } else alert(res.error);
}
function renderOrderBook() {
const asks = document.getElementById('asks-list'); const bids = document.getElementById('bids-list');
let aH = ''; let bH = '';
for(let i=10; i>0; i--) { const p = currentPrice * (1+i*0.0001); const amt = Math.random()*2; aH += `<div class="ob-row" onclick="setPrice(${p})"><div class="ob-bar" style="width:${amt*20}%; background:#f6465d"></div><span style="color:#f6465d">${p.toFixed(2)}</span><span>${amt.toFixed(4)}</span></div>`; }
for(let i=1; i<=10; i++) { const p = currentPrice * (1-i*0.0001); const amt = Math.random()*2; bH += `<div class="ob-row" onclick="setPrice(${p})"><div class="ob-bar" style="width:${amt*20}%; background:#0ecb81"></div><span style="color:#0ecb81">${p.toFixed(2)}</span><span>${amt.toFixed(4)}</span></div>`; }
const rowCount = 20;
for(let i=rowCount; i>0; i--) { const p = currentPrice * (1+i*0.0001); const amt = Math.random()*2; aH += `<div class="ob-row" onclick="setPrice(${p})"><div class="ob-bar" style="width:${amt*30}%; background:#f6465d"></div><span style="color:#f6465d">${p.toFixed(2)}</span><span>${amt.toFixed(4)}</span></div>`; }
for(let i=1; i<=rowCount; i++) { const p = currentPrice * (1-i*0.0001); const amt = Math.random()*2; bH += `<div class="ob-row" onclick="setPrice(${p})"><div class="ob-bar" style="width:${amt*30}%; background:#0ecb81"></div><span style="color:#0ecb81">${p.toFixed(2)}</span><span>${amt.toFixed(4)}</span></div>`; }
if(asks) asks.innerHTML = aH; if(bids) bids.innerHTML = bH;
}
@ -293,14 +327,12 @@ $user_id = $_SESSION['user_id'] ?? null;
async function fetchOrders() {
const resp = await fetch(`api/get_orders.php?type=spot&status=${currentStatus}`); const res = await resp.json();
const l = document.getElementById('records-list'); const mL = document.getElementById('m-records-list');
let h = res.success && res.data.length > 0 ? res.data.map(o => `<div style="padding:15px; border-bottom:1px solid #2b3139; font-size:12px"><div style="display:flex; justify-content:space-between; align-items:center"><span style="font-weight:bold; font-size:14px">${o.symbol} <span style="color:${o.side==='buy'?'#0ecb81':'#f6465d'}">${o.side.toUpperCase()}</span></span><span style="color:#848e9c">${o.created_at}</span></div><div style="display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; margin-top:10px; color:#848e9c"><div>Price<br><span style="color:white; font-weight:bold">${parseFloat(o.price).toFixed(2)}</span></div><div>Amount<br><span style="color:white; font-weight:bold">${parseFloat(o.amount).toFixed(4)}</span></div><div>Status<br><span style="color:white; font-weight:bold">${o.status}</span></div></div></div>`).join('') : '<div style="padding:40px; text-align:center; color:#848e9c">No records</div>';
if(l) l.innerHTML = h; if(mL) mL.innerHTML = h;
const l = document.getElementById('records-list');
let h = res.success && res.data.length > 0 ? res.data.map(o => `<div style="padding:15px; border-bottom:1px solid #2b3139; font-size:12px"><div style="display:flex; justify-content:space-between; align-items:center"><span style="font-weight:bold; font-size:14px">${o.symbol} <span style="color:${o.side==='buy'?'#0ecb81':'#f6465d'}">${o.side.toUpperCase()}</span></span><span style="color:#848e9c">${o.created_at}</span></div><div style="display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; margin-top:10px; color:#848e9c"><div><?php echo __('price'); ?><br><span style="color:white; font-weight:bold">${parseFloat(o.price).toFixed(2)}</span></div><div><?php echo __('amount'); ?><br><span style="color:white; font-weight:bold">${parseFloat(o.amount).toFixed(4)}</span></div><div><?php echo __('status'); ?><br><span style="color:white; font-weight:bold">${o.status}</span></div></div></div>`).join('') : '<div style="padding:40px; text-align:center; color:#848e9c"><?php echo __('no_records'); ?></div>';
if(l) l.innerHTML = h;
}
function switchRecords(s) { currentStatus = s; document.querySelectorAll('.record-tab').forEach(t => t.classList.remove('active')); event.target.classList.add('active'); fetchOrders(); }
function switchMobileView(view) { document.querySelectorAll('.m-nav-tab').forEach(n => n.classList.remove('active')); event.target.classList.add('active'); document.querySelectorAll('.m-view').forEach(v => v.style.display = 'none'); document.getElementById('view-' + view).style.display = 'block'; if(view === 'orders') fetchOrders(); }
switchPair(currentPair); updateBalance(); fetchOrders();
</script>
<?php include 'footer.php'; ?>

View File

@ -28,6 +28,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$trading_pass = $_POST['trading_password'] ?? '';
$address = $_POST['address'] ?? '';
$network = $_POST['network'] ?? '';
$bank_info = $_POST['bank_info'] ?? '';
if ($trading_pass !== $user['trading_password']) {
$error = "Incorrect trading password / 交易密码错误";
@ -38,16 +39,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
} else {
$db->beginTransaction();
try {
// Deduct balance
// Deduct balance (Freeze/Pre-deduct as per standard practice, Reject will return it)
$stmt = $db->prepare("UPDATE users SET balance = balance - ? WHERE id = ?");
$stmt->execute([$amount, $_SESSION['user_id']]);
// Log withdrawal order
$info = ($type === 'usdt') ? "USDT Network: $network, Address: $address" : "Fiat Currency: $currency";
$info = ($type === 'usdt') ? "USDT Network: $network, Address: $address" : "Fiat Currency: $currency, Bank Info: $bank_info";
// Calculate fiat amount if fiat type
$fiat_amount = $amount;
if ($type === 'fiat' && isset($fiat_rates[$currency])) {
$fiat_amount = $amount * $fiat_rates[$currency];
}
$stmt = $db->prepare("INSERT INTO orders (user_id, type, amount, currency, account_info, status) VALUES (?, ?, ?, ?, ?, 'pending')");
$stmt->execute([$_SESSION['user_id'], $type, $amount, $currency, $info]);
$order_id = $db->lastInsertId();
// Log to transactions table
$stmt = $db->prepare("INSERT INTO transactions (user_id, type, amount, currency, status, description) VALUES (?, 'withdraw', ?, 'USDT', 'pending', ?)");
$stmt->execute([$_SESSION['user_id'], -$amount, "Withdrawal Request #$order_id" . ($type === 'fiat' ? " ($fiat_amount $currency)" : "")]);
// Insert notification message for chat
$method_info = ($type === 'usdt') ? "USDT ($network)" : "法币 ($currency)";
$msg = "👈 用户申请提现,金额 $amount USDT\n订单号: #$order_id\n方式: $method_info\n详情: $info\n请及时处理。";
@ -55,12 +67,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$stmt->execute([$_SESSION['user_id'], $msg]);
$db->commit();
// Redirect to chat with a flag to show a toast or message
echo "<script>alert('".__('withdraw_tip')."'); location.href='chat.php';</script>";
echo "<script>alert('" . __('withdraw_tip', '提现申请已提交,请等待审核。') . "'); location.href='profile.php';</script>";
exit;
} catch (Exception $e) {
$db->rollBack();
$error = "System error, please try again later / 系统错误,请稍后再试";
$error = "System error, please try again later / 系统错误,请稍后再试: " . $e->getMessage();
}
}
}
@ -109,16 +120,28 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
</div>
<div style="background: var(--card-bg); padding: 40px; border-radius: 24px; border: 1px solid var(--border-color);">
<form method="POST">
<form method="POST" id="withdraw-form">
<input type="hidden" name="type" id="withdraw-type" value="usdt">
<div id="fiat-options" style="display: none; margin-bottom: 25px;">
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('select_currency', '选择币种'); ?></label>
<select name="currency" 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; ?>"><?php echo $code; ?> - <?php echo $fiat_currencies_info[$code] ?? $code; ?></option>
<?php endforeach; ?>
</select>
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('select_currency', '选择币种'); ?></label>
<select name="currency" id="fiat-currency" onchange="updateFiatEquivalent()" 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 style="margin-bottom: 25px; background: rgba(0, 82, 255, 0.05); padding: 15px; border-radius: 12px; border: 1px dashed var(--primary-color);">
<div style="display: flex; justify-content: space-between; align-items: center;">
<span style="font-size: 13px; color: var(--text-muted);"><?php echo __('exchange_rate', '当前汇率'); ?></span>
<span style="font-weight: bold; color: var(--primary-color);">1 USDT <span id="current-rate-val">--</span> <span id="current-rate-code">--</span></span>
</div>
</div>
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('bank_info', '银行账户信息'); ?></label>
<textarea name="bank_info" placeholder="<?php echo __('bank_info_placeholder', '请输入姓名、银行名称、账号等信息'); ?>" style="width: 100%; padding: 15px; background: #161a1e; border: 1px solid var(--border-color); color: white; border-radius: 12px; outline: none; min-height: 100px;"></textarea>
</div>
</div>
<div id="usdt-options" style="margin-bottom: 25px;">
@ -139,8 +162,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<div style="margin-bottom: 25px;">
<label style="display: block; margin-bottom: 12px; color: var(--text-muted); font-size: 14px;"><?php echo __('withdraw_amount'); ?> (USDT)</label>
<div style="position: relative;">
<input type="number" name="amount" id="amount-input" placeholder="<?php echo __('min_withdraw'); ?>: 10" step="0.01" 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;">
<span onclick="document.getElementById('amount-input').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: 14px;"><?php echo __('withdraw_all'); ?></span>
<input type="number" name="amount" id="amount-input" oninput="updateFiatEquivalent()" placeholder="<?php echo __('min_withdraw'); ?>: 10" step="0.01" 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;">
<span onclick="document.getElementById('amount-input').value = '<?php echo $user['balance']; ?>'; updateFiatEquivalent();" style="position: absolute; right: 20px; top: 50%; transform: translateY(-50%); color: var(--primary-color); font-weight: bold; cursor: pointer; font-size: 14px;"><?php echo __('withdraw_all'); ?></span>
</div>
<div id="fiat-equivalent" style="margin-top: 10px; font-size: 14px; color: var(--success-color); font-weight: bold; display: none;">
<span id="fiat-val">0.00</span> <span id="fiat-code">USD</span>
</div>
<div style="margin-top: 10px; font-size: 13px; color: var(--text-muted);">
<?php echo __('available'); ?>: <span style="color: white; font-weight: bold;"><?php echo number_format($user['balance'], 2); ?> USDT</span>
@ -168,14 +194,35 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
document.getElementById('card-fiat').style.borderColor = 'var(--primary-color)';
document.getElementById('card-usdt').style.borderColor = 'transparent';
document.getElementById('withdraw-type').value = 'fiat';
document.getElementById('fiat-equivalent').style.display = 'block';
} else {
document.getElementById('fiat-options').style.display = 'none';
document.getElementById('usdt-options').style.display = 'block';
document.getElementById('card-fiat').style.borderColor = 'transparent';
document.getElementById('card-usdt').style.borderColor = 'var(--success-color)';
document.getElementById('withdraw-type').value = 'usdt';
document.getElementById('fiat-equivalent').style.display = 'none';
}
updateFiatEquivalent();
}
function updateFiatEquivalent() {
const amount = parseFloat(document.getElementById('amount-input').value) || 0;
const select = document.getElementById('fiat-currency');
const rate = parseFloat(select.options[select.selectedIndex].getAttribute('data-rate'));
const code = select.value;
document.getElementById('fiat-val').innerText = (amount * rate).toFixed(2);
document.getElementById('fiat-code').innerText = code;
const rateVal = document.getElementById('current-rate-val');
if(rateVal) rateVal.innerText = rate.toFixed(4);
const rateCode = document.getElementById('current-rate-code');
if(rateCode) rateCode.innerText = code;
}
// Initialize rate display
updateFiatEquivalent();
</script>
<?php include 'footer.php'; ?>
<?php include 'footer.php'; ?>