487 lines
30 KiB
PHP
487 lines
30 KiB
PHP
<?php
|
|
session_start();
|
|
include 'header.php';
|
|
require_once 'db/config.php';
|
|
|
|
$user_id = $_SESSION['user_id'] ?? null;
|
|
$balance = 0;
|
|
if ($user_id) {
|
|
$stmt = db()->prepare("SELECT balance FROM users WHERE id = ?");
|
|
$stmt->execute([$user_id]);
|
|
$user = $stmt->fetch();
|
|
$balance = $user['balance'] ?? 0;
|
|
}
|
|
?>
|
|
|
|
<div style="background: #0b0e11; min-height: calc(100vh - 64px); padding: 10px 20px;">
|
|
<div class="futures-trading-layout" style="display: grid; grid-template-columns: 280px 1fr 320px; height: calc(100vh - 84px); background: #161a1e; border-radius: 8px; overflow: hidden; color: #EAECEF; font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; border: 1px solid #1e2329;">
|
|
|
|
<!-- Column 1: Pairs List -->
|
|
<div style="border-right: 1px solid #1e2329; display: flex; flex-direction: column; background: #161a1e;">
|
|
<div style="padding: 12px; border-bottom: 1px solid #1e2329;">
|
|
<div style="position: relative; margin-bottom: 12px;">
|
|
<input type="text" id="pair-search" placeholder="<?php echo __('search_market', '搜索合约币对'); ?>" style="width: 100%; background: #0b0e11; border: 1px solid #2b3139; color: white; padding: 8px 32px 8px 12px; border-radius: 4px; font-size: 13px; outline: none; transition: border-color 0.2s;" onfocus="this.style.borderColor='#4facfe'" onblur="this.style.borderColor='#2b3139'">
|
|
<i class="fas fa-search" style="position: absolute; right: 10px; top: 10px; color: #5e6673; font-size: 14px;"></i>
|
|
</div>
|
|
<div style="display: flex; gap: 15px;">
|
|
<button class="market-tab active" onclick="switchMarket('crypto')"><?php echo __('crypto', '永续合约'); ?></button>
|
|
</div>
|
|
</div>
|
|
<div style="display: flex; padding: 10px 12px; font-size: 11px; color: #848e9c; justify-content: space-between; border-bottom: 1px solid #1e2329;">
|
|
<span style="flex: 1.5;"><?php echo __('pair', '币对'); ?></span>
|
|
<span style="flex: 1; text-align: right;"><?php echo __('price', '价格'); ?></span>
|
|
<span style="flex: 1; text-align: right;"><?php echo __('change', '涨跌'); ?></span>
|
|
</div>
|
|
<div id="pairs-list" style="flex: 1; overflow-y: auto;">
|
|
<!-- JS Filled -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Column 2: K-Line & Orders -->
|
|
<div style="display: flex; flex-direction: column; border-right: 1px solid #1e2329; overflow: hidden; background: #0b0e11;">
|
|
<!-- Top Info Bar -->
|
|
<div style="height: 60px; border-bottom: 1px solid #1e2329; display: flex; align-items: center; padding: 0 20px; gap: 20px; background: #161a1e;">
|
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
<img id="current-icon" src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/btc.png" width="32" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
|
<div style="display: flex; flex-direction: column;">
|
|
<span style="font-weight: bold; font-size: 1.1rem; line-height: 1;" id="current-pair">BTC/USDT 永续</span>
|
|
<span id="leverage-display" onclick="toggleLeverageModal()" style="background: rgba(79, 172, 254, 0.1); color: #4facfe; font-size: 11px; padding: 2px 6px; border-radius: 2px; cursor: pointer; margin-top: 4px; display: inline-block; width: fit-content;">20x</span>
|
|
</div>
|
|
<div style="display: flex; flex-direction: column; margin-left: 10px;">
|
|
<span id="top-price" style="font-weight: bold; color: #00c087; font-size: 1.1rem;">--.---</span>
|
|
<span id="top-change" style="color: #00c087; font-size: 0.85rem;">--%</span>
|
|
</div>
|
|
</div>
|
|
<div style="flex: 1;"></div>
|
|
<div style="display: flex; gap: 20px;">
|
|
<div class="stat-box-small">
|
|
<div style="font-size: 11px; color: #848e9c;">Mark Price</div>
|
|
<div id="top-high" style="color: white; font-size: 13px;">--.---</div>
|
|
</div>
|
|
<div class="stat-box-small">
|
|
<div style="font-size: 11px; color: #848e9c;">Index Price</div>
|
|
<div id="top-low" style="color: white; font-size: 13px;">--.---</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chart Section -->
|
|
<div style="flex: 2; border-bottom: 1px solid #1e2329; position: relative;">
|
|
<div id="tradingview_chart" style="width: 100%; height: 100%;"></div>
|
|
</div>
|
|
|
|
<!-- Orders Section -->
|
|
<div style="flex: 1; display: flex; flex-direction: column; background: #161a1e; overflow: hidden;">
|
|
<div style="display: flex; gap: 25px; padding: 0 20px; border-bottom: 1px solid #1e2329; height: 40px; align-items: center; overflow-x: auto;">
|
|
<button class="order-tab-link active" onclick="switchOrderTab(this, 'positions')"><?php echo __('positions', '当前持仓'); ?></button>
|
|
<button class="order-tab-link" onclick="switchOrderTab(this, 'open')"><?php echo __('open_orders', '当前委托'); ?></button>
|
|
<button class="order-tab-link" onclick="switchOrderTab(this, 'tpsl')"><?php echo __('tpsl', '止盈止损'); ?></button>
|
|
<button class="order-tab-link" onclick="switchOrderTab(this, 'history')"><?php echo __('order_history', '历史委托'); ?></button>
|
|
</div>
|
|
<div style="flex: 1; overflow-y: auto;">
|
|
<table style="width: 100%; font-size: 12px; color: #848e9c; text-align: left; border-collapse: collapse;">
|
|
<thead style="position: sticky; top: 0; background: #161a1e; z-index: 1;">
|
|
<tr style="border-bottom: 1px solid #1e2329;">
|
|
<th style="padding: 10px 15px;"><?php echo __('pair', '币对'); ?></th>
|
|
<th style="padding: 10px 15px;"><?php echo __('side', '方向'); ?></th>
|
|
<th style="padding: 10px 15px;"><?php echo __('price', '价格'); ?></th>
|
|
<th style="padding: 10px 15px;"><?php echo __('amount', '数量'); ?></th>
|
|
<th style="padding: 10px 15px;"><?php echo __('pnl', '盈亏'); ?></th>
|
|
<th style="padding: 10px 15px;"><?php echo __('status', '状态'); ?></th>
|
|
<th style="padding: 10px 15px; text-align: right;"><?php echo __('action', '操作'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="orders-list-body">
|
|
<!-- JS Filled -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Column 3: Order Panel & Book -->
|
|
<div style="display: flex; flex-direction: column; background: #161a1e; overflow: hidden;">
|
|
<!-- Order Panel -->
|
|
<div style="padding: 0; border-bottom: 1px solid #1e2329; background: #161a1e;">
|
|
<div style="display: flex; background: #0b0e11; border-bottom: 1px solid #1e2329; padding: 2px;">
|
|
<button id="btn-isolated" class="margin-tab active" onclick="switchMargin('isolated')"><?php echo __('isolated', '逐仓'); ?></button>
|
|
<button id="btn-cross" class="margin-tab" onclick="switchMargin('cross')"><?php echo __('cross', '全仓'); ?></button>
|
|
<div style="width: 1px; background: #2b3139; margin: 8px 0;"></div>
|
|
<button id="btn-leverage-top" class="margin-tab" onclick="toggleLeverageModal()" style="color: #4facfe;">20x</button>
|
|
</div>
|
|
|
|
<div style="padding: 15px;">
|
|
<div style="display: flex; gap: 15px; margin-bottom: 15px; font-size: 13px;">
|
|
<span id="tab-market" class="type-tab active" onclick="switchTradeType('market')"><?php echo __('market_order', '市价'); ?></span>
|
|
<span id="tab-limit" class="type-tab" onclick="switchTradeType('limit')"><?php echo __('limit_order', '限价'); ?></span>
|
|
</div>
|
|
|
|
<div style="margin-bottom: 12px; font-size: 12px; color: #848e9c; display: flex; justify-content: space-between;">
|
|
<span><?php echo __('available', '可用'); ?></span>
|
|
<span style="color: white;"><span id="display-balance"><?php echo number_format($balance, 2); ?></span> USDT</span>
|
|
</div>
|
|
|
|
<!-- Price Box -->
|
|
<div class="input-group" style="margin-bottom: 12px;">
|
|
<span style="position: absolute; left: 12px; top: 12px; color: #848e9c; font-size: 13px;"><?php echo __('price', '价格'); ?></span>
|
|
<input type="text" id="trade-price-display" value="<?php echo __('market_price', '市价'); ?>" readonly style="width: 100%; background: #2b3139; border: 1px solid #2b3139; color: #848e9c; padding: 12px 12px 12px 60px; border-radius: 4px; outline: none; font-size: 14px; text-align: right;">
|
|
<input type="number" id="trade-price" placeholder="0.00" style="display: none; width: 100%; background: #2b3139; border: 1px solid #2b3139; color: white; padding: 12px 60px 12px 60px; border-radius: 4px; outline: none; font-size: 14px; text-align: right;">
|
|
<span style="position: absolute; right: 12px; top: 12px; color: #848e9c; font-size: 13px;">USDT</span>
|
|
</div>
|
|
|
|
<!-- Quantity Box -->
|
|
<div class="input-group" style="margin-bottom: 15px;">
|
|
<span style="position: absolute; left: 12px; top: 12px; color: #848e9c; font-size: 13px;"><?php echo __('amount', '数量'); ?></span>
|
|
<input type="number" id="trade-amount" placeholder="0.00" style="width: 100%; background: #2b3139; border: 1px solid #2b3139; color: white; padding: 12px 60px 12px 60px; border-radius: 4px; outline: none; font-size: 14px; text-align: right;">
|
|
<span id="amount-unit" style="position: absolute; right: 12px; top: 12px; color: #848e9c; font-size: 13px;">Cont</span>
|
|
</div>
|
|
|
|
<!-- TP/SL Boxes -->
|
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 15px;">
|
|
<div class="input-group">
|
|
<input type="number" id="tp-price" placeholder="止盈 (TP)" style="width: 100%; background: #2b3139; border: 1px solid #2b3139; color: #00c087; padding: 10px; border-radius: 4px; outline: none; font-size: 12px; text-align: center;">
|
|
</div>
|
|
<div class="input-group">
|
|
<input type="number" id="sl-price" placeholder="止损 (SL)" style="width: 100%; background: #2b3139; border: 1px solid #2b3139; color: #f6465d; padding: 10px; border-radius: 4px; outline: none; font-size: 12px; text-align: center;">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Percentage Slider -->
|
|
<div style="margin-bottom: 20px;">
|
|
<div style="position: relative; height: 20px; display: flex; align-items: center;">
|
|
<input type="range" class="custom-slider" min="0" max="100" value="0" id="trade-slider" oninput="updateFromSlider(this.value)">
|
|
<div class="slider-marks">
|
|
<span onclick="setPercent(0)"></span>
|
|
<span onclick="setPercent(25)"></span>
|
|
<span onclick="setPercent(50)"></span>
|
|
<span onclick="setPercent(75)"></span>
|
|
<span onclick="setPercent(100)"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
|
|
<button class="trade-btn buy" onclick="executeOrder('buy')"><?php echo __('buy_long', '买入开多'); ?></button>
|
|
<button class="trade-btn sell" onclick="executeOrder('sell')"><?php echo __('sell_short', '卖出开空'); ?></button>
|
|
</div>
|
|
|
|
<div style="margin-top: 15px; border-top: 1px solid #2b3139; padding-top: 15px; display: flex; justify-content: space-between; font-size: 12px;">
|
|
<span style="color: #848e9c;"><?php echo __('cost', '成本'); ?></span>
|
|
<span style="color: white;"><span id="trade-cost">0.00</span> USDT</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Order Book -->
|
|
<div style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
|
|
<div style="padding: 12px 15px; font-size: 13px; font-weight: bold; border-bottom: 1px solid #1e2329; display: flex; justify-content: space-between;">
|
|
<span><?php echo __('order_book', '订单簿'); ?></span>
|
|
</div>
|
|
<div style="padding: 6px 15px; font-size: 10px; color: #848e9c; display: flex; justify-content: space-between; background: #0b0e11;">
|
|
<span><?php echo __('price', '价格'); ?></span>
|
|
<span><?php echo __('amount', '数量'); ?></span>
|
|
</div>
|
|
<div style="flex: 1; overflow: hidden; display: flex; flex-direction: column;">
|
|
<div id="asks" style="flex: 1; display: flex; flex-direction: column-reverse; overflow: hidden;"></div>
|
|
<div id="mid-price-container" style="padding: 8px; text-align: center; background: rgba(255,255,255,0.02); border-top: 1px solid #1e2329; border-bottom: 1px solid #1e2329;">
|
|
<div id="mid-price" style="font-size: 1.1rem; font-weight: bold; color: #00c087;">--.---</div>
|
|
</div>
|
|
<div id="bids" style="flex: 1; display: flex; flex-direction: column; overflow: hidden;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Leverage Modal -->
|
|
<div id="leverage-modal" style="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: 2000;">
|
|
<div style="background: #161a1e; padding: 30px; border-radius: 16px; width: 400px; border: 1px solid #2b3139;">
|
|
<h3 style="margin-top: 0;">Adjust Leverage</h3>
|
|
<p style="color: #848e9c; font-size: 14px;">Select leverage for current pair.</p>
|
|
<div style="margin: 30px 0;">
|
|
<input type="range" min="1" max="125" value="20" style="width: 100%;" id="lev-slider" oninput="document.getElementById('lev-val').innerText = this.value + 'x'">
|
|
<div style="text-align: center; font-size: 2rem; font-weight: bold; margin-top: 10px;" id="lev-val">20x</div>
|
|
</div>
|
|
<div style="display: flex; gap: 15px;">
|
|
<button onclick="toggleLeverageModal()" style="flex: 1; padding: 12px; background: #2b3139; border: none; color: white; border-radius: 4px; cursor: pointer;">Cancel</button>
|
|
<button onclick="confirmLeverage()" style="flex: 1; padding: 12px; background: #4facfe; border: none; color: white; border-radius: 4px; cursor: pointer;">Confirm</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.market-tab { background: transparent; border: none; color: #848e9c; font-size: 13px; font-weight: bold; padding: 5px 0; cursor: pointer; border-bottom: 2px solid transparent; }
|
|
.market-tab.active { color: #4facfe; border-bottom-color: #4facfe; }
|
|
.stat-box-small { display: flex; flex-direction: column; align-items: flex-end; }
|
|
.order-tab-link { background: transparent; border: none; color: #848e9c; font-size: 13px; font-weight: bold; cursor: pointer; padding: 0; border-bottom: 2px solid transparent; white-space: nowrap; height: 100%; transition: color 0.2s; }
|
|
.order-tab-link.active { color: #4facfe; border-bottom-color: #4facfe; }
|
|
|
|
.margin-tab { flex: 1; padding: 8px; border: none; background: transparent; color: #848e9c; cursor: pointer; font-size: 11px; font-weight: bold; }
|
|
.margin-tab.active { background: #161a1e; color: white; border-radius: 4px; }
|
|
|
|
.type-tab { cursor: pointer; color: #848e9c; padding-bottom: 2px; border-bottom: 2px solid transparent; }
|
|
.type-tab.active { color: #4facfe; border-bottom-color: #4facfe; }
|
|
|
|
.input-group { position: relative; width: 100%; }
|
|
.trade-btn { width: 100%; padding: 12px; border: none; border-radius: 4px; font-weight: bold; cursor: pointer; color: white; font-size: 14px; transition: 0.2s; }
|
|
.trade-btn.buy { background: #00c087; }
|
|
.trade-btn.buy:hover { background: #00d696; }
|
|
.trade-btn.sell { background: #f6465d; }
|
|
.trade-btn.sell:hover { background: #ff526a; }
|
|
|
|
.custom-slider { -webkit-appearance: none; width: 100%; height: 4px; background: #2b3139; border-radius: 2px; outline: none; z-index: 2; position: relative; }
|
|
.custom-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; background: white; border-radius: 50%; cursor: pointer; border: 2px solid #4facfe; }
|
|
|
|
.slider-marks { position: absolute; left: 0; right: 0; top: 0; bottom: 0; display: flex; justify-content: space-between; align-items: center; padding: 0 2px; z-index: 1; pointer-events: none; }
|
|
.slider-marks span { width: 6px; height: 6px; background: #2b3139; border-radius: 50%; border: 1px solid #1e2329; pointer-events: auto; cursor: pointer; }
|
|
.slider-marks span:hover { background: #4facfe; }
|
|
|
|
.order-book-row { display: flex; justify-content: space-between; padding: 2px 15px; font-size: 11px; position: relative; cursor: pointer; }
|
|
.order-book-bg { position: absolute; right: 0; top: 0; bottom: 0; z-index: 0; opacity: 0.1; }
|
|
</style>
|
|
|
|
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
|
|
<script>
|
|
let currentSymbol = 'BTCUSDT';
|
|
let currentPrice = 0;
|
|
let leverage = 20;
|
|
let currentTradeType = 'market';
|
|
let currentOrderTab = 'positions';
|
|
let marketData = {};
|
|
let pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'LINKUSDT', 'LTCUSDT', 'PEPEUSDT', 'SHIBUSDT', 'AVAXUSDT', 'BCHUSDT', 'ARBUSDT', 'OPUSDT', 'NEARUSDT', 'TRXUSDT', 'FETUSDT', 'WIFUSDT'];
|
|
|
|
function initChart(symbol) {
|
|
new TradingView.widget({
|
|
"width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "15", "timezone": "Etc/UTC", "theme": "dark", "style": "1", "locale": "zh_CN", "container_id": "tradingview_chart", "backgroundColor": "#0b0e11", "gridColor": "rgba(42, 46, 57, 0.05)", "hide_side_toolbar": false, "allow_symbol_change": false, "save_image": false
|
|
});
|
|
}
|
|
initChart(currentSymbol);
|
|
|
|
let socket;
|
|
function connectWS() {
|
|
if (socket) socket.close();
|
|
socket = new WebSocket('wss://stream.binance.com:9443/ws/' + pairs.map(p => p.toLowerCase() + '@ticker').join('/'));
|
|
socket.onmessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
const s = data.s;
|
|
marketData[s] = data;
|
|
renderPairsList();
|
|
|
|
if (s === currentSymbol) {
|
|
currentPrice = parseFloat(data.c);
|
|
document.getElementById('top-price').innerText = currentPrice.toLocaleString();
|
|
document.getElementById('top-price').style.color = data.P >= 0 ? '#00c087' : '#f6465d';
|
|
document.getElementById('top-change').innerText = (data.P >= 0 ? '+' : '') + data.P + '%';
|
|
document.getElementById('top-change').style.color = data.P >= 0 ? '#00c087' : '#f6465d';
|
|
document.getElementById('mid-price').innerText = currentPrice.toLocaleString();
|
|
document.getElementById('top-high').innerText = parseFloat(data.c).toLocaleString();
|
|
document.getElementById('top-low').innerText = parseFloat(data.c).toLocaleString();
|
|
updateOrderBook(currentPrice);
|
|
}
|
|
};
|
|
}
|
|
connectWS();
|
|
|
|
function renderPairsList() {
|
|
const list = document.getElementById('pairs-list');
|
|
const searchTerm = document.getElementById('pair-search').value.toUpperCase();
|
|
if (!list) return;
|
|
let html = '';
|
|
pairs.forEach(p => {
|
|
if (searchTerm && !p.includes(searchTerm)) return;
|
|
const d = marketData[p] || {c: 0, P: 0};
|
|
const color = d.P >= 0 ? '#00c087' : '#f6465d';
|
|
const name = p.replace('USDT', '');
|
|
html += `
|
|
<div onclick="changePair('${p}')" style="display: flex; justify-content: space-between; padding: 10px 12px; cursor: pointer; border-bottom: 1px solid #1e2329; ${currentSymbol === p ? 'background: #2b3139;' : ''} transition: background 0.2s;">
|
|
<div style="display: flex; align-items: center; gap: 8px; flex: 1.5;">
|
|
<img src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png" width="20" height="20" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
|
<div>
|
|
<div style="font-weight: bold; font-size: 13px;">${name}/USDT</div>
|
|
<div style="font-size: 10px; color: #848e9c;">永续</div>
|
|
</div>
|
|
</div>
|
|
<span style="font-size: 13px; flex: 1; text-align: right;">${parseFloat(d.c).toLocaleString()}</span>
|
|
<span style="color: ${color}; font-size: 13px; flex: 1; text-align: right;">${d.P >= 0 ? '+' : ''}${d.P}%</span>
|
|
</div>
|
|
`;
|
|
});
|
|
list.innerHTML = html;
|
|
}
|
|
|
|
function changePair(pair) {
|
|
if (!pair.includes('USDT')) pair = pair + 'USDT';
|
|
currentSymbol = pair;
|
|
const name = pair.replace('USDT', '');
|
|
document.getElementById('current-pair').innerText = name + '/USDT 永续';
|
|
document.getElementById('current-icon').src = `https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png`;
|
|
initChart(pair);
|
|
renderPairsList();
|
|
document.getElementById('trade-price').value = '';
|
|
document.getElementById('trade-amount').value = '';
|
|
document.getElementById('trade-slider').value = 0;
|
|
document.getElementById('trade-cost').innerText = '0.00';
|
|
}
|
|
|
|
function updateOrderBook(price) {
|
|
let asksHtml = ''; let bidsHtml = '';
|
|
for(let i=1; i<=10; i++) {
|
|
const askPrice = (price + (i * 0.01 * price / 100)).toFixed(2);
|
|
const bidPrice = (price - (i * 0.01 * price / 100)).toFixed(2);
|
|
asksHtml += `
|
|
<div class="order-book-row">
|
|
<div class="order-book-bg" style="background: #f6465d; width: ${Math.random()*100}%"></div>
|
|
<span style="color: #f6465d; z-index: 1;">${parseFloat(askPrice).toLocaleString()}</span>
|
|
<span style="color: #EAECEF; z-index: 1;">${(Math.random()*2).toFixed(3)}</span>
|
|
</div>`;
|
|
bidsHtml += `
|
|
<div class="order-book-row">
|
|
<div class="order-book-bg" style="background: #00c087; width: ${Math.random()*100}%"></div>
|
|
<span style="color: #00c087; z-index: 1;">${parseFloat(bidPrice).toLocaleString()}</span>
|
|
<span style="color: #EAECEF; z-index: 1;">${(Math.random()*2).toFixed(3)}</span>
|
|
</div>`;
|
|
}
|
|
document.getElementById('asks').innerHTML = asksHtml;
|
|
document.getElementById('bids').innerHTML = bidsHtml;
|
|
}
|
|
|
|
function switchMargin(type) {
|
|
document.getElementById('btn-isolated').classList.toggle('active', type === 'isolated');
|
|
document.getElementById('btn-cross').classList.toggle('active', type === 'cross');
|
|
}
|
|
|
|
function switchTradeType(type) {
|
|
currentTradeType = type;
|
|
document.getElementById('tab-market').classList.toggle('active', type === 'market');
|
|
document.getElementById('tab-limit').classList.toggle('active', type === 'limit');
|
|
|
|
if (type === 'market') {
|
|
document.getElementById('trade-price').style.display = 'none';
|
|
document.getElementById('trade-price-display').style.display = 'block';
|
|
} else {
|
|
document.getElementById('trade-price').style.display = 'block';
|
|
document.getElementById('trade-price-display').style.display = 'none';
|
|
document.getElementById('trade-price').value = currentPrice;
|
|
}
|
|
}
|
|
|
|
function toggleLeverageModal() {
|
|
const m = document.getElementById('leverage-modal');
|
|
m.style.display = m.style.display === 'flex' ? 'none' : 'flex';
|
|
}
|
|
|
|
function confirmLeverage() {
|
|
leverage = document.getElementById('lev-slider').value;
|
|
document.getElementById('btn-leverage-top').innerText = leverage + 'x';
|
|
document.getElementById('leverage-display').innerText = leverage + 'x';
|
|
toggleLeverageModal();
|
|
updateFromSlider(document.getElementById('trade-slider').value);
|
|
}
|
|
|
|
function setPercent(p) {
|
|
document.getElementById('trade-slider').value = p;
|
|
updateFromSlider(p);
|
|
}
|
|
|
|
function updateFromSlider(val) {
|
|
const balance = <?php echo $balance; ?>;
|
|
const price = parseFloat(document.getElementById('trade-price').value) || currentPrice;
|
|
const maxNotional = (balance * leverage * val / 100);
|
|
document.getElementById('trade-amount').value = (maxNotional / price).toFixed(3);
|
|
document.getElementById('trade-cost').innerText = (maxNotional / leverage).toFixed(2);
|
|
}
|
|
|
|
async function executeOrder(side) {
|
|
const price = currentTradeType === 'market' ? currentPrice : parseFloat(document.getElementById('trade-price').value);
|
|
const amount = parseFloat(document.getElementById('trade-amount').value);
|
|
if (!amount) return alert('Please enter amount');
|
|
|
|
const response = await fetch('api/place_order.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
symbol: currentSymbol,
|
|
type: 'futures',
|
|
side: side,
|
|
order_type: currentTradeType,
|
|
price: price,
|
|
amount: amount,
|
|
total: price * amount,
|
|
leverage: leverage,
|
|
tp_price: document.getElementById('tp-price').value || null,
|
|
sl_price: document.getElementById('sl-price').value || null
|
|
})
|
|
});
|
|
const result = await response.json();
|
|
if (result.success) {
|
|
alert('Futures order placed successfully!');
|
|
fetchOrders();
|
|
} else {
|
|
alert('Error: ' + result.error);
|
|
}
|
|
}
|
|
|
|
function switchOrderTab(el, tab) {
|
|
currentOrderTab = tab;
|
|
document.querySelectorAll('.order-tab-link').forEach(t => t.classList.remove('active'));
|
|
el.classList.add('active');
|
|
fetchOrders();
|
|
}
|
|
|
|
async function fetchOrders() {
|
|
const response = await fetch(`api/get_orders.php?type=futures&status=${currentOrderTab}`);
|
|
const result = await response.json();
|
|
const tbody = document.getElementById('orders-list-body');
|
|
if (result.success && result.data.length > 0) {
|
|
let html = '';
|
|
result.data.forEach(o => {
|
|
const color = o.side === 'buy' ? '#00c087' : '#f6465d';
|
|
let pnl = '0.00';
|
|
let pnlColor = '#848e9c';
|
|
if (o.win_loss === 'win') {
|
|
pnl = '+' + (o.total * 0.1).toFixed(2);
|
|
pnlColor = '#00c087';
|
|
} else if (o.win_loss === 'loss') {
|
|
pnl = '-' + (o.total * 0.1).toFixed(2);
|
|
pnlColor = '#f6465d';
|
|
}
|
|
|
|
html += `
|
|
<tr style="border-bottom: 1px solid #1e2329;">
|
|
<td style="padding: 10px 15px; color: white; font-weight: bold;">${o.symbol}</td>
|
|
<td style="padding: 10px 15px; color: ${color}; font-weight: bold;">${o.side === 'buy' ? '做多' : '做空'}</td>
|
|
<td style="padding: 10px 15px;">${parseFloat(o.price).toLocaleString()}</td>
|
|
<td style="padding: 10px 15px;">${parseFloat(o.amount).toFixed(3)}</td>
|
|
<td style="padding: 10px 15px; color: ${pnlColor}; font-weight: bold;">${pnl} USDT</td>
|
|
<td style="padding: 10px 15px;"><span style="background: rgba(255,255,255,0.05); padding: 2px 6px; border-radius: 2px;">${o.status.toUpperCase()}</span></td>
|
|
<td style="padding: 10px 15px; text-align: right;">
|
|
${o.status === 'open' ? `<button onclick="cancelOrder(${o.id})" style="background: rgba(246, 70, 93, 0.1); border: 1px solid #f6465d; color: #f6465d; padding: 2px 8px; border-radius: 4px; cursor: pointer; font-size: 11px;">平仓</button>` : '--'}
|
|
</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
tbody.innerHTML = html;
|
|
} else {
|
|
tbody.innerHTML = `<tr><td colspan="7" style="text-align: center; padding: 50px; opacity: 0.3;"><i class="fas fa-folder-open" style="font-size: 32px; display: block; margin-bottom: 10px;"></i>暂无记录</td></tr>`;
|
|
}
|
|
}
|
|
|
|
async function cancelOrder(id) {
|
|
if (!confirm('确定撤单/平仓?')) return;
|
|
const response = await fetch('api/cancel_order.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ order_id: id })
|
|
});
|
|
const result = await response.json();
|
|
if (result.success) {
|
|
fetchOrders();
|
|
}
|
|
}
|
|
|
|
document.getElementById('pair-search').addEventListener('input', renderPairsList);
|
|
fetchOrders();
|
|
setInterval(fetchOrders, 5000);
|
|
</script>
|
|
|
|
<?php include 'footer.php'; ?>
|