408 lines
24 KiB
PHP
408 lines
24 KiB
PHP
<?php
|
|
include 'header.php';
|
|
require_once 'db/config.php';
|
|
|
|
$user_id = $_SESSION['user_id'] ?? null;
|
|
?>
|
|
|
|
<style>
|
|
/* Layout Fixes */
|
|
@media (max-width: 991px) {
|
|
.navbar, footer { display: none !important; }
|
|
body { padding-bottom: 65px !important; margin: 0 !important; max-width: 100% !important; }
|
|
}
|
|
|
|
.trading-container {
|
|
display: flex;
|
|
background: #0b0e11;
|
|
min-height: calc(100vh - 64px);
|
|
max-width: 100%;
|
|
margin: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
@media (max-width: 991px) {
|
|
.trading-container { min-height: 100vh; flex-direction: column; }
|
|
}
|
|
|
|
.left-col { width: 280px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-right: 1px solid #2b3139; }
|
|
.center-col { flex: 1; min-width: 0; background: #0b0e11; display: flex; flex-direction: column; overflow: hidden; }
|
|
.right-col { width: 320px; flex-shrink: 0; background: #161a1e; display: flex; flex-direction: column; border-left: 1px solid #2b3139; }
|
|
|
|
/* Pairs List */
|
|
#pairs-list { flex: 1; overflow-y: auto; }
|
|
.pair-item { display: flex; align-items: center; padding: 12px 15px; cursor: pointer; transition: all 0.2s; border-bottom: 1px solid rgba(255,255,255,0.02); }
|
|
.pair-item.active { background: #1e2329; border-left: 3px solid var(--primary-color); }
|
|
.coin-icon { width: 22px; height: 22px; margin-right: 12px; border-radius: 50%; }
|
|
|
|
/* Chart Area */
|
|
.chart-header { padding: 12px 20px; display: flex; align-items: center; gap: 20px; background: #161a1e; border-bottom: 1px solid #2b3139; }
|
|
.chart-box { flex: 1; min-height: 400px; background: #0b0e11; }
|
|
|
|
/* Order Records */
|
|
.record-tabs { display: flex; background: #161a1e; border-bottom: 1px solid #2b3139; padding: 0 15px; }
|
|
.record-tab { padding: 12px 0; margin-right: 25px; font-size: 13px; color: var(--text-muted); cursor: pointer; position: relative; }
|
|
.record-tab.active { color: var(--text-color); font-weight: 600; }
|
|
.record-tab.active::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 2px; background: var(--primary-color); }
|
|
.records-content { height: 300px; overflow-y: auto; background: #161a1e; }
|
|
|
|
@media (max-width: 991px) {
|
|
.records-content { min-height: 350px; padding-bottom: 100px; height: auto; }
|
|
}
|
|
|
|
/* Right Order Panel */
|
|
.order-panel { padding: 20px; }
|
|
.panel-label { color: #848e9c; font-size: 12px; margin-bottom: 8px; }
|
|
.duration-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 20px; }
|
|
.time-btn { background: #2b3139; border: 1px solid transparent; color: #eaecef; padding: 8px 4px; border-radius: 4px; font-size: 11px; cursor: pointer; text-align: center; display: flex; flex-direction: column; align-items: center; }
|
|
.time-btn.active { background: rgba(0, 82, 255, 0.1); border-color: var(--primary-color); color: var(--primary-color); }
|
|
.time-btn .rate { font-size: 10px; font-weight: bold; margin-top: 2px; }
|
|
|
|
.input-group { background: #2b3139; border-radius: 4px; padding: 10px 12px; display: flex; align-items: center; margin-bottom: 10px; border: 1px solid transparent; }
|
|
.input-group:focus-within { border-color: var(--primary-color); }
|
|
.input-group input { background: transparent; border: none; color: white; flex: 1; text-align: right; outline: none; font-size: 14px; width: 100%; }
|
|
.input-group .unit { color: #848e9c; margin-left: 8px; font-size: 12px; }
|
|
|
|
.balance-info { display: flex; justify-content: space-between; font-size: 12px; color: #848e9c; margin: 15px 0; }
|
|
.trade-btn { width: 100%; padding: 14px; border-radius: 4px; font-weight: bold; font-size: 15px; border: none; cursor: pointer; margin-top: 10px; }
|
|
.btn-up { background: #0ecb81; color: white; }
|
|
.btn-down { background: #f6465d; color: white; }
|
|
|
|
/* Mobile Components */
|
|
.m-trading-header { display: none; background: #161a1e; padding: 12px 15px; border-bottom: 1px solid #2b3139; }
|
|
.m-nav-tabs { display: none; background: #161a1e; border-bottom: 1px solid #2b3139; }
|
|
.m-currency-bar { display: none; overflow-x: auto; background: #161a1e; padding: 10px; gap: 10px; border-bottom: 1px solid #2b3139; scrollbar-width: none; }
|
|
|
|
@media (max-width: 991px) {
|
|
.m-trading-header, .m-nav-tabs, .m-currency-bar { display: flex; }
|
|
.m-trading-header { flex-direction: column; }
|
|
}
|
|
|
|
.m-coin-item { flex-shrink: 0; background: #2b3139; padding: 6px 12px; border-radius: 4px; display: flex; align-items: center; gap: 6px; border: 1px solid transparent; }
|
|
.m-coin-item.active { border-color: var(--primary-color); background: rgba(0, 82, 255, 0.1); }
|
|
.m-coin-item img { width: 16px; height: 16px; border-radius: 50%; }
|
|
|
|
.mobile-footer-actions { display: none; position: fixed; bottom: 65px; left: 0; width: 100%; background: #161a1e; padding: 12px 15px; border-top: 1px solid #2b3139; gap: 12px; z-index: 1000; }
|
|
@media (max-width: 991px) { .mobile-footer-actions { display: flex; } }
|
|
|
|
.m-order-sheet { position: fixed; bottom: -100%; left: 0; width: 100%; background: #1e2329; border-top-left-radius: 20px; border-top-right-radius: 20px; z-index: 2000; padding: 25px 20px; transition: bottom 0.3s ease; }
|
|
.m-order-sheet.show { bottom: 65px; }
|
|
.m-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 1999; display: none; }
|
|
.m-overlay.show { display: block; }
|
|
|
|
.progress-bar-container { width: 100%; height: 3px; background: #2b3139; border-radius: 2px; margin-top: 8px; overflow: hidden; }
|
|
.progress-bar-fill { height: 100%; background: var(--primary-color); width: 0%; transition: width 1s linear; }
|
|
</style>
|
|
|
|
<!-- Mobile Trading Header -->
|
|
<div class="m-trading-header">
|
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
<div style="display: flex; align-items: center; gap: 10px;" onclick="toggleSidebar()">
|
|
<i class="fas fa-bars" style="font-size: 18px;"></i>
|
|
<div style="font-size: 18px; font-weight: 800; display: flex; align-items: center; gap: 6px;">
|
|
<img id="m-curr-icon" src="" style="width:24px; height:24px; border-radius:50%">
|
|
<span id="m-curr-pair">BTC/USDT</span>
|
|
<i class="fas fa-chevron-down" style="font-size: 10px; opacity: 0.5;"></i>
|
|
</div>
|
|
</div>
|
|
<div style="text-align: right">
|
|
<div id="m-curr-price" style="font-size: 22px; font-weight: 800; color: #0ecb81; line-height: 1;">--</div>
|
|
<div id="m-curr-change" style="font-size: 12px; font-weight: 600; margin-top: 4px;">--</div>
|
|
</div>
|
|
</div>
|
|
<div style="display: flex; gap: 15px; margin-top: 10px; font-size: 11px; color: #848e9c;">
|
|
<span id="m-24h-high">H: --</span>
|
|
<span id="m-24h-low">L: --</span>
|
|
<span id="m-24h-vol">V: --</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Currency Bar -->
|
|
<div class="m-currency-bar" id="m-coin-list"></div>
|
|
|
|
<!-- Mobile Nav Tabs -->
|
|
<div class="m-nav-tabs">
|
|
<div class="m-nav-tab active" data-view="chart" onclick="switchMobileView('chart')"><?php echo __('chart'); ?></div>
|
|
<div class="m-nav-tab" data-view="orders" onclick="switchMobileView('orders')"><?php echo __('positions'); ?></div>
|
|
</div>
|
|
|
|
<div class="trading-container">
|
|
<div class="left-col d-none d-lg-flex">
|
|
<div class="market-header" style="padding:15px; font-weight:bold; border-bottom:1px solid #2b3139"><?php echo __('nav_market'); ?></div>
|
|
<div id="pairs-list"></div>
|
|
</div>
|
|
|
|
<div class="center-col">
|
|
<div class="chart-header d-none d-lg-flex">
|
|
<div style="display: flex; align-items: center; gap: 12px;">
|
|
<img id="curr-icon" src="" class="coin-icon" style="margin:0; width:32px; height:32px;">
|
|
<div>
|
|
<div style="font-weight: 800; font-size: 20px; line-height: 1.2;">
|
|
<span id="curr-pair">BTC/USDT</span>
|
|
</div>
|
|
<div style="font-size: 11px; color: var(--primary-color); font-weight: 600;"><?php echo __('nav_options'); ?></div>
|
|
</div>
|
|
</div>
|
|
<div style="flex:1"></div>
|
|
<div style="text-align: right">
|
|
<div id="curr-price" style="font-size: 24px; font-weight: 800; color: #0ecb81;">--</div>
|
|
<div id="curr-change" style="font-size: 13px; font-weight: 600;">--</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="chart-box" id="chart-section">
|
|
<div id="tv_chart_container" style="height: 100%;"></div>
|
|
</div>
|
|
|
|
<div id="records-section">
|
|
<div class="record-tabs">
|
|
<div class="record-tab active" onclick="switchRecords('pending')"><?php echo __('in_progress'); ?></div>
|
|
<div class="record-tab" onclick="switchRecords('completed')"><?php echo __('settled'); ?></div>
|
|
</div>
|
|
<div class="records-content" id="records-list"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="right-col d-none d-lg-flex">
|
|
<div class="order-panel">
|
|
<div class="panel-label"><?php echo __('settlement_time'); ?></div>
|
|
<div class="duration-grid">
|
|
<div class="time-btn active" data-duration="60" data-rate="8" data-min="100">60S <span class="rate">8%</span></div>
|
|
<div class="time-btn" data-duration="90" data-rate="12" data-min="5000">90S <span class="rate">12%</span></div>
|
|
<div class="time-btn" data-duration="120" data-rate="15" data-min="30000">120S <span class="rate">15%</span></div>
|
|
<div class="time-btn" data-duration="180" data-rate="20" data-min="100000">180S <span class="rate">20%</span></div>
|
|
<div class="time-btn" data-duration="300" data-rate="32" data-min="300000">300S <span class="rate">32%</span></div>
|
|
</div>
|
|
<div class="panel-label"><?php echo __('buy_amount'); ?></div>
|
|
<div class="input-group">
|
|
<input type="number" id="option-amount" placeholder="60S 最小 100 USDT">
|
|
<span class="unit">USDT</span>
|
|
</div>
|
|
<div class="balance-info">
|
|
<span><?php echo __('profit'); ?></span>
|
|
<span style="color: #0ecb81; font-weight: 800;" id="potential-profit">+0.00 USDT</span>
|
|
</div>
|
|
<button class="trade-btn btn-up" onclick="placeOptionOrder('up')"><?php echo __('buy_up'); ?></button>
|
|
<button class="trade-btn btn-down" onclick="placeOptionOrder('down')"><?php echo __('buy_down'); ?></button>
|
|
<div style="margin-top: 30px;">
|
|
<div class="balance-info">
|
|
<span><?php echo __('available'); ?></span>
|
|
<span id="usdt-balance" style="color: white; font-weight: 600;">0.00 USDT</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mobile-footer-actions">
|
|
<button class="trade-btn btn-up" style="margin:0; flex:1" onclick="openOrderSheet('up')"><?php echo __('buy_up'); ?></button>
|
|
<button class="trade-btn btn-down" style="margin:0; flex:1" onclick="openOrderSheet('down')"><?php echo __('buy_down'); ?></button>
|
|
</div>
|
|
|
|
<div class="m-overlay" id="sheet-overlay" onclick="closeOrderSheet()"></div>
|
|
<div class="m-order-sheet" id="m-order-sheet">
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px;">
|
|
<span style="font-weight: 800; font-size: 22px;" id="m-sheet-title"><?php echo __('buy_up'); ?></span>
|
|
<i class="fas fa-times" onclick="closeOrderSheet()" style="font-size: 20px; color: #848e9c"></i>
|
|
</div>
|
|
<div class="panel-label"><?php echo __('settlement_time'); ?></div>
|
|
<div class="duration-grid">
|
|
<div class="time-btn active" data-duration="60" data-rate="8" data-min="100">60S <span class="rate">8%</span></div>
|
|
<div class="time-btn" data-duration="90" data-rate="12" data-min="5000">90S <span class="rate">12%</span></div>
|
|
<div class="time-btn" data-duration="120" data-rate="15" data-min="30000">120S <span class="rate">15%</span></div>
|
|
<div class="time-btn" data-duration="180" data-rate="20" data-min="100000">180S <span class="rate">20%</span></div>
|
|
<div class="time-btn" data-duration="300" data-rate="32" data-min="300000">300S <span class="rate">32%</span></div>
|
|
</div>
|
|
<div class="panel-label"><?php echo __('buy_amount'); ?></div>
|
|
<div class="input-group">
|
|
<input type="number" id="m-option-amount" placeholder="60S 最小 100 USDT">
|
|
<span class="unit">USDT</span>
|
|
</div>
|
|
<div class="balance-info" style="margin-bottom: 25px;">
|
|
<span><?php echo __('available'); ?>: <span id="m-usdt-balance" style="color:white; font-weight:bold">0.00</span> USDT</span>
|
|
<span style="color: #0ecb81; font-weight:800" id="m-potential-profit">+0 USDT</span>
|
|
</div>
|
|
<button class="trade-btn" id="m-confirm-btn" style="background: #0ecb81; color: white;" onclick="confirmMobileOrder()"><?php echo __('confirm'); ?></button>
|
|
</div>
|
|
|
|
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
|
|
<script>
|
|
let currentPair = 'BTCUSDT';
|
|
let currentPrice = 0;
|
|
let currentDuration = 60;
|
|
let currentRate = 0.08;
|
|
let currentMin = 100;
|
|
let currentStatus = 'pending';
|
|
let mobileDirection = 'up';
|
|
const pairs = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'DOTUSDT', 'MATICUSDT', 'LTCUSDT', 'SHIBUSDT', 'TRXUSDT', 'AVAXUSDT', 'LINKUSDT', 'BCHUSDT', 'UNIUSDT', 'ETCUSDT', 'NEARUSDT', 'FILUSDT', 'ALGOUSDT', 'FTMUSDT', 'SANDUSDT', 'MANAUSDT', 'AXSUSDT', 'ATOMUSDT', 'HBARUSDT', 'ICPUSDT', 'VETUSDT'];
|
|
const marketData = {};
|
|
|
|
function getIcon(s) {
|
|
let sym = s.replace('USDT', '').toLowerCase();
|
|
return `https://cdn.jsdelivr.net/gh/atomiclabs/cryptocurrency-icons@1a72df150d6d8481e2345e691456c6c7d1e84a22/32/color/${sym}.png`;
|
|
}
|
|
|
|
function initChart(symbol) {
|
|
new TradingView.widget({
|
|
"width": "100%", "height": "100%", "symbol": "BINANCE:" + symbol,
|
|
"interval": "1", "theme": "dark", "style": "1", "locale": "<?php echo $lang == 'zh' ? 'zh_CN' : 'en'; ?>",
|
|
"container_id": "tv_chart_container", "backgroundColor": "#0b0e11", "hide_side_toolbar": true
|
|
});
|
|
}
|
|
initChart(currentPair);
|
|
|
|
const ws = new WebSocket('wss://stream.binance.com:9443/ws/' + pairs.map(p => p.toLowerCase() + '@ticker').join('/'));
|
|
ws.onmessage = (e) => {
|
|
const d = JSON.parse(e.data);
|
|
if (d.s === currentPair) {
|
|
currentPrice = parseFloat(d.c);
|
|
updatePriceUI(d);
|
|
}
|
|
marketData[d.s] = d;
|
|
renderPairs();
|
|
};
|
|
|
|
function updatePriceUI(d) {
|
|
const pStr = currentPrice.toLocaleString(undefined, {minimumFractionDigits: 2});
|
|
document.getElementById('curr-price').innerText = pStr;
|
|
document.getElementById('m-curr-price').innerText = pStr;
|
|
const color = d.P >= 0 ? '#0ecb81' : '#f6465d';
|
|
document.getElementById('curr-price').style.color = color;
|
|
document.getElementById('m-curr-price').style.color = color;
|
|
document.getElementById('curr-change').innerText = (d.P >= 0 ? '+' : '') + d.P + '%';
|
|
document.getElementById('m-curr-change').innerText = (d.P >= 0 ? '+' : '') + d.P + '%';
|
|
document.getElementById('curr-change').style.color = color;
|
|
document.getElementById('m-curr-change').style.color = color;
|
|
document.getElementById('m-24h-high').innerText = 'H: ' + parseFloat(d.h).toLocaleString();
|
|
document.getElementById('m-24h-low').innerText = 'L: ' + parseFloat(d.l).toLocaleString();
|
|
document.getElementById('m-24h-vol').innerText = 'V: ' + (parseFloat(d.v)/1000).toFixed(1) + 'K';
|
|
}
|
|
|
|
function renderPairs() {
|
|
const list = document.getElementById('pairs-list');
|
|
const mBar = document.getElementById('m-coin-list');
|
|
let lHtml = ''; let mHtml = '';
|
|
pairs.forEach(p => {
|
|
const d = marketData[p] || {c: 0, P: 0}; const icon = getIcon(p); const active = p === currentPair; const color = d.P >= 0 ? '#0ecb81' : '#f6465d';
|
|
lHtml += `<div class="pair-item ${active ? 'active' : ''}" onclick="switchPair('${p}')"><img src="${icon}" class="coin-icon"> <div style="flex:1"><div style="font-weight:700; font-size:13px">${p.replace('USDT', '')}/USDT</div></div> <div style="text-align:right"><div style="font-size:13px; font-weight:bold">${parseFloat(d.c).toLocaleString()}</div><div style="font-size:11px; color:${color}">${(d.P >= 0 ? '+' : '') + d.P}%</div></div></div>`;
|
|
mHtml += `<div class="m-coin-item ${active ? 'active' : ''}" onclick="switchPair('${p}')"><img src="${icon}"><span>${p.replace('USDT', '')}</span></div>`;
|
|
});
|
|
if(list) list.innerHTML = lHtml;
|
|
if(mBar) mBar.innerHTML = mHtml;
|
|
}
|
|
|
|
function switchPair(p) {
|
|
currentPair = p; const icon = getIcon(p);
|
|
document.getElementById('curr-pair').innerText = p.replace('USDT', '') + '/USDT';
|
|
document.getElementById('m-curr-pair').innerText = p.replace('USDT', '') + '/USDT';
|
|
document.getElementById('curr-icon').src = icon; document.getElementById('m-curr-icon').src = icon;
|
|
initChart(p); renderPairs();
|
|
}
|
|
|
|
document.querySelectorAll('.time-btn').forEach(btn => {
|
|
btn.addEventListener('click', function() {
|
|
currentDuration = parseInt(this.dataset.duration);
|
|
currentRate = parseInt(this.dataset.rate) / 100;
|
|
currentMin = parseInt(this.dataset.min);
|
|
document.querySelectorAll('.time-btn').forEach(b => b.classList.remove('active'));
|
|
document.querySelectorAll(`.time-btn[data-duration="${currentDuration}"]`).forEach(b => b.classList.add('active'));
|
|
const ph = `${currentDuration}S 最小 ${currentMin} USDT`;
|
|
document.getElementById('option-amount').placeholder = ph;
|
|
document.getElementById('m-option-amount').placeholder = ph;
|
|
updatePotentialProfit();
|
|
});
|
|
});
|
|
|
|
function updatePotentialProfit() {
|
|
const amt = parseFloat(document.getElementById('option-amount').value) || parseFloat(document.getElementById('m-option-amount').value) || 0;
|
|
const profit = (amt * currentRate).toFixed(2);
|
|
document.getElementById('potential-profit').innerText = '+' + profit + ' USDT';
|
|
document.getElementById('m-potential-profit').innerText = '+' + profit + ' USDT (+' + (currentRate * 100) + '%)';
|
|
}
|
|
|
|
document.getElementById('option-amount').addEventListener('input', updatePotentialProfit);
|
|
document.getElementById('m-option-amount').addEventListener('input', updatePotentialProfit);
|
|
|
|
async function placeOptionOrder(dir) {
|
|
const amt = parseFloat(document.getElementById('option-amount').value);
|
|
if (!amt || amt < currentMin) return alert('<?php echo __('min_amount'); ?>: ' + currentMin + ' USDT');
|
|
const resp = await fetch('api/place_option_order.php', { method: 'POST', body: JSON.stringify({ symbol: currentPair, amount: amt, direction: dir, duration: currentDuration, opening_price: currentPrice }) });
|
|
const res = await resp.json();
|
|
if (res.success) { alert('<?php echo __('order_placed'); ?>'); document.getElementById('option-amount').value = ''; updateBalance(); fetchOrders(); } else alert(res.error);
|
|
}
|
|
|
|
function openOrderSheet(dir) {
|
|
mobileDirection = dir;
|
|
document.getElementById('m-sheet-title').innerText = dir === 'up' ? '<?php echo __('buy_up'); ?>' : '<?php echo __('buy_down'); ?>';
|
|
document.getElementById('m-confirm-btn').style.background = dir === 'up' ? '#0ecb81' : '#f6465d';
|
|
document.getElementById('sheet-overlay').classList.add('show');
|
|
document.getElementById('m-order-sheet').classList.add('show');
|
|
}
|
|
|
|
function closeOrderSheet() { document.getElementById('sheet-overlay').classList.remove('show'); document.getElementById('m-order-sheet').classList.remove('show'); }
|
|
|
|
async function confirmMobileOrder() {
|
|
const amt = parseFloat(document.getElementById('m-option-amount').value);
|
|
if (!amt || amt < currentMin) return alert('<?php echo __('min_amount'); ?>: ' + currentMin + ' USDT');
|
|
const resp = await fetch('api/place_option_order.php', { method: 'POST', body: JSON.stringify({ symbol: currentPair, amount: amt, direction: mobileDirection, duration: currentDuration, opening_price: currentPrice }) });
|
|
const res = await resp.json();
|
|
if (res.success) { alert('<?php echo __('order_placed'); ?>'); closeOrderSheet(); updateBalance(); fetchOrders(); } else alert(res.error);
|
|
}
|
|
|
|
function switchRecords(s) { currentStatus = s; document.querySelectorAll('.record-tab').forEach(t => t.classList.remove('active')); event.target.classList.add('active'); fetchOrders(); }
|
|
|
|
async function fetchOrders() {
|
|
const resp = await fetch('api/get_option_orders.php?status=' + currentStatus);
|
|
const res = await resp.json();
|
|
const list = document.getElementById('records-list');
|
|
if (res.success && res.data.length > 0) {
|
|
list.innerHTML = res.data.map(o => `
|
|
<div style="padding:15px; border-bottom:1px solid #2b3139; font-size:13px">
|
|
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px">
|
|
<div><span style="color:${o.direction==='up'?'#0ecb81':'#f6465d'}; font-weight:800; font-size:14px">${o.direction==='up'?'▲':'▼'} ${o.symbol}</span> <span style="font-size:11px; color:#848e9c; margin-left:8px">${o.created_at}</span></div>
|
|
<div style="font-weight:800; color:${parseFloat(o.profit)>=0?'#0ecb81':'#f6465d'}; font-size:15px">${currentStatus==='pending'?'--':(parseFloat(o.profit)>=0?'+':'')+parseFloat(o.profit).toFixed(2)}</div>
|
|
</div>
|
|
<div style="display:grid; grid-template-columns:repeat(3, 1fr); gap:10px; color:#848e9c; font-size:11px">
|
|
<div>Amount<br><span style="color:white; font-weight:bold">${parseFloat(o.amount).toFixed(2)}</span></div>
|
|
<div>Open Price<br><span style="color:white; font-weight:bold">${parseFloat(o.opening_price).toLocaleString()}</span></div>
|
|
<div>${currentStatus==='pending'?'Time':'Close Price'}<br><span style="color:white; font-weight:bold">${currentStatus==='pending'?o.duration+'s':parseFloat(o.closing_price).toLocaleString()}</span></div>
|
|
</div>
|
|
${currentStatus==='pending'?`<div class="progress-bar-container"><div class="progress-bar-fill" id="pb-${o.id}" data-start="${new Date(o.created_at).getTime()}" data-duration="${o.duration}"></div></div>`:''}
|
|
</div>
|
|
`).join('');
|
|
if (currentStatus === 'pending') updateProgressBars();
|
|
} else list.innerHTML = `<div style="padding:60px 20px; text-align:center; color:#848e9c"><i class="fas fa-file-invoice" style="font-size:40px; margin-bottom:15px; display:block; opacity:0.3"></i><?php echo __('no_records'); ?></div>`;
|
|
}
|
|
|
|
function updateProgressBars() {
|
|
const bars = document.querySelectorAll('.progress-bar-fill');
|
|
const now = Date.now();
|
|
bars.forEach(bar => {
|
|
const start = parseInt(bar.dataset.start); const dur = parseInt(bar.dataset.duration) * 1000; const elapsed = now - start;
|
|
bar.style.width = Math.min(100, (elapsed / dur) * 100) + '%';
|
|
});
|
|
if (currentStatus === 'pending' && bars.length > 0) setTimeout(updateProgressBars, 1000);
|
|
}
|
|
|
|
async function updateBalance() {
|
|
const resp = await fetch('api/get_assets.php'); const res = await resp.json();
|
|
if (res.success) {
|
|
const usdt = res.data.find(a => a.symbol === 'USDT');
|
|
const bal = usdt ? parseFloat(usdt.amount).toFixed(2) : '0.00';
|
|
document.getElementById('usdt-balance').innerText = bal + ' USDT';
|
|
document.getElementById('m-usdt-balance').innerText = bal;
|
|
}
|
|
}
|
|
|
|
function switchMobileView(view) {
|
|
document.querySelectorAll('.m-nav-tab').forEach(t => t.classList.remove('active'));
|
|
document.querySelector(`.m-nav-tab[data-view="${view}"]`).classList.add('active');
|
|
document.getElementById('chart-section').style.display = view === 'chart' ? 'block' : 'none';
|
|
document.getElementById('records-section').style.display = view === 'orders' ? 'block' : 'none';
|
|
if (view === 'orders') fetchOrders();
|
|
}
|
|
|
|
if (window.innerWidth < 992) switchMobileView('chart');
|
|
setInterval(fetchOrders, 3000); updateBalance(); switchPair(currentPair);
|
|
</script>
|
|
<?php include 'footer.php'; ?>
|