Autosave: 20260216-073240

This commit is contained in:
Flatlogic Bot 2026-02-16 07:32:40 +00:00
parent 9f605f214e
commit e5387b40a5
15 changed files with 1835 additions and 200 deletions

View File

@ -7,7 +7,7 @@
--term-primary: #0062ff;
--term-success: #26a69a;
--term-danger: #ef5350;
--header-height: 60px;
--header-height: 70px;
--sidebar-width: 280px;
--orderbook-width: 300px;
}
@ -364,65 +364,216 @@
display: none;
}
/* Binary Order Panel */
/* Binary Order Panel Improvements */
.cycle-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 1px;
background: var(--term-border);
border: 1px solid var(--term-border);
border-radius: 4px;
overflow: hidden;
gap: 8px;
background: transparent;
border: none;
padding: 0;
margin-bottom: 20px;
}
.cycle-btn {
background: var(--term-bg);
border: none;
background: #1e2329;
border: 1px solid var(--term-border);
color: var(--term-muted);
padding: 12px 5px;
padding: 10px 4px;
font-size: 11px;
font-weight: 600;
transition: all 0.2s;
font-weight: 700;
border-radius: 8px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2px;
}
.cycle-btn:hover {
background: rgba(255,255,255,0.05);
color: var(--term-text);
background: #2b3139;
border-color: var(--term-primary);
color: #fff;
transform: translateY(-2px);
}
.cycle-btn.active {
background: var(--term-primary);
background: linear-gradient(135deg, var(--term-primary), #004ecc);
border-color: var(--term-primary);
color: #fff;
box-shadow: 0 4px 15px rgba(0, 98, 255, 0.3);
}
.cycle-btn .cycle-time { font-size: 13px; }
.cycle-btn .cycle-profit { font-size: 10px; opacity: 0.8; }
.amount-input-wrapper input {
height: 44px;
font-size: 16px;
font-weight: 700;
text-align: center;
border-radius: 8px;
background: #0b0e11 !important;
border: 1px solid var(--term-border) !important;
color: #fff !important;
}
.amount-input-wrapper input:focus {
border-color: var(--term-primary) !important;
box-shadow: 0 0 0 1px var(--term-primary) !important;
}
.binary-order-panel .btn-buy-sell {
height: 60px; /* Reduced height as requested */
border-radius: 12px;
transition: all 0.2s;
border: none;
position: relative;
overflow: hidden;
}
.binary-order-panel .btn-buy-sell:active {
transform: scale(0.98);
}
.btn-success.btn-buy-sell {
background: linear-gradient(135deg, #26a69a, #1b8076);
box-shadow: 0 4px 12px rgba(38, 166, 154, 0.2);
}
.btn-danger.btn-buy-sell {
background: linear-gradient(135deg, #ef5350, #c62828);
box-shadow: 0 4px 12px rgba(239, 83, 80, 0.2);
}
/* Ensure history is visible */
.terminal-content {
display: flex;
flex-direction: column;
height: 100%;
}
.kline-container {
flex: 1;
min-height: 300px; /* Allow it to shrink slightly to show more history */
}
.order-history {
height: 300px; /* Fixed height for scrollable area */
border-top: 1px solid var(--term-border);
background: var(--term-surface);
}
.trading-panels {
padding: 15px 20px;
border-bottom: 1px solid var(--term-border);
}
/* Enhanced Balance and Profit visibility */
.balance-highlight {
color: #0062ff !important;
text-shadow: 0 0 10px rgba(0, 98, 255, 0.3);
}
.profit-highlight {
color: #26a69a !important;
font-size: 1.1rem;
text-shadow: 0 0 10px rgba(38, 166, 154, 0.3);
}
/* Order Countdown Popup */
.order-popup-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
backdrop-filter: blur(5px);
z-index: 9999;
display: none;
align-items: center;
justify-content: center;
}
.order-popup {
background: #1e2329;
width: 360px;
border-radius: 20px;
padding: 30px;
box-shadow: 0 20px 40px rgba(0,0,0,0.5);
text-align: center;
border: 1px solid rgba(255,255,255,0.05);
}
.order-popup h5 {
color: #848e9c;
font-size: 16px;
margin-bottom: 30px;
}
.countdown-circle {
position: relative;
width: 160px;
height: 160px;
margin: 0 auto 30px;
}
.countdown-circle svg {
width: 160px;
height: 160px;
transform: rotate(-90deg);
}
.countdown-circle circle {
fill: none;
stroke-width: 8;
}
.countdown-circle .bg {
stroke: #2b3139;
}
.countdown-circle .progress {
stroke: #26a69a;
stroke-linecap: round;
transition: stroke-dashoffset 1s linear;
}
.countdown-circle .time-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 36px;
font-weight: 700;
color: #fff;
}
.amount-input-wrapper input {
height: 50px;
font-size: 18px;
font-weight: bold;
text-align: center;
border-radius: 8px;
}
.section-title {
font-size: 12px;
font-weight: 600;
color: var(--term-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.quick-amounts .btn {
font-weight: 600;
background: #2b3139;
border: none;
}
.quick-amounts .btn:hover {
background: #3b424c;
}
.binary-order-panel {
background: var(--term-surface);
.popup-details {
background: rgba(255,255,255,0.03);
border-radius: 12px;
padding: 15px;
margin-bottom: 20px;
}
.popup-row {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 13px;
}
.popup-row .label { color: #848e9c; }
.popup-row .value { color: #eaecef; font-weight: 600; }
.popup-footer {
font-size: 11px;
color: #5e6673;
}
.terminal-main {
height: calc(100vh - var(--header-height));
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -33,8 +33,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
} else {
try {
$hash = password_hash($password, PASSWORD_DEFAULT);
$uid = '618120' . mt_rand(100000, 999999);
$stmt = db()->prepare("INSERT INTO users (username, email, password_hash, uid, credit_score) VALUES (?, ?, ?, ?, ?)");
$uid = str_pad(mt_rand(0, 99999999), 8, '0', STR_PAD_LEFT);
$stmt = db()->prepare("INSERT INTO users (username, email, password_hash, uid, credit_score, total_recharge) VALUES (?, ?, ?, ?, ?, 0)");
$username = strpos($account, '@') === false ? $account : explode('@', $account)[0];
$email = strpos($account, '@') !== false ? $account : $account . '@byro.io';

View File

@ -0,0 +1,17 @@
-- Add missing fields for Profile, KYC and Security
ALTER TABLE users
ADD COLUMN total_recharge DECIMAL(16,4) DEFAULT 0,
ADD COLUMN transaction_password VARCHAR(255) DEFAULT NULL,
ADD COLUMN kyc_name VARCHAR(100) DEFAULT NULL,
ADD COLUMN kyc_id_number VARCHAR(50) DEFAULT NULL,
ADD COLUMN kyc_photo_front VARCHAR(255) DEFAULT NULL,
ADD COLUMN kyc_photo_back VARCHAR(255) DEFAULT NULL,
ADD COLUMN kyc_photo_handheld VARCHAR(255) DEFAULT NULL,
ADD COLUMN kyc_status INT DEFAULT 0 COMMENT '0: Unverified, 1: Pending, 2: Verified, 3: Rejected';
-- Update credit_score default
ALTER TABLE users MODIFY COLUMN credit_score INT DEFAULT 80;
-- Ensure existing users have a credit score and UID if missing
UPDATE users SET credit_score = 80 WHERE credit_score IS NULL;
UPDATE users SET uid = LPAD(FLOOR(RAND() * 100000000), 8, '0') WHERE uid IS NULL OR uid = '';

View File

@ -72,7 +72,10 @@
<!-- Customer Service Widget -->
<div id="cs-widget" style="position: fixed; bottom: 30px; right: 30px; z-index: 9999;">
<button class="btn btn-primary rounded-circle shadow-lg p-0 d-flex align-items-center justify-content-center transition-all" id="cs-toggle" style="width: 70px; height: 70px; border: none; background: linear-gradient(135deg, #00c6ff, #0072ff); box-shadow: 0 10px 20px rgba(0, 114, 255, 0.4);">
<img src="https://img.icons8.com/fluency/96/service.png" alt="Support" style="width: 45px; height: 45px;">
<div class="position-relative d-flex align-items-center justify-content-center">
<i class="bi bi-person-fill text-white position-absolute" style="font-size: 1.2rem; margin-top: 4px;"></i>
<i class="bi bi-headset text-white" style="font-size: 2.4rem;"></i>
</div>
</button>
<div class="pulse-ring"></div>
</div>

View File

@ -322,8 +322,11 @@ function getSetting($key, $default = null) {
<div class="user-stats">
<div class="stat-item">
<span class="stat-label"><?= __('real_name') ?? 'Real-name' ?></span>
<span class="stat-value <?= ($user['real_name_status'] ?? 0) ? 'success' : 'text-warning' ?>">
<?= ($user['real_name_status'] ?? 0) ? (__('verified') ?? 'Verified') : (__('unverified') ?? 'Unverified') ?>
<span class="stat-value <?= ($user['kyc_status'] ?? 0) == 2 ? 'success' : 'text-warning' ?>">
<?php
$statusMap = [0 => __('unverified'), 1 => __('pending'), 2 => __('verified'), 3 => __('rejected')];
echo $statusMap[$user['kyc_status'] ?? 0] ?? __('unverified');
?>
</span>
</div>
<div class="stat-item">

View File

@ -122,6 +122,83 @@ $translations = [
'buy_up' => '买涨',
'buy_down' => '买跌',
'profit' => '收益',
'enter_amount' => '请输入有效金额',
'insufficient_balance' => '余额不足',
'order_in_progress' => '订单进行中',
'current_price' => '现价',
'cycle' => '周期',
'direction' => '方向',
'quantity' => '数量',
'opening_price' => '开仓价',
'final_price_settlement' => '最终价格以系统结算为准',
'open_orders' => '当前委托',
'settlement_history' => '历史结算',
'no_records_found' => '暂无记录',
'executing' => '正在执行',
'loss' => '亏损',
'amount_too_low' => '买入金额低于最小限制',
'amount_too_high' => '买入金额超过最大限制',
'fiat_recharge' => '法币充值',
'crypto_recharge' => '数字货币充值',
'select_currency' => '选择币种',
'fiat_amount' => '法币金额',
'est_usdt' => '预计到账 (USDT)',
'confirm_order' => '确认订单',
'recharge_request_sent' => '充值请求已提交给客服',
'back' => '返回',
'network' => '网络',
'address' => '充值地址',
'copy' => '复制',
'withdraw_amount' => '提现金额',
'withdraw_address' => '提现地址',
'receive' => '预计到账',
'withdraw_request_sent' => '提现申请已提交,请等待审核',
'all' => '全部',
'crypto_withdraw' => 'USDT提现',
'fiat_withdraw' => '法币提现',
'withdraw_password' => '提现密码',
'to_receive' => '预计到账',
'est_receive_fiat' => '预计收到法币',
'recharge_steps' => '充值步骤',
'withdraw_steps' => '提现步骤',
'security_tips' => '安全提示',
'secure' => '安全',
'fast' => '极速',
'support_247' => '24/7支持',
'i_have_paid' => '我已完成支付',
'crypto_recharge_warning' => '请务必仅向此地址发送 USDT。发送其他资产可能会导致永久丢失。',
'kyc' => '实名认证',
'security' => '安全设置',
'vip_level' => 'VIP等级',
'unverified' => '未认证',
'pending' => '审核中',
'verified' => '已认证',
'rejected' => '已驳回',
'full_name' => '真实姓名',
'id_number' => '身份证号',
'id_front' => '身份证正面',
'id_back' => '身份证反面',
'id_handheld' => '手持身份证',
'upload' => '点击上传',
'submit' => '提交',
'login_password' => '登录密码',
'trade_password' => '交易密码',
'change_password' => '修改密码',
'set_password' => '设置密码',
'kyc_instructions' => '请确保上传的照片清晰可见,且与填写的身份证号一致。',
'security_instructions' => '请定期修改您的密码,并确保交易密码与登录密码不同。',
'old_password' => '原密码',
'new_password' => '新密码',
'confirm_new_password' => '确认新密码',
'kyc_steps' => '实名认证步骤',
'kyc_step1' => '填写您的真实姓名和身份证号码。',
'kyc_step2' => '上传您的身份证正反面照片。',
'kyc_step3' => '上传您手持身份证的照片,并确保面部清晰。',
'security_steps' => '安全设置步骤',
'security_step1' => '设置强密码,包含字母、数字和符号。',
'security_step2' => '交易密码用于提现和重要操作,请务必妥善保存。',
'frozen' => '冻结',
'converted_to' => '折合',
],
'en' => [
'home' => 'Home',
@ -237,6 +314,83 @@ $translations = [
'buy_up' => 'Buy Up',
'buy_down' => 'Buy Down',
'profit' => 'Profit',
'enter_amount' => 'Please enter a valid amount',
'insufficient_balance' => 'Insufficient balance',
'order_in_progress' => 'Order in Progress',
'current_price' => 'Current Price',
'cycle' => 'Cycle',
'direction' => 'Direction',
'quantity' => 'Quantity',
'opening_price' => 'Opening Price',
'final_price_settlement' => 'Final price is subject to system settlement',
'open_orders' => 'Open Orders',
'settlement_history' => 'Settlement History',
'no_records_found' => 'No records found',
'executing' => 'Executing',
'loss' => 'Loss',
'amount_too_low' => 'Amount too low',
'amount_too_high' => 'Amount too high',
'fiat_recharge' => 'Fiat Deposit',
'crypto_recharge' => 'Crypto Deposit',
'select_currency' => 'Select Currency',
'fiat_amount' => 'Fiat Amount',
'est_usdt' => 'Estimated USDT',
'confirm_order' => 'Confirm Order',
'recharge_request_sent' => 'Deposit request sent to support',
'back' => 'Back',
'network' => 'Network',
'address' => 'Deposit Address',
'copy' => 'Copy',
'withdraw_amount' => 'Withdraw Amount',
'withdraw_address' => 'Withdraw Address',
'receive' => 'Receive',
'withdraw_request_sent' => 'Withdrawal request submitted for review',
'all' => 'All',
'crypto_withdraw' => 'USDT Withdrawal',
'fiat_withdraw' => 'Fiat Withdrawal',
'withdraw_password' => 'Withdrawal Password',
'to_receive' => 'To Receive',
'est_receive_fiat' => 'Est. Fiat Receive',
'recharge_steps' => 'Recharge Steps',
'withdraw_steps' => 'Withdrawal Steps',
'security_tips' => 'Security Tips',
'secure' => 'Secure',
'fast' => 'Fast',
'support_247' => '24/7 Support',
'i_have_paid' => 'I have paid',
'crypto_recharge_warning' => 'Please only send USDT to this address. Sending other assets may result in permanent loss.',
'kyc' => 'Identity Verification',
'security' => 'Security Settings',
'vip_level' => 'VIP Level',
'unverified' => 'Unverified',
'pending' => 'Pending',
'verified' => 'Verified',
'rejected' => 'Rejected',
'full_name' => 'Full Name',
'id_number' => 'ID Number',
'id_front' => 'ID Front',
'id_back' => 'ID Back',
'id_handheld' => 'Hand-held ID',
'upload' => 'Upload',
'submit' => 'Submit',
'login_password' => 'Login Password',
'trade_password' => 'Trade Password',
'change_password' => 'Change Password',
'set_password' => 'Set Password',
'kyc_instructions' => 'Please ensure that the uploaded photos are clear and consistent with the ID number filled in.',
'security_instructions' => 'Please change your password regularly and ensure that the transaction password is different from the login password.',
'old_password' => 'Old Password',
'new_password' => 'New Password',
'confirm_new_password' => 'Confirm New Password',
'kyc_steps' => 'KYC Steps',
'kyc_step1' => 'Fill in your real name and ID number.',
'kyc_step2' => 'Upload photos of the front and back of your ID card.',
'kyc_step3' => 'Upload a photo of you holding your ID card, ensuring your face is clear.',
'security_steps' => 'Security Steps',
'security_step1' => 'Set a strong password containing letters, numbers, and symbols.',
'security_step2' => 'The transaction password is used for withdrawals and important operations. Please keep it safe.',
'frozen' => 'Frozen',
'converted_to' => 'Equivalent',
]
];

View File

@ -4,6 +4,14 @@ function renderTerminal($activeTab = 'spot') {
$currentSymbol = $_GET['symbol'] ?? 'BTC';
$currentSymbol = strtoupper($currentSymbol);
$usdt_balance = 0;
if ($user) {
$stmt = db()->prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = 'USDT'");
$stmt->execute([$user['id']]);
$bal = $stmt->fetch();
$usdt_balance = $bal['available'] ?? 0;
}
$full_coins = [
['symbol' => 'BTC', 'name' => 'Bitcoin', 'price' => '64,234.50', 'change' => '+2.45%'],
['symbol' => 'ETH', 'name' => 'Ethereum', 'price' => '3,456.20', 'change' => '+1.12%'],
@ -113,41 +121,59 @@ function renderTerminal($activeTab = 'spot') {
<div class="trading-panels">
<?php if ($activeTab === 'binary'): ?>
<div class="binary-order-panel w-100">
<div class="section-title mb-2"><?= __('cycle_settlement') ?? 'Cycle / Settlement' ?></div>
<div class="cycle-grid mb-3">
<button class="cycle-btn active" onclick="selectCycle(this, 60, 8, '100-4999')">60S/8%</button>
<button class="cycle-btn" onclick="selectCycle(this, 90, 12, '5000-29999')">90S/12%</button>
<button class="cycle-btn" onclick="selectCycle(this, 120, 15, '30000-99999')">120S/15%</button>
<button class="cycle-btn" onclick="selectCycle(this, 180, 20, '100000-299999')">180S/20%</button>
<button class="cycle-btn" onclick="selectCycle(this, 300, 30, '300000+')">300S/30%</button>
<div class="d-flex justify-content-between align-items-end mb-2">
<div class="section-title text-white"><?= __('cycle_settlement') ?? 'Cycle / Settlement' ?></div>
<div class="small text-white"><?= __('available_balance') ?>: <span class="text-white fw-bold balance-highlight" id="user-usdt-balance"><?= number_format($usdt_balance, 2) ?></span> USDT</div>
</div>
<div class="cycle-grid">
<button class="cycle-btn active" onclick="selectCycle(this, 60, 8, 100, 4999)">
<span class="cycle-time">60S</span>
<span class="cycle-profit">8%</span>
</button>
<button class="cycle-btn" onclick="selectCycle(this, 90, 12, 5000, 29999)">
<span class="cycle-time">90S</span>
<span class="cycle-profit">12%</span>
</button>
<button class="cycle-btn" onclick="selectCycle(this, 120, 15, 30000, 99999)">
<span class="cycle-time">120S</span>
<span class="cycle-profit">15%</span>
</button>
<button class="cycle-btn" onclick="selectCycle(this, 180, 20, 100000, 299999)">
<span class="cycle-time">180S</span>
<span class="cycle-profit">20%</span>
</button>
<button class="cycle-btn" onclick="selectCycle(this, 300, 30, 300000, 999999999)">
<span class="cycle-time">300S</span>
<span class="cycle-profit">30%</span>
</button>
</div>
<div class="section-title mb-2"><?= __('purchase_amount') ?? 'Purchase Amount' ?> (USDT)</div>
<div class="section-title text-white mb-2"><?= __('purchase_amount') ?? 'Purchase Amount' ?> (USDT)</div>
<div class="amount-input-wrapper mb-3">
<input type="number" id="binary-amount" class="form-control bg-black text-white border-secondary" placeholder="100-4999" oninput="calculateProfit()">
<input type="number" id="binary-amount" class="form-control" placeholder="100-4999" oninput="calculateProfit()">
</div>
<div class="quick-amounts d-flex gap-2 mb-3">
<?php foreach([10, 50, 100, 300, 500, 1000] as $amt): ?>
<button class="btn btn-dark btn-sm flex-fill" onclick="setBinaryAmount(<?= $amt ?>)"><?= $amt ?></button>
<?php foreach([100, 500, 1000, 5000, 10000, 50000] as $amt): ?>
<button class="btn btn-dark btn-sm flex-fill py-2" onclick="setBinaryAmount(<?= $amt ?>)"><?= $amt ?></button>
<?php endforeach; ?>
</div>
<div class="d-flex justify-content-between mb-3 small align-items-center">
<div class="text-muted"><?= __('available_balance') ?> <span class="text-white ms-1 fw-bold">1,000.00</span> USDT</div>
<div class="text-muted"><span class="text-success fw-bold fs-6" id="profit-display">0.00</span> USDT</div>
<div class="d-flex justify-content-between mb-3 small align-items-center bg-black bg-opacity-25 p-2 rounded">
<div class="text-white"><?= __('expected_profit') ?? 'Expected Profit' ?></div>
<div class="text-success fw-bold fs-6 profit-highlight" id="profit-display">0.00 USDT</div>
</div>
<div class="row g-2">
<div class="col-6">
<button class="btn btn-success w-100 py-3 fw-bold rounded-3 h-100 d-flex flex-column align-items-center justify-content-center">
<div class="fs-5"><?= __('buy_up') ?></div>
<button onclick="placeOrder('up')" class="btn btn-success btn-buy-sell w-100 fw-bold d-flex flex-column align-items-center justify-content-center">
<div class="fs-5"><i class="bi bi-graph-up-arrow me-1"></i><?= __('buy_up') ?></div>
<div class="small opacity-75 fw-normal profit-rate-hint"><?= __('profit') ?> 8%</div>
</button>
</div>
<div class="col-6">
<button class="btn btn-danger w-100 py-3 fw-bold rounded-3 h-100 d-flex flex-column align-items-center justify-content-center">
<div class="fs-5"><?= __('buy_down') ?></div>
<button onclick="placeOrder('down')" class="btn btn-danger btn-buy-sell w-100 fw-bold d-flex flex-column align-items-center justify-content-center">
<div class="fs-5"><i class="bi bi-graph-down-arrow me-1"></i><?= __('buy_down') ?></div>
<div class="small opacity-75 fw-normal profit-rate-hint"><?= __('profit') ?> 8%</div>
</button>
</div>
@ -156,13 +182,21 @@ function renderTerminal($activeTab = 'spot') {
<script>
let currentProfitRate = 8;
function selectCycle(btn, seconds, profit, hint) {
let currentSeconds = 60;
let minAmount = 100;
let maxAmount = 4999;
function selectCycle(btn, seconds, profit, min, max) {
document.querySelectorAll('.cycle-btn').forEach(el => el.classList.remove('active'));
btn.classList.add('active');
currentProfitRate = profit;
currentSeconds = seconds;
minAmount = min;
maxAmount = max;
const hint = max >= 999999999 ? min + '+' : min + '-' + max;
document.getElementById('binary-amount').placeholder = hint;
// Update profit hints on buttons
document.querySelectorAll('.profit-rate-hint').forEach(el => {
el.innerText = '<?= __("profit") ?> ' + profit + '%';
});
@ -179,6 +213,136 @@ function renderTerminal($activeTab = 'spot') {
const profit = (amount * currentProfitRate / 100).toFixed(2);
document.getElementById('profit-display').innerText = profit + ' USDT';
}
function placeOrder(direction) {
const amount = parseFloat(document.getElementById('binary-amount').value);
const balance = parseFloat(document.getElementById('user-usdt-balance').innerText.replace(',', ''));
if (!amount || amount <= 0) {
alert('<?= __("enter_amount") ?? "Please enter a valid amount" ?>');
return;
}
if (amount < minAmount) {
alert('<?= __("amount_too_low") ?> (' + minAmount + ')');
return;
}
if (amount > maxAmount) {
alert('<?= __("amount_too_high") ?> (' + maxAmount + ')');
return;
}
if (amount > balance) {
alert('<?= __("insufficient_balance") ?? "Insufficient balance" ?>');
return;
}
const openPrice = document.querySelector('.price-jump').innerText;
// Simulation of order placement
const order = {
id: Math.floor(Math.random() * 1000000),
time: new Date().toISOString().replace('T', ' ').substr(0, 19),
pair: '<?= $currentSymbol ?>/USDT',
type: 'Binary',
side: direction === 'up' ? '<?= __("buy_up") ?>' : '<?= __("buy_down") ?>',
side_type: direction,
price: openPrice,
amount: amount.toFixed(2),
total: '---',
status: 'Executing',
secondsLeft: currentSeconds,
totalSeconds: currentSeconds,
profitRate: currentProfitRate
};
historyData.open.unshift(order);
showHistoryTab('open');
// Show Popup
showOrderPopup(order);
// Deduct balance visually
document.getElementById('user-usdt-balance').innerText = (balance - amount).toLocaleString('en-US', {minimumFractionDigits: 2});
// Timer for settlement
const timer = setInterval(() => {
order.secondsLeft--;
// Update popup
updateOrderPopup(order);
if (showHistoryTab.currentTab === 'open') showHistoryTab('open');
if (order.secondsLeft <= 0) {
clearInterval(timer);
settleOrder(order);
hideOrderPopup();
}
}, 1000);
}
function showOrderPopup(order) {
const popup = document.getElementById('order-popup-overlay');
const sideColor = order.side.includes('Up') || order.side.includes('涨') ? '#26a69a' : '#ef5350';
document.getElementById('popup-price').innerText = order.price;
document.getElementById('popup-cycle').innerText = order.totalSeconds + 's';
document.getElementById('popup-direction').innerText = order.side;
document.getElementById('popup-direction').style.color = sideColor;
document.getElementById('popup-quantity').innerText = order.amount + ' USDT';
document.getElementById('popup-open-price').innerText = order.price;
popup.style.display = 'flex';
updateOrderPopup(order);
}
function updateOrderPopup(order) {
const timeText = document.getElementById('popup-time-text');
const progress = document.getElementById('popup-progress');
const currentPrice = document.getElementById('popup-price');
timeText.innerText = order.secondsLeft + 's';
// Update current price in popup
currentPrice.innerText = document.querySelector('.price-jump').innerText;
const radius = 70;
const circumference = 2 * Math.PI * radius;
const offset = circumference - (order.secondsLeft / order.totalSeconds) * circumference;
progress.style.strokeDasharray = `${circumference} ${circumference}`;
progress.style.strokeDashoffset = offset;
}
function hideOrderPopup() {
document.getElementById('order-popup-overlay').style.display = 'none';
}
function settleOrder(order) {
const isWin = Math.random() > 0.45; // 55% win rate for simulation
const amount = parseFloat(order.amount);
const profit = isWin ? (amount * order.profitRate / 100) : -amount;
order.status = isWin ? 'Profit' : 'Loss';
order.total = isWin ? (amount + profit).toFixed(2) : '0.00';
order.timeSettled = new Date().toISOString().replace('T', ' ').substr(0, 19);
// Move from open to settlement
historyData.open = historyData.open.filter(o => o.id !== order.id);
historyData.settlement.unshift(order);
if (showHistoryTab.currentTab === 'open' || showHistoryTab.currentTab === 'settlement') {
showHistoryTab(showHistoryTab.currentTab);
}
// Update balance visually if win
if (isWin) {
const balance = parseFloat(document.getElementById('user-usdt-balance').innerText.replace(',', ''));
document.getElementById('user-usdt-balance').innerText = (balance + amount + profit).toLocaleString('en-US', {minimumFractionDigits: 2});
}
}
</script>
<?php else: ?>
@ -188,7 +352,7 @@ function renderTerminal($activeTab = 'spot') {
<button class="active btn btn-sm btn-outline-secondary py-1 px-3">Limit</button>
<button class="btn btn-sm btn-outline-secondary py-1 px-3">Market</button>
</div>
<div class="small text-muted"><?= __('assets') ?>: <span class="text-white">1,000.00 USDT</span></div>
<div class="small text-muted"><?= __('assets') ?>: <span class="text-white"><?= number_format($usdt_balance, 2) ?> USDT</span></div>
</div>
<div class="row g-3">
<div class="col-6">
@ -241,26 +405,68 @@ function renderTerminal($activeTab = 'spot') {
</div>
<script>
// Simulating price jump
setInterval(() => {
const el = document.querySelector('.price-jump');
if (!el) return;
const current = parseFloat(el.innerText.replace(',', ''));
const diff = (Math.random() - 0.5) * 10;
const next = (current + diff).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
el.innerText = next;
el.style.color = diff > 0 ? '#26a69a' : '#ef5350';
setTimeout(() => el.style.color = '#26a69a', 500);
}, 2000);
// Real-time market price fetcher
async function updateMarketPrices() {
try {
const response = await fetch('https://api.binance.com/api/v3/ticker/24hr');
const data = await response.json();
const prices = {};
data.forEach(item => {
if (item.symbol.endsWith('USDT')) {
const base = item.symbol.replace('USDT', '');
prices[base] = {
price: parseFloat(item.lastPrice),
change: item.priceChangePercent
};
}
});
// Update Sidebar
document.querySelectorAll('.coin-row').forEach(row => {
const symbol = row.querySelector('.symbol').innerText;
if (prices[symbol]) {
const p = prices[symbol].price;
const c = prices[symbol].change;
row.querySelector('.price').innerText = p < 1 ? p.toFixed(6) : p.toLocaleString('en-US', {minimumFractionDigits: 2});
const changeEl = row.querySelector('.change');
changeEl.innerText = (c > 0 ? '+' : '') + c + '%';
changeEl.className = 'change ' + (c >= 0 ? 'text-success' : 'text-danger');
}
});
// Update Header for current symbol
const currentSymbol = '<?= $currentSymbol ?>';
if (prices[currentSymbol]) {
const p = prices[currentSymbol].price;
const c = prices[currentSymbol].change;
const priceEl = document.querySelector('.price-jump');
if (priceEl) {
const oldPrice = parseFloat(priceEl.innerText.replace(',', ''));
priceEl.innerText = p < 1 ? p.toFixed(6) : p.toLocaleString('en-US', {minimumFractionDigits: 2});
priceEl.style.color = p >= oldPrice ? '#26a69a' : '#ef5350';
setTimeout(() => priceEl.style.color = '#26a69a', 800);
}
const headerStats = document.querySelectorAll('.header-stat span');
if (headerStats[1]) {
headerStats[1].innerText = (c > 0 ? '+' : '') + c + '%';
headerStats[1].className = (c >= 0 ? 'text-success' : 'text-danger') + ' fw-bold';
}
}
} catch (e) {
console.error("Failed to fetch prices", e);
}
}
setInterval(updateMarketPrices, 3000);
updateMarketPrices();
</script>
<div class="order-history p-0">
<div class="d-flex gap-0 border-bottom border-secondary bg-dark history-tabs">
<h6 class="px-4 py-3 mb-0 active text-primary bg-black" onclick="showHistoryTab('open')" id="tab-open" style="cursor: pointer; font-size: 13px; font-weight: bold; border-bottom: 2px solid var(--term-primary) !important;">当前委托 (Open Orders)</h6>
<h6 class="px-4 py-3 mb-0 text-muted" onclick="showHistoryTab('settlement')" id="tab-settlement" style="cursor: pointer; font-size: 13px;">结算部位 (Settlement)</h6>
<h6 class="px-4 py-3 mb-0 text-muted" onclick="showHistoryTab('history')" id="tab-history" style="cursor: pointer; font-size: 13px;">成交历史 (Trade History)</h6>
<h6 class="px-4 py-3 mb-0 text-muted" onclick="showHistoryTab('assets')" id="tab-assets" style="cursor: pointer; font-size: 13px;">资产 (Assets)</h6>
<h6 class="px-4 py-3 mb-0 active text-white bg-black" onclick="showHistoryTab('open')" id="tab-open" style="cursor: pointer; font-size: 13px; font-weight: bold; border-bottom: 2px solid var(--term-primary) !important;"><?= __('open_orders') ?></h6>
<h6 class="px-4 py-3 mb-0 text-white opacity-75" onclick="showHistoryTab('settlement')" id="tab-settlement" style="cursor: pointer; font-size: 13px;"><?= __('settlement_history') ?></h6>
</div>
<div class="table-responsive">
<table class="table table-dark table-sm mb-0" id="history-table" style="font-size: 12px;">
@ -329,56 +535,72 @@ function renderTerminal($activeTab = 'spot') {
<script>
const historyData = {
open: [
{time: '2026-02-16 15:45:12', pair: 'BTC/USDT', type: 'Limit', side: 'Buy', price: '64,100.00', amount: '0.5000', total: '32,050.00', status: 'Pending'},
{time: '2026-02-16 15:40:05', pair: '<?= $currentSymbol ?>/USDT', type: 'Limit', side: 'Sell', price: '64,500.00', amount: '0.2500', total: '16,125.00', status: 'Pending'}
],
settlement: [
{time: '2026-02-16 14:30:11', pair: 'BTC/USDT', type: 'Binary', side: 'Buy Up', price: '64,234.50', amount: '100.00', total: '108.00', status: 'Profit'},
{time: '2026-02-16 13:15:22', pair: 'ETH/USDT', type: 'Binary', side: 'Buy Down', price: '3,456.20', amount: '50.00', total: '0.00', status: 'Loss'}
],
history: [
{time: '2026-02-16 12:00:00', pair: 'SOL/USDT', type: 'Market', side: 'Buy', price: '142.30', amount: '100.00', total: '14,230.00', status: 'Filled'}
],
assets: [
{time: '-', pair: 'USDT', type: 'Wallet', side: '-', price: '1.00', amount: '1,000.00', total: '1,000.00', status: 'Available'},
{time: '-', pair: 'BTC', type: 'Wallet', side: '-', price: '64,234.50', amount: '0.0500', total: '3,211.73', status: 'Available'}
]
open: [],
settlement: []
};
function showHistoryTab(tab) {
showHistoryTab.currentTab = tab;
// Update tabs UI
document.querySelectorAll('.history-tabs h6').forEach(el => {
el.classList.remove('active', 'text-primary', 'bg-black');
el.classList.add('text-muted');
el.classList.remove('active', 'text-white', 'bg-black', 'opacity-100');
el.classList.add('text-white', 'opacity-75');
el.style.borderBottom = 'none';
});
const activeTab = document.getElementById('tab-' + tab);
activeTab.classList.add('active', 'text-primary', 'bg-black');
activeTab.classList.remove('text-muted');
activeTab.style.borderBottom = '2px solid var(--term-primary)';
if (activeTab) {
activeTab.classList.add('active', 'text-white', 'bg-black', 'opacity-100');
activeTab.classList.remove('opacity-75');
activeTab.style.borderBottom = '2px solid var(--term-primary)';
}
// Update table content
const body = document.getElementById('history-body');
body.innerHTML = '';
if (!historyData[tab] || historyData[tab].length === 0) {
body.innerHTML = '<tr><td colspan="9" class="text-center py-5 text-muted">No records found</td></tr>';
body.innerHTML = '<tr><td colspan="9" class="text-center py-5 text-muted"><?= __("no_records_found") ?? "No records found" ?></td></tr>';
return;
}
historyData[tab].forEach(row => {
const tr = document.createElement('tr');
const isProfit = row.status === 'Profit';
const isLoss = row.status === 'Loss';
const isExecuting = row.status === 'Executing';
const statusClass = isProfit ? 'text-success' : (isLoss ? 'text-danger' : 'text-info');
const statusBg = isProfit ? 'bg-success' : (isLoss ? 'bg-danger' : 'bg-info');
let displayStatus = row.status;
if (isExecuting) displayStatus = '<?= __("executing") ?? "Executing" ?> (' + row.secondsLeft + 's)';
if (isProfit) displayStatus = '<?= __("profit") ?>';
if (isLoss) displayStatus = '<?= __("loss") ?? "Loss" ?>';
// Format total/profit for settled orders
let totalDisplay = row.total;
if (tab === 'settlement' && (isProfit || isLoss)) {
const amount = parseFloat(row.amount);
const total = parseFloat(row.total);
const pl = (total - amount).toFixed(2);
const plClass = pl >= 0 ? 'text-success' : 'text-danger';
totalDisplay = `<div class="${plClass} fw-bold">${total.toFixed(2)}</div><div class="small opacity-75">${pl >= 0 ? '+' : ''}${pl}</div>`;
}
const isUp = row.side_type === 'up' || row.side.includes('Up') || row.side.includes('涨') || row.side === 'Buy';
tr.innerHTML = `
<td class="ps-3 py-3 text-muted">${row.time}</td>
<td class="ps-3 py-3 text-muted" style="font-size: 11px;">${row.time}</td>
<td class="py-3 fw-bold text-white">${row.pair}</td>
<td class="py-3">${row.type}</td>
<td class="py-3 ${row.side === 'Buy' ? 'text-success' : (row.side === 'Sell' ? 'text-danger' : 'text-white')}">${row.side}</td>
<td class="py-3"><span class="small bg-secondary bg-opacity-25 px-1 rounded">${row.type}</span></td>
<td class="py-3 ${isUp ? 'text-success' : 'text-danger'}">
<i class="bi bi-graph-${isUp ? 'up' : 'down'} me-1"></i>${row.side}
</td>
<td class="py-3">${row.price}</td>
<td class="py-3">${row.amount}</td>
<td class="py-3">${row.total}</td>
<td class="py-3"><span class="badge bg-success bg-opacity-10 text-success">${row.status}</span></td>
<td class="pe-3 py-3 text-end"><button class="btn btn-sm btn-link text-muted p-0">Details</button></td>
<td class="py-3">${totalDisplay}</td>
<td class="py-3"><span class="badge ${statusBg} bg-opacity-10 ${statusClass} rounded-pill px-2" style="font-size: 10px;">${displayStatus}</span></td>
<td class="pe-3 py-3 text-end"><button class="btn btn-sm btn-dark px-2 py-0" style="font-size: 10px;">Details</button></td>
`;
body.appendChild(tr);
});
@ -387,6 +609,48 @@ function renderTerminal($activeTab = 'spot') {
// Initialize with open orders
showHistoryTab('open');
</script>
<!-- Order Countdown Popup Modal -->
<div class="order-popup-overlay" id="order-popup-overlay">
<div class="order-popup">
<h5><?= __('order_in_progress') ?></h5>
<div class="countdown-circle">
<svg>
<circle class="bg" cx="80" cy="80" r="70"></circle>
<circle class="progress" id="popup-progress" cx="80" cy="80" r="70"></circle>
</svg>
<div class="time-text" id="popup-time-text">60s</div>
</div>
<div class="popup-details">
<div class="popup-row">
<span class="label"><?= __('current_price') ?></span>
<span class="value" id="popup-price">---</span>
</div>
<div class="popup-row">
<span class="label"><?= __('cycle') ?></span>
<span class="value" id="popup-cycle">60s</span>
</div>
<div class="popup-row">
<span class="label"><?= __('direction') ?></span>
<span class="value" id="popup-direction">---</span>
</div>
<div class="popup-row">
<span class="label"><?= __('quantity') ?></span>
<span class="value" id="popup-quantity">---</span>
</div>
<div class="popup-row">
<span class="label"><?= __('opening_price') ?></span>
<span class="value" id="popup-open-price">---</span>
</div>
</div>
<div class="popup-footer">
<?= __('final_price_settlement') ?>
</div>
</div>
</div>
<?php
}
?>

203
kyc.php Normal file
View File

@ -0,0 +1,203 @@
<?php
include __DIR__ . '/includes/header.php';
if (!$user) {
header('Location: /auth/login.php');
exit;
}
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user['id']]);
$userData = $stmt->fetch();
$success = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$real_name = $_POST['real_name'] ?? '';
$id_number = $_POST['id_number'] ?? '';
// Handle uploads
$uploadDir = 'uploads/kyc/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0777, true);
$front = $userData['kyc_photo_front'];
$back = $userData['kyc_photo_back'];
$handheld = $userData['kyc_photo_handheld'];
if (isset($_FILES['photo_front']) && $_FILES['photo_front']['error'] === 0) {
$ext = pathinfo($_FILES['photo_front']['name'], PATHINFO_EXTENSION);
$front = $uploadDir . $user['id'] . '_front_' . time() . '.' . $ext;
move_uploaded_file($_FILES['photo_front']['tmp_name'], $front);
}
if (isset($_FILES['photo_back']) && $_FILES['photo_back']['error'] === 0) {
$ext = pathinfo($_FILES['photo_back']['name'], PATHINFO_EXTENSION);
$back = $uploadDir . $user['id'] . '_back_' . time() . '.' . $ext;
move_uploaded_file($_FILES['photo_back']['tmp_name'], $back);
}
if (isset($_FILES['photo_handheld']) && $_FILES['photo_handheld']['error'] === 0) {
$ext = pathinfo($_FILES['photo_handheld']['name'], PATHINFO_EXTENSION);
$handheld = $uploadDir . $user['id'] . '_handheld_' . time() . '.' . $ext;
move_uploaded_file($_FILES['photo_handheld']['tmp_name'], $handheld);
}
if (empty($real_name) || empty($id_number)) {
$error = "Please fill in all fields";
} else {
$stmt = db()->prepare("UPDATE users SET kyc_name = ?, kyc_id_number = ?, kyc_photo_front = ?, kyc_photo_back = ?, kyc_photo_handheld = ?, kyc_status = 1 WHERE id = ?");
$stmt->execute([$real_name, $id_number, $front, $back, $handheld, $user['id']]);
$success = "Verification request submitted successfully!";
// Refresh user data
$userData['kyc_status'] = 1;
}
}
$kycStatus = $userData['kyc_status'] ?? 0;
?>
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="mb-4">
<a href="/profile.php" class="text-white-50 text-decoration-none d-inline-flex align-items-center gap-2">
<i class="bi bi-arrow-left fs-4"></i>
<span><?= __('back') ?></span>
</a>
</div>
<div class="card bg-surface border-secondary rounded-4 shadow-lg overflow-hidden">
<div class="card-header border-secondary bg-black bg-opacity-20 p-4">
<h4 class="mb-0 fw-bold d-flex align-items-center gap-3 text-white">
<i class="bi bi-person-vcard text-primary"></i>
<?= __('kyc') ?>
</h4>
</div>
<div class="card-body p-4 p-md-5">
<?php if ($success): ?>
<div class="alert alert-success border-0 bg-success bg-opacity-10 text-success rounded-4 mb-4">
<i class="bi bi-check-circle-fill me-2"></i><?= $success ?>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger border-0 bg-danger bg-opacity-10 text-danger rounded-4 mb-4">
<i class="bi bi-exclamation-triangle-fill me-2"></i><?= $error ?>
</div>
<?php endif; ?>
<?php if ($kycStatus == 2): ?>
<div class="text-center py-5">
<i class="bi bi-patch-check-fill text-success" style="font-size: 80px;"></i>
<h3 class="text-white fw-bold mt-4"><?= __('verified') ?></h3>
<p class="text-white-50"><?= htmlspecialchars($userData['kyc_name']) ?> (<?= htmlspecialchars($userData['kyc_id_number']) ?>)</p>
</div>
<?php elseif ($kycStatus == 1): ?>
<div class="text-center py-5">
<i class="bi bi-clock-history text-warning" style="font-size: 80px;"></i>
<h3 class="text-white fw-bold mt-4"><?= __('pending') ?></h3>
<p class="text-white-50">Your application is being reviewed by our team.</p>
</div>
<?php else: ?>
<form method="POST" enctype="multipart/form-data">
<div class="row g-4 mb-4">
<div class="col-md-6">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('full_name') ?></label>
<input type="text" name="real_name" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" placeholder="Enter your full name" required>
</div>
<div class="col-md-6">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('id_number') ?></label>
<input type="text" name="id_number" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" placeholder="Enter your ID number" required>
</div>
</div>
<div class="row g-4 mb-5">
<div class="col-md-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('id_front') ?></label>
<div class="upload-area border-secondary rounded-4 p-4 text-center border-dashed position-relative" style="border: 2px dashed #2b3139; cursor: pointer;">
<input type="file" name="photo_front" class="position-absolute w-100 h-100 top-0 start-0 opacity-0" style="cursor: pointer;" required onchange="previewImg(this)">
<div class="preview-content">
<i class="bi bi-image text-white-50 fs-1 mb-2 d-block"></i>
<span class="text-white-50 small"><?= __('upload') ?></span>
</div>
<img class="img-preview d-none w-100 rounded-3 shadow" style="object-fit: cover;">
</div>
</div>
<div class="col-md-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('id_back') ?></label>
<div class="upload-area border-secondary rounded-4 p-4 text-center border-dashed position-relative" style="border: 2px dashed #2b3139; cursor: pointer;">
<input type="file" name="photo_back" class="position-absolute w-100 h-100 top-0 start-0 opacity-0" style="cursor: pointer;" required onchange="previewImg(this)">
<div class="preview-content">
<i class="bi bi-image text-white-50 fs-1 mb-2 d-block"></i>
<span class="text-white-50 small"><?= __('upload') ?></span>
</div>
<img class="img-preview d-none w-100 rounded-3 shadow" style="object-fit: cover;">
</div>
</div>
<div class="col-md-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('id_handheld') ?></label>
<div class="upload-area border-secondary rounded-4 p-4 text-center border-dashed position-relative" style="border: 2px dashed #2b3139; cursor: pointer;">
<input type="file" name="photo_handheld" class="position-absolute w-100 h-100 top-0 start-0 opacity-0" style="cursor: pointer;" required onchange="previewImg(this)">
<div class="preview-content">
<i class="bi bi-image text-white-50 fs-1 mb-2 d-block"></i>
<span class="text-white-50 small"><?= __('upload') ?></span>
</div>
<img class="img-preview d-none w-100 rounded-3 shadow" style="object-fit: cover;">
</div>
</div>
</div>
<div class="bg-black bg-opacity-20 rounded-4 p-4 mb-5 border border-secondary border-opacity-50">
<h6 class="text-white fw-bold mb-3 d-flex align-items-center gap-2">
<i class="bi bi-info-circle text-primary"></i> <?= __('kyc_steps') ?>
</h6>
<ul class="text-white-50 small mb-0 ps-3">
<li class="mb-2"><?= __('kyc_step1') ?></li>
<li class="mb-2"><?= __('kyc_step2') ?></li>
<li><?= __('kyc_step3') ?></li>
</ul>
</div>
<button type="submit" class="btn btn-primary w-100 py-3 rounded-pill fw-bold shadow-primary">
<?= __('submit') ?>
</button>
</form>
<?php endif; ?>
</div>
</div>
<!-- Additional Instructions Section -->
<div class="card bg-surface border-secondary rounded-4 mt-4">
<div class="card-body p-4">
<h6 class="text-white fw-bold mb-3"><i class="bi bi-shield-check text-success me-2"></i> <?= __('kyc_instructions') ?? 'Certification Instructions' ?></h6>
<p class="text-white-50 small mb-0">
<?= __('kyc_instructions') ?>
</p>
</div>
</div>
</div>
</div>
</div>
<script>
function previewImg(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
var parent = input.closest('.upload-area');
var preview = parent.querySelector('.img-preview');
var content = parent.querySelector('.preview-content');
reader.onload = function(e) {
preview.src = e.target.result;
preview.classList.remove('d-none');
content.classList.add('d-none');
}
reader.readAsDataURL(input.files[0]);
}
}
</script>
<?php include __DIR__ . '/includes/footer.php'; ?>

View File

@ -6,113 +6,163 @@ if (!$user) {
exit;
}
// Get user data again to ensure we have latest fields
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user['id']]);
$userData = $stmt->fetch();
// Get balances
$stmt = db()->prepare("SELECT * FROM user_balances WHERE user_id = ?");
$stmt->execute([$user['id']]);
$balances = $stmt->fetchAll();
// Total USDT Balance calculation
$totalBalanceUsdt = 0;
foreach ($balances as $b) {
if ($b['symbol'] === 'USDT') {
$totalBalanceUsdt += $b['available'] + $b['frozen'];
}
}
function getVipLevel($totalRecharge) {
if ($totalRecharge >= 10000000) return 7;
if ($totalRecharge >= 5000000) return 6;
if ($totalRecharge >= 1000000) return 5;
if ($totalRecharge >= 500000) return 4;
if ($totalRecharge >= 100000) return 3;
if ($totalRecharge >= 50000) return 2;
if ($totalRecharge >= 10001) return 1;
return 0;
}
$vipLevel = getVipLevel($userData['total_recharge'] ?? 0);
$kycStatusText = [
0 => __('unverified'),
1 => __('pending'),
2 => __('verified'),
3 => __('rejected')
];
$kycStatusColor = [
0 => 'text-white-50',
1 => 'text-warning',
2 => 'text-success',
3 => 'text-danger'
];
?>
<div class="container py-5">
<div class="container py-4">
<div class="row g-4">
<!-- User Info Card -->
<div class="col-lg-4">
<div class="card bg-dark border-0 shadow-lg h-100" style="background: #161a1e !important; border: 1px solid #2b3139 !important; border-radius: 24px;">
<div class="card-body p-4 text-center">
<div class="position-relative d-inline-block mb-3">
<div class="rounded-circle bg-primary d-flex align-items-center justify-content-center text-white shadow-lg" style="width: 100px; height: 100px; font-size: 40px; background: linear-gradient(135deg, #0062ff, #00d2ff) !important;">
<?= strtoupper(substr($user['username'], 0, 1)) ?>
</div>
<div class="position-absolute bottom-0 end-0 bg-success border border-4 border-dark rounded-circle" style="width: 25px; height: 25px;"></div>
</div>
<h3 class="fw-bold text-white mb-1"><?= htmlspecialchars($user['username']) ?></h3>
<p class="text-muted small mb-4"><?= htmlspecialchars($user['email'] ?? 'No email linked') ?></p>
<div class="bg-black bg-opacity-25 rounded-4 p-3 mb-4 text-start border border-secondary border-opacity-25">
<div class="d-flex justify-content-between mb-2 small">
<span class="text-muted">UID</span>
<span class="text-white fw-bold"><?= $user['uid'] ?? ($user['id'] + 10000) ?></span>
</div>
<div class="d-flex justify-content-between mb-2 small">
<span class="text-muted">Account Status</span>
<span class="text-success fw-bold"><i class="bi bi-patch-check-fill me-1"></i>Verified</span>
</div>
<div class="d-flex justify-content-between small">
<span class="text-muted">Credit Score</span>
<span class="text-primary fw-bold"><?= $user['credit_score'] ?? 80 ?></span>
<!-- Sidebar -->
<div class="col-lg-3">
<div class="card bg-surface border-secondary rounded-4 overflow-hidden h-100">
<div class="card-body p-0">
<!-- User Header -->
<div class="p-4 text-center border-bottom border-secondary bg-black bg-opacity-20">
<div class="avatar-wrapper mb-3 mx-auto">
<div class="rounded-circle bg-primary bg-gradient d-flex align-items-center justify-content-center text-white shadow" style="width: 80px; height: 80px; font-size: 32px;">
<?= strtoupper(substr($userData['username'], 0, 1)) ?>
</div>
</div>
<h5 class="fw-bold text-white mb-0"><?= htmlspecialchars($userData['username']) ?></h5>
</div>
<div class="d-grid gap-2">
<button class="btn btn-outline-secondary rounded-pill py-2 small fw-bold">Security Settings</button>
<button class="btn btn-outline-danger border-0 rounded-pill py-2 small fw-bold" onclick="location.href='/auth/logout.php'">Logout</button>
<!-- Menu List -->
<div class="list-group list-group-flush bg-transparent">
<div class="list-group-item bg-transparent border-secondary py-3 d-flex justify-content-between align-items-center">
<span class="text-white-50 small"><i class="bi bi-person-badge me-2 text-primary"></i>UID</span>
<span class="text-white fw-bold small"><?= $userData['uid'] ?></span>
</div>
<div class="list-group-item bg-transparent border-secondary py-3 d-flex justify-content-between align-items-center">
<span class="text-white-50 small"><i class="bi bi-shield-check me-2 text-info"></i><?= __('credit_score') ?></span>
<span class="text-info fw-bold small"><?= $userData['credit_score'] ?></span>
</div>
<div class="list-group-item bg-transparent border-secondary py-3 d-flex justify-content-between align-items-center">
<span class="text-white-50 small"><i class="bi bi-gem me-2 text-warning"></i><?= __('vip_level') ?></span>
<span class="badge bg-warning text-dark fw-bold">VIP <?= $vipLevel ?></span>
</div>
<a href="/kyc.php" class="list-group-item list-group-item-action bg-transparent border-secondary py-3 d-flex justify-content-between align-items-center text-white">
<span class="text-white-50 small"><i class="bi bi-person-vcard me-2 text-success"></i><?= __('kyc') ?></span>
<span class="small <?= $kycStatusColor[$userData['kyc_status'] ?? 0] ?>">
<?= $kycStatusText[$userData['kyc_status'] ?? 0] ?> <i class="bi bi-chevron-right ms-1"></i>
</span>
</a>
<a href="/security.php" class="list-group-item list-group-item-action bg-transparent border-secondary py-3 d-flex justify-content-between align-items-center text-white">
<span class="text-white-50 small"><i class="bi bi-lock me-2 text-danger"></i><?= __('security') ?></span>
<span class="text-white-50 small"><i class="bi bi-chevron-right"></i></span>
</a>
<a href="/auth/logout.php" class="list-group-item list-group-item-action bg-transparent border-0 py-3 d-flex justify-content-between align-items-center text-danger">
<span class="small"><i class="bi bi-box-arrow-right me-2"></i><?= __('logout') ?></span>
<span class="small"><i class="bi bi-chevron-right"></i></span>
</a>
</div>
</div>
</div>
</div>
<!-- Assets Card -->
<div class="col-lg-8">
<div class="card bg-dark border-0 shadow-lg h-100" style="background: #161a1e !important; border: 1px solid #2b3139 !important; border-radius: 24px;">
<!-- Main Content -->
<div class="col-lg-9">
<!-- Asset Summary -->
<div class="card bg-surface border-secondary rounded-4 mb-4">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="fw-bold text-white m-0">Wallet Balances</h4>
<div class="btn-group">
<button class="btn btn-primary btn-sm px-3 rounded-pill me-2"><?= __('deposit') ?></button>
<button class="btn btn-outline-light btn-sm px-3 rounded-pill"><?= __('withdraw') ?></button>
<div class="row align-items-center">
<div class="col-md-6">
<p class="text-white-50 small mb-1"><?= __('balance') ?> (USDT)</p>
<h2 class="text-white fw-bold mb-0"> <?= number_format($totalBalanceUsdt, 2) ?> <span class="fs-6 fw-normal text-white-50">USDT</span></h2>
</div>
<div class="col-md-6 text-md-end mt-3 mt-md-0">
<a href="/recharge.php" class="btn btn-primary rounded-pill px-4 me-2">
<i class="bi bi-plus-circle me-2"></i><?= __('deposit') ?>
</a>
<a href="/withdraw.php" class="btn btn-outline-light rounded-pill px-4">
<i class="bi bi-arrow-up-circle me-2"></i><?= __('withdraw') ?>
</a>
</div>
</div>
<div class="table-responsive">
<table class="table table-dark table-hover mb-0 align-middle">
<thead style="background: rgba(255,255,255,0.02);">
<tr class="text-muted small border-0">
<th class="ps-3 py-3 border-0">Asset</th>
<th class="py-3 border-0 text-center">Icon</th>
<th class="py-3 border-0">Available</th>
<th class="py-3 border-0">Frozen</th>
<th class="text-end pe-3 py-3 border-0">Action</th>
</tr>
</thead>
<tbody class="border-0">
<?php
$icons = [
'USDT' => '325/small/tether.png',
'BTC' => '1/small/bitcoin.png',
'ETH' => '279/small/ethereum.png',
'BNB' => '825/small/binance-coin-logo.png'
];
foreach($balances as $b):
?>
<tr style="border-bottom: 1px solid rgba(255,255,255,0.05);">
<td class="ps-3 py-4 border-0">
<div class="fw-bold text-white fs-5"><?= $b['symbol'] ?></div>
</td>
<td class="py-4 border-0 text-center">
<img src="<?= getCoinIcon($b['symbol']) ?>" width="24" height="24">
</td>
<td class="py-4 border-0">
<div class="fw-bold text-white"><?= number_format((float)$b['available'], 4) ?></div>
</td>
<td class="py-4 border-0 text-muted small">
<?= number_format((float)$b['frozen'], 4) ?>
</td>
<td class="text-end pe-3 border-0">
<a href="/trade.php?symbol=<?= $b['symbol'] ?>" class="btn btn-outline-primary btn-sm px-3 rounded-pill"><?= __('trade') ?></a>
</td>
</tr>
<?php endforeach; ?>
</div>
</div>
<?php if (empty($balances)): ?>
<tr>
<td colspan="5" class="py-5 text-center text-muted">
<i class="bi bi-wallet2 fs-1 d-block mb-2"></i>
No assets found in your wallet.
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Asset Table -->
<div class="card bg-surface border-secondary rounded-4 overflow-hidden">
<div class="table-responsive">
<table class="table table-dark table-hover mb-0 align-middle">
<thead class="bg-black bg-opacity-40 text-white-50 small border-secondary">
<tr>
<th class="ps-4 py-3 border-secondary text-white"><?= __('coin') ?></th>
<th class="py-3 border-secondary text-white"><?= __('available_balance') ?></th>
<th class="py-3 border-secondary text-white"><?= __('frozen') ?></th>
<th class="py-3 border-secondary text-white"><?= __('converted_to') ?> (USDT)</th>
<th class="text-end pe-4 py-3 border-secondary text-white"><?= __('trade') ?></th>
</tr>
</thead>
<tbody class="border-0">
<?php foreach ($balances as $b): ?>
<tr class="border-secondary">
<td class="ps-4 py-4">
<div class="d-flex align-items-center gap-3">
<img src="<?= getCoinIcon($b['symbol']) ?>" width="32" height="32" class="rounded-circle">
<span class="fw-bold text-white"><?= $b['symbol'] ?></span>
</div>
</td>
<td class="py-4">
<span class="text-white fw-bold"><?= number_format($b['available'], 4) ?></span>
</td>
<td class="py-4">
<span class="text-white-50 small"><?= number_format($b['frozen'], 4) ?></span>
</td>
<td class="py-4">
<span class="text-white-50 small"> <?= number_format($b['available'] + $b['frozen'], 2) ?></span>
</td>
<td class="text-end pe-4">
<a href="/trade.php?symbol=<?= $b['symbol'] ?>" class="btn btn-sm btn-outline-primary rounded-pill px-3"><?= __('trade') ?></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>

295
recharge.php Normal file
View File

@ -0,0 +1,295 @@
<?php
require_once __DIR__ . '/includes/header.php';
if (!$user) {
header('Location: /auth/login.php');
exit;
}
// Fetch settings
$stmt = db()->query("SELECT setting_key, setting_value FROM system_settings");
$settings = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
$trc20_addr = $settings['usdt_trc20_address'] ?? 'TYv9V5J1P1eEwz7y3WqJg9M2yv7f7xXv3x';
$erc20_addr = $settings['usdt_erc20_address'] ?? '0x742d35Cc6634C0532925a3b844Bc454e4438f44e';
$bep20_addr = $settings['usdt_bep20_address'] ?? '0x742d35Cc6634C0532925a3b844Bc454e4438f44e';
?>
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Back Button -->
<div class="mb-4">
<a href="javascript:history.back()" class="text-white-50 text-decoration-none d-inline-flex align-items-center gap-2">
<i class="bi bi-arrow-left fs-4"></i>
<span><?= __('back') ?></span>
</a>
</div>
<div class="card bg-surface border-secondary rounded-4 shadow-lg overflow-hidden mb-4">
<div class="card-header border-secondary bg-black bg-opacity-20 p-4">
<h4 class="mb-0 fw-bold d-flex align-items-center gap-3 text-white">
<i class="bi bi-wallet2 text-primary"></i>
<?= __('recharge') ?>
</h4>
</div>
<div class="card-body p-4">
<!-- Tabs -->
<ul class="nav nav-pills nav-fill mb-4 bg-dark p-1 rounded-pill" id="rechargeTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active rounded-pill px-4" id="fiat-tab" data-bs-toggle="pill" data-bs-target="#fiat" type="button" role="tab"><?= __('fiat_recharge') ?></button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link rounded-pill px-4" id="crypto-tab" data-bs-toggle="pill" data-bs-target="#crypto" type="button" role="tab"><?= __('crypto_recharge') ?></button>
</li>
</ul>
<div class="tab-content" id="rechargeTabsContent">
<!-- Fiat Recharge -->
<div class="tab-pane fade show active" id="fiat" role="tabpanel">
<form id="fiatRechargeForm">
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('select_currency') ?></label>
<select class="form-select bg-dark border-secondary text-white py-3" id="fiatCurrency" onchange="updateRate()">
<option value="USD" data-rate="1">🇺🇸 USD - US Dollar</option>
<option value="EUR" data-rate="0.92">🇪🇺 EUR - Euro</option>
<option value="GBP" data-rate="0.79">🇬🇧 GBP - British Pound</option>
<option value="CNY" data-rate="7.19">🇨🇳 CNY - Chinese Yuan</option>
<option value="JPY" data-rate="150.2">🇯🇵 JPY - Japanese Yen</option>
<option value="KRW" data-rate="1330.5">🇰🇷 KRW - Korean Won</option>
<option value="HKD" data-rate="7.82">🇭🇰 HKD - Hong Kong Dollar</option>
<option value="TWD" data-rate="31.5">🇹🇼 TWD - Taiwan Dollar</option>
<option value="SGD" data-rate="1.34">🇸🇬 SGD - Singapore Dollar</option>
<option value="MYR" data-rate="4.77">🇲🇾 MYR - Malaysian Ringgit</option>
<option value="THB" data-rate="35.8">🇹🇭 THB - Thai Baht</option>
<option value="VND" data-rate="24500">🇻🇳 VND - Vietnamese Dong</option>
</select>
</div>
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('fiat_amount') ?></label>
<div class="input-group">
<input type="number" class="form-control bg-dark border-secondary text-white py-3" id="fiatAmount" placeholder="0.00" oninput="calculateUSDT()">
<span class="input-group-text bg-dark border-secondary text-white-50 fw-bold" id="selectedCurrencyLabel">USD</span>
</div>
</div>
<div class="mb-5 p-4 bg-primary bg-opacity-10 border border-primary border-opacity-20 rounded-4">
<div class="d-flex justify-content-between align-items-center">
<span class="text-white-50"><?= __('est_usdt') ?></span>
<span class="h4 mb-0 fw-bold text-primary" id="estUsdt">0.00 USDT</span>
</div>
<div class="mt-2 small text-white-50">
<i class="bi bi-info-circle me-1"></i>
<?= __('rate') ?>: 1 USDT ≈ <span id="currentRateText" class="text-white">1.00 USD</span>
</div>
</div>
<button type="button" class="btn btn-primary w-100 py-3 rounded-pill fw-bold shadow-lg" onclick="confirmFiatOrder()">
<?= __('confirm_order') ?>
</button>
</form>
</div>
<!-- Crypto Recharge -->
<div class="tab-pane fade" id="crypto" role="tabpanel">
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('coin') ?></label>
<div class="d-flex align-items-center gap-3 p-3 bg-dark border border-secondary rounded-4">
<img src="<?= getCoinIcon('USDT') ?>" width="32" height="32" alt="USDT">
<div>
<div class="fw-bold text-white">USDT</div>
<div class="text-white-50 small">Tether USD</div>
</div>
</div>
</div>
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('network') ?></label>
<div class="d-flex gap-2" id="networkSelectors">
<button class="btn btn-outline-primary btn-sm px-4 rounded-pill active" onclick="selectNetwork('TRC20', '<?= $trc20_addr ?>')">TRC20</button>
<button class="btn btn-outline-secondary btn-sm px-4 rounded-pill" onclick="selectNetwork('ERC20', '<?= $erc20_addr ?>')">ERC20</button>
<button class="btn btn-outline-secondary btn-sm px-4 rounded-pill" onclick="selectNetwork('BEP20', '<?= $bep20_addr ?>')">BEP20</button>
</div>
</div>
<div class="text-center mb-4 p-3 bg-white rounded-4 mx-auto" style="width: 180px; height: 180px;">
<img id="qrCode" src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=<?= $trc20_addr ?>" alt="QR Code" class="img-fluid">
</div>
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('address') ?></label>
<div class="input-group">
<input type="text" class="form-control bg-dark border-secondary text-white py-3 small" value="<?= $trc20_addr ?>" readonly id="cryptoAddress">
<button class="btn btn-dark border-secondary text-primary" onclick="copyAddress()"><i class="bi bi-copy"></i></button>
</div>
</div>
<div class="p-3 bg-warning bg-opacity-10 border border-warning border-opacity-20 rounded-4 small text-warning mb-4">
<i class="bi bi-exclamation-triangle me-2"></i>
⚠️ <?= __('crypto_recharge_warning') ?? 'Please only send USDT to this address. Sending other assets may result in permanent loss.' ?>
</div>
<button type="button" class="btn btn-outline-primary w-100 py-3 rounded-pill fw-bold" onclick="confirmCryptoOrder()">
<?= __('i_have_paid') ?? 'I have paid' ?>
</button>
</div>
</div>
</div>
</div>
<!-- Rich Content Sections -->
<div class="row g-4 mb-5">
<div class="col-md-6">
<div class="card bg-surface border-secondary rounded-4 h-100">
<div class="card-body p-4">
<h5 class="text-white fw-bold mb-3"><i class="bi bi-journal-text text-primary me-2"></i> <?= __('recharge_steps') ?? 'Recharge Steps' ?></h5>
<div class="text-white-50 small lh-lg">
<div class="d-flex gap-3 mb-2">
<span class="badge bg-primary rounded-circle p-2" style="width:24px; height:24px; display:flex; align-items:center; justify-content:center;">1</span>
<span>选择充值方式(法币或加密货币)</span>
</div>
<div class="d-flex gap-3 mb-2">
<span class="badge bg-primary rounded-circle p-2" style="width:24px; height:24px; display:flex; align-items:center; justify-content:center;">2</span>
<span>填写金额或复制充值地址</span>
</div>
<div class="d-flex gap-3 mb-2">
<span class="badge bg-primary rounded-circle p-2" style="width:24px; height:24px; display:flex; align-items:center; justify-content:center;">3</span>
<span>完成支付后点击确认提交</span>
</div>
<div class="d-flex gap-3">
<span class="badge bg-primary rounded-circle p-2" style="width:24px; height:24px; display:flex; align-items:center; justify-content:center;">4</span>
<span>等待客服核实资金通常在2-5分钟内到账</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card bg-surface border-secondary rounded-4 h-100">
<div class="card-body p-4">
<h5 class="text-white fw-bold mb-3"><i class="bi bi-shield-lock text-success me-2"></i> <?= __('security_tips') ?? 'Security Tips' ?></h5>
<div class="text-white-50 small lh-lg">
<ul class="ps-3 mb-0">
<li>请勿向任何非官方提供的地址充值</li>
<li>充值前请仔细核对主网协议(如 TRC20/ERC20</li>
<li>请保管好您的支付凭证,以便在需要时提供给客服</li>
<li>平台绝不会要求您在非官方页面输入支付密码</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="text-center text-white-50 small mb-5">
<div class="d-flex justify-content-center gap-4">
<span><i class="bi bi-shield-check text-success me-1"></i> <?= __('secure') ?></span>
<span><i class="bi bi-lightning-fill text-warning me-1"></i> <?= __('fast') ?></span>
<span><i class="bi bi-headset text-primary me-1"></i> <?= __('support_247') ?></span>
</div>
</div>
</div>
</div>
</div>
<style>
.bg-surface { background-color: #1e2329; }
.bg-dark { background-color: #0b0e11; }
.form-select, .form-control { border-color: #2b3139; }
.form-select:focus, .form-control:focus { background-color: #1e2329; border-color: #0062ff; box-shadow: none; color: #fff; }
.nav-pills .nav-link { color: #9ba3af; font-weight: 500; }
.nav-pills .nav-link.active { background-color: #0062ff; color: #fff; }
.btn-outline-primary:hover { background-color: #0062ff; color: #fff; }
</style>
<script>
let currentNetwork = 'TRC20';
let currentAddress = '<?= $trc20_addr ?>';
function updateRate() {
const select = document.getElementById('fiatCurrency');
const symbol = select.value;
const rate = select.options[select.selectedIndex].getAttribute('data-rate');
document.getElementById('selectedCurrencyLabel').innerText = symbol;
document.getElementById('currentRateText').innerText = `${rate} ${symbol}`;
calculateUSDT();
}
function calculateUSDT() {
const amount = parseFloat(document.getElementById('fiatAmount').value) || 0;
const select = document.getElementById('fiatCurrency');
const rate = parseFloat(select.options[select.selectedIndex].getAttribute('data-rate'));
const est = amount / rate;
document.getElementById('estUsdt').innerText = est.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USDT';
}
function selectNetwork(net, addr) {
currentNetwork = net;
currentAddress = addr;
// Update UI
const btns = document.querySelectorAll('#networkSelectors button');
btns.forEach(btn => {
if (btn.innerText === net) {
btn.classList.add('active', 'btn-outline-primary');
btn.classList.remove('btn-outline-secondary');
} else {
btn.classList.remove('active', 'btn-outline-primary');
btn.classList.add('btn-outline-secondary');
}
});
document.getElementById('cryptoAddress').value = addr;
document.getElementById('qrCode').src = `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${addr}`;
}
function confirmFiatOrder() {
const amount = document.getElementById('fiatAmount').value;
const currency = document.getElementById('fiatCurrency').value;
const estUsdt = document.getElementById('estUsdt').innerText;
if (!amount || amount <= 0) {
alert('<?= __("enter_amount") ?>');
return;
}
const message = `【充值请求】\n充值方式法币充值\n法币金额${amount} ${currency}\n预计到账${estUsdt}\n请提供支付详情以便核实。`;
sendToCS(message);
}
function confirmCryptoOrder() {
const message = `【充值请求】\n充值方式加密货币 (USDT)\n主网${currentNetwork}\n地址${currentAddress}\n我已完成支付请核实。`;
sendToCS(message);
}
function sendToCS(message) {
// Open chat box
const csBox = document.getElementById('cs-box');
if (csBox.classList.contains('d-none')) {
const toggle = document.getElementById('cs-toggle');
if (toggle) toggle.click();
}
// Auto-fill and send message
const csInput = document.getElementById('cs-input');
if (csInput) {
csInput.value = message;
document.getElementById('cs-form').dispatchEvent(new Event('submit'));
alert('充值请求已发送,请在客服对话框中继续交流。');
} else {
alert('无法连接客服系统,请刷新页面重试。');
}
}
function copyAddress() {
const addr = document.getElementById('cryptoAddress');
addr.select();
document.execCommand('copy');
alert('地址已复制到剪贴板');
}
</script>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

162
security.php Normal file
View File

@ -0,0 +1,162 @@
<?php
include __DIR__ . '/includes/header.php';
if (!$user) {
header('Location: /auth/login.php');
exit;
}
$success = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
if ($action === 'change_login_password') {
$old_pwd = $_POST['old_password'] ?? '';
$new_pwd = $_POST['new_password'] ?? '';
$confirm_pwd = $_POST['confirm_new_password'] ?? '';
$stmt = db()->prepare("SELECT password_hash FROM users WHERE id = ?");
$stmt->execute([$user['id']]);
$current_pwd_hash = $stmt->fetchColumn();
if (!password_verify($old_pwd, $current_pwd_hash)) {
$error = "Old password incorrect";
} elseif ($new_pwd !== $confirm_pwd) {
$error = "Passwords do not match";
} elseif (strlen($new_pwd) < 6) {
$error = "Password must be at least 6 characters";
} else {
$new_hash = password_hash($new_pwd, PASSWORD_DEFAULT);
$stmt = db()->prepare("UPDATE users SET password_hash = ? WHERE id = ?");
$stmt->execute([$new_hash, $user['id']]);
$success = "Login password changed successfully";
}
} elseif ($action === 'set_trade_password') {
$trade_pwd = $_POST['trade_password'] ?? '';
$confirm_trade_pwd = $_POST['confirm_trade_password'] ?? '';
if ($trade_pwd !== $confirm_trade_pwd) {
$error = "Passwords do not match";
} elseif (strlen($trade_pwd) < 6) {
$error = "Transaction password must be at least 6 characters";
} else {
// Store plain or hashed? Usually hashed but user might want simple numeric.
// I'll hash it for security.
$trade_hash = password_hash($trade_pwd, PASSWORD_DEFAULT);
$stmt = db()->prepare("UPDATE users SET transaction_password = ? WHERE id = ?");
$stmt->execute([$trade_hash, $user['id']]);
$success = "Transaction password updated successfully";
}
}
}
$stmt = db()->prepare("SELECT transaction_password FROM users WHERE id = ?");
$stmt->execute([$user['id']]);
$hasTradePwd = !empty($stmt->fetchColumn());
?>
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="mb-4">
<a href="/profile.php" class="text-white-50 text-decoration-none d-inline-flex align-items-center gap-2">
<i class="bi bi-arrow-left fs-4"></i>
<span><?= __('back') ?></span>
</a>
</div>
<div class="card bg-surface border-secondary rounded-4 shadow-lg overflow-hidden mb-4">
<div class="card-header border-secondary bg-black bg-opacity-20 p-4">
<h4 class="mb-0 fw-bold d-flex align-items-center gap-3 text-white">
<i class="bi bi-lock text-danger"></i>
<?= __('security') ?>
</h4>
</div>
<div class="card-body p-4 p-md-5">
<?php if ($success): ?>
<div class="alert alert-success border-0 bg-success bg-opacity-10 text-success rounded-4 mb-4">
<i class="bi bi-check-circle-fill me-2"></i><?= $success ?>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger border-0 bg-danger bg-opacity-10 text-danger rounded-4 mb-4">
<i class="bi bi-exclamation-triangle-fill me-2"></i><?= $error ?>
</div>
<?php endif; ?>
<!-- Login Password Section -->
<div class="mb-5">
<h5 class="text-white fw-bold mb-4 d-flex align-items-center gap-2">
<i class="bi bi-key text-primary"></i> <?= __('login_password') ?>
</h5>
<form method="POST">
<input type="hidden" name="action" value="change_login_password">
<div class="row g-3">
<div class="col-md-4">
<input type="password" name="old_password" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" placeholder="<?= __('old_password') ?>" required>
</div>
<div class="col-md-4">
<input type="password" name="new_password" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" placeholder="<?= __('new_password') ?>" required>
</div>
<div class="col-md-4">
<input type="password" name="confirm_new_password" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" placeholder="<?= __('confirm_new_password') ?>" required>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary rounded-pill px-4 py-2 mt-2"><?= __('change_password') ?></button>
</div>
</div>
</form>
</div>
<hr class="border-secondary mb-5">
<!-- Trade Password Section -->
<div>
<h5 class="text-white fw-bold mb-4 d-flex align-items-center gap-2">
<i class="bi bi-shield-lock text-warning"></i> <?= __('trade_password') ?>
</h5>
<form method="POST">
<input type="hidden" name="action" value="set_trade_password">
<div class="row g-3">
<div class="col-md-6">
<input type="password" name="trade_password" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" placeholder="<?= $hasTradePwd ? __('new_password') : __('set_password') ?>" required>
</div>
<div class="col-md-6">
<input type="password" name="confirm_trade_password" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" placeholder="<?= __('confirm_new_password') ?>" required>
</div>
<div class="col-12">
<button type="submit" class="btn btn-warning rounded-pill px-4 py-2 mt-2 text-dark fw-bold"><?= $hasTradePwd ? __('change_password') : __('set_password') ?></button>
</div>
</div>
</form>
</div>
<div class="bg-black bg-opacity-20 rounded-4 p-4 mt-5 border border-secondary border-opacity-50">
<h6 class="text-white fw-bold mb-3 d-flex align-items-center gap-2">
<i class="bi bi-info-circle text-info"></i> <?= __('security_steps') ?>
</h6>
<ul class="text-white-50 small mb-0 ps-3">
<li class="mb-2"><?= __('security_step1') ?></li>
<li><?= __('security_step2') ?></li>
</ul>
</div>
<div class="card bg-black bg-opacity-20 border-secondary rounded-4 mt-4">
<div class="card-body p-4">
<h6 class="text-white fw-bold mb-3"><i class="bi bi-shield-shaded text-primary me-2"></i> <?= __('security_instructions') ?></h6>
<p class="text-white-50 small mb-0">
<?= __('security_instructions') ?>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?php include __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,6 +1,14 @@
<?php
require_once __DIR__ . '/includes/lang.php';
require_once __DIR__ . '/includes/header.php';
$usdt_balance = 0;
if ($user) {
$stmt = db()->prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = 'USDT'");
$stmt->execute([$user['id']]);
$bal = $stmt->fetch();
$usdt_balance = $bal['available'] ?? 0;
}
?>
<div class="container py-5 d-flex justify-content-center">
<div class="card bg-dark border-0 shadow-lg" style="width: 100%; max-width: 480px; border-radius: 28px; background: #0b0e11 !important; border: 1px solid #2b3139 !important; box-shadow: 0 20px 50px rgba(0,0,0,0.5) !important;">
@ -14,7 +22,7 @@ require_once __DIR__ . '/includes/header.php';
<div class="p-4 mb-2 rounded-4" style="background: #161a1e; border: 1px solid #2b3139;">
<div class="d-flex justify-content-between mb-3">
<span class="text-white opacity-50 small fw-bold text-uppercase" style="letter-spacing: 1px;"><?= __('from') ?></span>
<span class="text-white opacity-50 small"><?= __('balance') ?>: <span class="text-white fw-bold">1,000.00</span></span>
<span class="text-white opacity-50 small"><?= __('balance') ?>: <span class="text-white fw-bold"><?= number_format($usdt_balance, 2) ?></span></span>
</div>
<div class="d-flex align-items-center">
<input type="number" class="form-control bg-transparent border-0 text-white fs-1 p-0 shadow-none w-50 fw-bold" placeholder="0.00" style="color: #fff !important; font-size: 32px !important;">

325
withdraw.php Normal file
View File

@ -0,0 +1,325 @@
<?php
require_once __DIR__ . '/includes/header.php';
if (!$user) {
header('Location: /auth/login.php');
exit;
}
$stmt = db()->prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = 'USDT'");
$stmt->execute([$user['id']]);
$bal = $stmt->fetch();
$available = $bal['available'] ?? 0;
?>
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Back Button -->
<div class="mb-4">
<a href="javascript:history.back()" class="text-white-50 text-decoration-none d-inline-flex align-items-center gap-2">
<i class="bi bi-arrow-left fs-4"></i>
<span><?= __('back') ?></span>
</a>
</div>
<div class="card bg-surface border-secondary rounded-4 shadow-lg overflow-hidden mb-4">
<div class="card-header border-secondary bg-black bg-opacity-20 p-4">
<h4 class="mb-0 fw-bold d-flex align-items-center gap-3 text-white">
<i class="bi bi-cash-stack text-warning"></i>
<?= __('withdraw') ?>
</h4>
</div>
<div class="card-body p-4">
<!-- Tabs -->
<ul class="nav nav-pills nav-fill mb-4 bg-dark p-1 rounded-pill" id="withdrawTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active rounded-pill px-4" id="crypto-withdraw-tab" data-bs-toggle="pill" data-bs-target="#crypto-withdraw" type="button" role="tab"><?= __('crypto_withdraw') ?? 'USDT Withdrawal' ?></button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link rounded-pill px-4" id="fiat-withdraw-tab" data-bs-toggle="pill" data-bs-target="#fiat-withdraw" type="button" role="tab"><?= __('fiat_withdraw') ?? 'Fiat Withdrawal' ?></button>
</li>
</ul>
<div class="tab-content" id="withdrawTabsContent">
<!-- USDT Withdrawal -->
<div class="tab-pane fade show active" id="crypto-withdraw" role="tabpanel">
<form id="cryptoWithdrawForm">
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('coin') ?></label>
<div class="d-flex align-items-center gap-3 p-3 bg-dark border border-secondary rounded-4">
<img src="<?= getCoinIcon('USDT') ?>" width="32" height="32" alt="USDT">
<div>
<div class="fw-bold text-white">USDT</div>
<div class="text-white-50 small">Tether USD</div>
</div>
</div>
</div>
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('network') ?></label>
<div class="d-flex gap-2" id="withdrawNetworkSelectors">
<button type="button" class="btn btn-outline-warning btn-sm px-4 rounded-pill active" onclick="selectWithdrawNetwork('TRC20')">TRC20</button>
<button type="button" class="btn btn-outline-secondary btn-sm px-4 rounded-pill" onclick="selectWithdrawNetwork('ERC20')">ERC20</button>
<button type="button" class="btn btn-outline-secondary btn-sm px-4 rounded-pill" onclick="selectWithdrawNetwork('BEP20')">BEP20</button>
</div>
</div>
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('withdraw_address') ?></label>
<input type="text" class="form-control bg-dark border-secondary text-white py-3" id="withdrawAddress" placeholder="请输入您的 USDT 地址">
</div>
<div class="mb-4">
<div class="d-flex justify-content-between mb-2">
<label class="form-label text-white-50 small fw-bold"><?= __('withdraw_amount') ?> (USDT)</label>
<span class="small text-white-50"><?= __('balance') ?>: <span class="text-white"><?= number_format($available, 2) ?> USDT</span></span>
</div>
<div class="input-group">
<input type="number" class="form-control bg-dark border-secondary text-white py-3" id="withdrawAmount" placeholder="最小提现 10.00" oninput="calculateCryptoWithdraw()">
<button type="button" class="input-group-text bg-dark border-secondary text-primary fw-bold" onclick="setMax('withdrawAmount', 'cryptoReceiveAmount')">ALL</button>
</div>
</div>
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('withdraw_password') ?? '提现密码' ?></label>
<input type="password" class="form-control bg-dark border-secondary text-white py-3" id="withdrawPassword" placeholder="默认密码 123456">
</div>
<div class="mb-5 p-4 bg-warning bg-opacity-10 border border-warning border-opacity-20 rounded-4">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="text-white-50 small">手续费 (Fee)</span>
<span class="text-white small">1.00 USDT</span>
</div>
<div class="d-flex justify-content-between align-items-center">
<span class="text-white-50"><?= __('to_receive') ?? '预计到账' ?></span>
<span class="h4 mb-0 fw-bold text-warning" id="cryptoReceiveAmount">0.00 USDT</span>
</div>
</div>
<button type="button" class="btn btn-warning w-100 py-3 rounded-pill fw-bold shadow-lg" onclick="confirmCryptoWithdraw()">
<?= __('confirm_order') ?>
</button>
</form>
</div>
<!-- Fiat Withdrawal -->
<div class="tab-pane fade" id="fiat-withdraw" role="tabpanel">
<form id="fiatWithdrawForm">
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('select_currency') ?></label>
<select class="form-select bg-dark border-secondary text-white py-3" id="fiatWithdrawCurrency" onchange="updateFiatWithdrawRate()">
<option value="USD" data-rate="1">🇺🇸 USD - US Dollar</option>
<option value="EUR" data-rate="0.92">🇪🇺 EUR - Euro</option>
<option value="GBP" data-rate="0.79">🇬🇧 GBP - British Pound</option>
<option value="CNY" data-rate="7.19">🇨🇳 CNY - Chinese Yuan</option>
<option value="JPY" data-rate="150.2">🇯🇵 JPY - Japanese Yen</option>
<option value="KRW" data-rate="1330.5">🇰🇷 KRW - Korean Won</option>
<option value="HKD" data-rate="7.82">🇭🇰 HKD - Hong Kong Dollar</option>
<option value="TWD" data-rate="31.5">🇹🇼 TWD - Taiwan Dollar</option>
<option value="SGD" data-rate="1.34">🇸🇬 SGD - Singapore Dollar</option>
<option value="MYR" data-rate="4.77">🇲🇾 MYR - Malaysian Ringgit</option>
<option value="THB" data-rate="35.8">🇹🇭 THB - Thai Baht</option>
<option value="VND" data-rate="24500">🇻🇳 VND - Vietnamese Dong</option>
</select>
</div>
<div class="mb-4">
<div class="d-flex justify-content-between mb-2">
<label class="form-label text-white-50 small fw-bold"><?= __('withdraw_amount') ?> (USDT)</label>
<span class="small text-white-50"><?= __('balance') ?>: <span class="text-white"><?= number_format($available, 2) ?> USDT</span></span>
</div>
<div class="input-group">
<input type="number" class="form-control bg-dark border-secondary text-white py-3" id="fiatWithdrawAmount" placeholder="最小提现 10.00" oninput="calculateFiatWithdraw()">
<button type="button" class="input-group-text bg-dark border-secondary text-primary fw-bold" onclick="setMax('fiatWithdrawAmount', 'fiatReceiveAmount')">ALL</button>
</div>
</div>
<div class="mb-4">
<label class="form-label text-white-50 small fw-bold mb-2"><?= __('withdraw_password') ?? '提现密码' ?></label>
<input type="password" class="form-control bg-dark border-secondary text-white py-3" id="fiatWithdrawPassword" placeholder="默认密码 123456">
</div>
<div class="mb-5 p-4 bg-primary bg-opacity-10 border border-primary border-opacity-20 rounded-4">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="text-white-50 small"><?= __('rate') ?>: 1 USDT ≈ </span>
<span class="text-white small" id="fiatWithdrawRateText">1.00 USD</span>
</div>
<div class="d-flex justify-content-between align-items-center">
<span class="text-white-50"><?= __('est_receive_fiat') ?? '预计收到法币' ?></span>
<span class="h4 mb-0 fw-bold text-primary" id="fiatReceiveAmount">0.00 USD</span>
</div>
</div>
<button type="button" class="btn btn-primary w-100 py-3 rounded-pill fw-bold shadow-lg" onclick="confirmFiatWithdraw()">
<?= __('confirm_order') ?>
</button>
</form>
</div>
</div>
</div>
</div>
<!-- Rich Content Sections -->
<div class="row g-4 mb-5">
<div class="col-md-6">
<div class="card bg-surface border-secondary rounded-4 h-100">
<div class="card-body p-4">
<h5 class="text-white fw-bold mb-3"><i class="bi bi-journal-text text-warning me-2"></i> <?= __('withdraw_steps') ?? '提现步骤' ?></h5>
<div class="text-white-50 small lh-lg">
<div class="d-flex gap-3 mb-2">
<span class="badge bg-warning text-dark rounded-circle p-2" style="width:24px; height:24px; display:flex; align-items:center; justify-content:center;">1</span>
<span>选择提现方式(加密货币或法币)</span>
</div>
<div class="d-flex gap-3 mb-2">
<span class="badge bg-warning text-dark rounded-circle p-2" style="width:24px; height:24px; display:flex; align-items:center; justify-content:center;">2</span>
<span>填写提现地址/选择币种并输入金额</span>
</div>
<div class="d-flex gap-3 mb-2">
<span class="badge bg-warning text-dark rounded-circle p-2" style="width:24px; height:24px; display:flex; align-items:center; justify-content:center;">3</span>
<span>输入提现密码默认123456</span>
</div>
<div class="d-flex gap-3">
<span class="badge bg-warning text-dark rounded-circle p-2" style="width:24px; height:24px; display:flex; align-items:center; justify-content:center;">4</span>
<span>确认后提交审核预计10-30分钟内处理</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card bg-surface border-secondary rounded-4 h-100">
<div class="card-body p-4">
<h5 class="text-white fw-bold mb-3"><i class="bi bi-shield-lock text-danger me-2"></i> <?= __('security_tips') ?? '安全提示' ?></h5>
<div class="text-white-50 small lh-lg">
<ul class="ps-3 mb-0">
<li>提现前请务必确认地址正确,转错将无法找回</li>
<li>为了您的资金安全,大额提现可能需要人工电话核实</li>
<li>请确保提现主网与接收端主网一致(如均为 TRC20</li>
<li>严禁参与任何非法洗钱活动,平台将配合监管部门调查</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="text-center text-white-50 small mb-5">
<div class="d-flex justify-content-center gap-4">
<span><i class="bi bi-shield-check text-success me-1"></i> <?= __('secure') ?></span>
<span><i class="bi bi-lightning-fill text-warning me-1"></i> <?= __('fast') ?></span>
<span><i class="bi bi-headset text-primary me-1"></i> <?= __('support_247') ?></span>
</div>
</div>
</div>
</div>
</div>
<style>
.bg-surface { background-color: #1e2329; }
.bg-dark { background-color: #0b0e11; }
.form-select, .form-control { border-color: #2b3139; }
.form-select:focus, .form-control:focus { background-color: #1e2329; border-color: #ffc107; box-shadow: none; color: #fff; }
.nav-pills .nav-link { color: #9ba3af; font-weight: 500; }
.nav-pills .nav-link.active { background-color: #ffc107; color: #000; }
.btn-outline-warning:hover { background-color: #ffc107; color: #000; }
</style>
<script>
let currentWithdrawNetwork = 'TRC20';
function setMax(inputId, displayId) {
document.getElementById(inputId).value = <?= $available ?>;
if (inputId === 'withdrawAmount') calculateCryptoWithdraw();
else calculateFiatWithdraw();
}
function selectWithdrawNetwork(net) {
currentWithdrawNetwork = net;
const btns = document.querySelectorAll('#withdrawNetworkSelectors button');
btns.forEach(btn => {
if (btn.innerText === net) {
btn.classList.add('active', 'btn-outline-warning');
btn.classList.remove('btn-outline-secondary');
} else {
btn.classList.remove('active', 'btn-outline-warning');
btn.classList.add('btn-outline-secondary');
}
});
}
function calculateCryptoWithdraw() {
const amount = parseFloat(document.getElementById('withdrawAmount').value) || 0;
const fee = amount > 0 ? 1 : 0;
const receive = Math.max(0, amount - fee);
document.getElementById('cryptoReceiveAmount').innerText = receive.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' USDT';
}
function updateFiatWithdrawRate() {
const select = document.getElementById('fiatWithdrawCurrency');
const symbol = select.value;
const rate = select.options[select.selectedIndex].getAttribute('data-rate');
document.getElementById('fiatWithdrawRateText').innerText = `${rate} ${symbol}`;
calculateFiatWithdraw();
}
function calculateFiatWithdraw() {
const amount = parseFloat(document.getElementById('fiatWithdrawAmount').value) || 0;
const select = document.getElementById('fiatWithdrawCurrency');
const rate = parseFloat(select.options[select.selectedIndex].getAttribute('data-rate'));
const est = amount * rate;
document.getElementById('fiatReceiveAmount').innerText = est.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' ' + select.value;
}
function confirmCryptoWithdraw() {
const addr = document.getElementById('withdrawAddress').value.trim();
const amount = parseFloat(document.getElementById('withdrawAmount').value);
const password = document.getElementById('withdrawPassword').value;
if (!addr) { alert('请输入提现地址'); return; }
if (!amount || amount < 10) { alert('最小提现金额为 10 USDT'); return; }
if (amount > <?= $available ?>) { alert('余额不足'); return; }
if (!password) { alert('请输入提现密码'); return; }
const message = `【提现请求】\n提现方式加密货币 (USDT)\n主网${currentWithdrawNetwork}\n地址${addr}\n金额${amount} USDT\n手续费1.00 USDT\n实际到账${document.getElementById('cryptoReceiveAmount').innerText}\n提现密码${password}`;
sendWithdrawToCS(message);
}
function confirmFiatWithdraw() {
const amount = parseFloat(document.getElementById('fiatWithdrawAmount').value);
const currency = document.getElementById('fiatWithdrawCurrency').value;
const estFiat = document.getElementById('fiatReceiveAmount').innerText;
const password = document.getElementById('fiatWithdrawPassword').value;
if (!amount || amount < 10) { alert('最小提现金额为 10 USDT'); return; }
if (amount > <?= $available ?>) { alert('余额不足'); return; }
if (!password) { alert('请输入提现密码'); return; }
const message = `【提现请求】\n提现方式法币提现\n申请金额${amount} USDT\n预计收到${estFiat}\n提现密码${password}\n请客服核实并提供收款方式。`;
sendWithdrawToCS(message);
}
function sendWithdrawToCS(message) {
// Open chat box
const csBox = document.getElementById('cs-box');
if (csBox.classList.contains('d-none')) {
const toggle = document.getElementById('cs-toggle');
if (toggle) toggle.click();
}
// Auto-fill and send message
const csInput = document.getElementById('cs-input');
if (csInput) {
csInput.value = message;
document.getElementById('cs-form').dispatchEvent(new Event('submit'));
alert('提现请求已发送,请在客服对话框中继续交流。');
} else {
alert('无法连接客服系统,请刷新页面重试。');
}
}
</script>
<?php require_once __DIR__ . '/includes/footer.php'; ?>