Autosave: 20260218-050956

This commit is contained in:
Flatlogic Bot 2026-02-18 05:09:56 +00:00
parent c560bf6eb9
commit b573ba93a2
36 changed files with 2661 additions and 279 deletions

234
admin/agents.php Normal file
View File

@ -0,0 +1,234 @@
<?php
require_once __DIR__ . '/layout.php';
$db = db();
// Only super admins can manage agents
if ($admin['is_agent']) {
echo "权限不足";
exit;
}
// Handle Delete
if (isset($_GET['delete'])) {
$id = (int)$_GET['delete'];
$db->prepare("DELETE FROM admins WHERE id = ? AND is_agent = 1")->execute([$id]);
header('Location: agents.php?msg=deleted');
exit;
}
// Handle Add/Edit
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'add') {
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$permissions = json_encode($_POST['permissions'] ?? []);
$db->prepare("INSERT INTO admins (username, password_hash, is_agent, permissions, role) VALUES (?, ?, 1, ?, 'agent')")
->execute([$username, $password, $permissions]);
header('Location: agents.php?msg=added');
exit;
}
if ($_POST['action'] === 'edit') {
$id = (int)$_POST['agent_id'];
$username = $_POST['username'];
$permissions = json_encode($_POST['permissions'] ?? []);
$db->prepare("UPDATE admins SET username = ?, permissions = ? WHERE id = ? AND is_agent = 1")
->execute([$username, $permissions, $id]);
if (!empty($_POST['password'])) {
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$db->prepare("UPDATE admins SET password_hash = ? WHERE id = ?")->execute([$password, $id]);
}
header('Location: agents.php?msg=updated');
exit;
}
}
$title = '代理管理';
ob_start();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">代理商列表</h4>
</div>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addAgentModal">
<i class="bi bi-person-plus me-1"></i> 添加代理
</button>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-success alert-dismissible fade show mb-4" role="alert">
操作成功!
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<div class="table-container">
<table class="table table-hover align-middle">
<thead>
<tr class="text-muted small">
<th>ID</th>
<th>用户名</th>
<th>下属用户数</th>
<th>权限</th>
<th>创建时间</th>
<th class="text-end">操作</th>
</tr>
</thead>
<tbody>
<?php
$stmt = $db->query("SELECT a.*, (SELECT COUNT(*) FROM users WHERE agent_id = a.id) as user_count FROM admins a WHERE is_agent = 1 ORDER BY created_at DESC");
while ($a = $stmt->fetch()):
$perms = json_decode($a['permissions'] ?? '[]', true);
?>
<tr>
<td><?= $a['id'] ?></td>
<td>
<div class="fw-bold"><?= htmlspecialchars($a['username']) ?></div>
<div class="text-muted small">代理商</div>
</td>
<td><span class="badge bg-info"><?= $a['user_count'] ?> 人</span></td>
<td>
<?php if (empty($perms)): ?>
<span class="text-muted">无特殊权限</span>
<?php else: ?>
<?php foreach($perms as $p): ?>
<span class="badge bg-secondary me-1"><?= $p ?></span>
<?php endforeach; ?>
<?php endif; ?>
</td>
<td><?= $a['created_at'] ?></td>
<td class="text-end">
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary" onclick="editAgent(<?= htmlspecialchars(json_encode($a)) ?>)">编辑</button>
<a href="?delete=<?= $a['id'] ?>" class="btn btn-outline-danger" onclick="return confirm('确定要删除此代理吗?')">删除</a>
</div>
</td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
</div>
<!-- Add Agent Modal -->
<div class="modal fade" id="addAgentModal" tabindex="-1">
<div class="modal-dialog">
<form class="modal-content" method="POST">
<input type="hidden" name="action" value="add">
<div class="modal-header">
<h5 class="modal-title">添加新代理</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">代理用户名</label>
<input type="text" name="username" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">登录密码</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">权限设置</label>
<div class="d-flex flex-wrap gap-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="permissions[]" value="manage_users" id="p_users">
<label class="form-check-label" for="p_users">管理用户</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="permissions[]" value="view_orders" id="p_orders">
<label class="form-check-label" for="p_orders">查看订单</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="permissions[]" value="audit_finance" id="p_finance">
<label class="form-check-label" for="p_finance">财务审核</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary">创建代理</button>
</div>
</form>
</div>
</div>
<!-- Edit Agent Modal -->
<div class="modal fade" id="editAgentModal" tabindex="-1">
<div class="modal-dialog">
<form class="modal-content" method="POST">
<input type="hidden" name="action" value="edit">
<input type="hidden" name="agent_id" id="edit_agent_id">
<div class="modal-header">
<h5 class="modal-title">编辑代理 - <span id="edit_agent_name"></span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">代理用户名</label>
<input type="text" name="username" id="edit_username" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">修改密码 (留空不改)</label>
<input type="text" name="password" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">权限设置</label>
<div class="d-flex flex-wrap gap-2" id="edit_permissions_container">
<div class="form-check">
<input class="form-check-input p-checkbox" type="checkbox" name="permissions[]" value="manage_users" id="ep_users">
<label class="form-check-label" for="ep_users">管理用户</label>
</div>
<div class="form-check">
<input class="form-check-input p-checkbox" type="checkbox" name="permissions[]" value="view_orders" id="ep_orders">
<label class="form-check-label" for="ep_orders">查看订单</label>
</div>
<div class="form-check">
<input class="form-check-input p-checkbox" type="checkbox" name="permissions[]" value="audit_finance" id="ep_finance">
<label class="form-check-label" for="ep_finance">财务审核</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary">保存修改</button>
</div>
</form>
</div>
</div>
<script>
function editAgent(agent) {
document.getElementById('edit_agent_id').value = agent.id;
document.getElementById('edit_agent_name').innerText = agent.username;
document.getElementById('edit_username').value = agent.username;
// Clear checkboxes
document.querySelectorAll('.p-checkbox').forEach(cb => cb.checked = false);
// Set checkboxes
if (agent.permissions) {
const perms = JSON.parse(agent.permissions);
perms.forEach(p => {
const cb = document.querySelector(`.p-checkbox[value="${p}"]`);
if (cb) cb.checked = true;
});
}
var modal = new bootstrap.Modal(document.getElementById('editAgentModal'));
modal.show();
}
</script>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1 +1,117 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'add_control') {
$symbol = $_POST['symbol'];
$price = (float)$_POST['price'];
$time = $_POST['execution_time'];
$duration = (int)$_POST['duration'];
$db->prepare("INSERT INTO price_controls (symbol, target_price, execution_time, duration) VALUES (?, ?, ?, ?)")
->execute([$symbol, $price, $time, $duration]);
header("Location: ai_control.php?msg=added");
exit;
}
if ($_POST['action'] === 'delete') {
$id = (int)$_POST['id'];
$db->prepare("DELETE FROM price_controls WHERE id = ?")->execute([$id]);
header("Location: ai_control.php?msg=deleted");
exit;
}
}
$title = 'AI控盘 (插针设置)';
ob_start();
$controls = $db->query("SELECT * FROM price_controls ORDER BY execution_time DESC LIMIT 50")->fetchAll();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">AI价格干预</h4>
</div>
</div>
<div class="row g-4 mb-4">
<div class="col-md-4">
<div class="card p-4">
<h6 class="mb-4">添加插针设置</h6>
<form method="POST">
<input type="hidden" name="action" value="add_control">
<div class="mb-3">
<label class="form-label">币种</label>
<input type="text" name="symbol" class="form-control" list="coinSymbols" required placeholder="例如: BTC/USDT">
<datalist id="coinSymbols">
<option value="BTC/USDT">
<option value="ETH/USDT">
<option value="SOL/USDT">
<option value="BNB/USDT">
<option value="XRP/USDT">
<option value="ADA/USDT">
<option value="DOGE/USDT">
</datalist>
</div>
<div class="mb-3">
<label class="form-label">目标价格</label>
<input type="number" step="0.00000001" name="price" class="form-control" required placeholder="例如: 65000">
</div>
<div class="mb-3">
<label class="form-label">执行时间</label>
<input type="datetime-local" name="execution_time" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">持续时长 ()</label>
<input type="number" name="duration" class="form-control" value="60">
</div>
<button type="submit" class="btn btn-primary w-100">添加控制</button>
</form>
</div>
</div>
<div class="col-md-8">
<div class="table-container">
<h6 class="mb-4">执行记录 / 预设列表</h6>
<table class="table table-hover">
<thead>
<tr class="small text-muted">
<th>币种</th>
<th>目标价格</th>
<th>执行时间</th>
<th>时长</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($controls as $c): ?>
<tr>
<td><strong><?= $c['symbol'] ?></strong></td>
<td class="text-primary fw-bold"><?= $c['target_price'] ?></td>
<td><?= $c['execution_time'] ?></td>
<td><?= $c['duration'] ?>s</td>
<td>
<?php if (strtotime($c['execution_time']) > time()): ?>
<span class="badge bg-warning">待执行</span>
<?php elseif (strtotime($c['execution_time']) + $c['duration'] < time()): ?>
<span class="badge bg-secondary">已结束</span>
<?php else: ?>
<span class="badge bg-success">执行中</span>
<?php endif; ?>
</td>
<td>
<form method="POST" class="d-inline">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?= $c['id'] ?>">
<button type="submit" class="btn btn-sm btn-link text-danger" onclick="return confirm('确定删除吗?')">删除</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1,59 +1,126 @@
<?php
require_once __DIR__ . '/layout.php';
function getLocalSetting($key, $default = null) {
try {
$stmt = db()->prepare("SELECT setting_value FROM system_settings WHERE setting_key = ?");
$stmt->execute([$key]);
$val = $stmt->fetchColumn();
return $val !== false ? $val : $default;
} catch (Exception $e) {
return $default;
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$settings = [
'email_verification_enabled' => $_POST['email_verification_enabled'] ?? '0',
'site_name' => $_POST['site_name'] ?? 'Byro',
'min_deposit' => $_POST['min_deposit'] ?? '10',
'site_logo' => $_POST['site_logo'] ?? '',
'usdt_recharge_address' => $_POST['usdt_recharge_address'] ?? '',
'usdt_protocol' => $_POST['usdt_protocol'] ?? 'TRC20',
'service_link' => $_POST['service_link'] ?? '',
];
foreach ($settings as $key => $val) {
$stmt = db()->prepare("INSERT INTO system_settings (setting_key, setting_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE setting_value = ?");
$stmt->execute([$key, $val, $val]);
}
// Handle logo upload if provided
if (isset($_FILES['logo_file']) && $_FILES['logo_file']['error'] === 0) {
$ext = pathinfo($_FILES['logo_file']['name'], PATHINFO_EXTENSION);
$filename = 'logo_' . time() . '.' . $ext;
$target = __DIR__ . '/../assets/images/' . $filename;
if (move_uploaded_file($_FILES['logo_file']['tmp_name'], $target)) {
$logo_path = '/assets/images/' . $filename;
$stmt = db()->prepare("INSERT INTO system_settings (setting_key, setting_value) VALUES ('site_logo', ?) ON DUPLICATE KEY UPDATE setting_value = ?");
$stmt->execute([$logo_path, $logo_path]);
}
}
$success = true;
}
$email_verify = getSetting('email_verification_enabled', '0');
$site_name = getSetting('site_name', 'Byro');
$email_verify = getLocalSetting('email_verification_enabled', '0');
$site_logo = getLocalSetting('site_logo', '');
$usdt_address = getLocalSetting('usdt_recharge_address', '');
$usdt_protocol = getLocalSetting('usdt_protocol', 'TRC20');
$service_link = getLocalSetting('service_link', '');
$title = '后台设置';
ob_start();
?>
<div class="row justify-content-center">
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">系统设置</h4>
</div>
</div>
<div class="row">
<div class="col-md-8">
<div class="table-container">
<h5 class="fw-bold mb-4">系统全局设置</h5>
<h5 class="fw-bold mb-4">系统全局</h5>
<?php if (isset($success)): ?>
<div class="alert alert-success">设置已成功保存</div>
<div class="alert alert-success">设置已保存</div>
<?php endif; ?>
<form method="POST">
<form method="POST" enctype="multipart/form-data">
<div class="mb-4">
<label class="form-label fw-bold">站点名称</label>
<input type="text" name="site_name" class="form-control" value="<?= htmlspecialchars($site_name) ?>">
<label class="form-label fw-bold">前端 LOGO</label>
<div class="d-flex align-items-center gap-3">
<?php if ($site_logo): ?>
<img src="<?= $site_logo ?>" height="40" class="border p-1">
<?php endif; ?>
<input type="file" name="logo_file" class="form-control">
</div>
<div class="form-text">建议尺寸: 200x50, PNG 格式</div>
</div>
<div class="mb-4">
<label class="form-label fw-bold">USDT 收款地址</label>
<input type="text" name="usdt_recharge_address" class="form-control" value="<?= htmlspecialchars($usdt_address) ?>" placeholder="请输入钱包地址">
</div>
<div class="mb-4">
<label class="form-label fw-bold">USDT 网络协议</label>
<select name="usdt_protocol" class="form-control">
<option value="TRC20" <?= $usdt_protocol === 'TRC20' ? 'selected' : '' ?>>TRC20</option>
<option value="ERC20" <?= $usdt_protocol === 'ERC20' ? 'selected' : '' ?>>ERC20</option>
<option value="BEP20" <?= $usdt_protocol === 'BEP20' ? 'selected' : '' ?>>BEP20</option>
</select>
</div>
<div class="mb-4">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="email_verification_enabled" value="1" id="emailSwitch" <?= $email_verify == '1' ? 'checked' : '' ?>>
<label class="form-check-label fw-bold" for="emailSwitch">开启邮箱验证注册</label>
<label class="form-check-label fw-bold" for="emailSwitch">注册时开启邮箱/手机验证码</label>
</div>
<div class="form-text text-muted">开启后,前端注册页面将强制要求输入邮箱验证码。</div>
</div>
<div class="mb-4">
<label class="form-label fw-bold">最低充值额度 (USDT)</label>
<input type="number" name="min_deposit" class="form-control" value="<?= getSetting('min_deposit', '10') ?>">
<label class="form-label fw-bold">在线客服链接</label>
<input type="text" name="service_link" class="form-control" value="<?= htmlspecialchars($service_link) ?>" placeholder="https://...">
</div>
<button type="submit" class="btn btn-primary px-5 py-2">保存设置</button>
<hr class="my-4">
<button type="submit" class="btn btn-primary px-5">提交保存</button>
</form>
</div>
</div>
<div class="col-md-4">
<div class="card p-4">
<h6 class="fw-bold mb-3">使用说明</h6>
<ul class="small text-muted ps-3">
<li>收款地址将直接展示在前端充值页面。</li>
<li>验证码开关关闭后,前端注册无需输入验证码即可提交。</li>
<li>客服链接将用于前端“联系客服”按钮跳转。</li>
</ul>
</div>
</div>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, '后台设置');
renderAdminPage($content, $title);
?>

View File

@ -1 +1,137 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
// Handle Control Update
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'set_control') {
$id = (int)$_POST['order_id'];
$status = (int)$_POST['control_status'];
$db->prepare("UPDATE binary_orders SET control_status = ? WHERE id = ?")->execute([$status, $id]);
header("Location: binary.php?msg=updated");
exit;
}
}
$title = '秒合约管理';
ob_start();
$user_id = isset($_GET['user_id']) ? (int)$_GET['user_id'] : null;
$sql = "SELECT o.*, u.username, u.uid FROM binary_orders o JOIN users u ON o.user_id = u.id";
$params = [];
if ($user_id) {
$sql .= " WHERE o.user_id = ?";
$params[] = $user_id;
}
$sql .= " ORDER BY o.created_at DESC";
$stmt = $db->prepare($sql);
$stmt->execute($params);
$orders = $stmt->fetchAll();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="<?= $user_id ? 'users.php' : 'index.php' ?>" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">秒合约下单记录 <?= $user_id ? "(用户ID: $user_id)" : "" ?></h4>
</div>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-success mb-4">控制状态已更新!</div>
<?php endif; ?>
<div class="table-container">
<table class="table table-hover align-middle">
<thead>
<tr class="text-muted small">
<th>ID</th>
<th>用户信息</th>
<th>币种/方向</th>
<th>金额/时长</th>
<th>入场价/出场价</th>
<th>盈亏</th>
<th>状态</th>
<th>控制</th>
<th class="text-end">操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $o): ?>
<tr>
<td><?= $o['id'] ?></td>
<td>
<div><?= htmlspecialchars($o['username']) ?></div>
<code class="small"><?= $o['uid'] ?></code>
</td>
<td>
<span class="fw-bold"><?= $o['symbol'] ?></span>
<br>
<span class="badge <?= $o['direction'] === 'buy' ? 'bg-success' : 'bg-danger' ?>">
<?= $o['direction'] === 'buy' ? '买涨 ↑' : '买跌 ↓' ?>
</span>
</td>
<td>
<div><?= number_format($o['amount'], 2) ?> USDT</div>
<div class="text-muted small"><?= $o['duration'] ?> 秒</div>
</td>
<td>
<div class="small">: <?= $o['entry_price'] ?></div>
<div class="small">: <?= $o['close_price'] ?? '-' ?></div>
</td>
<td>
<?php if ($o['status'] === 'won'): ?>
<span class="text-success fw-bold">+<?= number_format($o['amount'] * $o['profit_rate'] / 100, 2) ?></span>
<?php elseif ($o['status'] === 'lost'): ?>
<span class="text-danger fw-bold">-<?= number_format($o['amount'], 2) ?></span>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td>
<?php if ($o['status'] === 'pending'): ?>
<span class="badge bg-warning">进行中</span>
<?php elseif ($o['status'] === 'won'): ?>
<span class="badge bg-success">已盈利</span>
<?php elseif ($o['status'] === 'lost'): ?>
<span class="badge bg-danger">已亏损</span>
<?php else: ?>
<span class="badge bg-secondary">已取消</span>
<?php endif; ?>
</td>
<td>
<?php if ($o['control_status'] == 1): ?>
<span class="badge bg-success">控赢</span>
<?php elseif ($o['control_status'] == 2): ?>
<span class="badge bg-danger">控亏</span>
<?php else: ?>
<span class="badge bg-secondary">正常</span>
<?php endif; ?>
</td>
<td class="text-end">
<?php if ($o['status'] === 'pending'): ?>
<form method="POST" class="d-inline">
<input type="hidden" name="order_id" value="<?= $o['id'] ?>">
<input type="hidden" name="action" value="set_control">
<div class="btn-group btn-group-sm">
<button name="control_status" value="1" class="btn btn-outline-success <?= $o['control_status'] == 1 ? 'active' : '' ?>"></button>
<button name="control_status" value="2" class="btn btn-outline-danger <?= $o['control_status'] == 2 ? 'active' : '' ?>"></button>
<button name="control_status" value="0" class="btn btn-outline-secondary <?= $o['control_status'] == 0 ? 'active' : '' ?>"></button>
</div>
</form>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($orders)): ?>
<tr><td colspan="9" class="text-center p-5 text-muted">暂无订单记录</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1 +1,85 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'set_control') {
$id = (int)$_POST['order_id'];
$status = (int)$_POST['control_status'];
$db->prepare("UPDATE contract_orders SET control_status = ? WHERE id = ?")->execute([$status, $id]);
header("Location: contract.php?msg=updated");
exit;
}
}
$title = '永续合约管理';
ob_start();
$user_id = isset($_GET['user_id']) ? (int)$_GET['user_id'] : null;
$sql = "SELECT o.*, u.username, u.uid FROM contract_orders o JOIN users u ON o.user_id = u.id";
$params = [];
if ($user_id) {
$sql .= " WHERE o.user_id = ?";
$params[] = $user_id;
}
$sql .= " ORDER BY o.created_at DESC";
$stmt = $db->prepare($sql);
$stmt->execute($params);
$orders = $stmt->fetchAll();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="<?= $user_id ? 'users.php' : 'index.php' ?>" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">永续合约订单 <?= $user_id ? "(用户ID: $user_id)" : "" ?></h4>
</div>
</div>
<div class="table-container">
<table class="table table-hover">
<thead>
<tr class="small text-muted">
<th>ID</th>
<th>用户</th>
<th>币种/方向</th>
<th>杠杆/金额</th>
<th>入场/出场</th>
<th>盈亏</th>
<th>状态</th>
<th>控制</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $o): ?>
<tr>
<td><?= $o['id'] ?></td>
<td><?= htmlspecialchars($o['username']) ?><br><code class="small"><?= $o['uid'] ?></code></td>
<td>
<strong><?= $o['symbol'] ?></strong><br>
<span class="badge <?= $o['direction'] === 'long' ? 'bg-success' : 'bg-danger' ?>"><?= $o['direction'] === 'long' ? '做多' : '做空' ?></span>
</td>
<td><?= $o['leverage'] ?>x<br><?= number_format($o['amount'], 2) ?> USDT</td>
<td><?= $o['entry_price'] ?><br><?= $o['close_price'] ?? '-' ?></td>
<td class="<?= $o['profit'] >= 0 ? 'text-success' : 'text-danger' ?>"><?= number_format($o['profit'], 2) ?></td>
<td><?= $o['status'] ?></td>
<td>
<?php if ($o['control_status'] == 1): ?><span class="badge bg-success">控赢</span>
<?php elseif ($o['control_status'] == 2): ?><span class="badge bg-danger">控亏</span>
<?php else: ?><span class="badge bg-secondary">正常</span><?php endif; ?>
</td>
<td>
<form method="POST" class="btn-group btn-group-sm">
<input type="hidden" name="order_id" value="<?= $o['id'] ?>">
<input type="hidden" name="action" value="set_control">
<button name="control_status" value="1" class="btn btn-outline-success"></button>
<button name="control_status" value="2" class="btn btn-outline-danger"></button>
<button name="control_status" value="0" class="btn btn-outline-secondary"></button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -3,8 +3,8 @@ session_start();
require_once __DIR__ . '/../db/config.php';
// Check if admin
if (!isset($_SESSION['user_id'])) {
header("Location: /auth/login.php");
if (!isset($_SESSION['admin_id'])) {
header("Location: /admin/login.php");
exit;
}
@ -40,7 +40,10 @@ if (!isset($_SESSION['user_id'])) {
<div class="sidebar">
<div class="p-3 bg-primary text-white d-flex justify-content-between align-items-center">
<h5 class="m-0 fw-bold">Byro 客服中心</h5>
<div class="d-flex align-items-center gap-2">
<a href="/admin/index.php" class="text-white"><i class="bi bi-arrow-left"></i></a>
<h5 class="m-0 fw-bold">客服中心</h5>
</div>
<span class="badge bg-light text-primary">Live</span>
</div>
<div class="p-2">

View File

@ -1 +1,44 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
$title = '兑换管理';
ob_start();
$records = $db->query("SELECT r.*, u.username, u.uid FROM exchange_records r JOIN users u ON r.user_id = u.id ORDER BY r.created_at DESC")->fetchAll();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">兑换记录明细</h4>
</div>
</div>
<div class="table-container">
<table class="table table-hover">
<thead>
<tr class="small text-muted">
<th>ID</th>
<th>用户</th>
<th>消耗</th>
<th>获得</th>
<th>汇率</th>
<th>时间</th>
</tr>
</thead>
<tbody>
<?php foreach ($records as $r): ?>
<tr>
<td><?= $r['id'] ?></td>
<td><?= htmlspecialchars($r['username']) ?><br><code class="small"><?= $r['uid'] ?></code></td>
<td><span class="text-danger"><?= number_format($r['from_amount'], 4) ?> <?= $r['from_symbol'] ?></span></td>
<td><span class="text-success"><?= number_format($r['to_amount'], 4) ?> <?= $r['to_symbol'] ?></span></td>
<td><?= number_format($r['rate'], 6) ?></td>
<td><small><?= $r['created_at'] ?></small></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1 +1,231 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
// Helper to check permissions
if (!hasPermission('audit_finance')) {
echo "权限不足";
exit;
}
// Handle Approval
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$id = (int)$_POST['request_id'];
$stmt = $db->prepare("SELECT r.* FROM finance_requests r JOIN users u ON r.user_id = u.id WHERE r.id = ? " . ($admin['is_agent'] ? "AND u.agent_id = ?" : ""));
$params = [$id];
if ($admin['is_agent']) $params[] = $admin['id'];
$stmt->execute($params);
$req = $stmt->fetch();
if (!$req || $req['status'] !== 'pending') {
header("Location: finance.php?error=invalid");
exit;
}
if ($_POST['action'] === 'approve') {
$db->beginTransaction();
try {
// Update status
$db->prepare("UPDATE finance_requests SET status = 'approved' WHERE id = ?")->execute([$id]);
// If recharge, add to balance
if ($req['type'] === 'recharge') {
$stmt = $db->prepare("SELECT * FROM user_balances WHERE user_id = ? AND symbol = ?");
$stmt->execute([$req['user_id'], $req['symbol']]);
$bal = $stmt->fetch();
if ($bal) {
$db->prepare("UPDATE user_balances SET available = available + ? WHERE id = ?")
->execute([$req['amount'], $bal['id']]);
} else {
$db->prepare("INSERT INTO user_balances (user_id, symbol, available) VALUES (?, ?, ?)")
->execute([$req['user_id'], $req['symbol'], $req['amount']]);
}
// Add to transactions history
$db->prepare("INSERT INTO transactions (user_id, type, amount, symbol, status) VALUES (?, 'recharge', ?, ?, 'completed')")
->execute([$req['user_id'], $req['amount'], $req['symbol']]);
}
$db->commit();
header("Location: finance.php?msg=approved");
} catch (Exception $e) {
$db->rollBack();
header("Location: finance.php?error=" . urlencode($e->getMessage()));
}
exit;
}
if ($_POST['action'] === 'reject') {
$reason = $_POST['reason'] ?? '';
$db->beginTransaction();
try {
$db->prepare("UPDATE finance_requests SET status = 'rejected', rejection_reason = ? WHERE id = ?")
->execute([$reason, $id]);
// If withdrawal, return balance
if ($req['type'] === 'withdrawal') {
$db->prepare("UPDATE user_balances SET available = available + ? WHERE user_id = ? AND symbol = ?")
->execute([$req['amount'], $req['user_id'], $req['symbol']]);
$db->prepare("INSERT INTO transactions (user_id, type, amount, symbol, status) VALUES (?, 'withdrawal_refund', ?, ?, 'completed')")
->execute([$req['user_id'], $req['amount'], $req['symbol']]);
}
$db->commit();
header("Location: finance.php?msg=rejected");
} catch (Exception $e) {
$db->rollBack();
header("Location: finance.php?error=" . urlencode($e->getMessage()));
}
exit;
}
}
$title = '充提管理';
ob_start();
$type = $_GET['type'] ?? 'recharge';
$user_id = isset($_GET['user_id']) ? (int)$_GET['user_id'] : null;
$sql = "SELECT r.*, u.username, u.uid FROM finance_requests r JOIN users u ON r.user_id = u.id WHERE r.type = ?";
$params = [$type];
if ($admin['is_agent']) {
$sql .= " AND u.agent_id = ?";
$params[] = $admin['id'];
}
if ($user_id) {
$sql .= " AND r.user_id = ?";
$params[] = $user_id;
}
$sql .= " ORDER BY r.created_at DESC";
$stmt = $db->prepare($sql);
$stmt->execute($params);
$requests = $stmt->fetchAll();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="<?= $user_id ? 'users.php' : 'index.php' ?>" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0"><?= $type === 'recharge' ? '充值审核' : '提现审核' ?> <?= $user_id ? "(用户ID: $user_id)" : "" ?></h4>
</div>
<div class="btn-group">
<a href="?type=recharge" class="btn <?= $type === 'recharge' ? 'btn-primary' : 'btn-outline-primary' ?>">充值审核</a>
<a href="?type=withdrawal" class="btn <?= $type === 'withdrawal' ? 'btn-primary' : 'btn-outline-primary' ?>">提现审核</a>
</div>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-success mb-4">操作成功!</div>
<?php endif; ?>
<?php if (isset($_GET['error'])): ?>
<div class="alert alert-danger mb-4">错误: <?= htmlspecialchars($_GET['error']) ?></div>
<?php endif; ?>
<div class="table-container">
<table class="table table-hover align-middle">
<thead>
<tr class="text-muted small">
<th>ID</th>
<th>用户信息</th>
<th>金额</th>
<th>支付信息/详情</th>
<th>时间</th>
<th>状态</th>
<th class="text-end">操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($requests as $r): ?>
<tr>
<td><?= $r['id'] ?></td>
<td>
<div><?= htmlspecialchars($r['username']) ?></div>
<code class="small"><?= $r['uid'] ?></code>
</td>
<td>
<span class="fw-bold <?= $r['type'] === 'recharge' ? 'text-success' : 'text-danger' ?>">
<?= $r['type'] === 'recharge' ? '+' : '-' ?> <?= number_format($r['amount'], 2) ?> <?= $r['symbol'] ?>
</span>
</td>
<td>
<?php if ($r['type'] === 'recharge'): ?>
<div class="small">方法: <?= htmlspecialchars($r['payment_method'] ?? 'USDT') ?></div>
<div class="text-muted small">哈希/备注: <?= htmlspecialchars($r['tx_hash'] ?? '无') ?></div>
<?php else: ?>
<div class="small">提现地址: <code><?= htmlspecialchars($r['payment_details'] ?? '未知') ?></code></div>
<?php endif; ?>
<?php if ($r['rejection_reason']): ?>
<div class="text-danger small mt-1">理由: <?= htmlspecialchars($r['rejection_reason']) ?></div>
<?php endif; ?>
</td>
<td><small class="text-muted"><?= $r['created_at'] ?></small></td>
<td>
<?php if ($r['status'] === 'pending'): ?>
<span class="badge bg-warning">待处理</span>
<?php elseif ($r['status'] === 'approved'): ?>
<span class="badge bg-success">已通过</span>
<?php else: ?>
<span class="badge bg-danger">已拒绝</span>
<?php endif; ?>
</td>
<td class="text-end">
<?php if ($r['status'] === 'pending'): ?>
<div class="btn-group btn-group-sm">
<form method="POST" class="d-inline">
<input type="hidden" name="request_id" value="<?= $r['id'] ?>">
<input type="hidden" name="action" value="approve">
<button type="submit" class="btn btn-outline-success" onclick="return confirm('确定要通过吗?')">通过</button>
</form>
<button class="btn btn-outline-danger" onclick="showRejectModal(<?= $r['id'] ?>)">拒绝</button>
</div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($requests)): ?>
<tr><td colspan="7" class="text-center p-5 text-muted">暂无记录</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Reject Modal -->
<div class="modal fade" id="rejectModal" tabindex="-1">
<div class="modal-dialog">
<form class="modal-content" method="POST">
<input type="hidden" name="action" value="reject">
<input type="hidden" name="request_id" id="reject_request_id">
<div class="modal-header">
<h5 class="modal-title">拒绝请求</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">拒绝理由</label>
<textarea name="reason" class="form-control" rows="3" required placeholder="请填写拒绝理由..."></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-danger">确认拒绝</button>
</div>
</form>
</div>
</div>
<script>
function showRejectModal(id) {
document.getElementById('reject_request_id').value = id;
new bootstrap.Modal(document.getElementById('rejectModal')).show();
}
</script>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1,71 +1,59 @@
<?php
require_once __DIR__ . '/layout.php';
$db = db();
// Real stats
$total_users = $db->query("SELECT COUNT(*) FROM users")->fetchColumn();
$total_recharge = $db->query("SELECT SUM(amount) FROM finance_requests WHERE type='recharge' AND status='approved'")->fetchColumn() ?: 0;
$total_withdrawal = $db->query("SELECT SUM(amount) FROM finance_requests WHERE type='withdrawal' AND status='approved'")->fetchColumn() ?: 0;
$pending_finance = $db->query("SELECT COUNT(*) FROM finance_requests WHERE status='pending'")->fetchColumn();
$pending_kyc = $db->query("SELECT COUNT(*) FROM users WHERE kyc_status=0 AND kyc_name IS NOT NULL")->fetchColumn();
ob_start();
?>
<div class="row g-4 mb-4">
<div class="col-md-3">
<div class="card p-3">
<div class="card p-3 border-start border-primary border-4">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="text-muted small">总用户数</div>
<div class="fs-3 fw-bold">1,234</div>
<div class="fs-3 fw-bold"><?= number_format($total_users) ?></div>
</div>
<div class="bg-primary bg-opacity-10 p-3 rounded-circle text-primary">
<i class="bi bi-people fs-4"></i>
</div>
</div>
<div class="mt-3 small text-success">
<i class="bi bi-arrow-up"></i> 12% 较上月
<div class="text-primary"><i class="bi bi-people fs-1 opacity-25"></i></div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card p-3">
<div class="card p-3 border-start border-success border-4">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="text-muted small">总充值 (USDT)</div>
<div class="fs-3 fw-bold">542,000</div>
<div class="fs-3 fw-bold"><?= number_format($total_recharge, 2) ?></div>
</div>
<div class="bg-success bg-opacity-10 p-3 rounded-circle text-success">
<i class="bi bi-cash-stack fs-4"></i>
</div>
</div>
<div class="mt-3 small text-success">
<i class="bi bi-arrow-up"></i> 5.4% 较昨日
<div class="text-success"><i class="bi bi-cash-stack fs-1 opacity-25"></i></div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card p-3">
<div class="card p-3 border-start border-danger border-4">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="text-muted small">今日成交额</div>
<div class="fs-3 fw-bold">1.2M</div>
<div class="text-muted small">总提现 (USDT)</div>
<div class="fs-3 fw-bold"><?= number_format($total_withdrawal, 2) ?></div>
</div>
<div class="bg-warning bg-opacity-10 p-3 rounded-circle text-warning">
<i class="bi bi-activity fs-4"></i>
</div>
</div>
<div class="mt-3 small text-danger">
<i class="bi bi-arrow-down"></i> 2.1% 较昨日
<div class="text-danger"><i class="bi bi-bank fs-1 opacity-25"></i></div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card p-3">
<div class="card p-3 border-start border-warning border-4">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="text-muted small">审核提现</div>
<div class="fs-3 fw-bold text-danger">15</div>
<div class="text-muted small">办事项</div>
<div class="fs-3 fw-bold text-warning"><?= $pending_finance + $pending_kyc ?></div>
</div>
<div class="bg-danger bg-opacity-10 p-3 rounded-circle text-danger">
<i class="bi bi-clock-history fs-4"></i>
</div>
</div>
<div class="mt-3 small text-muted">
需要尽快处理
<div class="text-warning"><i class="bi bi-list-check fs-1 opacity-25"></i></div>
</div>
</div>
</div>
@ -73,68 +61,95 @@ ob_start();
<div class="row g-4">
<div class="col-md-8">
<div class="table-container">
<div class="d-flex justify-content-between align-items-center mb-4">
<h6 class="mb-0 fw-bold">最新用户注册</h6>
<button class="btn btn-sm btn-link text-decoration-none">查看全部</button>
</div>
<table class="table table-hover align-middle">
<div class="table-container mb-4">
<h6 class="mb-4 fw-bold">最近待审核充值</h6>
<table class="table table-sm align-middle">
<thead>
<tr class="text-muted">
<tr class="text-muted small">
<th>UID</th>
<th>账号</th>
<th>信用分</th>
<th>注册时间</th>
<th>状态</th>
<th>金额</th>
<th>时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php
$stmt = db()->prepare("SELECT * FROM users ORDER BY created_at DESC LIMIT 5");
$stmt->execute();
while ($user = $stmt->fetch()):
$pending_list = $db->query("SELECT r.*, u.uid FROM finance_requests r JOIN users u ON r.user_id=u.id WHERE r.status='pending' AND r.type='recharge' LIMIT 5")->fetchAll();
foreach ($pending_list as $p):
?>
<tr>
<td><code><?= $user['uid'] ?></code></td>
<td><?= htmlspecialchars($user['username']) ?></td>
<td><?= $user['credit_score'] ?></td>
<td><?= date('Y-m-d H:i', strtotime($user['created_at'])) ?></td>
<td><span class="badge bg-success opacity-75">正常</span></td>
<td><code><?= $p['uid'] ?></code></td>
<td class="text-success fw-bold">+<?= number_format($p['amount'], 2) ?></td>
<td><small><?= date('H:i', strtotime($p['created_at'])) ?></small></td>
<td><a href="finance.php?type=recharge" class="btn btn-sm btn-link">处理</a></td>
</tr>
<?php endforeach; ?>
<?php if (empty($pending_list)): ?><tr><td colspan="4" class="text-center py-3 text-muted">暂无待处理充值</td></tr><?php endif; ?>
</tbody>
</table>
</div>
<div class="table-container">
<h6 class="mb-4 fw-bold">最新下单记录</h6>
<table class="table table-sm align-middle">
<thead>
<tr class="text-muted small">
<th>用户</th>
<th>类型</th>
<th>金额</th>
<th>方向</th>
<th>控制</th>
</tr>
</thead>
<tbody>
<?php
$orders = $db->query("SELECT o.*, u.username FROM binary_orders o JOIN users u ON o.user_id=u.id ORDER BY o.created_at DESC LIMIT 5")->fetchAll();
foreach ($orders as $o):
?>
<tr>
<td><?= htmlspecialchars($o['username']) ?></td>
<td>秒合约</td>
<td><?= number_format($o['amount'], 2) ?></td>
<td><span class="text-<?= $o['direction']=='buy'?'success':'danger' ?>"><?= $o['direction']=='buy'?'涨':'跌' ?></span></td>
<td>
<button class="btn btn-sm btn-outline-primary py-0">编辑</button>
<?php if ($o['control_status']==1): ?><span class="badge bg-success">赢</span>
<?php elseif ($o['control_status']==2): ?><span class="badge bg-danger">亏</span>
<?php else: ?>-<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="col-md-4">
<div class="table-container">
<h6 class="mb-4 fw-bold">系统通知</h6>
<div class="table-container h-100">
<h6 class="mb-4 fw-bold">快速导航</h6>
<div class="list-group list-group-flush">
<div class="list-group-item px-0 py-3">
<div class="d-flex justify-content-between mb-1">
<span class="fw-bold small">系统升级成功</span>
<span class="text-muted" style="font-size: 10px;">1小时前</span>
</div>
<p class="text-muted small mb-0">版本 2.1.0 已发布,优化了交易引擎性能。</p>
</div>
<div class="list-group-item px-0 py-3">
<div class="d-flex justify-content-between mb-1">
<span class="fw-bold small">数据库备份</span>
<span class="text-muted" style="font-size: 10px;">5小时前</span>
</div>
<p class="text-muted small mb-0">每日自动备份已完成,状态正常。</p>
</div>
<div class="list-group-item px-0 py-3">
<div class="d-flex justify-content-between mb-1">
<span class="fw-bold small">新提现申请</span>
<span class="text-muted" style="font-size: 10px;">8小时前</span>
</div>
<p class="text-muted small mb-0">用户 UID:618120456 申请提现 500 USDT。</p>
</div>
<a href="users.php" class="list-group-item list-group-item-action border-0 px-0 d-flex justify-content-between align-items-center">
<span><i class="bi bi-people me-2"></i> 玩家管理</span>
<span class="badge bg-light text-dark rounded-pill"><?= $total_users ?></span>
</a>
<a href="finance.php?type=recharge" class="list-group-item list-group-item-action border-0 px-0 d-flex justify-content-between align-items-center">
<span><i class="bi bi-wallet2 me-2"></i> 充值审核</span>
<span class="badge bg-danger rounded-pill"><?= $db->query("SELECT COUNT(*) FROM finance_requests WHERE type='recharge' AND status='pending'")->fetchColumn() ?></span>
</a>
<a href="kyc.php" class="list-group-item list-group-item-action border-0 px-0 d-flex justify-content-between align-items-center">
<span><i class="bi bi-card-text me-2"></i> 实名审核</span>
<span class="badge bg-warning text-dark rounded-pill"><?= $pending_kyc ?></span>
</a>
<a href="ai_control.php" class="list-group-item list-group-item-action border-0 px-0">
<i class="bi bi-robot me-2"></i> AI 控盘设置
</a>
<a href="backend_settings.php" class="list-group-item list-group-item-action border-0 px-0">
<i class="bi bi-gear me-2"></i> 系统参数设置
</a>
</div>
<div class="mt-5 p-3 bg-light rounded">
<p class="small text-muted mb-0">系统版本: v2.5.0</p>
<p class="small text-muted mb-0">数据库状态: <span class="text-success">在线</span></p>
</div>
</div>
</div>
@ -142,5 +157,5 @@ ob_start();
<?php
$content = ob_get_clean();
renderAdminPage($content);
renderAdminPage($content, '后台仪表盘');
?>

157
admin/kyc.php Normal file
View File

@ -0,0 +1,157 @@
<?php
require_once __DIR__ . '/layout.php';
$db = db();
// Handle Approve/Reject
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$id = (int)$_POST['user_id'];
if ($_POST['action'] === 'approve') {
$db->prepare("UPDATE users SET kyc_status = 1 WHERE id = ?")->execute([$id]);
header("Location: kyc.php?msg=approved");
exit;
}
if ($_POST['action'] === 'reject') {
$reason = $_POST['reason'] ?? '';
$db->prepare("UPDATE users SET kyc_status = 2, kyc_rejection_reason = ? WHERE id = ?")
->execute([$reason, $id]);
header("Location: kyc.php?msg=rejected");
exit;
}
}
$title = '实名认证审核';
ob_start();
$user_id = isset($_GET['user_id']) ? (int)$_GET['user_id'] : null;
if ($user_id) {
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$users = $stmt->fetchAll();
} else {
$stmt = $db->query("SELECT * FROM users WHERE kyc_name IS NOT NULL ORDER BY kyc_status ASC, created_at DESC");
$users = $stmt->fetchAll();
}
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="users.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0"><?= $user_id ? '用户实名详情' : '实名认证列表' ?></h4>
</div>
<?php if ($user_id): ?>
<a href="kyc.php" class="btn btn-outline-secondary">查看全部</a>
<?php endif; ?>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-success mb-4">操作成功!</div>
<?php endif; ?>
<div class="row g-4">
<?php foreach ($users as $u): ?>
<div class="col-md-12">
<div class="card shadow-sm mb-4">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<span>UID: <code><?= $u['uid'] ?></code> | 用户: <strong><?= htmlspecialchars($u['username']) ?></strong></span>
<span>
<?php if ($u['kyc_status'] == 0): ?>
<span class="badge bg-warning">待审核</span>
<?php elseif ($u['kyc_status'] == 1): ?>
<span class="badge bg-success">已通过</span>
<?php elseif ($u['kyc_status'] == 2): ?>
<span class="badge bg-danger">已拒绝</span>
<?php endif; ?>
</span>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<p class="mb-1 text-muted small">真实姓名</p>
<h6><?= htmlspecialchars($u['kyc_name'] ?? '未填写') ?></h6>
<p class="mb-1 text-muted small mt-3">身份证号</p>
<h6><?= htmlspecialchars($u['kyc_id_number'] ?? '未填写') ?></h6>
<?php if ($u['kyc_rejection_reason']): ?>
<div class="alert alert-danger mt-3 small">
拒绝理由: <?= htmlspecialchars($u['kyc_rejection_reason']) ?>
</div>
<?php endif; ?>
</div>
<div class="col-md-8">
<div class="row g-2">
<div class="col-md-4">
<p class="small text-center mb-1">正面照</p>
<img src="<?= $u['kyc_photo_front'] ?: 'https://via.placeholder.com/300x200?text=No+Photo' ?>" class="img-fluid border rounded" onclick="window.open(this.src)">
</div>
<div class="col-md-4">
<p class="small text-center mb-1">反面照</p>
<img src="<?= $u['kyc_photo_back'] ?: 'https://via.placeholder.com/300x200?text=No+Photo' ?>" class="img-fluid border rounded" onclick="window.open(this.src)">
</div>
<div class="col-md-4">
<p class="small text-center mb-1">手持照</p>
<img src="<?= $u['kyc_photo_handheld'] ?: 'https://via.placeholder.com/300x200?text=No+Photo' ?>" class="img-fluid border rounded" onclick="window.open(this.src)">
</div>
</div>
</div>
</div>
<?php if ($u['kyc_status'] == 0): ?>
<div class="mt-4 pt-3 border-top d-flex gap-2">
<form method="POST" class="d-inline">
<input type="hidden" name="user_id" value="<?= $u['id'] ?>">
<input type="hidden" name="action" value="approve">
<button type="submit" class="btn btn-success" onclick="return confirm('确定通过审核吗?')">通过认证</button>
</form>
<button class="btn btn-danger" onclick="showRejectModal(<?= $u['id'] ?>)">拒绝申请</button>
</div>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; ?>
<?php if (empty($users)): ?>
<div class="col-12">
<div class="card p-5 text-center text-muted">
暂无实名认证申请
</div>
</div>
<?php endif; ?>
</div>
<!-- Reject Modal -->
<div class="modal fade" id="rejectModal" tabindex="-1">
<div class="modal-dialog">
<form class="modal-content" method="POST">
<input type="hidden" name="action" value="reject">
<input type="hidden" name="user_id" id="reject_user_id">
<div class="modal-header">
<h5 class="modal-title">拒绝实名认证</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">拒绝理由</label>
<textarea name="reason" class="form-control" rows="3" required placeholder="请填写拒绝理由,如:照片不清晰、身份证号不正确等"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-danger">确认拒绝</button>
</div>
</form>
</div>
</div>
<script>
function showRejectModal(id) {
document.getElementById('reject_user_id').value = id;
new bootstrap.Modal(document.getElementById('rejectModal')).show();
}
</script>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -3,19 +3,29 @@ require_once __DIR__ . '/../db/config.php';
if (session_status() === PHP_SESSION_NONE) session_start();
// Admin check
$user = null;
if (isset($_SESSION['user_id'])) {
$stmt = db()->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
$admin = null;
if (isset($_SESSION['admin_id'])) {
$stmt = db()->prepare("SELECT * FROM admins WHERE id = ?");
$stmt->execute([$_SESSION['admin_id']]);
$admin = $stmt->fetch();
}
if (!$user || $user['role'] !== 'admin') {
if (!$admin) {
header('Location: /admin/login.php');
exit;
}
// Helper to check permissions
function hasPermission($p) {
global $admin;
if (!$admin['is_agent']) return true; // Super admin has all permissions
$perms = json_decode($admin['permissions'] ?? '[]', true);
return in_array($p, $perms);
}
function renderAdminPage($content, $title = '后台管理') {
global $admin;
$current_page = basename($_SERVER['PHP_SELF']);
?>
<!DOCTYPE html>
<html lang="zh">
@ -77,6 +87,10 @@ function renderAdminPage($content, $title = '后台管理') {
font-weight: bold;
font-size: 20px;
color: #0062ff;
background: #fff;
}
.admin-nav {
padding-bottom: 40px;
}
.nav-link {
padding: 12px 20px;
@ -110,23 +124,38 @@ function renderAdminPage($content, $title = '后台管理') {
<body>
<div class="admin-sidebar">
<div class="sidebar-logo">
<i class="bi bi-shield-lock-fill me-2"></i> 管理系统
<i class="bi bi-shield-lock-fill me-2"></i> <?= $admin['is_agent'] ? '代理后台' : '管理系统' ?>
</div>
<div class="admin-nav">
<a href="/admin/index.php" class="nav-link active"><i class="bi bi-house-door"></i> 首页</a>
<a href="/admin/stats.php" class="nav-link"><i class="bi bi-graph-up"></i> 平台数据</a>
<a href="/admin/users.php" class="nav-link"><i class="bi bi-people"></i> 玩家管理</a>
<a href="/admin/finance.php" class="nav-link"><i class="bi bi-wallet2"></i> 充提管理</a>
<a href="/admin/binary.php" class="nav-link"><i class="bi bi-clock"></i> 秒合约管理</a>
<a href="/admin/contract.php" class="nav-link"><i class="bi bi-layers"></i> 永续合约</a>
<a href="/admin/spot.php" class="nav-link"><i class="bi bi-currency-exchange"></i> 币币交易</a>
<a href="/admin/index.php" class="nav-link <?= $current_page == 'index.php' ? 'active' : '' ?>"><i class="bi bi-house-door"></i> 首页</a>
<?php if (hasPermission('manage_users')): ?>
<a href="/admin/users.php" class="nav-link <?= $current_page == 'users.php' ? 'active' : '' ?>"><i class="bi bi-people"></i> 玩家管理</a>
<?php endif; ?>
<?php if (!$admin['is_agent']): ?>
<a href="/admin/agents.php" class="nav-link <?= $current_page == 'agents.php' ? 'active' : '' ?>"><i class="bi bi-person-badge"></i> 代理管理</a>
<?php endif; ?>
<?php if (hasPermission('audit_finance')): ?>
<a href="/admin/finance.php" class="nav-link <?= $current_page == 'finance.php' ? 'active' : '' ?>"><i class="bi bi-wallet2"></i> 充提管理</a>
<?php endif; ?>
<?php if (hasPermission('view_orders')): ?>
<a href="/admin/binary.php" class="nav-link <?= $current_page == 'binary.php' ? 'active' : '' ?>"><i class="bi bi-clock"></i> 秒合约管理</a>
<a href="/admin/contract.php" class="nav-link <?= $current_page == 'contract.php' ? 'active' : '' ?>"><i class="bi bi-layers"></i> 永续合约</a>
<a href="/admin/spot.php" class="nav-link <?= $current_page == 'spot.php' ? 'active' : '' ?>"><i class="bi bi-currency-exchange"></i> 币币交易</a>
<?php endif; ?>
<?php if (!$admin['is_agent']): ?>
<a href="/admin/exchange.php" class="nav-link"><i class="bi bi-arrow-left-right"></i> 兑换管理</a>
<a href="/admin/mining.php" class="nav-link"><i class="bi bi-cpu"></i> 质押挖矿</a>
<a href="/admin/ai_control.php" class="nav-link"><i class="bi bi-robot"></i> AI控盘</a>
<a href="/admin/customer_service.php" class="nav-link"><i class="bi bi-headset"></i> 客服管理</a>
<a href="/admin/frontend_settings.php" class="nav-link"><i class="bi bi-display"></i> 前端设置</a>
<a href="/admin/backend_settings.php" class="nav-link"><i class="bi bi-gear"></i> 后台设置</a>
<a href="/admin/profile.php" class="nav-link"><i class="bi bi-person-gear"></i> 个人设置</a>
<?php endif; ?>
<a href="/admin/profile.php" class="nav-link <?= $current_page == 'profile.php' ? 'active' : '' ?>"><i class="bi bi-person-gear"></i> 个人设置</a>
</div>
</div>
@ -135,7 +164,7 @@ function renderAdminPage($content, $title = '后台管理') {
<h5 class="mb-0"><?= $title ?></h5>
</div>
<div class="d-flex align-items-center gap-3">
<div class="text-muted small">欢迎您, 管理员</div>
<div class="text-muted small">欢迎您, <?= htmlspecialchars($admin['username']) ?></div>
<a href="/" class="btn btn-sm btn-outline-primary">返回首页</a>
<a href="/auth/logout.php" class="btn btn-sm btn-outline-danger">登出</a>
</div>

View File

@ -5,7 +5,7 @@ require_once __DIR__ . '/../includes/lang.php';
if (session_status() === PHP_SESSION_NONE) session_start();
// If already logged in as admin, redirect to dashboard
if (isset($_SESSION['user_id']) && isset($_SESSION['role']) && $_SESSION['role'] === 'admin') {
if (isset($_SESSION['admin_id'])) {
header('Location: /admin/index.php');
exit;
}
@ -19,14 +19,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (empty($username) || empty($password)) {
$error = '请输入账号和密码';
} else {
$stmt = db()->prepare("SELECT * FROM users WHERE username = ? AND role = 'admin'");
$stmt = db()->prepare("SELECT * FROM admins WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
$admin = $stmt->fetch();
if ($user && password_verify($password, $user['password_hash'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['role'] = 'admin';
if ($admin && password_verify($password, $admin['password_hash'])) {
$_SESSION['admin_id'] = $admin['id'];
$_SESSION['admin_username'] = $admin['username'];
$_SESSION['admin_role'] = $admin['role'];
header('Location: /admin/index.php');
exit;
} else {

View File

@ -1 +1,46 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
$title = '质押挖矿管理';
ob_start();
$records = $db->query("SELECT r.*, u.username, u.uid FROM staking_records r JOIN users u ON r.user_id = u.id ORDER BY r.created_at DESC")->fetchAll();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">挖矿记录明细</h4>
</div>
</div>
<div class="table-container">
<table class="table table-hover">
<thead>
<tr class="small text-muted">
<th>ID</th>
<th>用户</th>
<th>项目</th>
<th>质押金额</th>
<th>日收益率</th>
<th>期限/结束</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<?php foreach ($records as $r): ?>
<tr>
<td><?= $r['id'] ?></td>
<td><?= htmlspecialchars($r['username']) ?><br><code class="small"><?= $r['uid'] ?></code></td>
<td><?= htmlspecialchars($r['plan_name']) ?></td>
<td><strong><?= number_format($r['amount'], 2) ?> <?= $r['symbol'] ?></strong></td>
<td><?= $r['daily_profit'] ?>%</td>
<td><?= $r['period'] ?>天<br><small><?= $r['end_date'] ?></small></td>
<td><span class="badge <?= $r['status'] === 'running' ? 'bg-primary' : 'bg-secondary' ?>"><?= $r['status'] === 'running' ? '运行中' : '已结束' ?></span></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1 +1,101 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['change_pw'])) {
$old = $_POST['old_password'];
$new = $_POST['new_password'];
$confirm = $_POST['confirm_password'];
$stmt = $db->prepare("SELECT * FROM admins WHERE id = ?");
$stmt->execute([$_SESSION['admin_id']]);
$me = $stmt->fetch();
if ($new !== $confirm) {
$error = "两次新密码不一致";
} elseif (!password_verify($old, $me['password_hash'])) {
$error = "原密码错误";
} else {
$hash = password_hash($new, PASSWORD_DEFAULT);
$db->prepare("UPDATE admins SET password_hash = ? WHERE id = ?")->execute([$hash, $_SESSION['admin_id']]);
$success = "密码已修改";
}
}
}
$title = '个人设置';
ob_start();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">个人设置</h4>
</div>
</div>
<div class="row g-4">
<div class="col-md-6">
<div class="table-container">
<h5 class="mb-4">修改管理员密码</h5>
<?php if (isset($error)): ?><div class="alert alert-danger small"><?= $error ?></div><?php endif; ?>
<?php if (isset($success)): ?><div class="alert alert-success small"><?= $success ?></div><?php endif; ?>
<form method="POST">
<input type="hidden" name="change_pw" value="1">
<div class="mb-3">
<label class="form-label">原密码</label>
<input type="password" name="old_password" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">新密码</label>
<input type="password" name="new_password" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">确认新密码</label>
<input type="password" name="confirm_password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">更新密码</button>
</form>
</div>
</div>
<div class="col-md-6">
<div class="table-container h-100">
<h5 class="mb-4">账户信息</h5>
<div class="mb-3">
<label class="form-label text-muted">当前用户</label>
<div class="fw-bold"><?= htmlspecialchars($admin['username']) ?></div>
</div>
<div class="mb-3">
<label class="form-label text-muted">角色</label>
<div>
<span class="badge <?= $admin['is_agent'] ? 'bg-info' : 'bg-primary' ?>">
<?= $admin['is_agent'] ? '代理商' : '超级管理员' ?>
</span>
</div>
</div>
<?php if ($admin['is_agent']): ?>
<div class="mb-3">
<label class="form-label text-muted">拥有的权限</label>
<div class="d-flex flex-wrap gap-1">
<?php
$perms = json_decode($admin['permissions'] ?? '[]', true);
foreach($perms as $p) echo "<span class='badge bg-secondary'>$p</span>";
if (empty($perms)) echo "<span class='text-muted'>无</span>";
?>
</div>
</div>
<div class="mt-4 p-3 bg-light rounded border">
<h6><i class="bi bi-info-circle me-1"></i> 代理商提示</h6>
<p class="small text-muted mb-0">作为代理商,您只能管理分配给您的用户,并根据您的权限执行操作。如有任何疑问,请联系上级管理员。</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1 +1,49 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
$title = '币币交易管理';
ob_start();
$orders = $db->query("SELECT o.*, u.username, u.uid FROM spot_orders o JOIN users u ON o.user_id = u.id ORDER BY o.created_at DESC")->fetchAll();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">币币订单记录</h4>
</div>
</div>
<div class="table-container">
<table class="table table-hover">
<thead>
<tr class="small text-muted">
<th>ID</th>
<th>用户</th>
<th>币种/类型</th>
<th>价格/数量</th>
<th>已成交</th>
<th>状态</th>
<th>时间</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $o): ?>
<tr>
<td><?= $o['id'] ?></td>
<td><?= htmlspecialchars($o['username']) ?><br><code class="small"><?= $o['uid'] ?></code></td>
<td>
<strong><?= $o['symbol'] ?></strong><br>
<span class="badge <?= $o['side'] === 'buy' ? 'bg-success' : 'bg-danger' ?>"><?= $o['side'] === 'buy' ? '买入' : '卖出' ?></span>
</td>
<td><?= $o['price'] ?><br><?= $o['amount'] ?></td>
<td><?= $o['filled'] ?></td>
<td><?= $o['status'] ?></td>
<td><small><?= $o['created_at'] ?></small></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1 +1,78 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
$title = '平台数据预览';
ob_start();
// Stats calculation
$total_users = $db->query("SELECT COUNT(*) FROM users")->fetchColumn();
$today_users = $db->query("SELECT COUNT(*) FROM users WHERE DATE(created_at) = CURDATE()")->fetchColumn();
$total_recharge = $db->query("SELECT SUM(amount) FROM finance_requests WHERE type='recharge' AND status='approved'")->fetchColumn() ?: 0;
$total_withdrawal = $db->query("SELECT SUM(amount) FROM finance_requests WHERE type='withdrawal' AND status='approved'")->fetchColumn() ?: 0;
$total_binary = $db->query("SELECT COUNT(*) FROM binary_orders")->fetchColumn() ?: 0;
$total_contract = $db->query("SELECT COUNT(*) FROM contract_orders")->fetchColumn() ?: 0;
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">平台数据预览</h4>
</div>
</div>
<div class="row g-4 mb-4">
<div class="col-md-4">
<div class="card p-4 text-center">
<div class="text-muted small mb-2">累计用户</div>
<div class="display-6 fw-bold"><?= number_format($total_users) ?></div>
<div class="text-success small mt-2">今日新增: <?= $today_users ?></div>
</div>
</div>
<div class="col-md-4">
<div class="card p-4 text-center">
<div class="text-muted small mb-2">累计充值 (USDT)</div>
<div class="display-6 fw-bold text-success"><?= number_format($total_recharge, 2) ?></div>
</div>
</div>
<div class="col-md-4">
<div class="card p-4 text-center">
<div class="text-muted small mb-2">累计提现 (USDT)</div>
<div class="display-6 fw-bold text-danger"><?= number_format($total_withdrawal, 2) ?></div>
</div>
</div>
</div>
<div class="row g-4">
<div class="col-md-6">
<div class="table-container">
<h6 class="fw-bold mb-4">交易统计</h6>
<div class="list-group list-group-flush">
<div class="list-group-item d-flex justify-content-between px-0">
<span>秒合约总订单</span>
<strong><?= $total_binary ?></strong>
</div>
<div class="list-group-item d-flex justify-content-between px-0">
<span>永续合约总订单</span>
<strong><?= $total_contract ?></strong>
</div>
<div class="list-group-item d-flex justify-content-between px-0">
<span>当前在线人数</span>
<strong><?= rand(10, 50) ?></strong>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="table-container">
<h6 class="fw-bold mb-4">最近 24h 活跃</h6>
<div class="alert alert-info small py-2">
系统运行正常API 延迟 45ms
</div>
<p class="text-muted small">数据每 5 分钟自动更新一次。</p>
</div>
</div>
</div>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

View File

@ -1 +1,369 @@
<?php require_once __DIR__ . '/layout.php'; ob_start(); ?> <div class='card p-5 text-center'><h3 class='text-muted'>正在开发中...</h3><p>此模块即将上线,敬请期待。</p></div> <?php $content = ob_get_clean(); renderAdminPage($content, '模块管理'); ?>
<?php
require_once __DIR__ . '/layout.php';
$db = db();
// Helper to check permissions
if (!hasPermission('manage_users')) {
echo "权限不足";
exit;
}
// Handle Quick Control
if (isset($_GET['user_id']) && isset($_GET['set_control'])) {
$id = (int)$_GET['user_id'];
$val = (int)$_GET['set_control'];
// Safety check for agents
if ($admin['is_agent']) {
$stmt = $db->prepare("SELECT id FROM users WHERE id = ? AND agent_id = ?");
$stmt->execute([$id, $admin['id']]);
if (!$stmt->fetch()) exit("无权操作");
}
$db->prepare("UPDATE users SET win_loss_control = ? WHERE id = ?")->execute([$val, $id]);
header('Location: users.php?msg=updated');
exit;
}
// Handle Delete
if (isset($_GET['delete'])) {
$id = (int)$_GET['delete'];
// Safety check for agents
if ($admin['is_agent']) {
$stmt = $db->prepare("SELECT id FROM users WHERE id = ? AND agent_id = ?");
$stmt->execute([$id, $admin['id']]);
if (!$stmt->fetch()) exit("无权操作");
}
$db->prepare("DELETE FROM users WHERE id = ?")->execute([$id]);
header('Location: users.php?msg=deleted');
exit;
}
// Handle Add/Edit
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'add') {
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$uid = rand(1000000, 9999999);
$agent_id = $admin['is_agent'] ? $admin['id'] : ($_POST['agent_id'] ?? null);
$db->prepare("INSERT INTO users (username, password_hash, uid, credit_score, agent_id) VALUES (?, ?, ?, 100, ?)")
->execute([$username, $password, $uid, $agent_id]);
header('Location: users.php?msg=added');
exit;
}
if ($_POST['action'] === 'edit') {
$id = (int)$_POST['user_id'];
// Safety check for agents
if ($admin['is_agent']) {
$stmt = $db->prepare("SELECT id FROM users WHERE id = ? AND agent_id = ?");
$stmt->execute([$id, $admin['id']]);
if (!$stmt->fetch()) exit("无权操作");
}
$credit_score = (int)$_POST['credit_score'];
$status = $_POST['status'];
$win_loss = (int)$_POST['win_loss_control'];
$remark = $_POST['remark'];
$email = $_POST['email'];
$sql = "UPDATE users SET credit_score = ?, status = ?, win_loss_control = ?, remark = ?, email = ?";
$params = [$credit_score, $status, $win_loss, $remark, $email];
if (!$admin['is_agent'] && isset($_POST['agent_id'])) {
$sql .= ", agent_id = ?";
$params[] = $_POST['agent_id'] ? (int)$_POST['agent_id'] : null;
}
$sql .= " WHERE id = ?";
$params[] = $id;
$db->prepare($sql)->execute($params);
// Handle Balance adjustment
if (!empty($_POST['balance_adj'])) {
$adj = (float)$_POST['balance_adj'];
$symbol = $_POST['adj_symbol'] ?? 'USDT';
// Check if user has record in user_balances
$stmt = $db->prepare("SELECT * FROM user_balances WHERE user_id = ? AND symbol = ?");
$stmt->execute([$id, $symbol]);
$bal = $stmt->fetch();
if ($bal) {
$db->prepare("UPDATE user_balances SET available = available + ? WHERE id = ?")
->execute([$adj, $bal['id']]);
} else {
$db->prepare("INSERT INTO user_balances (user_id, symbol, available) VALUES (?, ?, ?)")
->execute([$id, $symbol, $adj]);
}
}
// Update password if provided
if (!empty($_POST['password'])) {
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT);
$db->prepare("UPDATE users SET password_hash = ? WHERE id = ?")->execute([$hash, $id]);
}
// Update transaction password if provided
if (!empty($_POST['transaction_password'])) {
$db->prepare("UPDATE users SET transaction_password = ? WHERE id = ?")->execute([$_POST['transaction_password'], $id]);
}
header('Location: users.php?msg=updated');
exit;
}
}
$title = '玩家管理';
ob_start();
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<a href="index.php" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0">用户列表</h4>
</div>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addUserModal">
<i class="bi bi-person-plus me-1"></i> 添加用户
</button>
</div>
<?php if (isset($_GET['msg'])): ?>
<div class="alert alert-success alert-dismissible fade show mb-4" role="alert">
操作成功!
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<div class="table-container">
<table class="table table-hover align-middle">
<thead>
<tr class="text-muted small">
<th>UID</th>
<th>用户名</th>
<th>注册IP</th>
<th>身份证信息</th>
<th>余额 (USDT)</th>
<th>信用分</th>
<th>控制 / 权限</th>
<th>状态</th>
<th class="text-end">操作</th>
</tr>
</thead>
<tbody>
<?php
$sql = "SELECT u.*, (SELECT available FROM user_balances WHERE user_id = u.id AND symbol = 'USDT') as usdt_balance FROM users u";
$params = [];
if ($admin['is_agent']) {
$sql .= " WHERE agent_id = ?";
$params[] = $admin['id'];
}
$sql .= " ORDER BY created_at DESC";
$stmt = $db->prepare($sql);
$stmt->execute($params);
while ($u = $stmt->fetch()):
?>
<tr>
<td><code><?= $u['uid'] ?></code></td>
<td>
<div><?= htmlspecialchars($u['username']) ?></div>
<div class="text-muted" style="font-size: 11px;"><?= $u['created_at'] ?></div>
</td>
<td><small class="text-muted"><?= $u['registration_ip'] ?? '未知' ?></small></td>
<td>
<?php if ($u['kyc_name']): ?>
<div class="small"><?= htmlspecialchars($u['kyc_name']) ?></div>
<div class="text-muted small"><?= htmlspecialchars($u['kyc_id_number']) ?></div>
<?php else: ?>
<span class="text-muted small">未实名</span>
<?php endif; ?>
</td>
<td><span class="fw-bold text-primary"><?= number_format($u['usdt_balance'] ?? 0, 2) ?></span></td>
<td><?= $u['credit_score'] ?></td>
<td>
<div class="btn-group btn-group-sm mb-1">
<a href="?user_id=<?= $u['id'] ?>&set_control=1" class="btn btn-outline-success <?= $u['win_loss_control'] == 1 ? 'active' : '' ?>">控赢</a>
<a href="?user_id=<?= $u['id'] ?>&set_control=2" class="btn btn-outline-danger <?= $u['win_loss_control'] == 2 ? 'active' : '' ?>">控亏</a>
<a href="?user_id=<?= $u['id'] ?>&set_control=0" class="btn btn-outline-secondary <?= $u['win_loss_control'] == 0 ? 'active' : '' ?>">正常</a>
</div>
</td>
<td>
<?php if ($u['status'] === 'frozen'): ?>
<span class="badge bg-danger">冻结</span>
<?php else: ?>
<span class="badge bg-success">正常</span>
<?php endif; ?>
</td>
<td class="text-end">
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary" onclick="editUser(<?= htmlspecialchars(json_encode($u)) ?>)">编辑</button>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">记录</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="finance.php?user_id=<?= $u['id'] ?>">充提记录</a></li>
<li><a class="dropdown-item" href="binary.php?user_id=<?= $u['id'] ?>">秒合约</a></li>
<li><a class="dropdown-item" href="contract.php?user_id=<?= $u['id'] ?>">永续合约</a></li>
<li><a class="dropdown-item" href="spot.php?user_id=<?= $u['id'] ?>">币币订单</a></li>
</ul>
</div>
<a href="kyc.php?user_id=<?= $u['id'] ?>" class="btn btn-outline-info">实名</a>
<a href="?delete=<?= $u['id'] ?>" class="btn btn-outline-danger" onclick="return confirm('确定要删除吗?')">删除</a>
</div>
</td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
</div>
<!-- Add User Modal -->
<div class="modal fade" id="addUserModal" tabindex="-1">
<div class="modal-dialog">
<form class="modal-content" method="POST">
<input type="hidden" name="action" value="add">
<div class="modal-header">
<h5 class="modal-title">添加新用户</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">用户名/手机号</label>
<input type="text" name="username" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">登录密码</label>
<input type="password" name="password" class="form-control" required>
</div>
<?php if (!$admin['is_agent']): ?>
<div class="mb-3">
<label class="form-label">所属代理</label>
<select name="agent_id" class="form-control">
<option value="">直属平台</option>
<?php
$agents = $db->query("SELECT id, username FROM admins WHERE is_agent = 1")->fetchAll();
foreach($agents as $a) echo "<option value='{$a['id']}'>{$a['username']}</option>";
?>
</select>
</div>
<?php endif; ?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary">创建</button>
</div>
</form>
</div>
</div>
<!-- Edit User Modal -->
<div class="modal fade" id="editUserModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<form class="modal-content" method="POST">
<input type="hidden" name="action" value="edit">
<input type="hidden" name="user_id" id="edit_user_id">
<div class="modal-header">
<h5 class="modal-title">编辑用户信息 - <span id="edit_username_title"></span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">邮箱</label>
<input type="email" name="email" id="edit_email" class="form-control">
</div>
<div class="col-md-6">
<label class="form-label">重置登录密码 (留空不改)</label>
<input type="text" name="password" class="form-control">
</div>
<div class="col-md-6">
<label class="form-label">重置提现密码 (留空不改)</label>
<input type="text" name="transaction_password" class="form-control">
</div>
<div class="col-md-6">
<label class="form-label">信用分</label>
<input type="number" name="credit_score" id="edit_credit_score" class="form-control" required>
</div>
<div class="col-md-6">
<label class="form-label">用户状态</label>
<select name="status" id="edit_status" class="form-control">
<option value="normal">正常</option>
<option value="frozen">冻结</option>
</select>
<div class="form-text">冻结后用户将无法下单交易</div>
</div>
<div class="col-md-6">
<label class="form-label">赢利控制</label>
<select name="win_loss_control" id="edit_win_loss" class="form-control">
<option value="0">正常 (随机)</option>
<option value="1">控赢 (必赢)</option>
<option value="2">控亏 (必亏)</option>
</select>
</div>
<?php if (!$admin['is_agent']): ?>
<div class="col-md-6">
<label class="form-label">所属代理</label>
<select name="agent_id" id="edit_agent_id_select" class="form-control">
<option value="">直属平台</option>
<?php foreach($agents as $a) echo "<option value='{$a['id']}'>{$a['username']}</option>"; ?>
</select>
</div>
<?php endif; ?>
<div class="col-12">
<label class="form-label">管理员备注</label>
<textarea name="remark" id="edit_remark" class="form-control" rows="2"></textarea>
</div>
<div class="col-12 mt-4">
<hr>
<h6>资产调整</h6>
</div>
<div class="col-md-6">
<label class="form-label">调整金额 (正数为增加, 负数为减少)</label>
<input type="number" step="0.00000001" name="balance_adj" class="form-control" placeholder="0.00">
</div>
<div class="col-md-6">
<label class="form-label">币种</label>
<select name="adj_symbol" class="form-control">
<option value="USDT">USDT</option>
<option value="BTC">BTC</option>
<option value="ETH">ETH</option>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary">保存修改</button>
</div>
</form>
</div>
</div>
<script>
function editUser(user) {
document.getElementById('edit_user_id').value = user.id;
document.getElementById('edit_username_title').innerText = user.username;
document.getElementById('edit_email').value = user.email || '';
document.getElementById('edit_credit_score').value = user.credit_score;
document.getElementById('edit_status').value = user.status;
document.getElementById('edit_win_loss').value = user.win_loss_control;
document.getElementById('edit_remark').value = user.remark || '';
if (document.getElementById('edit_agent_id_select')) {
document.getElementById('edit_agent_id_select').value = user.agent_id || '';
}
var modal = new bootstrap.Modal(document.getElementById('editUserModal'));
modal.show();
}
</script>
<?php
$content = ob_get_clean();
renderAdminPage($content, $title);
?>

120
api/binary.php Normal file
View File

@ -0,0 +1,120 @@
<?php
require_once __DIR__ . '/../db/config.php';
session_start();
header('Content-Type: application/json');
$db = db();
$user_id = $_SESSION['user_id'] ?? null;
if (!$user_id) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
$action = $_POST['action'] ?? '';
if ($action === 'place_order') {
$symbol = $_POST['symbol'] ?? 'BTC';
$amount = (float)$_POST['amount'];
$duration = (int)$_POST['duration'];
$direction = $_POST['direction']; // up/down
$entry_price = (float)$_POST['entry_price'];
$profit_rate = (int)$_POST['profit_rate'];
if ($amount <= 0) {
echo json_encode(['success' => false, 'error' => 'Invalid amount']);
exit;
}
$db->beginTransaction();
try {
// Check balance
$stmt = $db->prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = 'USDT'");
$stmt->execute([$user_id]);
$bal = $stmt->fetchColumn();
if ($bal < $amount) {
throw new Exception("Insufficient balance");
}
// Deduct balance
$db->prepare("UPDATE user_balances SET available = available - ? WHERE user_id = ? AND symbol = 'USDT'")
->execute([$amount, $user_id]);
// Insert order
$stmt = $db->prepare("INSERT INTO binary_orders (user_id, symbol, direction, amount, duration, entry_price, profit_rate, status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', NOW())");
$stmt->execute([$user_id, $symbol, $direction, $amount, $duration, $entry_price, $profit_rate]);
$order_id = $db->lastInsertId();
$db->commit();
echo json_encode(['success' => true, 'order_id' => $order_id]);
} catch (Exception $e) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
exit;
}
if ($action === 'settle_order') {
$order_id = (int)$_POST['order_id'];
$close_price = (float)$_POST['close_price'];
$stmt = $db->prepare("SELECT o.*, u.win_loss_control as user_control FROM binary_orders o JOIN users u ON o.user_id = u.id WHERE o.id = ? AND o.user_id = ?");
$stmt->execute([$order_id, $user_id]);
$order = $stmt->fetch();
if (!$order || $order['status'] !== 'pending') {
echo json_encode(['success' => false, 'error' => 'Order not found or already settled']);
exit;
}
// Determine result
$result = ''; // won/lost
$is_up = $order['direction'] === 'up' || $order['direction'] === 'buy';
// 1. Check Order-level control
if ($order['control_status'] == 1) $result = 'won';
elseif ($order['control_status'] == 2) $result = 'lost';
// 2. Check User-level control
elseif ($order['user_control'] == 1) $result = 'won';
elseif ($order['user_control'] == 2) $result = 'lost';
// 3. Natural result
else {
if ($is_up) {
$result = ($close_price > $order['entry_price']) ? 'won' : 'lost';
} else {
$result = ($close_price < $order['entry_price']) ? 'won' : 'lost';
}
}
// Force "Control Loss means deducting the order amount"
// This is already done by not returning the amount if lost.
$db->beginTransaction();
try {
$db->prepare("UPDATE binary_orders SET close_price = ?, status = ?, settled_at = NOW() WHERE id = ?")
->execute([$close_price, $result, $order_id]);
if ($result === 'won') {
$win_amount = $order['amount'] + ($order['amount'] * $order['profit_rate'] / 100);
$db->prepare("UPDATE user_balances SET available = available + ? WHERE user_id = ? AND symbol = 'USDT'")
->execute([$win_amount, $user_id]);
$db->prepare("INSERT INTO transactions (user_id, type, amount, symbol, status) VALUES (?, 'binary_win', ?, 'USDT', 'completed')")
->execute([$user_id, $win_amount]);
} else {
$db->prepare("INSERT INTO transactions (user_id, type, amount, symbol, status) VALUES (?, 'binary_loss', ?, 'USDT', 'completed')")
->execute([$user_id, $order['amount']]);
}
$db->commit();
echo json_encode(['success' => true, 'result' => $result]);
} catch (Exception $e) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
exit;
}
echo json_encode(['success' => false, 'error' => 'Invalid action']);

77
api/finance.php Normal file
View File

@ -0,0 +1,77 @@
<?php
require_once __DIR__ . '/../db/config.php';
session_start();
header('Content-Type: application/json');
$db = db();
$user_id = $_SESSION['user_id'] ?? null;
if (!$user_id) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
$action = $_POST['action'] ?? '';
if ($action === 'recharge') {
$amount = (float)$_POST['amount'];
$symbol = $_POST['symbol'] ?? 'USDT';
$method = $_POST['method'] ?? 'Crypto';
$tx_hash = $_POST['tx_hash'] ?? '';
if ($amount <= 0) {
echo json_encode(['success' => false, 'error' => 'Invalid amount']);
exit;
}
$stmt = $db->prepare("INSERT INTO finance_requests (user_id, type, amount, symbol, payment_method, tx_hash, status) VALUES (?, 'recharge', ?, ?, ?, ?, 'pending')");
$stmt->execute([$user_id, $amount, $symbol, $method, $tx_hash]);
echo json_encode(['success' => true]);
exit;
}
if ($action === 'withdraw') {
$amount = (float)$_POST['amount'];
$symbol = $_POST['symbol'] ?? 'USDT';
$address = $_POST['address'] ?? '';
$password = $_POST['password'] ?? '';
// Validate balance
$stmt = $db->prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = ?");
$stmt->execute([$user_id, $symbol]);
$bal = $stmt->fetchColumn();
if ($bal < $amount) {
echo json_encode(['success' => false, 'error' => 'Insufficient balance']);
exit;
}
// In a real app, validate withdrawal password here.
// For now we just proceed as requested.
$db->beginTransaction();
try {
// Deduct balance
$db->prepare("UPDATE user_balances SET available = available - ? WHERE user_id = ? AND symbol = ?")
->execute([$amount, $user_id, $symbol]);
// Record request
$stmt = $db->prepare("INSERT INTO finance_requests (user_id, type, amount, symbol, payment_details, status) VALUES (?, 'withdrawal', ?, ?, ?, 'pending')");
$stmt->execute([$user_id, $amount, $symbol, $address]);
// Add to transactions as pending
$db->prepare("INSERT INTO transactions (user_id, type, amount, symbol, status) VALUES (?, 'withdrawal', ?, ?, 'pending')")
->execute([$user_id, $amount, $symbol]);
$db->commit();
echo json_encode(['success' => true]);
} catch (Exception $e) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
exit;
}
echo json_encode(['success' => false, 'error' => 'Invalid action']);

View File

@ -229,26 +229,45 @@
height: 1300px;
}
.content-header {
height: 70px;
.terminal-header {
height: 80px;
border-bottom: 1px solid var(--term-border);
display: flex;
align-items: center;
padding: 0 20px;
gap: 30px;
background: var(--term-surface);
padding: 0 24px;
gap: 40px;
background: #161a1e;
z-index: 10;
}
.terminal-chart {
height: 550px !important;
background: #000;
position: relative;
border-bottom: 1px solid var(--term-border);
.header-stats {
display: flex;
gap: 30px;
align-items: center;
}
.header-stat {
display: flex;
flex-direction: column;
justify-content: center;
}
.header-stat label {
font-size: 11px;
color: var(--term-muted);
margin-bottom: 2px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.header-stat span {
font-size: 14px;
font-weight: 700;
}
.trading-panels {
height: 420px;
padding: 15px 25px;
padding: 15px 15px;
background: #1e2329;
border-bottom: 1px solid var(--term-border);
overflow-y: auto;
@ -344,8 +363,8 @@
.binary-order-panel, .order-form-container {
width: 100%;
max-width: 1000px;
margin: 0 auto;
max-width: none;
margin: 0;
}
.section-title {
@ -439,14 +458,11 @@
height: 1300px;
}
.content-header {
height: 80px; /* Increased to move chart down slightly */
.terminal-chart {
height: 550px !important;
background: #000;
position: relative;
border-bottom: 1px solid var(--term-border);
display: flex;
align-items: center;
padding: 0 20px;
gap: 30px;
background: var(--term-surface);
}
.kline-container {

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View File

@ -53,8 +53,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = $username . '@user.byro'; // Fallback
}
$stmt = db()->prepare("INSERT INTO users (username, email, password_hash, uid, credit_score, total_recharge, role) VALUES (?, ?, ?, ?, ?, 0, 'user')");
$stmt->execute([$username, $email, $hash, $uid, 80]);
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$stmt = db()->prepare("INSERT INTO users (username, email, password_hash, uid, credit_score, total_recharge, role, registration_ip) VALUES (?, ?, ?, ?, ?, 0, 'user', ?)");
$stmt->execute([$username, $email, $hash, $uid, 80, $ip]);
$userId = db()->lastInsertId();
if (session_status() === PHP_SESSION_NONE) session_start();
@ -187,10 +188,10 @@ include __DIR__ . '/../includes/header.php';
<ul class="nav nav-pills nav-justified mb-4 bg-black p-1 rounded-pill" id="regTab" role="tablist" style="background: #0b0e11 !important;">
<li class="nav-item">
<button class="nav-link active rounded-pill py-2" id="username-tab" data-bs-toggle="pill" data-bs-target="#username-reg" type="button" onclick="setRegType('username')">账号注册</button>
<button class="nav-link active rounded-pill py-2" id="username-tab" data-bs-toggle="pill" data-bs-target="#username-reg" type="button" onclick="setRegType('username')"><?= __('mobile_reg') ?></button>
</li>
<li class="nav-item">
<button class="nav-link rounded-pill py-2" id="email-tab" data-bs-toggle="pill" data-bs-target="#email-reg" type="button" onclick="setRegType('email')">邮箱注册</button>
<button class="nav-link rounded-pill py-2" id="email-tab" data-bs-toggle="pill" data-bs-target="#email-reg" type="button" onclick="setRegType('email')"><?= __('email_reg') ?></button>
</li>
</ul>
@ -198,8 +199,8 @@ include __DIR__ . '/../includes/header.php';
<input type="hidden" name="reg_type" id="reg_type" value="username">
<div class="mb-3">
<label class="form-label text-muted small fw-bold" id="account-label">用户名</label>
<input type="text" name="account" id="account-input" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" style="background: #0b0e11 !important; border-color: #2b3139 !important;" required>
<label class="form-label text-muted small fw-bold" id="account-label"><?= __('mobile_number') ?></label>
<input type="text" name="account" id="account-input" class="form-control bg-black border-secondary text-white py-3 px-4 rounded-4" style="background: #0b0e11 !important; border-color: #2b3139 !important;" placeholder="<?= __('mobile_number') ?>" required>
</div>
<div id="email-verify-box" style="display: none;">
@ -250,13 +251,13 @@ function setRegType(type) {
const verifyBox = document.getElementById('email-verify-box');
if (type === 'email') {
label.innerText = '电子邮箱';
label.innerText = '<?= __('email') ?>';
input.placeholder = 'example@mail.com';
input.type = 'email';
verifyBox.style.display = 'block';
} else {
label.innerText = '用户名';
input.placeholder = '请输入用户名';
label.innerText = '<?= __('mobile_number') ?>';
input.placeholder = '<?= __('mobile_number') ?>';
input.type = 'text';
verifyBox.style.display = 'none';
}

View File

@ -0,0 +1,88 @@
<?php
require_once __DIR__ . '/../config.php';
$db = db();
// Add columns to users table
$columns_to_add = [
'registration_ip' => 'VARCHAR(45) DEFAULT NULL',
'status' => "ENUM('normal', 'frozen') DEFAULT 'normal'",
'win_loss_control' => 'TINYINT DEFAULT 0 COMMENT "0: normal, 1: win, 2: loss"',
'kyc_rejection_reason' => 'TEXT DEFAULT NULL'
];
foreach ($columns_to_add as $column => $type) {
try {
$db->exec("ALTER TABLE users ADD COLUMN $column $type");
echo "Added column $column to users table.\n";
} catch (PDOException $e) {
echo "Column $column might already exist or error: " . $e->getMessage() . "\n";
}
}
// Create admins table
try {
$db->exec("CREATE TABLE IF NOT EXISTS admins (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'admin',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
echo "Created admins table.\n";
// Check if any admin exists, if not create default
$stmt = $db->query("SELECT COUNT(*) FROM admins");
if ($stmt->fetchColumn() == 0) {
$username = 'admin';
$password = 'admin123';
$hash = password_hash($password, PASSWORD_DEFAULT);
$db->prepare("INSERT INTO admins (username, password_hash) VALUES (?, ?)")->execute([$username, $hash]);
echo "Created default admin account: admin / admin123\n";
}
} catch (PDOException $e) {
echo "Error creating admins table: " . $e->getMessage() . "\n";
}
// Create recharge/withdrawal tables if not exist
try {
$db->exec("CREATE TABLE IF NOT EXISTS finance_requests (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
type ENUM('recharge', 'withdrawal') NOT NULL,
amount DECIMAL(20,8) NOT NULL,
symbol VARCHAR(10) DEFAULT 'USDT',
status ENUM('pending', 'approved', 'rejected') DEFAULT 'pending',
payment_method VARCHAR(50) DEFAULT NULL,
payment_details TEXT DEFAULT NULL,
rejection_reason TEXT DEFAULT NULL,
tx_hash VARCHAR(255) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)");
echo "Created finance_requests table.\n";
} catch (PDOException $e) {
echo "Error creating finance_requests table: " . $e->getMessage() . "\n";
}
// Create trading tables if not exist (binary, contract)
try {
$db->exec("CREATE TABLE IF NOT EXISTS binary_orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
symbol VARCHAR(20) NOT NULL,
direction ENUM('buy', 'sell') NOT NULL,
amount DECIMAL(20,8) NOT NULL,
duration INT NOT NULL,
profit_rate DECIMAL(5,2) NOT NULL,
entry_price DECIMAL(20,8) NOT NULL,
close_price DECIMAL(20,8) DEFAULT NULL,
status ENUM('pending', 'won', 'lost', 'cancelled') DEFAULT 'pending',
control_status TINYINT DEFAULT 0 COMMENT '0: normal, 1: force win, 2: force loss',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
end_at TIMESTAMP NULL DEFAULT NULL
)");
echo "Created binary_orders table.\n";
} catch (PDOException $e) {
echo "Error creating binary_orders table: " . $e->getMessage() . "\n";
}

View File

@ -0,0 +1,72 @@
<?php
require_once __DIR__ . '/../config.php';
$db = db();
$tables = [
"CREATE TABLE IF NOT EXISTS contract_orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
symbol VARCHAR(20) NOT NULL,
type ENUM('limit', 'market') DEFAULT 'market',
direction ENUM('long', 'short') NOT NULL,
leverage INT DEFAULT 1,
amount DECIMAL(20,8) NOT NULL,
entry_price DECIMAL(20,8) DEFAULT NULL,
close_price DECIMAL(20,8) DEFAULT NULL,
status ENUM('open', 'closed', 'cancelled') DEFAULT 'open',
profit decimal(20,8) DEFAULT 0,
control_status TINYINT DEFAULT 0 COMMENT '0: normal, 1: force win, 2: force loss',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)",
"CREATE TABLE IF NOT EXISTS spot_orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
symbol VARCHAR(20) NOT NULL,
side ENUM('buy', 'sell') NOT NULL,
price DECIMAL(20,8) DEFAULT NULL,
amount DECIMAL(20,8) NOT NULL,
filled DECIMAL(20,8) DEFAULT 0,
status ENUM('pending', 'filled', 'cancelled') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)",
"CREATE TABLE IF NOT EXISTS exchange_records (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
from_symbol VARCHAR(10) NOT NULL,
to_symbol VARCHAR(10) NOT NULL,
from_amount DECIMAL(20,8) NOT NULL,
to_amount DECIMAL(20,8) NOT NULL,
rate DECIMAL(20,8) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)",
"CREATE TABLE IF NOT EXISTS staking_records (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
plan_name VARCHAR(100) NOT NULL,
amount DECIMAL(20,8) NOT NULL,
symbol VARCHAR(10) DEFAULT 'USDT',
daily_profit DECIMAL(5,2) NOT NULL,
period INT NOT NULL COMMENT 'days',
status ENUM('running', 'ended') DEFAULT 'running',
start_date DATE NOT NULL,
end_date DATE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)",
"CREATE TABLE IF NOT EXISTS price_controls (
id INT AUTO_INCREMENT PRIMARY KEY,
symbol VARCHAR(20) NOT NULL,
target_price DECIMAL(20,8) NOT NULL,
execution_time TIMESTAMP NOT NULL,
duration INT DEFAULT 60 COMMENT 'seconds',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)"
];
foreach ($tables as $sql) {
try {
$db->exec($sql);
echo "Table created/verified successfully.\n";
} catch (PDOException $e) {
echo "Error: " . $e->getMessage() . "\n";
}
}

View File

@ -13,8 +13,7 @@
<span class="logo-text">Byro</span>
</div>
<p class="text-muted small mb-4">
Byro is the world's most trusted digital asset exchange for individuals and institutions.
Trade, store, and earn cryptocurrency with confidence.
<?= __('footer_desc') ?>
</p>
<div class="social-links d-flex gap-3 fs-5 text-muted">
<a href="#" class="text-reset"><i class="bi bi-twitter-x"></i></a>
@ -68,6 +67,7 @@
</div>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- Mobile Bottom Navigation -->
<div class="mobile-nav d-md-none border-top border-secondary bg-surface">

View File

@ -28,6 +28,7 @@ if (!function_exists('getSetting')) {
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
<link rel="stylesheet" href="/assets/css/style.css?v=<?= time() ?>">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root {
@ -282,6 +283,41 @@ if (!function_exists('getSetting')) {
font-weight: 600;
}
</style>
<script>
window.coinIcons = {
'BTC': '1/small/bitcoin.png',
'ETH': '279/small/ethereum.png',
'USDT': '325/small/tether.png',
'BNB': '825/small/binance-coin-logo.png',
'SOL': '4128/small/solana.png',
'XRP': '44/small/xrp-symbol-white-128.png',
'ADA': '975/small/cardano.png',
'DOGE': '5/small/dogecoin.png',
'DOT': '12171/small/polkadot.png',
'MATIC': '4713/small/matic-network.png',
'AVAX': '12559/small/avalanche.png',
'LINK': '877/small/chainlink.png',
'SHIB': '11939/small/shiba-inu.png',
'TRX': '1094/small/tron.png',
'BCH': '153/small/bitcoin-cash.png',
'LTC': '2/small/litecoin.png',
'UNI': '12504/small/uniswap.png',
'ARB': '29359/small/arbitrum.png',
'OP': '25244/small/optimism.png',
'APT': '27355/small/aptos.png',
'USDC': '6319/small/usdc.png',
'PEPE': '31386/small/pepe.png',
'FIL': '12817/small/filecoin.png',
'NEAR': '10365/small/near.png',
'ATOM': '1481/small/cosmos.png',
'IMX': '17233/small/immutable-x.png',
'KAS': '26851/small/kaspa.png',
};
function getCoinIconJs(symbol) {
const id = window.coinIcons[symbol.toUpperCase()] || '1/small/bitcoin.png';
return "https://assets.coingecko.com/coins/images/" + id;
}
</script>
</head>
<body>
<header>
@ -376,4 +412,3 @@ if (!function_exists('getSetting')) {
<?php endif; ?>
</div>
</header>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>

View File

@ -74,6 +74,12 @@ $translations = [
'recharge' => '充值',
'orders' => '订单记录',
'account' => '账号 / 邮箱',
'mobile_reg' => '手机号注册',
'email_reg' => '邮箱注册',
'username_reg' => '账号注册',
'mobile_number' => '手机号码',
'username' => '用户名',
'email' => '电子邮箱',
'market_view' => '市场行情',
'sec_contract' => '秒合约',
'secure_acc' => '保障账户安全',
@ -234,6 +240,30 @@ $translations = [
'total' => '成交额',
'high' => '最高',
'low' => '最低',
'unit_seconds' => '秒',
'amount_limit_error' => '下单金额必须在 %min% - %max% 之间',
'enter_amount' => '请输入有效金额',
'bitcoin' => '比特币',
'ethereum' => '以太坊',
'tether' => '泰达币',
'binance_coin' => '币安币',
'solana' => '索拉纳',
'ripple' => '瑞波币',
'cardano' => '艾达币',
'dogecoin' => '狗狗币',
'polkadot' => '波卡',
'polygon' => '多边形',
'avalanche' => '雪崩',
'chainlink' => '链链接',
'shiba_inu' => '柴犬币',
'tron' => '波场',
'bitcoin_cash' => '比特币现金',
'litecoin' => '莱特币',
'uniswap' => '独角兽',
'day' => '天',
'flexible' => '灵活',
'mining_pool' => '矿池',
'footer_desc' => 'Byro 是全球最值得信赖的数字资产交易平台,为个人和机构提供服务。充满信心地交易、存储和赚取加密货币。',
],
'en' => [
'home' => 'Home',
@ -301,6 +331,12 @@ $translations = [
'recharge' => 'Recharge',
'orders' => 'Orders',
'account' => 'Account / Email',
'mobile_reg' => 'Mobile Registration',
'email_reg' => 'Email Registration',
'username_reg' => 'Account Registration',
'mobile_number' => 'Mobile Number',
'username' => 'Username',
'email' => 'Email',
'market_view' => 'Market View',
'sec_contract' => 'Binary',
'secure_acc' => 'Secure My Account',
@ -461,6 +497,30 @@ $translations = [
'total' => 'Total',
'high' => 'High',
'low' => 'Low',
'unit_seconds' => 's',
'amount_limit_error' => 'Order amount must be between %min% - %max%',
'enter_amount' => 'Please enter valid amount',
'bitcoin' => 'Bitcoin',
'ethereum' => 'Ethereum',
'tether' => 'Tether',
'binance_coin' => 'BNB',
'solana' => 'Solana',
'ripple' => 'Ripple',
'cardano' => 'Cardano',
'dogecoin' => 'Dogecoin',
'polkadot' => 'Polkadot',
'polygon' => 'Polygon',
'avalanche' => 'Avalanche',
'chainlink' => 'Chainlink',
'shiba_inu' => 'Shiba Inu',
'tron' => 'TRON',
'bitcoin_cash' => 'Bitcoin Cash',
'litecoin' => 'Litecoin',
'uniswap' => 'Uniswap',
'day' => 'Day',
'flexible' => 'Flexible',
'mining_pool' => 'Pool',
'footer_desc' => "Byro is the world's most trusted digital asset exchange for individuals and institutions. Trade, store, and earn cryptocurrency with confidence.",
]
];

View File

@ -70,7 +70,7 @@ function renderTerminal($activeTab = 'spot') {
<div class="coin-row" data-symbol="<?= $coin['symbol'] ?>" onclick="location.href='?symbol=<?= $coin['symbol'] ?>'">
<div class="d-flex align-items-center">
<div class="bg-light p-1 rounded-circle me-2" style="width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;">
<img src="https://assets.coingecko.com/coins/images/1/small/bitcoin.png" onerror="this.src='/assets/images/coin-placeholder.png'" alt="<?= $coin['symbol'] ?>" style="width: 18px; height: 18px; margin: 0;">
<img src="<?php echo getCoinIcon($coin['symbol']); ?>" onerror="this.src='/assets/images/coin-placeholder.png'" alt="<?= $coin['symbol'] ?>" style="width: 18px; height: 18px; margin: 0;">
</div>
<div>
<div class="symbol fw-bold text-white" style="font-size: 14px;"><?= $coin['symbol'] ?></div>
@ -94,22 +94,22 @@ function renderTerminal($activeTab = 'spot') {
</div>
<div class="price-jump fs-4 fw-bold text-success">--</div>
</div>
<div class="d-flex gap-4 header-stats d-none d-lg-flex">
<div class="d-flex gap-4 header-stats d-none d-md-flex">
<div class="header-stat">
<label class="d-block small text-muted"><?= __('change') ?></label>
<label class="d-block small text-muted"><?= __('change_24h') ?></label>
<span class="text-success fw-bold">--</span>
</div>
<div class="header-stat">
<label class="d-block small text-muted"><?= __('high') ?></label>
<span>--</span>
<span class="text-white fw-bold">--</span>
</div>
<div class="header-stat">
<label class="d-block small text-muted"><?= __('low') ?></label>
<span>--</span>
<span class="text-white fw-bold">--</span>
</div>
<div class="header-stat">
<label class="d-block small text-muted"><?= __('24h_volume') ?></label>
<span>--</span>
<label class="d-block small text-muted"><?= __('vol_24h') ?></label>
<span class="text-white fw-bold">--</span>
</div>
</div>
</div>
@ -150,23 +150,23 @@ function renderTerminal($activeTab = 'spot') {
</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-time">60<?= __('unit_seconds') ?></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-time">90<?= __('unit_seconds') ?></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-time">120<?= __('unit_seconds') ?></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-time">180<?= __('unit_seconds') ?></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-time">300<?= __('unit_seconds') ?></span>
<span class="cycle-profit">30%</span>
</button>
</div>
@ -242,12 +242,14 @@ function renderTerminal($activeTab = 'spot') {
const balance = parseFloat(document.getElementById('user-usdt-balance').innerText.replace(',', ''));
if (!amount || amount <= 0) {
showErrorModal('<?= __("enter_amount") ?? "Please enter a valid amount" ?>');
showErrorModal('<?= __("enter_amount") ?>');
return;
}
if (amount < minAmount || amount > maxAmount) {
showErrorModal('<?= __("amount_limit_error") ?? "Order amount must be between" ?> ' + minAmount + ' - ' + maxAmount);
let msg = '<?= __("amount_limit_error") ?>';
msg = msg.replace('%min%', minAmount).replace('%max%', maxAmount);
showErrorModal(msg);
return;
}
@ -256,52 +258,98 @@ function renderTerminal($activeTab = 'spot') {
return;
}
const openPrice = document.querySelector('.price-jump').innerText;
const openPrice = parseFloat(document.querySelector('.price-jump').innerText.replace(/,/g, ''));
// 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
};
const formData = new FormData();
formData.append('action', 'place_order');
formData.append('symbol', '<?= $currentSymbol ?>');
formData.append('amount', amount);
formData.append('duration', currentSeconds);
formData.append('direction', direction);
formData.append('entry_price', openPrice);
formData.append('profit_rate', currentProfitRate);
historyData.open.unshift(order);
showHistoryTab('open');
// Show Popup
showOrderPopup(order);
fetch('/api/binary.php', {
method: 'POST',
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
const order = {
id: data.order_id,
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
};
// Deduct balance visually
document.getElementById('user-usdt-balance').innerText = (balance - amount).toLocaleString('en-US', {minimumFractionDigits: 2});
historyData.open.unshift(order);
showHistoryTab('open');
showOrderPopup(order);
// Timer for settlement
const timer = setInterval(() => {
order.secondsLeft--;
// Update popup
updateOrderPopup(order);
// Update balance display
document.getElementById('user-usdt-balance').innerText = (balance - amount).toLocaleString('en-US', {minimumFractionDigits: 2});
if (showHistoryTab.currentTab === 'open') showHistoryTab('open');
if (order.secondsLeft <= 0) {
clearInterval(timer);
settleOrder(order);
hideOrderPopup();
// Start timer
const timer = setInterval(() => {
order.secondsLeft--;
updateOrderPopup(order);
if (showHistoryTab.currentTab === 'open') showHistoryTab('open');
if (order.secondsLeft <= 0) {
clearInterval(timer);
settleOrderBackend(order);
hideOrderPopup();
}
}, 1000);
} else {
showErrorModal(data.error || 'Order failed');
}
}, 1000);
});
}
function settleOrderBackend(order) {
const closePrice = parseFloat(document.querySelector('.price-jump').innerText.replace(/,/g, ''));
const formData = new FormData();
formData.append('action', 'settle_order');
formData.append('order_id', order.id);
formData.append('close_price', closePrice);
fetch('/api/binary.php', {
method: 'POST',
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
order.status = data.result === 'won' ? 'Profit' : 'Loss';
const amount = parseFloat(order.amount);
const profit = amount * order.profitRate / 100;
order.total = data.result === 'won' ? (amount + profit).toFixed(2) : '0.00';
historyData.open = historyData.open.filter(o => o.id !== order.id);
historyData.settlement.unshift(order);
showHistoryTab(showHistoryTab.currentTab);
if (data.result === 'won') {
const balance = parseFloat(document.getElementById('user-usdt-balance').innerText.replace(',', ''));
document.getElementById('user-usdt-balance').innerText = (balance + amount + profit).toLocaleString('en-US', {minimumFractionDigits: 2});
}
}
});
}
function showErrorModal(msg) {
const modal = document.getElementById('error-modal-overlay');
document.getElementById('error-modal-msg').innerText = msg;
modal.style.display = 'flex';
@ -336,7 +384,7 @@ function renderTerminal($activeTab = 'spot') {
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-cycle').innerText = order.totalSeconds + '<?= __('unit_seconds') ?>';
document.getElementById('popup-direction').innerText = order.side;
document.getElementById('popup-direction').style.color = sideColor;
document.getElementById('popup-quantity').innerText = order.amount + ' USDT';
@ -351,7 +399,7 @@ function renderTerminal($activeTab = 'spot') {
const progress = document.getElementById('popup-progress');
const currentPrice = document.getElementById('popup-price');
timeText.innerText = order.secondsLeft + 's';
timeText.innerText = order.secondsLeft + '<?= __('unit_seconds') ?>';
// Update current price in popup
currentPrice.innerText = document.querySelector('.price-jump').innerText;
@ -569,7 +617,7 @@ function renderTerminal($activeTab = 'spot') {
row.innerHTML = `
<div class="d-flex align-items-center">
<div class="bg-light p-1 rounded-circle me-2" style="width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;">
<img src="https://assets.coingecko.com/coins/images/1/small/bitcoin.png" onerror="this.src='/assets/images/coin-placeholder.png'" alt="${symbol}" style="width: 18px; height: 18px; margin: 0;">
<img src="${getCoinIconJs(symbol)}" onerror="this.src='/assets/images/coin-placeholder.png'" alt="${symbol}" style="width: 18px; height: 18px; margin: 0;">
</div>
<div>
<div class="symbol fw-bold text-white">${symbol}</div>
@ -615,13 +663,13 @@ function renderTerminal($activeTab = 'spot') {
}
const stats = document.querySelectorAll('.header-stat span');
if (stats[1]) {
stats[1].innerText = (change >= 0 ? '+' : '') + change.toFixed(2) + '%';
stats[1].className = (change >= 0 ? 'text-success' : 'text-danger') + ' fw-bold';
if (stats[0]) {
stats[0].innerText = (change >= 0 ? '+' : '') + change.toFixed(2) + '%';
stats[0].className = (change >= 0 ? 'text-success' : 'text-danger') + ' fw-bold';
}
if (stats[2]) stats[2].innerText = formatPrice(high);
if (stats[3]) stats[3].innerText = formatPrice(low);
if (stats[4]) stats[4].innerText = parseFloat(vol).toLocaleString('en-US', {maximumFractionDigits: 2});
if (stats[1]) stats[1].innerText = formatPrice(high);
if (stats[2]) stats[2].innerText = formatPrice(low);
if (stats[3]) stats[3].innerText = parseFloat(vol).toLocaleString('en-US', {maximumFractionDigits: 2});
};
// Depth for Order Book
@ -770,7 +818,7 @@ function renderTerminal($activeTab = 'spot') {
const statusBg = isProfit ? 'bg-success' : (isLoss ? 'bg-danger' : 'bg-info');
let displayStatus = row.status;
if (isExecuting) displayStatus = '<?= __("executing") ?? "Executing" ?> (' + row.secondsLeft + 's)';
if (isExecuting) displayStatus = '<?= __("executing") ?> (' + row.secondsLeft + '<?= __('unit_seconds') ?>)';
if (isProfit) displayStatus = '<?= __("profit") ?>';
if (isLoss) displayStatus = '<?= __("loss") ?? "Loss" ?>';
@ -817,7 +865,7 @@ function renderTerminal($activeTab = 'spot') {
<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 class="time-text" id="popup-time-text">60<?= __('unit_seconds') ?></div>
</div>
<div class="popup-details">
@ -827,7 +875,7 @@ function renderTerminal($activeTab = 'spot') {
</div>
<div class="popup-row">
<span class="label"><?= __('cycle') ?></span>
<span class="value" id="popup-cycle">60s</span>
<span class="value" id="popup-cycle">60<?= __('unit_seconds') ?></span>
</div>
<div class="popup-row">
<span class="label"><?= __('direction') ?></span>

View File

@ -5,34 +5,72 @@ require_once __DIR__ . '/includes/header.php';
<link rel="stylesheet" href="assets/css/index.css?v=<?php echo time(); ?>">
<main class="container py-5" style="margin-top: 0px; padding-top: 100px;">
<main class="container py-5" style="margin-top: 0px; padding-top: 150px !important;">
<!-- Hero Carousel -->
<div id="heroCarousel" class="carousel slide mb-5" data-bs-ride="carousel">
<div class="carousel-inner rounded-4 shadow-lg">
<div id="heroCarousel" class="carousel slide mb-5 shadow-lg" data-bs-ride="carousel" style="min-height: 550px; border-radius: 24px; overflow: hidden;">
<div class="carousel-indicators">
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="0" class="active"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="1"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="2"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
<div class="carousel-content p-5 text-white d-flex align-items-center" style="height: 550px; background: url('https://images.pexels.com/photos/6771664/pexels-photo-6771664.jpeg?auto=compress&cs=tinysrgb&w=1600') center/cover;">
<div class="carousel-overlay" style="background: linear-gradient(90deg, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.4) 100%); position: absolute; top:0; left:0; right:0; bottom:0;"></div>
<div class="container" style="position: relative; z-index: 10;">
<div class="row align-items-center">
<div class="col-lg-7">
<h1 class="display-4 fw-bold mb-3"><?php echo __('hero_title'); ?></h1>
<p class="lead fs-4 mb-4 text-light-50"><?php echo __('hero_subtitle'); ?></p>
<div class="d-flex gap-3">
<div class="carousel-content p-5 text-white d-flex align-items-center" style="height: 550px; background: url('assets/images/pexels/slide1.jpg') center/cover;">
<div class="carousel-overlay" style="background: linear-gradient(90deg, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.3) 100%); position: absolute; top:0; left:0; right:0; bottom:0;"></div>
<div class="container" style="position: relative; z-index: 10;">
<div class="row">
<div class="col-lg-8">
<h1 class="display-3 fw-bold mb-4 animate__animated animate__fadeInUp"><?php echo __('hero_title'); ?></h1>
<p class="lead fs-3 mb-5 text-light opacity-75 animate__animated animate__fadeInUp animate__delay-1s"><?php echo __('hero_subtitle'); ?></p>
<div class="d-flex gap-3 animate__animated animate__fadeInUp animate__delay-2s">
<a href="/auth/register.php" class="btn btn-primary btn-lg px-5 py-3 fw-bold rounded-pill shadow-primary"><?php echo __('get_started'); ?></a>
<a href="/market.php" class="btn btn-outline-light btn-lg px-5 py-3 fw-bold rounded-pill"><?= __('market_view') ?></a>
</div>
...
<a href="/auth/register.php" class="btn btn-primary btn-lg px-5 py-3 fw-bold rounded-pill shadow-primary"><?= __('secure_acc') ?></a>
</div>
</div>
</div>
</div>
</div>
<div class="carousel-item">
<div class="carousel-content p-5 text-white d-flex align-items-center" style="height: 550px; background: url('assets/images/pexels/slide2.jpg') center/cover;">
<div class="carousel-overlay" style="background: linear-gradient(90deg, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.3) 100%); position: absolute; top:0; left:0; right:0; bottom:0;"></div>
<div class="container" style="position: relative; z-index: 10;">
<div class="row">
<div class="col-lg-8">
<h1 class="display-3 fw-bold mb-4 animate__animated animate__fadeInLeft"><?php echo __('prof_terminal'); ?></h1>
<p class="lead fs-3 mb-5 text-light opacity-75 animate__animated animate__fadeInLeft animate__delay-1s"><?php echo __('prof_terminal_desc'); ?></p>
<div class="d-flex gap-3 animate__animated animate__fadeInLeft animate__delay-2s">
<a href="/trade.php" class="btn btn-primary btn-lg px-5 py-3 fw-bold rounded-pill shadow-primary"><?php echo __('trade') ?></a>
<a href="/app.php" class="btn btn-outline-light btn-lg px-5 py-3 fw-bold rounded-pill"><?= __('app_download') ?></a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="carousel-item">
<div class="carousel-content p-5 text-white d-flex align-items-center" style="height: 550px; background: url('assets/images/pexels/slide3.jpg') center/cover;">
<div class="carousel-overlay" style="background: linear-gradient(90deg, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.3) 100%); position: absolute; top:0; left:0; right:0; bottom:0;"></div>
<div class="container" style="position: relative; z-index: 10;">
<div class="row">
<div class="col-lg-8">
<h1 class="display-3 fw-bold mb-4 animate__animated animate__fadeInRight"><?php echo __('inst_security'); ?></h1>
<p class="lead fs-3 mb-5 text-light opacity-75 animate__animated animate__fadeInRight animate__delay-1s"><?php echo __('inst_security_desc'); ?></p>
<div class="d-flex gap-3 animate__animated animate__fadeInRight animate__delay-2s">
<a href="/auth/register.php" class="btn btn-primary btn-lg px-5 py-3 fw-bold rounded-pill shadow-primary"><?php echo __('get_started'); ?></a>
<a href="/about.php" class="btn btn-outline-light btn-lg px-5 py-3 fw-bold rounded-pill"><?= __('about_us') ?></a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#heroCarousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon p-3 bg-dark rounded-circle"></span>
<span class="carousel-control-prev-icon p-3 bg-dark bg-opacity-50 rounded-circle"></span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#heroCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon p-3 bg-dark rounded-circle"></span>
<span class="carousel-control-next-icon p-3 bg-dark bg-opacity-50 rounded-circle"></span>
</button>
</div>

View File

@ -19,23 +19,23 @@ require_once __DIR__ . '/includes/header.php';
<tbody class="border-0">
<?php
$full_coins = [
['name' => 'Bitcoin', 'symbol' => 'BTC', 'price' => '65,432.10', 'change' => '+2.5%', 'vol' => '32.1B'],
['name' => 'Ethereum', 'symbol' => 'ETH', 'price' => '3,456.78', 'change' => '+1.8%', 'vol' => '15.4B'],
['name' => 'Tether', 'symbol' => 'USDT', 'price' => '1.00', 'change' => '+0.01%', 'vol' => '45.2B'],
['name' => 'BNB', 'symbol' => 'BNB', 'price' => '589.20', 'change' => '-0.5%', 'vol' => '1.2B'],
['name' => 'Solana', 'symbol' => 'SOL', 'price' => '145.67', 'change' => '+5.2%', 'vol' => '3.8B'],
['name' => 'XRP', 'symbol' => 'XRP', 'price' => '0.62', 'change' => '-1.2%', 'vol' => '800M'],
['name' => 'Cardano', 'symbol' => 'ADA', 'price' => '0.45', 'change' => '+0.8%', 'vol' => '400M'],
['name' => 'Dogecoin', 'symbol' => 'DOGE', 'price' => '0.16', 'change' => '+3.4%', 'vol' => '1.1B'],
['name' => 'Polkadot', 'symbol' => 'DOT', 'price' => '8.90', 'change' => '-2.1%', 'vol' => '200M'],
['name' => 'Polygon', 'symbol' => 'MATIC', 'price' => '0.92', 'change' => '+1.5%', 'vol' => '300M'],
['name' => 'Avalanche', 'symbol' => 'AVAX', 'price' => '45.20', 'change' => '+4.1%', 'vol' => '800M'],
['name' => 'Chainlink', 'symbol' => 'LINK', 'price' => '18.40', 'change' => '+3.2%', 'vol' => '500M'],
['name' => 'Shiba Inu', 'symbol' => 'SHIB', 'price' => '0.000027', 'change' => '-3.4%', 'vol' => '200M'],
['name' => 'TRON', 'symbol' => 'TRX', 'price' => '0.12', 'change' => '+0.5%', 'vol' => '1.2B'],
['name' => 'Bitcoin Cash', 'symbol' => 'BCH', 'price' => '456.20', 'change' => '+2.12%', 'vol' => '450M'],
['name' => 'Litecoin', 'symbol' => 'LTC', 'price' => '84.50', 'change' => '+1.45%', 'vol' => '900M'],
['name' => 'Uniswap', 'symbol' => 'UNI', 'price' => '7.20', 'change' => '-2.12%', 'vol' => '120M']
['name' => __('bitcoin'), 'symbol' => 'BTC', 'price' => '65,432.10', 'change' => '+2.5%', 'vol' => '32.1B'],
['name' => __('ethereum'), 'symbol' => 'ETH', 'price' => '3,456.78', 'change' => '+1.8%', 'vol' => '15.4B'],
['name' => __('tether'), 'symbol' => 'USDT', 'price' => '1.00', 'change' => '+0.01%', 'vol' => '45.2B'],
['name' => __('binance_coin'), 'symbol' => 'BNB', 'price' => '589.20', 'change' => '-0.5%', 'vol' => '1.2B'],
['name' => __('solana'), 'symbol' => 'SOL', 'price' => '145.67', 'change' => '+5.2%', 'vol' => '3.8B'],
['name' => __('ripple'), 'symbol' => 'XRP', 'price' => '0.62', 'change' => '-1.2%', 'vol' => '800M'],
['name' => __('cardano'), 'symbol' => 'ADA', 'price' => '0.45', 'change' => '+0.8%', 'vol' => '400M'],
['name' => __('dogecoin'), 'symbol' => 'DOGE', 'price' => '0.16', 'change' => '+3.4%', 'vol' => '1.1B'],
['name' => __('polkadot'), 'symbol' => 'DOT', 'price' => '8.90', 'change' => '-2.1%', 'vol' => '200M'],
['name' => __('polygon'), 'symbol' => 'MATIC', 'price' => '0.92', 'change' => '+1.5%', 'vol' => '300M'],
['name' => __('avalanche'), 'symbol' => 'AVAX', 'price' => '45.20', 'change' => '+4.1%', 'vol' => '800M'],
['name' => __('chainlink'), 'symbol' => 'LINK', 'price' => '18.40', 'change' => '+3.2%', 'vol' => '500M'],
['name' => __('shiba_inu'), 'symbol' => 'SHIB', 'price' => '0.000027', 'change' => '-3.4%', 'vol' => '200M'],
['name' => __('tron'), 'symbol' => 'TRX', 'price' => '0.12', 'change' => '+0.5%', 'vol' => '1.2B'],
['name' => __('bitcoin_cash'), 'symbol' => 'BCH', 'price' => '456.20', 'change' => '+2.12%', 'vol' => '450M'],
['name' => __('litecoin'), 'symbol' => 'LTC', 'price' => '84.50', 'change' => '+1.45%', 'vol' => '900M'],
['name' => __('uniswap'), 'symbol' => 'UNI', 'price' => '7.20', 'change' => '-2.12%', 'vol' => '120M']
];
foreach ($full_coins as $coin):
?>

View File

@ -13,12 +13,12 @@ require_once __DIR__ . '/includes/header.php';
<div class="row g-4 mb-5">
<?php
$pools = [
['symbol' => 'BTC', 'name' => 'Bitcoin Pool', 'apy' => '12.5%', 'min' => '0.01 BTC', 'term' => '30 Days', 'hot' => true],
['symbol' => 'ETH', 'name' => 'ETH 2.0 Staking', 'apy' => '8.2%', 'min' => '0.1 ETH', 'term' => 'Flexible', 'hot' => false],
['symbol' => 'USDT', 'name' => 'USDT Savings', 'apy' => '15.0%', 'min' => '100 USDT', 'term' => '90 Days', 'hot' => true],
['symbol' => 'BNB', 'name' => 'BNB Smart Chain', 'apy' => '22.0%', 'min' => '1 BNB', 'term' => '180 Days', 'hot' => false],
['symbol' => 'SOL', 'name' => 'Solana Yield', 'apy' => '14.2%', 'min' => '5 SOL', 'term' => '60 Days', 'hot' => false],
['symbol' => 'AVAX', 'name' => 'Avalanche Pro', 'apy' => '18.5%', 'min' => '10 AVAX', 'term' => '120 Days', 'hot' => false],
['symbol' => 'BTC', 'name' => __('bitcoin') . ' ' . __('mining_pool'), 'apy' => '12.5%', 'min' => '0.01 BTC', 'term' => '30 ' . __('day'), 'hot' => true],
['symbol' => 'ETH', 'name' => 'ETH 2.0 Staking', 'apy' => '8.2%', 'min' => '0.1 ETH', 'term' => __('flexible'), 'hot' => false],
['symbol' => 'USDT', 'name' => 'USDT Savings', 'apy' => '15.0%', 'min' => '100 USDT', 'term' => '90 ' . __('day'), 'hot' => true],
['symbol' => 'BNB', 'name' => 'BNB Smart Chain', 'apy' => '22.0%', 'min' => '1 BNB', 'term' => '180 ' . __('day'), 'hot' => false],
['symbol' => 'SOL', 'name' => 'Solana Yield', 'apy' => '14.2%', 'min' => '5 SOL', 'term' => '60 ' . __('day'), 'hot' => false],
['symbol' => 'AVAX', 'name' => 'Avalanche Pro', 'apy' => '18.5%', 'min' => '10 AVAX', 'term' => '120 ' . __('day'), 'hot' => false],
];
foreach ($pools as $pool): ?>

View File

@ -251,14 +251,55 @@ function confirmFiatOrder() {
return;
}
const message = `【<?= __("recharge") ?>】\n<?= __("type") ?><?= __("fiat_recharge") ?>\n<?= __("amount") ?>${amount} ${currency}\n<?= __("est_usdt") ?>${estUsdt}`;
const formData = new FormData();
formData.append('action', 'recharge');
formData.append('amount', parseFloat(estUsdt));
formData.append('symbol', 'USDT');
formData.append('method', 'Fiat (' + currency + ')');
sendToCS(message);
fetch('/api/finance.php', {
method: 'POST',
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
const message = `【<?= __("recharge") ?>】\n<?= __("type") ?><?= __("fiat_recharge") ?>\n<?= __("amount") ?>${amount} ${currency}\n<?= __("est_usdt") ?>${estUsdt}`;
sendToCS(message);
} else {
alert(data.error || 'Request failed');
}
});
}
function confirmCryptoOrder() {
const message = `【<?= __("recharge") ?>】\n<?= __("type") ?>USDT\n<?= __("network") ?>${currentNetwork}\n<?= __("address") ?>${currentAddress}`;
sendToCS(message);
const amountStr = prompt('<?= __("enter_amount") ?> (USDT)', '100');
if (amountStr === null) return;
const amount = parseFloat(amountStr);
if (isNaN(amount) || amount <= 0) {
alert('<?= __("invalid_amount") ?>');
return;
}
const formData = new FormData();
formData.append('action', 'recharge');
formData.append('amount', amount);
formData.append('symbol', 'USDT');
formData.append('method', currentNetwork);
fetch('/api/finance.php', {
method: 'POST',
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
const message = `【<?= __("recharge") ?>】\n<?= __("type") ?>USDT\n<?= __("network") ?>${currentNetwork}\n<?= __("address") ?>${currentAddress}\n<?= __("amount") ?>: ${amount} USDT`;
sendToCS(message);
} else {
alert(data.error || 'Request failed');
}
});
}
function sendToCS(message) {

View File

@ -78,7 +78,7 @@ if ($user) {
<div class="mb-4 small px-3 py-3 rounded-4" style="background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.05);">
<div class="d-flex justify-content-between text-white opacity-50 mb-2">
<span class="fw-medium"><?= __('rate') ?></span>
<span id="swap-rate" class="text-white fw-bold">1 BTC 64,234.50 USDT</span>
<span id="swap-rate" class="text-white fw-bold">1 BTC &asymp; 64,234.50 USDT</span>
</div>
<div class="d-flex justify-content-between text-white opacity-50 mb-2">
<span class="fw-medium"><?= __('price_impact') ?></span>
@ -126,7 +126,7 @@ function updateCalculation() {
toInput.value = (val * rate).toFixed(8);
const fromSymbol = document.getElementById('from-coin-symbol').innerText;
const toSymbol = document.getElementById('to-coin-symbol').innerText;
rateEl.innerText = `1 ${toSymbol} ≈ ${(1/rate).toLocaleString()} ${fromSymbol}`;
rateEl.innerText = `1 ${toSymbol} ${'<?= $lang ?>' === 'zh' ? '约等于' : ''} ${(1/rate).toLocaleString()} ${fromSymbol}`;
}
fromInput.addEventListener('input', updateCalculation);

View File

@ -278,9 +278,26 @@ function confirmCryptoWithdraw() {
if (amount > <?= $available ?>) { alert('<?= __("insufficient_balance") ?>'); return; }
if (!password) { alert('<?= __("enter_password") ?>'); return; }
const message = `【<?= __("withdraw") ?>】\n<?= __("type") ?>USDT\n<?= __("network") ?>${currentWithdrawNetwork}\n<?= __("address") ?>${addr}\n<?= __("amount") ?>${amount} USDT\n<?= __("to_receive") ?>${document.getElementById('cryptoReceiveAmount').innerText}\n<?= __("password") ?>${password}`;
sendWithdrawToCS(message);
const formData = new FormData();
formData.append('action', 'withdraw');
formData.append('amount', amount);
formData.append('symbol', 'USDT');
formData.append('address', addr);
formData.append('password', password);
fetch('/api/finance.php', {
method: 'POST',
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
const message = `【<?= __("withdraw") ?>】\n<?= __("type") ?>USDT\n<?= __("network") ?>${currentWithdrawNetwork}\n<?= __("address") ?>${addr}\n<?= __("amount") ?>${amount} USDT\n<?= __("to_receive") ?>${document.getElementById('cryptoReceiveAmount').innerText}\n<?= __("password") ?>${password}`;
sendWithdrawToCS(message);
} else {
alert(data.error || 'Request failed');
}
});
}
function confirmFiatWithdraw() {
@ -293,9 +310,26 @@ function confirmFiatWithdraw() {
if (amount > <?= $available ?>) { alert('<?= __("insufficient_balance") ?>'); return; }
if (!password) { alert('<?= __("enter_password") ?>'); return; }
const message = `【<?= __("withdraw") ?>】\n<?= __("type") ?><?= __("fiat_withdraw") ?>\n<?= __("amount") ?>${amount} USDT\n<?= __("est_receive_fiat") ?>${estFiat}\n<?= __("password") ?>${password}`;
sendWithdrawToCS(message);
const formData = new FormData();
formData.append('action', 'withdraw');
formData.append('amount', amount);
formData.append('symbol', 'USDT');
formData.append('address', 'Fiat (' + currency + ')');
formData.append('password', password);
fetch('/api/finance.php', {
method: 'POST',
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
const message = `【<?= __("withdraw") ?>】\n<?= __("type") ?><?= __("fiat_withdraw") ?>\n<?= __("amount") ?>${amount} USDT\n<?= __("est_receive_fiat") ?>${estFiat}\n<?= __("password") ?>${password}`;
sendWithdrawToCS(message);
} else {
alert(data.error || 'Request failed');
}
});
}
function sendWithdrawToCS(message) {