422 lines
26 KiB
PHP
422 lines
26 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;
|
|
}
|
|
?>
|
|
|
|
<style>
|
|
* { box-sizing: border-box; }
|
|
:root {
|
|
--bg-color: #0b0e11;
|
|
--panel-bg: #161a1e;
|
|
--border-color: #2b3139;
|
|
--text-primary: #EAECEF;
|
|
--text-secondary: #848e9c;
|
|
--accent-color: #4facfe;
|
|
--up-color: #00c087;
|
|
--down-color: #f6465d;
|
|
--input-bg: #1e2329;
|
|
}
|
|
|
|
body { background-color: var(--bg-color); color: var(--text-primary); font-family: 'Inter', 'PingFang SC', sans-serif; margin: 0; }
|
|
|
|
.trading-layout { display: flex; gap: 1px; background: var(--border-color); min-height: 800px; }
|
|
.panel { background: var(--panel-bg); display: flex; flex-direction: column; }
|
|
|
|
/* Market Panel */
|
|
.market-panel { width: 300px; flex-shrink: 0; border-right: 1px solid var(--border-color); }
|
|
#pairs-list { height: 800px; overflow-y: auto; scrollbar-width: thin; }
|
|
.pair-item { display: flex; align-items: center; padding: 10px 16px; cursor: pointer; border-bottom: 1px solid rgba(255,255,255,0.02); transition: 0.2s; }
|
|
.pair-item:hover { background: rgba(255,255,255,0.05); }
|
|
.pair-item.active { background: rgba(79, 172, 254, 0.08); border-left: 3px solid var(--accent-color); }
|
|
.pair-icon { width: 24px; height: 24px; margin-right: 12px; border-radius: 50%; }
|
|
|
|
/* Center Panel */
|
|
.center-panel { flex: 1; background: var(--bg-color); display: flex; flex-direction: column; min-width: 0; }
|
|
.info-bar { height: 66px; display: flex; align-items: center; padding: 0 20px; gap: 25px; border-bottom: 1px solid var(--border-color); background: var(--panel-bg); }
|
|
.chart-container { height: 500px; background: var(--bg-color); border-bottom: 1px solid var(--border-color); }
|
|
|
|
.order-form-panel { padding: 25px; background: var(--panel-bg); border-bottom: 1px solid var(--border-color); }
|
|
.order-form-grid { display: grid; grid-template-columns: 1.2fr 1fr; gap: 40px; }
|
|
.input-row { background: var(--input-bg); border: 1px solid var(--border-color); border-radius: 6px; display: flex; align-items: center; margin-bottom: 12px; padding: 10px 15px; transition: 0.2s; }
|
|
.input-row:focus-within { border-color: var(--accent-color); }
|
|
.input-row input { flex: 1; background: transparent; border: none; color: white; text-align: right; outline: none; font-size: 14px; font-weight: 600; }
|
|
.btn-trade { padding: 14px; border: none; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer; color: white; transition: 0.3s; margin-top: 10px; }
|
|
.btn-trade:hover { opacity: 0.9; transform: translateY(-1px); }
|
|
|
|
/* Order Book Panel */
|
|
.order-book-panel { width: 320px; flex-shrink: 0; border-left: 1px solid var(--border-color); display: flex; flex-direction: column; }
|
|
.ob-header { padding: 12px 16px; font-size: 12px; color: var(--text-secondary); border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; font-weight: 600; }
|
|
.ob-row { display: flex; justify-content: space-between; padding: 4px 16px; font-size: 12px; position: relative; font-family: 'Roboto Mono', monospace; cursor: pointer; }
|
|
.ob-row:hover { background: rgba(255,255,255,0.05); }
|
|
.ob-vol-bar { position: absolute; top: 0; right: 0; bottom: 0; z-index: 0; opacity: 0.15; transition: width 0.3s; }
|
|
|
|
/* Tabs */
|
|
.tab-btn { background: none; border: none; color: var(--text-secondary); padding: 15px 20px; font-size: 14px; font-weight: 600; cursor: pointer; position: relative; transition: 0.2s; white-space: nowrap; }
|
|
.tab-btn.active { color: var(--accent-color); }
|
|
.tab-btn.active::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 3px; background: var(--accent-color); border-radius: 3px 3px 0 0; }
|
|
|
|
@media (max-width: 1200px) {
|
|
.market-panel { display: none; }
|
|
}
|
|
@media (max-width: 992px) {
|
|
.trading-layout { flex-direction: column; min-height: auto; }
|
|
.order-book-panel { width: 100%; border-left: none; border-top: 1px solid var(--border-color); }
|
|
.chart-container { height: 400px; }
|
|
.order-form-grid { grid-template-columns: 1fr; gap: 20px; }
|
|
.info-bar { height: auto; padding: 15px; flex-wrap: wrap; gap: 15px; }
|
|
#pairs-list { height: 400px; }
|
|
}
|
|
</style>
|
|
|
|
<div class="trading-layout">
|
|
<!-- Left Panel -->
|
|
<div class="panel market-panel">
|
|
<div style="padding: 15px; border-bottom: 1px solid var(--border-color);">
|
|
<div style="position: relative;">
|
|
<i class="fas fa-search" style="position: absolute; left: 12px; top: 12px; color: var(--text-secondary); font-size: 14px;"></i>
|
|
<input type="text" id="market-search" placeholder="<?php echo __('search_contract'); ?>" style="width: 100%; background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 10px 12px 10px 35px; border-radius: 8px; font-size: 13px; outline: none;">
|
|
</div>
|
|
</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: 12px;">
|
|
<img id="current-logo" src="https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/btc.png" width="32" height="32" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
|
<div>
|
|
<div id="current-pair-display" style="font-size: 18px; font-weight: 800; letter-spacing: -0.5px;">BTC/USDT <?php echo __('perpetual'); ?></div>
|
|
<div id="leverage-display" style="font-size: 12px; color: var(--accent-color); cursor: pointer; font-weight: 600;" onclick="showLevModal()"><span id="leverage-val-info">20</span>x</div>
|
|
</div>
|
|
</div>
|
|
<div style="display: flex; flex-direction: column;">
|
|
<span id="last-price" style="font-size: 18px; font-weight: 700; color: var(--up-color); font-family: 'Roboto Mono', monospace;">--</span>
|
|
<span id="price-change" style="font-size: 11px; font-weight: 600;">--</span>
|
|
</div>
|
|
<div style="margin-left: auto; display: flex; gap: 25px; font-size: 12px;" class="desktop-only">
|
|
<div style="color: var(--text-secondary);">Mark <span id="mark-price" style="color: white; font-weight: 600; display: block; margin-top: 4px;">--</span></div>
|
|
<div style="color: var(--text-secondary);">24h Vol <span id="vol-24h" style="color: white; font-weight: 600; display: block; margin-top: 4px;">--</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="chart-container">
|
|
<div id="tv_chart_container" style="height: 100%;"></div>
|
|
</div>
|
|
|
|
<div class="center-content">
|
|
<div class="order-form-panel">
|
|
<div style="display: flex; gap: 12px; margin-bottom: 20px; align-items: center;">
|
|
<button class="ctrl-btn active" id="margin-isolated" onclick="setMargin('isolated')" style="background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 6px 15px; border-radius: 6px; font-size: 13px; cursor: pointer; font-weight: 600;"><?php echo __('isolated'); ?></button>
|
|
<button class="ctrl-btn" onclick="showLevModal()" style="background: var(--input-bg); border: 1px solid var(--border-color); color: white; padding: 6px 15px; border-radius: 6px; font-size: 13px; cursor: pointer; font-weight: 600;"><span id="leverage-val">20</span>x</button>
|
|
<div style="display: flex; gap: 20px; margin-left: 15px; align-items: center;">
|
|
<button onclick="setOrderType('limit')" id="order-type-limit" style="background: none; border: none; color: var(--text-secondary); font-size: 14px; cursor: pointer; font-weight: 700;"><?php echo __('limit'); ?></button>
|
|
<button onclick="setOrderType('market')" id="order-type-market" style="background: none; border: none; color: var(--accent-color); font-weight: 700; font-size: 14px; cursor: pointer;"><?php echo __('market'); ?></button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="order-form-grid">
|
|
<div>
|
|
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 10px;">
|
|
<span style="color: var(--text-secondary);"><?php echo __('available'); ?></span>
|
|
<span id="available-bal" style="color: white; font-weight: 600;"><?php echo number_format($balance, 2); ?> USDT</span>
|
|
</div>
|
|
<div class="input-row" id="price-row" style="display: none;">
|
|
<span style="color: var(--text-secondary); font-size: 13px; width: 60px; font-weight: 600;"><?php echo __('price'); ?></span>
|
|
<input type="number" id="order-price" placeholder="0.00">
|
|
</div>
|
|
<div class="input-row">
|
|
<span style="color: var(--text-secondary); font-size: 13px; width: 60px; font-weight: 600;"><?php echo __('amount'); ?></span>
|
|
<input type="number" id="order-amount" placeholder="Cont">
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div style="margin: 10px 0 20px;">
|
|
<input type="range" min="0" max="100" value="0" id="order-slider" style="width: 100%; accent-color: var(--accent-color); cursor: pointer;" oninput="updateFromSlider(this.value)">
|
|
<div style="display: flex; justify-content: space-between; font-size: 11px; color: var(--text-secondary); margin-top: 8px; font-weight: 500;">
|
|
<span onclick="setSlider(0)" style="cursor: pointer;">0%</span><span onclick="setSlider(25)" style="cursor: pointer;">25%</span><span onclick="setSlider(50)" style="cursor: pointer;">50%</span><span onclick="setSlider(75)" style="cursor: pointer;">75%</span><span onclick="setSlider(100)" style="cursor: pointer;">100%</span>
|
|
</div>
|
|
</div>
|
|
<div style="font-size: 14px; display: flex; justify-content: space-between; margin-top: 15px;">
|
|
<span style="color: var(--text-secondary); font-weight: 600;"><?php echo __('margin'); ?></span>
|
|
<span style="font-weight: 700;"><span id="order-cost">0.00</span> USDT</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 25px;">
|
|
<button class="btn-trade" style="background: var(--up-color);" onclick="placeOrder('buy')"><?php echo __('open_long'); ?></button>
|
|
<button class="btn-trade" style="background: var(--down-color);" onclick="placeOrder('sell')"><?php echo __('open_short'); ?></button>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="background: var(--panel-bg);">
|
|
<div style="display: flex; border-bottom: 1px solid var(--border-color); padding: 0 10px; overflow-x: auto;">
|
|
<button class="tab-btn active" onclick="switchTab(this, 'positions')"><?php echo __('positions'); ?></button>
|
|
<button class="tab-btn" onclick="switchTab(this, 'open')"><?php echo __('open_orders'); ?></button>
|
|
</div>
|
|
<div style="padding: 15px; overflow-x: auto;">
|
|
<table style="width: 100%; font-size: 13px; border-collapse: collapse; min-width: 800px;">
|
|
<thead id="data-thead" style="color: var(--text-secondary); text-align: left; background: rgba(255,255,255,0.02);"></thead>
|
|
<tbody id="data-tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Panel (Order Book) -->
|
|
<div class="panel order-book-panel">
|
|
<div class="ob-header">
|
|
<span>Price / Amount</span>
|
|
</div>
|
|
<div id="asks-list" style="display: flex; flex-direction: column-reverse; flex: 1; overflow: hidden; min-height: 380px;"></div>
|
|
<div id="ob-mid-price" style="padding: 15px 0; text-align: center; font-weight: 800; border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); font-size: 18px; font-family: 'Roboto Mono', monospace; background: rgba(255,255,255,0.01);">--</div>
|
|
<div id="bids-list" style="flex: 1; overflow: hidden; min-height: 380px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="lev-modal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.85); display: none; align-items: center; justify-content: center; z-index: 2100; backdrop-filter: blur(5px);">
|
|
<div style="background: var(--panel-bg); padding: 40px; border-radius: 20px; width: 360px; text-align: center; border: 1px solid var(--border-color); box-shadow: 0 20px 60px rgba(0,0,0,0.5);">
|
|
<h3 style="margin-bottom: 25px; font-size: 1.5rem; font-weight: 800;"><?php echo __('adjust_leverage'); ?></h3>
|
|
<div id="lev-val-big" style="font-size: 48px; font-weight: 800; color: var(--accent-color); margin-bottom: 30px; font-family: 'Roboto Mono', monospace;">20x</div>
|
|
<input type="range" min="1" max="125" value="20" id="lev-range" style="width: 100%; accent-color: var(--accent-color); cursor: pointer;" oninput="document.getElementById('lev-val-big').innerText = this.value + 'x'">
|
|
<div style="display: flex; gap: 20px; margin-top: 40px;">
|
|
<button onclick="hideLevModal()" style="flex: 1; padding: 12px; background: #2b3139; border: none; color: white; border-radius: 10px; font-weight: 700; cursor: pointer;"><?php echo __('cancel'); ?></button>
|
|
<button onclick="confirmLev()" style="flex: 1; padding: 12px; background: var(--accent-color); border: none; color: white; border-radius: 10px; font-weight: 700; cursor: pointer;"><?php echo __('confirm'); ?></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
|
|
<script>
|
|
let currentPair = 'BTCUSDT';
|
|
let currentPrice = 0;
|
|
let leverage = 20;
|
|
let usdtBalance = <?php echo $balance; ?>;
|
|
let marketData = {};
|
|
let orderType = 'market';
|
|
let activeTab = 'positions';
|
|
const faceValue = 10;
|
|
const lang = '<?php echo $lang; ?>';
|
|
|
|
const pairs = [
|
|
'BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'AVAXUSDT', 'DOGEUSDT', 'DOTUSDT', 'LINKUSDT',
|
|
'MATICUSDT', 'NEARUSDT', 'LTCUSDT', 'ATOMUSDT', 'UNIUSDT', 'XLMUSDT', 'ALGOUSDT', 'TRXUSDT', 'BCHUSDT', 'SHIBUSDT'
|
|
];
|
|
|
|
function initChart(symbol) {
|
|
new TradingView.widget({
|
|
"width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol, "interval": "15", "theme": "dark", "style": "1", "locale": lang === 'zh' ? 'zh_CN' : 'en', "container_id": "tv_chart_container", "backgroundColor": "#0b0e11", "hide_side_toolbar": true
|
|
});
|
|
}
|
|
initChart(currentPair);
|
|
|
|
let ws;
|
|
function connectWS() {
|
|
const streams = pairs.map(p => p.toLowerCase() + '@ticker').join('/');
|
|
ws = new WebSocket(`wss://fstream.binance.com/ws/${streams}`);
|
|
ws.onmessage = (e) => {
|
|
const data = JSON.parse(e.data);
|
|
marketData[data.s] = data;
|
|
renderPairs();
|
|
if (data.s === currentPair) updateUI(data);
|
|
};
|
|
}
|
|
connectWS();
|
|
|
|
function updateUI(data) {
|
|
currentPrice = parseFloat(data.c);
|
|
document.getElementById('last-price').innerText = currentPrice.toLocaleString();
|
|
document.getElementById('last-price').style.color = data.P >= 0 ? 'var(--up-color)' : 'var(--down-color)';
|
|
document.getElementById('price-change').innerText = (data.P >= 0 ? '+' : '') + data.P + '%';
|
|
document.getElementById('mark-price').innerText = currentPrice.toLocaleString();
|
|
document.getElementById('vol-24h').innerText = parseFloat(data.q).toLocaleString();
|
|
document.getElementById('ob-mid-price').innerText = currentPrice.toLocaleString();
|
|
document.getElementById('ob-mid-price').style.color = data.P >= 0 ? 'var(--up-color)' : 'var(--down-color)';
|
|
updateOrderBook();
|
|
}
|
|
|
|
function renderPairs() {
|
|
const list = document.getElementById('pairs-list');
|
|
if (!list) return;
|
|
let html = '';
|
|
pairs.forEach(p => {
|
|
const d = marketData[p] || {c: 0, P: 0};
|
|
const name = p.replace('USDT', '');
|
|
const icon = `https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${name.toLowerCase()}.png`;
|
|
html += `
|
|
<div class="pair-item ${currentPair === p ? 'active' : ''}" onclick="switchPair('${p}')">
|
|
<img src="${icon}" class="pair-icon" onerror="this.src='https://cdn-icons-png.flaticon.com/512/2585/2585274.png'">
|
|
<div style="flex: 1;">
|
|
<div style="font-weight: 700; font-size: 14px;">${name}/USDT</div>
|
|
<div style="font-size: 11px; color: var(--text-secondary);">Vol ${parseFloat(d.q || 0).toLocaleString()}</div>
|
|
</div>
|
|
<div style="text-align: right;">
|
|
<div style="font-weight: 600; font-family: 'Roboto Mono', monospace; font-size: 13px;">${parseFloat(d.c).toLocaleString()}</div>
|
|
<div style="color: ${d.P >= 0 ? 'var(--up-color)' : 'var(--down-color)'}; font-size: 11px; font-weight: 600;">${(d.P >= 0 ? '+' : '') + d.P}%</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
list.innerHTML = html;
|
|
}
|
|
|
|
function switchPair(p) {
|
|
if (currentPair === p) return;
|
|
currentPair = p;
|
|
document.getElementById('current-pair-display').innerText = p + '/USDT ' + (lang === 'zh' ? '永续' : 'Perpetual');
|
|
document.getElementById('current-logo').src = `https://raw.githubusercontent.com/spothq/cryptocurrency-icons/master/128/color/${p.replace('USDT','').toLowerCase()}.png`;
|
|
initChart(p);
|
|
}
|
|
|
|
function updateOrderBook() {
|
|
const asks = document.getElementById('asks-list');
|
|
const bids = document.getElementById('bids-list');
|
|
let aH = ''; let bH = '';
|
|
let maxVol = 0;
|
|
const rows = 15;
|
|
const askData = [];
|
|
const bidData = [];
|
|
|
|
for(let i=0; i<rows; i++) {
|
|
const av = Math.random() * 200 + 10;
|
|
const bv = Math.random() * 200 + 10;
|
|
askData.push(av);
|
|
bidData.push(bv);
|
|
maxVol = Math.max(maxVol, av, bv);
|
|
}
|
|
|
|
for(let i=0; i<rows; i++) {
|
|
const ap = currentPrice * (1 + (i + 1) * 0.0003);
|
|
const bp = currentPrice * (1 - (i + 1) * 0.0003);
|
|
const av = askData[i];
|
|
const bv = bidData[i];
|
|
|
|
aH += `
|
|
<div class="ob-row" onclick="setPrice(${ap.toFixed(1)})">
|
|
<div class="ob-vol-bar" style="width: ${(av/maxVol*100)}%; background: var(--down-color);"></div>
|
|
<span style="color: var(--down-color); font-weight: 600; z-index: 1;">${ap.toFixed(1)}</span>
|
|
<span style="color: white; opacity: 0.9; z-index: 1;">${av.toFixed(0)}</span>
|
|
</div>`;
|
|
bH += `
|
|
<div class="ob-row" onclick="setPrice(${bp.toFixed(1)})">
|
|
<div class="ob-vol-bar" style="width: ${(bv/maxVol*100)}%; background: var(--up-color);"></div>
|
|
<span style="color: var(--up-color); font-weight: 600; z-index: 1;">${bp.toFixed(1)}</span>
|
|
<span style="color: white; opacity: 0.9; z-index: 1;">${bv.toFixed(0)}</span>
|
|
</div>`;
|
|
}
|
|
asks.innerHTML = aH; bids.innerHTML = bH;
|
|
}
|
|
|
|
function setPrice(p) {
|
|
if (orderType === 'limit') document.getElementById('order-price').value = p;
|
|
}
|
|
|
|
function setSlider(val) { document.getElementById('order-slider').value = val; updateFromSlider(val); }
|
|
function updateFromSlider(val) {
|
|
const cost = usdtBalance * (val / 100);
|
|
document.getElementById('order-amount').value = Math.floor((cost * leverage) / faceValue);
|
|
document.getElementById('order-cost').innerText = cost.toFixed(2);
|
|
}
|
|
|
|
function showLevModal() { document.getElementById('lev-modal').style.display = 'flex'; }
|
|
function hideLevModal() { document.getElementById('lev-modal').style.display = 'none'; }
|
|
function confirmLev() {
|
|
leverage = document.getElementById('lev-range').value;
|
|
document.getElementById('leverage-display').innerText = leverage + 'x';
|
|
document.getElementById('leverage-val-info').innerText = leverage;
|
|
document.getElementById('leverage-val').innerText = leverage;
|
|
hideLevModal();
|
|
updateFromSlider(document.getElementById('order-slider').value);
|
|
}
|
|
|
|
function setOrderType(type) {
|
|
orderType = type;
|
|
document.getElementById('order-type-limit').style.color = type === 'limit' ? 'var(--accent-color)' : 'var(--text-secondary)';
|
|
document.getElementById('order-type-market').style.color = type === 'market' ? 'var(--accent-color)' : 'var(--text-secondary)';
|
|
document.getElementById('price-row').style.display = type === 'limit' ? 'flex' : 'none';
|
|
}
|
|
|
|
async function placeOrder(side) {
|
|
const amount = parseFloat(document.getElementById('order-amount').value);
|
|
if (!amount || amount <= 0) return alert(lang === 'zh' ? '请输入有效数量' : 'Please enter a valid amount');
|
|
const price = orderType === 'limit' ? parseFloat(document.getElementById('order-price').value) : currentPrice;
|
|
const resp = 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
|
|
})
|
|
});
|
|
const res = await resp.json();
|
|
if (res.success) {
|
|
alert(lang === 'zh' ? '下单成功' : 'Order Placed Successfully');
|
|
fetchOrders();
|
|
} else { alert(res.error); }
|
|
}
|
|
|
|
async function fetchOrders() {
|
|
const resp = await fetch(`api/get_orders.php?type=futures&status=${activeTab}`);
|
|
const res = await resp.json();
|
|
const tbody = document.getElementById('data-tbody');
|
|
const thead = document.getElementById('data-thead');
|
|
if (activeTab === 'positions') {
|
|
thead.innerHTML = `<tr><th style="padding: 12px 10px;"><?php echo __('pair'); ?></th><th style="padding: 12px 10px;"><?php echo __('direction'); ?></th><th style="padding: 12px 10px;"><?php echo __('price'); ?></th><th style="padding: 12px 10px;"><?php echo __('pnl'); ?></th><th style="padding: 12px 10px; text-align: right;"><?php echo __('action'); ?></th></tr>`;
|
|
} else {
|
|
thead.innerHTML = `<tr><th style="padding: 12px 10px;"><?php echo __('time'); ?></th><th style="padding: 12px 10px;"><?php echo __('pair'); ?></th><th style="padding: 12px 10px;"><?php echo __('direction'); ?></th><th style="padding: 12px 10px;"><?php echo __('price'); ?></th><th style="padding: 12px 10px;"><?php echo __('amount'); ?></th><th style="padding: 12px 10px; text-align: right;"><?php echo __('action'); ?></th></tr>`;
|
|
}
|
|
if (res.success && res.data.length > 0) {
|
|
tbody.innerHTML = res.data.map(o => {
|
|
const color = o.side === 'buy' ? 'var(--up-color)' : 'var(--down-color)';
|
|
if (activeTab === 'positions') {
|
|
return `<tr style="border-bottom: 1px solid var(--border-color);">
|
|
<td style="padding: 15px 10px; font-weight: 700;">${o.symbol}</td>
|
|
<td style="padding: 15px 10px; color: ${color}; font-weight: 700;">${o.side === 'buy' ? (lang === 'zh' ? '多' : 'LONG') : (lang === 'zh' ? '空' : 'SHORT')} ${o.leverage}x</td>
|
|
<td style="padding: 15px 10px; font-family: 'Roboto Mono', monospace;">${parseFloat(o.price).toLocaleString()}</td>
|
|
<td style="padding: 15px 10px; font-weight: 700;">--</td>
|
|
<td style="padding: 15px 10px; text-align: right;"><button onclick="closePos(${o.id})" style="background: rgba(255,255,255,0.05); color: white; border: 1px solid var(--border-color); padding: 5px 15px; border-radius: 6px; cursor: pointer; font-size: 12px;"><?php echo __('close_position'); ?></button></td>
|
|
</tr>`;
|
|
} else {
|
|
return `<tr style="border-bottom: 1px solid var(--border-color);">
|
|
<td style="padding: 15px 10px;">${o.created_at}</td>
|
|
<td style="padding: 15px 10px; font-weight: 700;">${o.symbol}</td>
|
|
<td style="padding: 15px 10px; color: ${color}; font-weight: 700;">${o.side.toUpperCase()}</td>
|
|
<td style="padding: 15px 10px; font-family: 'Roboto Mono', monospace;">${parseFloat(o.price).toLocaleString()}</td>
|
|
<td style="padding: 15px 10px;">${o.amount}</td>
|
|
<td style="padding: 15px 10px; text-align: right;"><button onclick="cancelOrder(${o.id})" style="background: var(--danger-color); color: white; border: none; padding: 5px 15px; border-radius: 6px; cursor: pointer; font-size: 12px;"><?php echo __('cancel'); ?></button></td>
|
|
</tr>`;
|
|
}
|
|
}).join('');
|
|
} else { tbody.innerHTML = `<tr><td colspan="5" style="text-align: center; padding: 60px; color: var(--text-secondary);"><?php echo __('no_records'); ?></td></tr>`; }
|
|
}
|
|
|
|
function switchTab(btn, tab) {
|
|
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
btn.classList.add('active'); activeTab = tab; fetchOrders();
|
|
}
|
|
|
|
document.getElementById('market-search').addEventListener('input', function(e) {
|
|
const q = e.target.value.toUpperCase();
|
|
document.querySelectorAll('.pair-item').forEach(item => {
|
|
const text = item.querySelector('div div').innerText;
|
|
item.style.display = text.includes(q) ? 'flex' : 'none';
|
|
});
|
|
});
|
|
|
|
fetchOrders(); setInterval(fetchOrders, 4000);
|
|
</script>
|
|
|
|
<?php include 'footer.php'; ?>
|