Autosave: 20260212-050303
This commit is contained in:
parent
b61cbbc19a
commit
c93c7ad3ca
@ -18,7 +18,8 @@ if (isset($_POST['action']) && isset($_POST['order_id'])) {
|
||||
$margin = $order['total'] / $order['leverage'];
|
||||
|
||||
if ($action == 'approve') {
|
||||
// Settle at TP price (or current price if tp not set, but here we assume admin uses the TP field as exit price)
|
||||
// "WIN": Approve and settle at TP price (if set) or current manual price
|
||||
// The requirement says: "后台可以按照用户下单的止盈价格接受,同意就是按照止盈价格计算出盈利"
|
||||
$exit_price = (float)($order['tp_price'] ?: $order['price']);
|
||||
$entry_price = (float)$order['price'];
|
||||
$nominal = (float)$order['amount'] * $faceValue;
|
||||
@ -30,17 +31,18 @@ if (isset($_POST['action']) && isset($_POST['order_id'])) {
|
||||
$profit = (1 - $exit_price / $entry_price) * $nominal;
|
||||
}
|
||||
|
||||
// Apply leverage to profit or it's already calculated in nominal?
|
||||
// Nominal is amount * 10 (value in USDT).
|
||||
// PNL = (PriceChange / EntryPrice) * NominalValue. This is correct.
|
||||
|
||||
$payout = $margin + $profit;
|
||||
if ($payout < 0) $payout = 0; // Negative equity handled as 0 payout (liquidation)
|
||||
if ($payout < 0) $payout = 0;
|
||||
|
||||
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$payout, $user_id]);
|
||||
$pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved', win_loss = 'win' WHERE id = ?")->execute([$oid]);
|
||||
$pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved' WHERE id = ?")->execute([$oid]);
|
||||
} elseif ($action == 'reject') {
|
||||
// Reject usually means loss/liquidation. No payout.
|
||||
$pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected', win_loss = 'loss' WHERE id = ?")->execute([$oid]);
|
||||
} elseif ($action == 'set_win_loss') {
|
||||
$win_loss = $_POST['win_loss'];
|
||||
$pdo->prepare("UPDATE trading_orders SET win_loss = ? WHERE id = ?")->execute([$win_loss, $oid]);
|
||||
// "LOSS": Reject. Margin is already deducted and not returned.
|
||||
$pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected' WHERE id = ?")->execute([$oid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,24 +60,23 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
.admin-layout { display: flex; min-height: 100vh; }
|
||||
.sidebar { width: 250px; background: #1E2329; border-right: 1px solid #2B3139; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #0B0E11; color: white; }
|
||||
.menu-item { padding: 12px; color: #848E9C; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #2B3139; color: white; }
|
||||
.badge { background: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.sidebar { width: 250px; background: #FFFFFF; border-right: 1px solid #EAECEF; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #FFFFFF; color: #1E2329; }
|
||||
.menu-item { padding: 12px; color: #474D57; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #F5F5F5; color: #F0B90B; }
|
||||
.badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
|
||||
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #2B3139; font-size: 0.8rem; }
|
||||
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #EAECEF; font-size: 0.8rem; color: #1E2329; }
|
||||
.btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; }
|
||||
.btn-approve { background: #00c087; color: white; }
|
||||
.btn-reject { background: #f6465d; color: white; }
|
||||
.back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
select { background: #1e2329; border: 1px solid #2b3139; color: white; padding: 5px; border-radius: 4px; font-size: 0.75rem; }
|
||||
.back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body style="background: white;">
|
||||
<div class="admin-layout">
|
||||
<div class="sidebar">
|
||||
<h3 style="color: white; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<h3 style="color: #1E2329; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<a href="index.php" class="menu-item"><i class="fas fa-chart-pie"></i> 仪表盘</a>
|
||||
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
|
||||
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
|
||||
@ -90,20 +91,20 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h2>合约交易详情</h2>
|
||||
<h2 style="color: #1E2329;">合约交易管理 (后台控赢/亏)</h2>
|
||||
<p style="color: #707A8A; font-size: 0.9rem;">提示:同意结算将按用户设置的“止盈价”计算盈利并返还保证金;拒绝(亏损)将扣除全部保证金。</p>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>用户</th>
|
||||
<th>交易对</th>
|
||||
<th>币对</th>
|
||||
<th>方向</th>
|
||||
<th>杠杆</th>
|
||||
<th>开仓价</th>
|
||||
<th>退出价(止盈)</th>
|
||||
<th>止盈价(结算价)</th>
|
||||
<th>保证金</th>
|
||||
<th>盈亏控制</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
@ -117,24 +118,13 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
<td><span style="color: <?php echo $o['side'] == 'buy' ? '#00c087' : '#f6465d'; ?>"><?php echo strtoupper($o['side'] == 'buy' ? '做多' : '做空'); ?></span></td>
|
||||
<td><?php echo $o['leverage']; ?>x</td>
|
||||
<td><?php echo number_format($o['price'], 4); ?></td>
|
||||
<td><?php echo number_format($o['tp_price'], 4); ?></td>
|
||||
<td><span style="color: #00c087; font-weight: bold;"><?php echo $o['tp_price'] ? number_format($o['tp_price'], 4) : '--'; ?></span></td>
|
||||
<td><?php echo number_format($o['total'] / $o['leverage'], 2); ?></td>
|
||||
<td>
|
||||
<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="set_win_loss">
|
||||
<select name="win_loss" onchange="this.form.submit()">
|
||||
<option value="none" <?php echo $o['win_loss'] == 'none' ? 'selected' : ''; ?>>正常</option>
|
||||
<option value="win" <?php echo $o['win_loss'] == 'win' ? 'selected' : ''; ?>>控盈</option>
|
||||
<option value="loss" <?php echo $o['win_loss'] == 'loss' ? 'selected' : ''; ?>>控亏</option>
|
||||
</select>
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if ($o['status'] == 'open') echo '<span style="color: #f0b90b;">持有中</span>';
|
||||
elseif ($o['status'] == 'closed') echo '<span style="color: #00c087;">已平仓</span>';
|
||||
else echo '<span style="color: #848e9c;">已撤销</span>';
|
||||
if ($o['status'] == 'open') echo '<span style="color: #f0b90b; font-weight: bold;">待结算</span>';
|
||||
elseif ($o['status'] == 'closed') echo '<span style="color: #00c087;">已止盈结算</span>';
|
||||
else echo '<span style="color: #f6465d;">已判定亏损</span>';
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
@ -143,12 +133,12 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
<form method="POST">
|
||||
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
|
||||
<input type="hidden" name="action" value="approve">
|
||||
<button type="submit" class="btn-sm btn-approve" title="按退出价结算">同意结算</button>
|
||||
<button type="submit" class="btn-sm btn-approve" title="按止盈价结算盈利">同意(盈)</button>
|
||||
</form>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
|
||||
<input type="hidden" name="action" value="reject">
|
||||
<button type="submit" class="btn-sm btn-reject" title="按亏损处理">拒绝结算</button>
|
||||
<button type="submit" class="btn-sm btn-reject" title="判定为亏损">拒绝(亏)</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
@ -17,18 +17,18 @@ $unread_msgs = $db->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' A
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
.admin-layout { display: flex; min-height: 100vh; }
|
||||
.sidebar { width: 250px; background: #1E2329; border-right: 1px solid #2B3139; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #0B0E11; }
|
||||
.menu-item { padding: 12px; color: #848E9C; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #2B3139; color: white; }
|
||||
.badge { background: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.stat-card { background: #1E2329; padding: 20px; border-radius: 8px; border: 1px solid #2B3139; }
|
||||
.sidebar { width: 250px; background: #FFFFFF; border-right: 1px solid #EAECEF; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #FFFFFF; }
|
||||
.menu-item { padding: 12px; color: #474D57; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #F5F5F5; color: #F0B90B; }
|
||||
.badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.stat-card { background: #F9FAFB; padding: 20px; border-radius: 8px; border: 1px solid #EAECEF; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body style="background-color: #FFFFFF; color: #1E2329;">
|
||||
<div class="admin-layout">
|
||||
<div class="sidebar">
|
||||
<h3 style="color: white; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<h3 style="color: #1E2329; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<a href="index.php" class="menu-item active"><i class="fas fa-chart-pie"></i> 仪表盘</a>
|
||||
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
|
||||
<a href="kyc.php" class="menu-item">
|
||||
@ -45,48 +45,48 @@ $unread_msgs = $db->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' A
|
||||
<i class="fas fa-wallet"></i> 充值记录
|
||||
</a>
|
||||
<a href="settings.php" class="menu-item"><i class="fas fa-cog"></i> 系统设置</a>
|
||||
<a href="../index.php" class="menu-item" style="margin-top: 2rem; color: orange;"><i class="fas fa-external-link-alt"></i> 查看前端</a>
|
||||
<a href="../index.php" class="menu-item" style="margin-top: 2rem; color: #F0B90B;"><i class="fas fa-external-link-alt"></i> 查看前端</a>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<h2 style="color: white; margin-bottom: 2rem;">系统概览</h2>
|
||||
<h2 style="color: #1E2329; margin-bottom: 2rem;">系统概览</h2>
|
||||
<div style="grid-template-columns: repeat(4, 1fr); display: grid; gap: 1.5rem;">
|
||||
<div class="stat-card">
|
||||
<div style="color: #848E9C; font-size: 0.9rem;">总注册人数</div>
|
||||
<div style="font-size: 2rem; color: white; margin-top: 10px;"><?php echo $total_users; ?></div>
|
||||
<div style="color: #707A8A; font-size: 0.9rem;">总注册人数</div>
|
||||
<div style="font-size: 2rem; color: #1E2329; margin-top: 10px;"><?php echo $total_users; ?></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div style="color: #848E9C; font-size: 0.9rem;">待处理 KYC</div>
|
||||
<div style="color: #707A8A; font-size: 0.9rem;">待处理 KYC</div>
|
||||
<div style="font-size: 2rem; color: #F0B90B; margin-top: 10px;"><?php echo $pending_kyc; ?></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div style="color: #848E9C; font-size: 0.9rem;">待匹配/审核充值</div>
|
||||
<div style="color: #707A8A; font-size: 0.9rem;">待匹配/审核充值</div>
|
||||
<div style="font-size: 2rem; color: #F0B90B; margin-top: 10px;"><?php echo $pending_orders; ?></div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div style="color: #848E9C; font-size: 0.9rem;">未读消息</div>
|
||||
<div style="color: #707A8A; font-size: 0.9rem;">未读消息</div>
|
||||
<div style="font-size: 2rem; color: #00C087; margin-top: 10px;"><?php echo $unread_msgs; ?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 3rem; background: #1E2329; padding: 25px; border-radius: 8px;">
|
||||
<h3 style="color: white; margin-bottom: 20px;">控制中心</h3>
|
||||
<div style="margin-top: 3rem; background: #F9FAFB; padding: 25px; border-radius: 8px; border: 1px solid #EAECEF;">
|
||||
<h3 style="color: #1E2329; margin-bottom: 20px;">控制中心</h3>
|
||||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
|
||||
<div style="border: 1px solid #2B3139; padding: 20px; border-radius: 6px;">
|
||||
<h4 style="color: #848E9C;">客服与充值管理</h4>
|
||||
<p style="color: #848E9C; font-size: 0.8rem;">与用户对话并处理实时的充值匹配请求。</p>
|
||||
<div style="border: 1px solid #EAECEF; padding: 20px; border-radius: 6px; background: white;">
|
||||
<h4 style="color: #474D57;">客服与充值管理</h4>
|
||||
<p style="color: #707A8A; font-size: 0.8rem;">与用户对话并处理实时的充值匹配请求。</p>
|
||||
<a href="chat.php" class="btn-primary" style="display: inline-block; margin-top: 15px; font-size: 0.8rem; padding: 8px 15px;">进入工作台</a>
|
||||
</div>
|
||||
<div style="border: 1px solid #2B3139; padding: 20px; border-radius: 6px;">
|
||||
<h4 style="color: #848E9C;">交易管理</h4>
|
||||
<p style="color: #848E9C; font-size: 0.8rem;">审核并处理现货及合约交易订单。</p>
|
||||
<div style="border: 1px solid #EAECEF; padding: 20px; border-radius: 6px; background: white;">
|
||||
<h4 style="color: #474D57;">交易管理</h4>
|
||||
<p style="color: #707A8A; font-size: 0.8rem;">审核并处理现货及合约交易订单。</p>
|
||||
<div style="display:flex; gap: 10px; margin-top: 15px;">
|
||||
<a href="spot_orders.php" class="btn-primary" style="font-size: 0.75rem; padding: 5px 10px; background: #377aff;">现货</a>
|
||||
<a href="futures_orders.php" class="btn-primary" style="font-size: 0.75rem; padding: 5px 10px; background: #f0b90b; color: black;">合约</a>
|
||||
<a href="futures_orders.php" class="btn-primary" style="font-size: 0.75rem; padding: 5px 10px; background: #f0b90b; color: white;">合约</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="border: 1px solid #2B3139; padding: 20px; border-radius: 6px;">
|
||||
<h4 style="color: #848E9C;">价格控制</h4>
|
||||
<p style="color: #848E9C; font-size: 0.8rem;">手动覆盖特定交易对的实时价格及插针控制。</p>
|
||||
<div style="border: 1px solid #EAECEF; padding: 20px; border-radius: 6px; background: white;">
|
||||
<h4 style="color: #474D57;">价格控制</h4>
|
||||
<p style="color: #707A8A; font-size: 0.8rem;">手动覆盖特定交易对的实时价格及插针控制。</p>
|
||||
<a href="settings.php" class="btn-primary" style="display: inline-block; margin-top: 15px; font-size: 0.8rem; padding: 8px 15px;">立即配置</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -22,20 +22,21 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
.admin-layout { display: flex; min-height: 100vh; }
|
||||
.sidebar { width: 250px; background: #1E2329; border-right: 1px solid #2B3139; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #0B0E11; color: white; }
|
||||
.menu-item { padding: 12px; color: #848E9C; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #2B3139; color: white; }
|
||||
.badge { background: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.kyc-card { background: #1E2329; border: 1px solid #2B3139; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
|
||||
.kyc-img { width: 200px; height: 120px; object-fit: cover; border-radius: 4px; cursor: pointer; border: 1px solid #2B3139; }
|
||||
.back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
.sidebar { width: 250px; background: #FFFFFF; border-right: 1px solid #EAECEF; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #FFFFFF; color: #1E2329; }
|
||||
.menu-item { padding: 12px; color: #474D57; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #F5F5F5; color: #F0B90B; }
|
||||
.badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.kyc-card { background: #F9FAFB; border: 1px solid #EAECEF; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
|
||||
.kyc-img { width: 200px; height: 120px; object-fit: cover; border-radius: 4px; cursor: pointer; border: 1px solid #EAECEF; }
|
||||
.back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
.btn-primary { padding: 10px 20px; border-radius: 4px; border: none; cursor: pointer; color: white; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body style="background: white;">
|
||||
<div class="admin-layout">
|
||||
<div class="sidebar">
|
||||
<h3 style="color: white; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<h3 style="color: #1E2329; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<a href="index.php" class="menu-item"><i class="fas fa-chart-pie"></i> 仪表盘</a>
|
||||
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
|
||||
<a href="kyc.php" class="menu-item active"><i class="fas fa-id-card"></i> KYC 审核</a>
|
||||
@ -50,19 +51,19 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h2>待审核 KYC</h2>
|
||||
<h2 style="color: #1E2329;">待审核 KYC</h2>
|
||||
|
||||
<?php if(empty($kyc_list)): ?>
|
||||
<p style="color: #848E9C; margin-top: 2rem;">暂无待审核申请。</p>
|
||||
<p style="color: #707A8A; margin-top: 2rem;">暂无待审核申请。</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach($kyc_list as $k): ?>
|
||||
<div class="kyc-card">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
|
||||
<div>
|
||||
<h4 style="margin-bottom: 10px;"><?php echo htmlspecialchars($k['kyc_name']); ?></h4>
|
||||
<p style="color: #848E9C; font-size: 0.9rem;">身份证号: <?php echo htmlspecialchars($k['kyc_id_number']); ?></p>
|
||||
<p style="color: #848E9C; font-size: 0.8rem; margin-top: 5px;">用户名: <?php echo htmlspecialchars($k['username']); ?> (UID: <?php echo $k['uid']; ?>)</p>
|
||||
<h4 style="margin-bottom: 10px; color: #1E2329;"><?php echo htmlspecialchars($k['kyc_name']); ?></h4>
|
||||
<p style="color: #707A8A; font-size: 0.9rem;">身份证号: <?php echo htmlspecialchars($k['kyc_id_number']); ?></p>
|
||||
<p style="color: #707A8A; font-size: 0.8rem; margin-top: 5px;">用户名: <?php echo htmlspecialchars($k['username']); ?> (UID: <?php echo $k['uid']; ?>)</p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<form method="POST">
|
||||
@ -87,4 +88,4 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -17,24 +17,16 @@ if (isset($_POST['action']) && isset($_POST['order_id'])) {
|
||||
$coin_symbol = str_replace('USDT', '', $symbol);
|
||||
|
||||
if ($action == 'approve') {
|
||||
// "WIN": Approve and settle
|
||||
if ($order['side'] == 'buy') {
|
||||
// Buy approved: Add coins to user_assets
|
||||
$stmt = $pdo->prepare("INSERT INTO user_assets (user_id, symbol, amount) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE amount = amount + ?");
|
||||
$stmt->execute([$user_id, $coin_symbol, $order['amount'], $order['amount']]);
|
||||
} else {
|
||||
// Sell approved: Add USDT to users balance
|
||||
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['total'], $user_id]);
|
||||
}
|
||||
$pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved' WHERE id = ?")->execute([$oid]);
|
||||
} elseif ($action == 'reject') {
|
||||
if ($order['side'] == 'buy') {
|
||||
// Buy rejected: Refund USDT to users balance
|
||||
$pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['total'], $user_id]);
|
||||
} else {
|
||||
// Sell rejected: Refund coins to user_assets
|
||||
$stmt = $pdo->prepare("INSERT INTO user_assets (user_id, symbol, amount) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE amount = amount + ?");
|
||||
$stmt->execute([$user_id, $coin_symbol, $order['amount'], $order['amount']]);
|
||||
}
|
||||
// "LOSS": Reject. No assets returned.
|
||||
$pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected' WHERE id = ?")->execute([$oid]);
|
||||
}
|
||||
}
|
||||
@ -53,23 +45,23 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
.admin-layout { display: flex; min-height: 100vh; }
|
||||
.sidebar { width: 250px; background: #1E2329; border-right: 1px solid #2B3139; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #0B0E11; color: white; }
|
||||
.menu-item { padding: 12px; color: #848E9C; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #2B3139; color: white; }
|
||||
.badge { background: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.sidebar { width: 250px; background: #FFFFFF; border-right: 1px solid #EAECEF; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #FFFFFF; color: #1E2329; }
|
||||
.menu-item { padding: 12px; color: #474D57; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #F5F5F5; color: #F0B90B; }
|
||||
.badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
|
||||
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #2B3139; font-size: 0.85rem; }
|
||||
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #EAECEF; font-size: 0.85rem; color: #1E2329; }
|
||||
.btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; }
|
||||
.btn-approve { background: #00c087; color: white; }
|
||||
.btn-reject { background: #f6465d; color: white; }
|
||||
.back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
.back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body style="background: white;">
|
||||
<div class="admin-layout">
|
||||
<div class="sidebar">
|
||||
<h3 style="color: white; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<h3 style="color: #1E2329; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<a href="index.php" class="menu-item"><i class="fas fa-chart-pie"></i> 仪表盘</a>
|
||||
<a href="users.php" class="menu-item"><i class="fas fa-users"></i> 用户管理</a>
|
||||
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
|
||||
@ -84,55 +76,71 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<a href="index.php" class="back-btn"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h2>现货交易详情</h2>
|
||||
<h2 style="color: #1E2329;">现货交易管理 (后台控赢/亏)</h2>
|
||||
<p style="color: #707A8A; font-size: 0.9rem;">提示:同意即为用户盈(得币/得USDT);拒绝即为用户亏(资产不退)。</p>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>用户</th>
|
||||
<th>交易对</th>
|
||||
<th>币对</th>
|
||||
<th>方向</th>
|
||||
<th>类型</th>
|
||||
<th>价格</th>
|
||||
<th>成本价</th>
|
||||
<th>卖出/买入价</th>
|
||||
<th>数量</th>
|
||||
<th>总计</th>
|
||||
<th>总计(USDT)</th>
|
||||
<th>盈利差额</th>
|
||||
<th>状态</th>
|
||||
<th>时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($orders as $o): ?>
|
||||
<?php foreach($orders as $o):
|
||||
$diff = 0;
|
||||
if ($o['side'] == 'sell' && $o['tp_price'] > 0) {
|
||||
$diff = ($o['price'] - $o['tp_price']) * $o['amount'];
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td>#<?php echo $o['id']; ?></td>
|
||||
<td><?php echo htmlspecialchars($o['username']); ?></td>
|
||||
<td><?php echo $o['symbol']; ?></td>
|
||||
<td><span style="color: <?php echo $o['side'] == 'buy' ? '#00c087' : '#f6465d'; ?>"><?php echo strtoupper($o['side'] == 'buy' ? '买入' : '卖出'); ?></span></td>
|
||||
<td><?php echo strtoupper($o['order_type'] == 'limit' ? '限价' : '市价'); ?></td>
|
||||
<td><?php echo number_format($o['tp_price'], 4); ?></td>
|
||||
<td><?php echo number_format($o['price'], 4); ?></td>
|
||||
<td><?php echo number_format($o['amount'], 4); ?></td>
|
||||
<td><?php echo number_format($o['total'], 2); ?></td>
|
||||
<td>
|
||||
<?php if($o['side'] == 'sell'): ?>
|
||||
<span style="color: <?php echo $diff >= 0 ? '#00c087' : '#f6465d'; ?>; font-weight: bold;">
|
||||
<?php echo ($diff >= 0 ? '+' : '') . number_format($diff, 2); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
--
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if ($o['status'] == 'open') echo '<span style="color: #f0b90b;">进行中</span>';
|
||||
elseif ($o['status'] == 'closed') echo '<span style="color: #00c087;">已成交</span>';
|
||||
else echo '<span style="color: #848e9c;">已取消</span>';
|
||||
if ($o['status'] == 'open') echo '<span style="color: #f0b90b; font-weight: bold;">待处理</span>';
|
||||
elseif ($o['status'] == 'closed') echo '<span style="color: #00c087;">已结算</span>';
|
||||
else echo '<span style="color: #f6465d;">已亏损</span>';
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo $o['created_at']; ?></td>
|
||||
<td>
|
||||
<?php if($o['status'] == 'open'): ?>
|
||||
<form method="POST" style="display:inline;">
|
||||
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
|
||||
<input type="hidden" name="action" value="approve">
|
||||
<button type="submit" class="btn-sm btn-approve">同意并结算</button>
|
||||
</form>
|
||||
<form method="POST" style="display:inline;">
|
||||
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
|
||||
<input type="hidden" name="action" value="reject">
|
||||
<button type="submit" class="btn-sm btn-reject">拒绝并取消</button>
|
||||
</form>
|
||||
<div style="display: flex; gap: 5px;">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
|
||||
<input type="hidden" name="action" value="approve">
|
||||
<button type="submit" class="btn-sm btn-approve">同意(盈)</button>
|
||||
</form>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="order_id" value="<?php echo $o['id']; ?>">
|
||||
<input type="hidden" name="action" value="reject">
|
||||
<button type="submit" class="btn-sm btn-reject">拒绝(亏)</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -51,35 +51,35 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
.admin-layout { display: flex; min-height: 100vh; }
|
||||
.sidebar { width: 250px; background: #1E2329; border-right: 1px solid #2B3139; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #0B0E11; color: white; }
|
||||
.menu-item { padding: 12px; color: #848E9C; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #2B3139; color: white; }
|
||||
.badge { background: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.sidebar { width: 250px; background: #FFFFFF; border-right: 1px solid #EAECEF; padding: 1rem; }
|
||||
.main-content { flex: 1; padding: 2rem; background: #FFFFFF; color: #1E2329; }
|
||||
.menu-item { padding: 12px; color: #474D57; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; }
|
||||
.menu-item:hover, .menu-item.active { background: #F5F5F5; color: #F0B90B; }
|
||||
.badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; }
|
||||
.table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
|
||||
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #2B3139; font-size: 0.85rem; }
|
||||
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #EAECEF; font-size: 0.85rem; color: #1E2329; }
|
||||
.btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; text-decoration: none; display: inline-block; }
|
||||
.btn-edit { background: #f0b90b; color: #000; }
|
||||
.btn-delete { background: #f6465d; color: white; }
|
||||
.btn-status { background: #5e6673; color: white; }
|
||||
.btn-add { background: #00c087; color: white; padding: 10px 20px; border-radius: 4px; border: none; cursor: pointer; margin-bottom: 20px; }
|
||||
|
||||
.modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 1000; }
|
||||
.modal-content { background: #1E2329; width: 500px; margin: 50px auto; padding: 30px; border-radius: 8px; border: 1px solid #2B3139; }
|
||||
.modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; }
|
||||
.modal-content { background: #FFFFFF; width: 500px; margin: 50px auto; padding: 30px; border-radius: 8px; border: 1px solid #EAECEF; color: #1E2329; }
|
||||
.form-group { margin-bottom: 15px; }
|
||||
.form-group label { display: block; margin-bottom: 5px; color: #848E9C; }
|
||||
.form-group input, .form-group select { width: 100%; padding: 8px; background: #0B0E11; border: 1px solid #2B3139; color: white; border-radius: 4px; }
|
||||
.form-group label { display: block; margin-bottom: 5px; color: #474D57; }
|
||||
.form-group input, .form-group select { width: 100%; padding: 8px; background: #F9FAFB; border: 1px solid #EAECEF; color: #1E2329; border-radius: 4px; outline: none; }
|
||||
.modal-footer { margin-top: 20px; text-align: right; }
|
||||
|
||||
.header-actions { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
|
||||
.back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; }
|
||||
.back-btn:hover { color: white; }
|
||||
.back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; }
|
||||
.back-btn:hover { color: #1E2329; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body style="background: white;">
|
||||
<div class="admin-layout">
|
||||
<div class="sidebar">
|
||||
<h3 style="color: white; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<h3 style="color: #1E2329; margin-bottom: 2rem;">NovaEx 管理员</h3>
|
||||
<a href="index.php" class="menu-item"><i class="fas fa-chart-pie"></i> 仪表盘</a>
|
||||
<a href="users.php" class="menu-item active"><i class="fas fa-users"></i> 用户管理</a>
|
||||
<a href="kyc.php" class="menu-item"><i class="fas fa-id-card"></i> KYC 审核</a>
|
||||
@ -239,4 +239,4 @@ function editUser(user) {
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -1,3 +1,4 @@
|
||||
* { box-sizing: border-box; }
|
||||
:root {
|
||||
--bg-color: #0B0E11;
|
||||
--nav-bg: #0B0E11;
|
||||
|
||||
BIN
assets/pasted-20260212-045129-d8e4cda7.png
Normal file
BIN
assets/pasted-20260212-045129-d8e4cda7.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
270
futures.php
270
futures.php
@ -14,6 +14,7 @@ if ($user_id) {
|
||||
?>
|
||||
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
:root {
|
||||
--bg-color: #0b0e11;
|
||||
--panel-bg: #161a1e;
|
||||
@ -26,20 +27,58 @@ if ($user_id) {
|
||||
--input-bg: #1e2329;
|
||||
}
|
||||
|
||||
body { background-color: var(--bg-color); color: var(--text-primary); font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; margin: 0; overflow: hidden; }
|
||||
.trading-layout { display: flex; height: calc(100vh - 60px); gap: 1px; background: var(--border-color); }
|
||||
.panel { background: var(--panel-bg); display: flex; flex-direction: column; overflow: hidden; }
|
||||
.market-panel { width: 280px; flex-shrink: 0; }
|
||||
.search-box { padding: 12px; border-bottom: 1px solid var(--border-color); }
|
||||
.search-input-wrapper { position: relative; }
|
||||
.search-input-wrapper input { width: 100%; background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 6px 12px 6px 32px; border-radius: 4px; font-size: 13px; outline: none; }
|
||||
.search-input-wrapper i { position: absolute; left: 10px; top: 8px; color: var(--text-secondary); }
|
||||
body {
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-primary);
|
||||
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||
margin: 0;
|
||||
overflow: hidden; /* Prevent whole page scroll */
|
||||
height: 100vh;
|
||||
}
|
||||
.trading-layout {
|
||||
display: flex;
|
||||
height: calc(100vh - 64px);
|
||||
gap: 1px;
|
||||
background: var(--border-color);
|
||||
overflow: hidden;
|
||||
}
|
||||
.panel {
|
||||
background: var(--panel-bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
/* Left: Markets - Scrollable */
|
||||
.market-panel {
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.search-box { padding: 12px; border-bottom: 1px solid var(--border-color); width: 100%; position: sticky; top: 0; background: var(--panel-bg); z-index: 5; }
|
||||
.search-input-wrapper { position: relative; width: 100%; }
|
||||
.search-input-wrapper input { width: 100%; background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 6px 12px 6px 32px; border-radius: 4px; font-size: 13px; outline: none; display: block; }
|
||||
.search-input-wrapper i { position: absolute; left: 10px; top: 9px; color: var(--text-secondary); }
|
||||
.market-list-header { display: flex; padding: 8px 12px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); position: sticky; top: 57px; background: var(--panel-bg); z-index: 5; }
|
||||
.pair-item { display: flex; justify-content: space-between; padding: 10px 12px; cursor: pointer; transition: background 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
|
||||
.pair-item:hover { background: rgba(255,255,255,0.05); }
|
||||
.pair-item.active { background: rgba(79, 172, 254, 0.1); }
|
||||
.center-panel { flex: 1; overflow-y: auto; }
|
||||
.info-bar { height: 50px; display: flex; align-items: center; padding: 0 15px; gap: 20px; border-bottom: 1px solid var(--border-color); }
|
||||
.chart-container { height: 400px; background: var(--bg-color); }
|
||||
|
||||
/* Center: Chart (Fixed) and scrollable content below */
|
||||
.center-panel {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.info-bar { height: 50px; display: flex; align-items: center; padding: 0 15px; gap: 20px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; background: var(--panel-bg); }
|
||||
.chart-container { height: 350px; background: var(--bg-color); flex-shrink: 0; border-bottom: 1px solid var(--border-color); }
|
||||
|
||||
/* Scrollable content below chart */
|
||||
.center-content-scroll {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.order-form-panel { padding: 20px; background: var(--panel-bg); border-bottom: 1px solid var(--border-color); }
|
||||
.order-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; }
|
||||
.margin-controls { display: flex; gap: 10px; margin-bottom: 15px; align-items: center; }
|
||||
@ -65,26 +104,40 @@ if ($user_id) {
|
||||
.btn-trade:active { opacity: 0.8; }
|
||||
.btn-trade.buy { background: var(--up-color); }
|
||||
.btn-trade.sell { background: var(--down-color); }
|
||||
.tabs-section { flex: 1; }
|
||||
.tabs-header { display: flex; border-bottom: 1px solid var(--border-color); padding: 0 15px; }
|
||||
|
||||
.tabs-section { min-height: 400px; }
|
||||
.tabs-header { display: flex; border-bottom: 1px solid var(--border-color); padding: 0 15px; position: sticky; top: 0; background: var(--panel-bg); z-index: 9; }
|
||||
.tab-btn { background: none; border: none; color: var(--text-secondary); padding: 12px 15px; font-size: 14px; cursor: pointer; border-bottom: 2px solid transparent; }
|
||||
.tab-btn.active { color: var(--accent-color); border-bottom-color: var(--accent-color); }
|
||||
.order-book-panel { width: 300px; flex-shrink: 0; }
|
||||
.ob-header { padding: 10px 15px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; }
|
||||
|
||||
/* Right Panel - Scrollable */
|
||||
.order-book-panel {
|
||||
width: 300px;
|
||||
flex-shrink: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.ob-header { padding: 10px 15px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; position: sticky; top: 0; background: var(--panel-bg); z-index: 5; }
|
||||
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; }
|
||||
.ob-bar { position: absolute; right: 0; top: 0; bottom: 0; z-index: 0; }
|
||||
.ob-val { z-index: 1; position: relative; }
|
||||
|
||||
input[type=range] { -webkit-appearance: none; width: 100%; background: transparent; margin: 0; padding: 0; }
|
||||
input[type=range]:focus { outline: none; }
|
||||
input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; background: var(--border-color); border-radius: 2px; }
|
||||
input[type=range]::-webkit-slider-thumb { height: 14px; width: 14px; border-radius: 50%; background: white; cursor: pointer; -webkit-appearance: none; margin-top: -5px; box-shadow: 0 0 2px rgba(0,0,0,0.5); border: 2px solid var(--accent-color); z-index: 3; position: relative; }
|
||||
|
||||
.modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); display: none; align-items: center; justify-content: center; z-index: 1000; }
|
||||
.modal-box { background: var(--panel-bg); padding: 30px; border-radius: 8px; width: 400px; border: 1px solid var(--border-color); }
|
||||
|
||||
::-webkit-scrollbar { width: 4px; }
|
||||
::-webkit-scrollbar-thumb { background: #333; border-radius: 10px; }
|
||||
|
||||
#pairs-list { }
|
||||
#asks-list, #bids-list { }
|
||||
</style>
|
||||
|
||||
<div class="trading-layout">
|
||||
<!-- Left Panel -->
|
||||
<div class="panel market-panel">
|
||||
<div class="search-box">
|
||||
<div class="search-input-wrapper">
|
||||
@ -92,14 +145,15 @@ if ($user_id) {
|
||||
<input type="text" id="market-search" placeholder="搜索永续合约" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; padding: 8px 12px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color);">
|
||||
<div class="market-list-header">
|
||||
<span style="flex: 1.5;">币对</span>
|
||||
<span style="flex: 1; text-align: right;">价格</span>
|
||||
<span style="flex: 1; text-align: right;">涨跌</span>
|
||||
</div>
|
||||
<div id="pairs-list" style="flex: 1; overflow-y: auto;"></div>
|
||||
<div id="pairs-list"></div>
|
||||
</div>
|
||||
|
||||
<!-- Center Panel -->
|
||||
<div class="panel center-panel">
|
||||
<div class="info-bar">
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
@ -122,94 +176,108 @@ if ($user_id) {
|
||||
<div id="tv_chart_container" style="height: 100%;"></div>
|
||||
</div>
|
||||
|
||||
<div class="order-form-panel">
|
||||
<div class="margin-controls">
|
||||
<button class="ctrl-btn active" id="margin-isolated" onclick="setMargin('isolated')">逐仓</button>
|
||||
<button class="ctrl-btn" id="margin-cross" onclick="setMargin('cross')">全仓</button>
|
||||
<button class="ctrl-btn" onclick="showLevModal()"><span id="leverage-val">20</span>x</button>
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn active" onclick="setOrderType('limit')">限价</button>
|
||||
<button class="order-type-btn" onclick="setOrderType('market')">市价</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="order-form-grid">
|
||||
<div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">合约开仓</span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="available-bal" style="color: white;"><?php echo number_format($balance, 2); ?></span> USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="order-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" value="市场最优价" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="order-amount" placeholder="0" step="1">
|
||||
<span class="input-unit">张</span>
|
||||
<!-- Scrollable content below chart -->
|
||||
<div class="center-content-scroll">
|
||||
<div class="order-form-panel">
|
||||
<div class="margin-controls">
|
||||
<button class="ctrl-btn active" id="margin-isolated" onclick="setMargin('isolated')">逐仓</button>
|
||||
<button class="ctrl-btn" id="margin-cross" onclick="setMargin('cross')">全仓</button>
|
||||
<button class="ctrl-btn" onclick="showLevModal()"><span id="leverage-val">20</span>x</button>
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn active" id="order-type-limit" onclick="setOrderType('limit')">限价</button>
|
||||
<button class="order-type-btn" id="order-type-market" onclick="setOrderType('market')">市价</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="slider-container" style="margin-top: 25px;">
|
||||
<input type="range" min="0" max="100" value="0" id="order-slider" oninput="updateFromSlider(this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider(0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(100)"></div>
|
||||
|
||||
<div class="order-form-grid">
|
||||
<div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">合约开仓</span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="available-bal" style="color: white;"><?php echo number_format($balance, 2); ?></span> USDT</span>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider(0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider(25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider(50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider(75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider(100)">100%</div>
|
||||
<div class="input-row" id="price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="order-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" id="market-price-display" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="order-amount" placeholder="0" step="1">
|
||||
<span class="input-unit">张</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<div class="input-row" style="flex: 1;">
|
||||
<span class="input-label" style="width: 40px;">止盈</span>
|
||||
<input type="number" id="tp-price" placeholder="价格">
|
||||
</div>
|
||||
<div class="input-row" style="flex: 1;">
|
||||
<span class="input-label" style="width: 40px;">止损</span>
|
||||
<input type="number" id="sl-price" placeholder="价格">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">所需成本</span>
|
||||
<span><span id="order-cost">0.00</span> USDT</span>
|
||||
<div>
|
||||
<div class="slider-container" style="margin-top: 25px;">
|
||||
<input type="range" min="0" max="100" value="0" id="order-slider" oninput="updateFromSlider(this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider(0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider(100)"></div>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider(0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider(25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider(50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider(75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider(100)">100%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">所需成本</span>
|
||||
<span><span id="order-cost">0.00</span> USDT</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="trade-btns">
|
||||
<button class="btn-trade buy" onclick="placeOrder('buy')">买入/开多</button>
|
||||
<button class="btn-trade sell" onclick="placeOrder('sell')">卖出/开空</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="trade-btns">
|
||||
<button class="btn-trade buy" onclick="placeOrder('buy')">买入/开多</button>
|
||||
<button class="btn-trade sell" onclick="placeOrder('sell')">卖出/开空</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tabs-section">
|
||||
<div class="tabs-header">
|
||||
<button class="tab-btn active" id="tab-positions" onclick="switchTab(this, 'positions')">当前持仓</button>
|
||||
<button class="tab-btn" id="tab-orders" onclick="switchTab(this, 'open')">当前委托</button>
|
||||
<button class="tab-btn" id="tab-history" onclick="switchTab(this, 'history')">历史委托</button>
|
||||
</div>
|
||||
<div id="tab-content" style="padding: 0; min-height: 250px;">
|
||||
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||
<thead id="data-thead" style="color: var(--text-secondary); text-align: left; background: rgba(0,0,0,0.1);">
|
||||
</thead>
|
||||
<tbody id="data-tbody"></tbody>
|
||||
</table>
|
||||
<div class="tabs-section">
|
||||
<div class="tabs-header">
|
||||
<button class="tab-btn active" id="tab-positions" onclick="switchTab(this, 'positions')">当前持仓</button>
|
||||
<button class="tab-btn" id="tab-orders" onclick="switchTab(this, 'open')">当前委托</button>
|
||||
<button class="tab-btn" id="tab-history" onclick="switchTab(this, 'history')">历史委托</button>
|
||||
</div>
|
||||
<div id="tab-content" style="padding: 0; min-height: 250px;">
|
||||
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||
<thead id="data-thead" style="color: var(--text-secondary); text-align: left; background: rgba(0,0,0,0.1);">
|
||||
</thead>
|
||||
<tbody id="data-tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div class="panel order-book-panel">
|
||||
<div class="ob-header"><span>价格(USDT)</span><span>数量(张)</span></div>
|
||||
<div id="asks-list" style="display: flex; flex-direction: column-reverse; flex: 1; overflow: hidden;"></div>
|
||||
<div id="asks-list" style="display: flex; flex-direction: column-reverse;"></div>
|
||||
<div id="mid-price-area" style="padding: 10px 15px; border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); text-align: center;">
|
||||
<div id="ob-mid-price" style="font-size: 16px; font-weight: bold;">--</div>
|
||||
<div style="font-size: 11px; color: var(--text-secondary);">指数价格 <span id="ob-index-price">--</span></div>
|
||||
</div>
|
||||
<div id="bids-list" style="flex: 1; overflow: hidden;"></div>
|
||||
<div id="bids-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -232,7 +300,7 @@ if ($user_id) {
|
||||
let leverage = 20;
|
||||
let usdtBalance = <?php echo $balance; ?>;
|
||||
let marketData = {};
|
||||
let orderType = 'limit';
|
||||
let orderType = 'market';
|
||||
let activeTab = 'positions';
|
||||
const faceValue = 10;
|
||||
|
||||
@ -277,6 +345,9 @@ if ($user_id) {
|
||||
document.getElementById('vol-24h').innerText = parseFloat(data.q).toLocaleString();
|
||||
document.getElementById('ob-mid-price').innerText = currentPrice.toLocaleString();
|
||||
document.getElementById('ob-index-price').innerText = (currentPrice * 0.9998).toFixed(2);
|
||||
|
||||
document.getElementById('market-price-display').value = currentPrice.toFixed(2);
|
||||
|
||||
updateOrderBook();
|
||||
|
||||
const op = document.getElementById('order-price');
|
||||
@ -284,10 +355,13 @@ if ($user_id) {
|
||||
op.value = currentPrice;
|
||||
op.setAttribute('data-auto', 'true');
|
||||
}
|
||||
|
||||
if (orderType === 'market') updateFromSlider(document.getElementById('order-slider').value);
|
||||
}
|
||||
|
||||
function renderPairs() {
|
||||
const list = document.getElementById('pairs-list');
|
||||
if (!list) return;
|
||||
const search = document.getElementById('market-search').value.toUpperCase();
|
||||
let html = '';
|
||||
pairs.forEach(p => {
|
||||
@ -328,6 +402,8 @@ if ($user_id) {
|
||||
document.getElementById('order-amount').value = '';
|
||||
document.getElementById('order-slider').value = 0;
|
||||
document.getElementById('order-cost').innerText = '0.00';
|
||||
document.getElementById('tp-price').value = '';
|
||||
document.getElementById('sl-price').value = '';
|
||||
updateSliderMarks(0);
|
||||
initChart(p);
|
||||
renderPairs();
|
||||
@ -335,7 +411,8 @@ if ($user_id) {
|
||||
|
||||
function setOrderType(type) {
|
||||
orderType = type;
|
||||
document.querySelectorAll('.order-type-btn').forEach(btn => btn.classList.toggle('active', btn.innerText.includes(type === 'limit' ? '限价' : '市价')));
|
||||
document.getElementById('order-type-limit').classList.toggle('active', type === 'limit');
|
||||
document.getElementById('order-type-market').classList.toggle('active', type === 'market');
|
||||
document.getElementById('price-row').style.display = type === 'limit' ? 'flex' : 'none';
|
||||
document.getElementById('market-price-row').style.display = type === 'market' ? 'flex' : 'none';
|
||||
updateFromSlider(document.getElementById('order-slider').value);
|
||||
@ -344,6 +421,7 @@ if ($user_id) {
|
||||
function updateOrderBook() {
|
||||
const asks = document.getElementById('asks-list');
|
||||
const bids = document.getElementById('bids-list');
|
||||
if (!asks || !bids) return;
|
||||
let asksHtml = ''; let bidsHtml = '';
|
||||
const step = currentPrice * 0.0001;
|
||||
for(let i=0; i<15; i++) {
|
||||
@ -409,12 +487,16 @@ if ($user_id) {
|
||||
const amount = parseFloat(document.getElementById('order-amount').value);
|
||||
if (!amount) return alert('请输入数量');
|
||||
const price = orderType === 'limit' ? parseFloat(document.getElementById('order-price').value || currentPrice) : currentPrice;
|
||||
const tp = document.getElementById('tp-price').value;
|
||||
const sl = document.getElementById('sl-price').value;
|
||||
|
||||
const response = await fetch('api/place_order.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
symbol: currentPair, type: 'futures', side: side,
|
||||
order_type: orderType, price: price, amount: amount, leverage: leverage, total: amount * faceValue
|
||||
order_type: orderType, price: price, amount: amount, leverage: leverage, total: amount * faceValue,
|
||||
tp_price: tp, sl_price: sl
|
||||
})
|
||||
});
|
||||
const res = await response.json();
|
||||
@ -427,7 +509,7 @@ if ($user_id) {
|
||||
if (res.success) {
|
||||
const usdt = res.data.find(a => a.symbol === 'USDT');
|
||||
if (usdt) {
|
||||
usdtBalance = usdt.amount;
|
||||
usdtBalance = parseFloat(usdt.amount);
|
||||
document.getElementById('available-bal').innerText = usdtBalance.toFixed(2);
|
||||
}
|
||||
}
|
||||
@ -438,9 +520,10 @@ if ($user_id) {
|
||||
const res = await response.json();
|
||||
const tbody = document.getElementById('data-tbody');
|
||||
const thead = document.getElementById('data-thead');
|
||||
if (!tbody || !thead) return;
|
||||
|
||||
if (activeTab === 'positions') {
|
||||
thead.innerHTML = `<tr><th style="padding: 12px;">合约</th><th style="padding: 12px;">仓位</th><th style="padding: 12px;">开仓价</th><th style="padding: 12px;">当前价</th><th style="padding: 12px;">强平价</th><th style="padding: 12px;">未实现盈亏</th><th style="padding: 12px; text-align: right;">操作</th></tr>`;
|
||||
thead.innerHTML = `<tr><th style="padding: 12px;">合约</th><th style="padding: 12px;">仓位</th><th style="padding: 12px;">开仓价</th><th style="padding: 12px;">当前价</th><th style="padding: 12px;">盈亏</th><th style="padding: 12px; text-align: right;">操作</th></tr>`;
|
||||
} else {
|
||||
thead.innerHTML = `<tr><th style="padding: 12px;">时间</th><th style="padding: 12px;">合约</th><th style="padding: 12px;">方向</th><th style="padding: 12px;">委托价</th><th style="padding: 12px;">数量(张)</th><th style="padding: 12px;">状态</th><th style="padding: 12px; text-align: right;">操作</th></tr>`;
|
||||
}
|
||||
@ -459,10 +542,9 @@ if ($user_id) {
|
||||
html += `
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 12px;"><div style="font-weight: bold;">${o.symbol}</div><div style="font-size: 10px; color: var(--text-secondary);">永续</div></td>
|
||||
<td style="padding: 12px;"><span style="color: color;">${o.side === 'buy' ? '做多' : '做空'} ${o.leverage}x</span><br>${o.amount} 张</td>
|
||||
<td style="padding: 12px;"><span style="color: ${color};">${o.side === 'buy' ? '做多' : '做空'} ${o.leverage}x</span><br>${o.amount} 张</td>
|
||||
<td style="padding: 12px;">${parseFloat(o.price).toLocaleString()}</td>
|
||||
<td style="padding: 12px;">${price.toLocaleString()}</td>
|
||||
<td style="padding: 12px;">${(o.side === 'buy' ? o.price * (1 - 0.9/o.leverage) : o.price * (1 + 0.9/o.leverage)).toFixed(2)}</td>
|
||||
<td style="padding: 12px; color: ${pnl >= 0 ? 'var(--up-color)' : 'var(--down-color)'}">${(pnl >= 0 ? '+' : '') + pnl.toFixed(2)} USDT</td>
|
||||
<td style="padding: 12px; text-align: right;">
|
||||
<button onclick="closePosition(${o.id})" style="background: none; border: 1px solid var(--text-secondary); color: white; padding: 4px 10px; border-radius: 4px; cursor: pointer; font-size: 12px;">平仓</button>
|
||||
@ -514,4 +596,4 @@ if ($user_id) {
|
||||
setInterval(() => { if (activeTab === 'positions') fetchOrders(); }, 3000);
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
<?php include 'footer.php'; ?>
|
||||
131
profile.php
131
profile.php
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
session_start();
|
||||
include 'header.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
@ -22,6 +23,13 @@ $kyc_labels = [
|
||||
$kyc_colors = [0 => '#888', 1 => '#f0b90b', 2 => 'var(--success-color)', 3 => 'var(--danger-color)'];
|
||||
?>
|
||||
|
||||
<style>
|
||||
.profile-tabs { display: flex; gap: 30px; border-bottom: 1px solid var(--border-color); margin-bottom: 30px; }
|
||||
.profile-tab-btn { background: none; border: none; color: var(--text-muted); padding: 10px 0; font-size: 1.1rem; font-weight: 600; cursor: pointer; border-bottom: 2px solid transparent; }
|
||||
.profile-tab-btn.active { color: white; border-bottom-color: var(--primary-color); }
|
||||
.record-item { padding: 15px; background: rgba(255,255,255,0.02); border-radius: 12px; border: 1px solid var(--border-color); margin-bottom: 10px; }
|
||||
</style>
|
||||
|
||||
<main style="padding: 40px 20px; background: #0b0e11; min-height: 100vh;">
|
||||
<div style="max-width: 1200px; margin: 0 auto;">
|
||||
|
||||
@ -92,21 +100,41 @@ $kyc_colors = [0 => '#888', 1 => '#f0b90b', 2 => 'var(--success-color)', 3 => 'v
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 50px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px;">
|
||||
<h3 style="margin: 0; font-size: 1.5rem; color: white;"><?php echo __('asset_details', '资产详情'); ?></h3>
|
||||
<a href="#" style="color: var(--primary-color); text-decoration: none; font-size: 14px;"><?php echo __('transaction_records', '账单明细'); ?> <i class="fas fa-history" style="margin-left: 5px;"></i></a>
|
||||
</div>
|
||||
|
||||
<div class="profile-tabs">
|
||||
<button class="profile-tab-btn active" onclick="switchProfileTab(this, 'assets-tab')"><?php echo __('asset_details', '资产详情'); ?></button>
|
||||
<button class="profile-tab-btn" onclick="switchProfileTab(this, 'records-tab')"><?php echo __('transaction_records', '交易记录'); ?></button>
|
||||
</div>
|
||||
|
||||
<!-- Assets Tab -->
|
||||
<div id="assets-tab" class="tab-content">
|
||||
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||
<?php
|
||||
$coins = [
|
||||
['symbol' => 'USDT', 'name' => 'Tether', 'balance' => $user['balance'] ?? 0, 'price' => 1.00],
|
||||
['symbol' => 'BTC', 'name' => 'Bitcoin', 'balance' => 0.0000, 'price' => 65432.10],
|
||||
['symbol' => 'ETH', 'name' => 'Ethereum', 'balance' => 0.0000, 'price' => 3456.78],
|
||||
['symbol' => 'BNB', 'name' => 'Binance Coin', 'balance' => 0.0000, 'price' => 589.20],
|
||||
['symbol' => 'SOL', 'name' => 'Solana', 'balance' => 0.0000, 'price' => 145.60],
|
||||
['symbol' => 'BTC', 'name' => 'Bitcoin', 'balance' => 0.0000, 'price' => 0],
|
||||
['symbol' => 'ETH', 'name' => 'Ethereum', 'balance' => 0.0000, 'price' => 0],
|
||||
['symbol' => 'SOL', 'name' => 'Solana', 'balance' => 0.0000, 'price' => 0],
|
||||
['symbol' => 'BNB', 'name' => 'Binance Coin', 'balance' => 0.0000, 'price' => 0],
|
||||
];
|
||||
// Fetch real user assets if table exists
|
||||
try {
|
||||
$asset_stmt = $db->prepare("SELECT * FROM user_assets WHERE user_id = ?");
|
||||
$asset_stmt->execute([$_SESSION['user_id']]);
|
||||
$db_assets = $asset_stmt->fetchAll();
|
||||
foreach ($db_assets as $da) {
|
||||
$found = false;
|
||||
foreach ($coins as &$c) {
|
||||
if ($c['symbol'] === $da['symbol']) {
|
||||
$c['balance'] = $da['amount'];
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
$coins[] = ['symbol' => $da['symbol'], 'name' => '', 'balance' => $da['amount'], 'price' => 0];
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {}
|
||||
|
||||
foreach ($coins as $coin):
|
||||
?>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; padding: 20px; background: rgba(255,255,255,0.02); border-radius: 16px; border: 1px solid transparent; transition: 0.2s;" onmouseover="this.style.borderColor='var(--border-color)'; this.style.background='rgba(255,255,255,0.04)'" onmouseout="this.style.borderColor='transparent'; this.style.background='rgba(255,255,255,0.02)'">
|
||||
@ -118,16 +146,93 @@ $kyc_colors = [0 => '#888', 1 => '#f0b90b', 2 => 'var(--success-color)', 3 => 'v
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-weight: bold; font-family: monospace; font-size: 1.1rem; color: white;"><?php echo number_format($coin['balance'], $coin['symbol'] === 'USDT' ? 2 : 4); ?></div>
|
||||
<div style="font-size: 0.8rem; color: var(--text-muted);">$ <?php echo number_format($coin['balance'] * $coin['price'], 2); ?></div>
|
||||
<div style="font-weight: bold; font-family: monospace; font-size: 1.1rem; color: white;"><?php echo number_format($coin['balance'], $coin['symbol'] === 'USDT' ? 2 : 6); ?></div>
|
||||
<div style="font-size: 0.8rem; color: var(--text-muted);">USDT</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Records Tab -->
|
||||
<div id="records-tab" class="tab-content" style="display: none;">
|
||||
<div id="records-list">
|
||||
<div style="text-align: center; padding: 40px; color: var(--text-muted);">加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
<script>
|
||||
function switchProfileTab(btn, tabId) {
|
||||
document.querySelectorAll('.profile-tab-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
document.querySelectorAll('.tab-content').forEach(c => c.style.display = 'none');
|
||||
document.getElementById(tabId).style.display = 'block';
|
||||
if (tabId === 'records-tab') {
|
||||
loadTransactionRecords();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTransactionRecords() {
|
||||
const container = document.getElementById('records-list');
|
||||
try {
|
||||
const [spotResp, futuresResp] = await Promise.all([
|
||||
fetch('api/get_orders.php?type=spot&status=history'),
|
||||
fetch('api/get_orders.php?type=futures&status=history')
|
||||
]);
|
||||
const spotRes = await spotResp.json();
|
||||
const futuresRes = await futuresResp.json();
|
||||
|
||||
let allRecords = [];
|
||||
if (spotRes.success) {
|
||||
spotRes.data.forEach(r => { r.trade_type = '现货'; allRecords.push(r); });
|
||||
}
|
||||
if (futuresRes.success) {
|
||||
futuresRes.data.forEach(r => { r.trade_type = '合约'; allRecords.push(r); });
|
||||
}
|
||||
|
||||
allRecords.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
||||
|
||||
if (allRecords.length === 0) {
|
||||
container.innerHTML = '<div style="text-align: center; padding: 40px; color: var(--text-muted);">暂无交易记录</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '';
|
||||
allRecords.forEach(r => {
|
||||
const isProfit = parseFloat(r.profit) > 0;
|
||||
const profitText = r.profit ? (isProfit ? '+' : '') + parseFloat(r.profit).toFixed(2) : '0.00';
|
||||
const profitColor = isProfit ? 'var(--success-color)' : (parseFloat(r.profit) < 0 ? 'var(--danger-color)' : 'var(--text-muted)');
|
||||
|
||||
html += `
|
||||
<div class="record-item">
|
||||
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
||||
<span style="font-weight: bold; color: white;">${r.symbol} <span style="font-size: 11px; background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 4px; margin-left: 5px;">${r.trade_type}</span></span>
|
||||
<span style="color: var(--text-muted); font-size: 12px;">${r.created_at}</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="font-size: 13px;">
|
||||
<span style="color: ${r.side === 'buy' ? 'var(--success-color)' : 'var(--danger-color)'}">${r.side === 'buy' ? '买入' : '卖出'}</span>
|
||||
<span style="color: var(--text-muted); margin-left: 10px;">价格: ${parseFloat(r.price).toLocaleString()}</span>
|
||||
<span style="color: var(--text-muted); margin-left: 10px;">数量: ${parseFloat(r.amount).toFixed(4)}</span>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-size: 11px; color: var(--text-muted);">盈亏</div>
|
||||
<div style="font-weight: bold; color: ${profitColor};">${profitText} USDT</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
container.innerHTML = html;
|
||||
} catch (e) {
|
||||
container.innerHTML = '<div style="text-align: center; padding: 40px; color: var(--danger-color);">加载失败</div>';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
335
spot.php
335
spot.php
@ -14,6 +14,7 @@ if ($user_id) {
|
||||
?>
|
||||
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
:root {
|
||||
--bg-color: #0b0e11;
|
||||
--panel-bg: #161a1e;
|
||||
@ -31,39 +32,55 @@ if ($user_id) {
|
||||
color: var(--text-primary);
|
||||
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
overflow: hidden; /* Prevent whole page scroll */
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.trading-layout {
|
||||
display: flex;
|
||||
height: calc(100vh - 60px);
|
||||
height: calc(100vh - 64px); /* Fixed height excluding navbar */
|
||||
gap: 1px;
|
||||
background: var(--border-color);
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background: var(--panel-bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
height: 100%; /* Fill the layout height */
|
||||
}
|
||||
|
||||
/* Left: Markets */
|
||||
.market-panel { width: 280px; flex-shrink: 0; }
|
||||
.search-box { padding: 12px; border-bottom: 1px solid var(--border-color); }
|
||||
.search-input-wrapper { position: relative; }
|
||||
.search-input-wrapper input { width: 100%; background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 6px 12px 6px 32px; border-radius: 4px; font-size: 13px; outline: none; }
|
||||
.search-input-wrapper i { position: absolute; left: 10px; top: 8px; color: var(--text-secondary); }
|
||||
.pairs-list-header { display: flex; padding: 8px 12px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); }
|
||||
/* Left: Markets - Scrollable */
|
||||
.market-panel {
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.search-box { padding: 12px; border-bottom: 1px solid var(--border-color); width: 100%; position: sticky; top: 0; background: var(--panel-bg); z-index: 5; }
|
||||
.search-input-wrapper { position: relative; width: 100%; }
|
||||
.search-input-wrapper input { width: 100%; background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 6px 12px 6px 32px; border-radius: 4px; font-size: 13px; outline: none; display: block; }
|
||||
.search-input-wrapper i { position: absolute; left: 10px; top: 9px; color: var(--text-secondary); }
|
||||
.pairs-list-header { display: flex; padding: 8px 12px; font-size: 11px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); position: sticky; top: 57px; background: var(--panel-bg); z-index: 5; }
|
||||
.pair-item { display: flex; justify-content: space-between; padding: 8px 12px; cursor: pointer; transition: background 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
|
||||
.pair-item:hover { background: rgba(255,255,255,0.05); }
|
||||
.pair-item.active { background: rgba(240, 185, 11, 0.1); }
|
||||
|
||||
/* Center: Chart, Form, Tabs */
|
||||
.center-panel { flex: 1; overflow-y: auto; }
|
||||
.info-bar { height: 50px; display: flex; align-items: center; padding: 0 15px; gap: 20px; border-bottom: 1px solid var(--border-color); }
|
||||
.chart-container { height: 450px; background: var(--bg-color); }
|
||||
/* Center: Chart (Fixed) and scrollable content below */
|
||||
.center-panel {
|
||||
flex: 1;
|
||||
overflow: hidden; /* Internal scroll only */
|
||||
}
|
||||
.info-bar { height: 50px; display: flex; align-items: center; padding: 0 15px; gap: 20px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; background: var(--panel-bg); }
|
||||
.chart-container { height: 350px; background: var(--bg-color); flex-shrink: 0; border-bottom: 1px solid var(--border-color); }
|
||||
|
||||
/* Scrollable content below chart */
|
||||
.center-content-scroll {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.order-placement-panel { display: flex; gap: 20px; padding: 20px; border-bottom: 1px solid var(--border-color); background: var(--panel-bg); }
|
||||
.order-side-column { flex: 1; }
|
||||
.order-type-tabs { display: flex; gap: 15px; margin-bottom: 15px; }
|
||||
@ -88,14 +105,18 @@ if ($user_id) {
|
||||
.execute-btn.buy { background: var(--up-color); }
|
||||
.execute-btn.sell { background: var(--down-color); }
|
||||
|
||||
.bottom-tabs { flex: 1; }
|
||||
.tabs-header { display: flex; border-bottom: 1px solid var(--border-color); padding: 0 15px; }
|
||||
.bottom-tabs { min-height: 400px; }
|
||||
.tabs-header { display: flex; border-bottom: 1px solid var(--border-color); padding: 0 15px; position: sticky; top: 0; background: var(--panel-bg); z-index: 9; }
|
||||
.tab-btn { background: none; border: none; color: var(--text-secondary); padding: 12px 15px; font-size: 14px; cursor: pointer; border-bottom: 2px solid transparent; }
|
||||
.tab-btn.active { color: var(--accent-color); border-bottom-color: var(--accent-color); }
|
||||
|
||||
/* Right: Order Book */
|
||||
.order-book-panel { width: 300px; flex-shrink: 0; }
|
||||
.order-book-header { padding: 10px 15px; font-size: 12px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; }
|
||||
/* Right: Order Book - Scrollable */
|
||||
.order-book-panel {
|
||||
width: 300px;
|
||||
flex-shrink: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.order-book-header { padding: 10px 15px; font-size: 12px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; position: sticky; top: 0; background: var(--panel-bg); z-index: 5; }
|
||||
.ob-row { display: flex; justify-content: space-between; padding: 3px 15px; font-size: 12px; position: relative; }
|
||||
.ob-bar { position: absolute; right: 0; top: 0; bottom: 0; z-index: 0; }
|
||||
.ob-val { z-index: 1; position: relative; }
|
||||
@ -107,9 +128,12 @@ if ($user_id) {
|
||||
|
||||
::-webkit-scrollbar { width: 4px; }
|
||||
::-webkit-scrollbar-thumb { background: #333; border-radius: 10px; }
|
||||
|
||||
#pairs-list { }
|
||||
</style>
|
||||
|
||||
<div class="trading-layout">
|
||||
<!-- Left Panel -->
|
||||
<div class="panel market-panel">
|
||||
<div class="search-box">
|
||||
<div class="search-input-wrapper">
|
||||
@ -122,9 +146,10 @@ if ($user_id) {
|
||||
<span style="flex: 1; text-align: right;">价格</span>
|
||||
<span style="flex: 1; text-align: right;">涨跌</span>
|
||||
</div>
|
||||
<div id="pairs-list" style="flex: 1; overflow-y: auto;"></div>
|
||||
<div id="pairs-list"></div>
|
||||
</div>
|
||||
|
||||
<!-- Center Panel -->
|
||||
<div class="panel center-panel">
|
||||
<div class="info-bar">
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
@ -144,143 +169,147 @@ if ($user_id) {
|
||||
<div id="tv_chart_container" style="height: 100%;"></div>
|
||||
</div>
|
||||
|
||||
<div class="order-placement-panel">
|
||||
<div class="order-side-column" id="buy-column">
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn active" onclick="setOrderType('buy', 'limit')">限价委托</button>
|
||||
<button class="order-type-btn" onclick="setOrderType('buy', 'market')">市价委托</button>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">买入 <span class="asset-name">BTC</span></span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="buy-available" style="color: white;">--</span> USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="buy-price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="buy-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="buy-market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" value="以市场最优价格成交" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="buy-amount" placeholder="0.00" step="0.0001">
|
||||
<span class="input-unit asset-name">BTC</span>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input type="range" min="0" max="100" value="0" id="buy-slider" oninput="updateFromSlider('buy', this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider('buy', 0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 100)"></div>
|
||||
<!-- Scrollable content below chart -->
|
||||
<div class="center-content-scroll">
|
||||
<div class="order-placement-panel">
|
||||
<div class="order-side-column" id="buy-column">
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn" id="buy-limit-btn" onclick="setOrderType('buy', 'limit')">限价买入</button>
|
||||
<button class="order-type-btn active" id="buy-market-btn" onclick="setOrderType('buy', 'market')">市价买入</button>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider('buy', 0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 100)">100%</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">买入 <span class="asset-name">BTC</span></span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="buy-available" style="color: white;">--</span> USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="buy-price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="buy-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="buy-market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" id="buy-market-price-display" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="buy-amount" placeholder="0.00" step="0.0001">
|
||||
<span class="input-unit asset-name">BTC</span>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input type="range" min="0" max="100" value="0" id="buy-slider" oninput="updateFromSlider('buy', this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider('buy', 0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('buy', 100)"></div>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider('buy', 0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider('buy', 100)">100%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">交易额</span>
|
||||
<span><span id="buy-total">0.00</span> USDT</span>
|
||||
</div>
|
||||
<button class="execute-btn buy" onclick="placeOrder('buy')">买入 BTC</button>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">交易额</span>
|
||||
<span><span id="buy-total">0.00</span> USDT</span>
|
||||
|
||||
<div class="order-side-column" id="sell-column">
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn active" id="sell-limit-btn" onclick="setOrderType('sell', 'limit')">限价卖出</button>
|
||||
<button class="order-type-btn" id="sell-market-btn" onclick="setOrderType('sell', 'market')">市价卖出</button>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">卖出 <span class="asset-name">BTC</span></span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="sell-available" style="color: white;">--</span> <span class="asset-name">BTC</span></span>
|
||||
</div>
|
||||
<div class="input-row" id="sell-price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="sell-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="sell-market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" id="sell-market-price-display" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="sell-amount" placeholder="0.00" step="0.0001">
|
||||
<span class="input-unit asset-name">BTC</span>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input type="range" min="0" max="100" value="0" id="sell-slider" oninput="updateFromSlider('sell', this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider('sell', 0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 100)"></div>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider('sell', 0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 100)">100%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">成交总计</span>
|
||||
<span><span id="sell-total">0.00</span> USDT</span>
|
||||
</div>
|
||||
<button class="execute-btn sell" onclick="placeOrder('sell')">卖出 BTC</button>
|
||||
</div>
|
||||
<button class="execute-btn buy" onclick="placeOrder('buy')">买入 BTC</button>
|
||||
</div>
|
||||
|
||||
<div class="order-side-column" id="sell-column">
|
||||
<div class="order-type-tabs">
|
||||
<button class="order-type-btn active" onclick="setOrderType('sell', 'limit')">限价委托</button>
|
||||
<button class="order-type-btn" onclick="setOrderType('sell', 'market')">市价委托</button>
|
||||
<div class="bottom-tabs">
|
||||
<div class="tabs-header">
|
||||
<button class="tab-btn active" id="tab-open" onclick="switchTab(this, 'open')">当前委托</button>
|
||||
<button class="tab-btn" id="tab-history" onclick="switchTab(this, 'history')">历史委托</button>
|
||||
<button class="tab-btn" id="tab-assets" onclick="switchTab(this, 'assets')">资产余额</button>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 8px;">
|
||||
<span style="color: var(--text-secondary);">卖出 <span class="asset-name">BTC</span></span>
|
||||
<span style="color: var(--text-secondary);">可用: <span id="sell-available" style="color: white;">--</span> <span class="asset-name">BTC</span></span>
|
||||
<div id="tab-content-area" style="padding: 15px;">
|
||||
<table id="orders-table" style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||
<thead style="color: var(--text-secondary); text-align: left;">
|
||||
<tr id="table-header">
|
||||
<th style="padding: 8px;">时间</th>
|
||||
<th style="padding: 8px;">币对</th>
|
||||
<th style="padding: 8px;">类型</th>
|
||||
<th style="padding: 8px;">方向</th>
|
||||
<th style="padding: 8px;">价格</th>
|
||||
<th style="padding: 8px;">数量</th>
|
||||
<th style="padding: 8px;">状态</th>
|
||||
<th style="padding: 8px; text-align: right;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="orders-tbody">
|
||||
<tr><td colspan="8" style="text-align: center; padding: 40px; color: var(--text-secondary);">暂无记录</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="input-row" id="sell-price-row">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="number" id="sell-price" placeholder="0.00" step="0.01">
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row" id="sell-market-price-row" style="display: none;">
|
||||
<span class="input-label">价格</span>
|
||||
<input type="text" value="以市场最优价格成交" disabled>
|
||||
<span class="input-unit">USDT</span>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<span class="input-label">数量</span>
|
||||
<input type="number" id="sell-amount" placeholder="0.00" step="0.0001">
|
||||
<span class="input-unit asset-name">BTC</span>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input type="range" min="0" max="100" value="0" id="sell-slider" oninput="updateFromSlider('sell', this.value)">
|
||||
<div class="slider-marks">
|
||||
<div class="mark-dot" onclick="setSlider('sell', 0)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 25)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 50)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 75)"></div>
|
||||
<div class="mark-dot" onclick="setSlider('sell', 100)"></div>
|
||||
</div>
|
||||
<div class="slider-labels">
|
||||
<div class="label-item" onclick="setSlider('sell', 0)">0%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 25)">25%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 50)">50%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 75)">75%</div>
|
||||
<div class="label-item" onclick="setSlider('sell', 100)">100%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px; font-size: 13px; display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--text-secondary);">交易额</span>
|
||||
<span><span id="sell-total">0.00</span> USDT</span>
|
||||
</div>
|
||||
<button class="execute-btn sell" onclick="placeOrder('sell')">卖出 BTC</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bottom-tabs">
|
||||
<div class="tabs-header">
|
||||
<button class="tab-btn active" id="tab-open" onclick="switchTab(this, 'open')">当前委托</button>
|
||||
<button class="tab-btn" id="tab-history" onclick="switchTab(this, 'history')">历史委托</button>
|
||||
<button class="tab-btn" id="tab-assets" onclick="switchTab(this, 'assets')">资产余额</button>
|
||||
</div>
|
||||
<div id="tab-content-area" style="padding: 15px;">
|
||||
<table id="orders-table" style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||
<thead style="color: var(--text-secondary); text-align: left;">
|
||||
<tr id="table-header">
|
||||
<th style="padding: 8px;">时间</th>
|
||||
<th style="padding: 8px;">币对</th>
|
||||
<th style="padding: 8px;">类型</th>
|
||||
<th style="padding: 8px;">方向</th>
|
||||
<th style="padding: 8px;">价格</th>
|
||||
<th style="padding: 8px;">数量</th>
|
||||
<th style="padding: 8px;">状态</th>
|
||||
<th style="padding: 8px; text-align: right;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="orders-tbody">
|
||||
<tr><td colspan="8" style="text-align: center; padding: 40px; color: var(--text-secondary);">暂无记录</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div class="panel order-book-panel">
|
||||
<div class="order-book-header">
|
||||
<span>价格(USDT)</span>
|
||||
<span>数量(BTC)</span>
|
||||
</div>
|
||||
<div id="asks-list" style="display: flex; flex-direction: column-reverse; flex: 1; overflow: hidden;"></div>
|
||||
<div id="asks-list" style="display: flex; flex-direction: column-reverse;"></div>
|
||||
<div id="mid-price-container" style="padding: 10px 15px; border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); text-align: center;">
|
||||
<div id="ob-mid-price" style="font-size: 16px; font-weight: bold;">--</div>
|
||||
<div id="ob-index-price" style="font-size: 11px; color: var(--text-secondary);">指数价格 --</div>
|
||||
</div>
|
||||
<div id="bids-list" style="flex: 1; overflow: hidden;"></div>
|
||||
<div id="bids-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -291,7 +320,7 @@ if ($user_id) {
|
||||
let usdtBalance = 0;
|
||||
let userAssets = {};
|
||||
let marketData = {};
|
||||
let orderTypes = { buy: 'limit', sell: 'limit' };
|
||||
let orderTypes = { buy: 'market', sell: 'limit' };
|
||||
let activeTab = 'open';
|
||||
|
||||
const pairs = [
|
||||
@ -336,11 +365,14 @@ if ($user_id) {
|
||||
document.getElementById('high-24h').innerText = parseFloat(data.h).toLocaleString();
|
||||
document.getElementById('low-24h').innerText = parseFloat(data.l).toLocaleString();
|
||||
document.getElementById('vol-24h').innerText = parseFloat(data.v).toLocaleString();
|
||||
|
||||
document.getElementById('buy-market-price-display').value = currentPrice.toFixed(2);
|
||||
document.getElementById('sell-market-price-display').value = currentPrice.toFixed(2);
|
||||
|
||||
updateOrderBook();
|
||||
|
||||
const bp = document.getElementById('buy-price');
|
||||
const sp = document.getElementById('sell-price');
|
||||
// Only set value if empty or if user hasn't typed anything yet (simple heuristic)
|
||||
if (!bp.value || bp.getAttribute('data-auto') === 'true') {
|
||||
bp.value = currentPrice;
|
||||
bp.setAttribute('data-auto', 'true');
|
||||
@ -349,10 +381,14 @@ if ($user_id) {
|
||||
sp.value = currentPrice;
|
||||
sp.setAttribute('data-auto', 'true');
|
||||
}
|
||||
|
||||
if (orderTypes.buy === 'market') updateFromSlider('buy', document.getElementById('buy-slider').value);
|
||||
if (orderTypes.sell === 'market') updateFromSlider('sell', document.getElementById('sell-slider').value);
|
||||
}
|
||||
|
||||
function renderPairs() {
|
||||
const list = document.getElementById('pairs-list');
|
||||
if (!list) return;
|
||||
const search = document.getElementById('market-search').value.toUpperCase();
|
||||
let html = '';
|
||||
pairs.forEach(p => {
|
||||
@ -379,7 +415,7 @@ if ($user_id) {
|
||||
if (res.success) {
|
||||
userAssets = {};
|
||||
res.data.forEach(a => {
|
||||
userAssets[a.symbol] = a.amount;
|
||||
userAssets[a.symbol] = parseFloat(a.amount);
|
||||
});
|
||||
usdtBalance = userAssets['USDT'] || 0;
|
||||
updateAvailableDisplay();
|
||||
@ -412,7 +448,6 @@ if ($user_id) {
|
||||
document.getElementById('sell-price').value = '';
|
||||
}
|
||||
|
||||
// Reset auto flag on switch so it picks up the new price
|
||||
document.getElementById('buy-price').setAttribute('data-auto', 'true');
|
||||
document.getElementById('sell-price').setAttribute('data-auto', 'true');
|
||||
|
||||
@ -431,10 +466,8 @@ if ($user_id) {
|
||||
|
||||
function setOrderType(side, type) {
|
||||
orderTypes[side] = type;
|
||||
const column = document.getElementById(side + '-column');
|
||||
column.querySelectorAll('.order-type-btn').forEach(btn => {
|
||||
btn.classList.toggle('active', btn.innerText.includes(type === 'limit' ? '限价' : '市价'));
|
||||
});
|
||||
document.getElementById(`${side}-limit-btn`).classList.toggle('active', type === 'limit');
|
||||
document.getElementById(`${side}-market-btn`).classList.toggle('active', type === 'market');
|
||||
document.getElementById(`${side}-price-row`).style.display = type === 'limit' ? 'flex' : 'none';
|
||||
document.getElementById(`${side}-market-price-row`).style.display = type === 'market' ? 'flex' : 'none';
|
||||
updateFromSlider(side, document.getElementById(side + '-slider').value);
|
||||
@ -443,6 +476,7 @@ if ($user_id) {
|
||||
function updateOrderBook() {
|
||||
const asks = document.getElementById('asks-list');
|
||||
const bids = document.getElementById('bids-list');
|
||||
if (!asks || !bids) return;
|
||||
let asksHtml = ''; let bidsHtml = '';
|
||||
const step = currentPrice * 0.0002;
|
||||
for(let i=0; i<15; i++) {
|
||||
@ -485,7 +519,11 @@ if ($user_id) {
|
||||
const coin = currentPair.replace('USDT', '');
|
||||
|
||||
const total = price * amount;
|
||||
document.getElementById(side + '-total').innerText = total.toFixed(2);
|
||||
if (isBuy) {
|
||||
document.getElementById('buy-total').innerText = total.toFixed(2);
|
||||
} else {
|
||||
document.getElementById('sell-total').innerText = total.toFixed(2);
|
||||
}
|
||||
|
||||
let percentage = 0;
|
||||
if (isBuy) {
|
||||
@ -533,7 +571,8 @@ if ($user_id) {
|
||||
body: JSON.stringify({
|
||||
symbol: currentPair, type: 'spot', side: side,
|
||||
order_type: type,
|
||||
price: price, amount: amount, total: price * amount
|
||||
price: price, amount: amount, total: price * amount,
|
||||
tp_price: currentPrice
|
||||
})
|
||||
});
|
||||
const res = await response.json();
|
||||
@ -553,6 +592,7 @@ if ($user_id) {
|
||||
const res = await response.json();
|
||||
const tbody = document.getElementById('orders-tbody');
|
||||
const thead = document.getElementById('table-header');
|
||||
if (!tbody || !thead) return;
|
||||
|
||||
thead.innerHTML = `
|
||||
<th style="padding: 8px;">时间</th>
|
||||
@ -598,6 +638,7 @@ if ($user_id) {
|
||||
await fetchAssets();
|
||||
const tbody = document.getElementById('orders-tbody');
|
||||
const thead = document.getElementById('table-header');
|
||||
if (!tbody || !thead) return;
|
||||
|
||||
thead.innerHTML = `
|
||||
<th style="padding: 8px;">资产</th>
|
||||
@ -659,4 +700,4 @@ if ($user_id) {
|
||||
}, 5000);
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
<?php include 'footer.php'; ?>
|
||||
Loading…
x
Reference in New Issue
Block a user