Autosave: 20260218-050956
This commit is contained in:
parent
c560bf6eb9
commit
b573ba93a2
234
admin/agents.php
Normal file
234
admin/agents.php
Normal 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);
|
||||
?>
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
138
admin/binary.php
138
admin/binary.php
@ -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);
|
||||
?>
|
||||
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
173
admin/index.php
173
admin/index.php
@ -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
157
admin/kyc.php
Normal 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);
|
||||
?>
|
||||
@ -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>
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
@ -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);
|
||||
?>
|
||||
|
||||
370
admin/users.php
370
admin/users.php
@ -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
120
api/binary.php
Normal 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
77
api/finance.php
Normal 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']);
|
||||
@ -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 {
|
||||
|
||||
BIN
assets/images/pexels/slide1.jpg
Normal file
BIN
assets/images/pexels/slide1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 164 KiB |
BIN
assets/images/pexels/slide2.jpg
Normal file
BIN
assets/images/pexels/slide2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 200 KiB |
BIN
assets/images/pexels/slide3.jpg
Normal file
BIN
assets/images/pexels/slide3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 114 KiB |
@ -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';
|
||||
}
|
||||
|
||||
88
db/migrations/20260218_admin_system.php
Normal file
88
db/migrations/20260218_admin_system.php
Normal 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";
|
||||
}
|
||||
72
db/migrations/20260218_trading_tables.php
Normal file
72
db/migrations/20260218_trading_tables.php
Normal 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";
|
||||
}
|
||||
}
|
||||
@ -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">
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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.",
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
70
index.php
70
index.php
@ -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>
|
||||
|
||||
|
||||
34
market.php
34
market.php
@ -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):
|
||||
?>
|
||||
|
||||
12
mining.php
12
mining.php
@ -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): ?>
|
||||
|
||||
49
recharge.php
49
recharge.php
@ -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) {
|
||||
|
||||
4
swap.php
4
swap.php
@ -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 ≈ 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);
|
||||
|
||||
46
withdraw.php
46
withdraw.php
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user