index.php 11.9 KB
<?php
require_once __DIR__ . '/../vendor/autoload.php';

// Ensure $config is available (passed from start.php context or loaded manually)
if (!isset($config)) {
    $config = require __DIR__ . '/../config.php';
}

$pdo = null;
$message = '';

// 连接数据库
try {
    $db = $config['database'];
    $dsn = "mysql:host={$db['host']};port={$db['port']};dbname={$db['database']};charset=utf8mb4";
    $pdo = new PDO($dsn, $db['username'], $db['password']);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    // FATAL: Do NOT use die() in Workerman, it kills the worker process!
    $message = "<div style='color: red; padding: 20px; text-align: center; border: 1px solid red; background: #ffe6e6;'>Database Connection Failed: " . htmlspecialchars($e->getMessage()) . "</div>";
    $pdo = null;
}

// 处理绑定表单提交
if ($pdo && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'bind') {
    $deviceId = trim($_POST['device_id']);
    $phone = trim($_POST['phone']);
    $isPrimary = isset($_POST['is_primary']) ? 1 : 0;

    if ($deviceId && $phone) {
        // 1. 查找用户
        try {
            $stmt = $pdo->prepare("SELECT id, nickname FROM users WHERE phone = ?");
            $stmt->execute([$phone]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($user) {
                // 2. 验证设备是否存在 (Prevent Ghost Bindings)
                $deviceCheck = $pdo->prepare("SELECT id FROM devices WHERE id = ?");
                $deviceCheck->execute([$deviceId]);

                if (!$deviceCheck->fetch()) {
                    $message = "<div style='color: red; margin-bottom: 20px;'> 设备ID <b>$deviceId</b> 不存在。请确认该设备已录入系统。</div>";
                } else {
                    // 3. 插入/更新绑定
                    // 先检查是否已存在
                    $check = $pdo->prepare("SELECT id FROM user_device_bindings WHERE user_id = ? AND device_id = ?");
                    $check->execute([$user['id'], $deviceId]);

                    if (!$check->fetch()) {
                        // FIX: use 'bound_at' instead of 'created_at'
                        $bind = $pdo->prepare("INSERT INTO user_device_bindings (user_id, device_id, is_primary, bound_at) VALUES (?, ?, ?, NOW())");
                        $bind->execute([$user['id'], $deviceId, $isPrimary]);
                        $message = "<div style='color: green; margin-bottom: 20px; background: #e6fffa; padding: 10px; border-radius: 4px;'> 成功将设备 <b>$deviceId</b> 绑定给用户 <b>{$user['nickname']}</b></div>";
                    } else {
                        $message = "<div style='color: orange; margin-bottom: 20px;'>⚠️ 该用户已经绑定过此设备,无需重复操作。</div>";
                    }
                }
            } else {
                $message = "<div style='color: red; margin-bottom: 20px;'> 手机号 <b>$phone</b> 未找到。请确保用户已在小程序登录过。</div>";
            }
        } catch (Exception $e) {
            $message = "<div style='color: red;'>Operation Failed: " . $e->getMessage() . "</div>";
        }
    }
}

// 获取所有设备列表 (含绑定信息)
$devices = [];
if ($pdo) {
    try {
        $devices = $pdo->query("
            SELECT d.id, d.name, d.status, d.last_seen, u.phone AS bound_phone, u.nickname AS bound_user
            FROM devices d
            LEFT JOIN user_device_bindings b ON d.id = b.device_id
            LEFT JOIN users u ON b.user_id = u.id
            ORDER BY d.created_at DESC
        ")->fetchAll(PDO::FETCH_ASSOC);
    } catch (Exception $e) {
        // Silent fail or log
    }
}

// 获取绑定历史 (已有的逻辑)
$bindings = [];
if ($pdo) {
    try {
        // FIX: use 'bound_at' instead of 'created_at'
        $bindings = $pdo->query("
            SELECT b.id, u.nickname, u.phone, b.device_id, b.is_primary, b.bound_at
            FROM user_device_bindings b
            JOIN users u ON b.user_id = u.id
            ORDER BY b.bound_at DESC
        ")->fetchAll(PDO::FETCH_ASSOC);
    } catch (Exception $e) {
        if (empty($message))
            $message = "<div style='color: red;'>Load Error: " . $e->getMessage() . "</div>";
    }
}

?>
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Moltbot 管理后台</title>
    <link rel="stylesheet" href="style.css">
    <link rel="icon" href="data:,">
    <script>
        function fillBind(deviceId) {
            document.querySelector('input[name="device_id"]').value = deviceId;
            document.querySelector('input[name="phone"]').focus();
        }
    </script>
</head>

<body>

    <div class="header">
        <div class="brand">Moltbot Admin</div>
        <div><?php echo date('Y-m-d H:i'); ?></div>
    </div>

    <div class="container">

        <?php echo $message; ?>

        <?php if (!$pdo): ?>
            <div class="card">
                <h3 style="color: red;">System Error</h3>
                <p>Cannot connect to the database. Please check your configuration.</p>
            </div>
        <?php else: ?>

            <!-- 新增绑定卡片 -->
            <div class="card">
                <div class="title">新增绑定</div>
                <form method="POST" action="">
                    <input type="hidden" name="action" value="bind">
                    <div style="display: flex; gap: 20px;">
                        <div class="form-group" style="flex: 1;">
                            <label class="form-label">设备 ID</label>
                            <input type="text" name="device_id" class="form-control" placeholder="点击下方列表选择或手动输入" required>
                        </div>
                        <div class="form-group" style="flex: 1;">
                            <label class="form-label">用户手机号</label>
                            <input type="text" name="phone" class="form-control" placeholder="输入用户注册手机号" required>
                        </div>
                    </div>
                    <div class="form-group">
                        <label>
                            <input type="checkbox" name="is_primary" value="1" checked> 设为主设备 (默认)
                        </label>
                    </div>
                    <button type="submit" class="btn btn-primary">立即绑定</button>
                </form>
            </div>

            <!-- 设备列表 (Auto-Registered Devices) -->
            <div class="card">
                <div class="title">所有设备 (<?php echo count($devices); ?>)</div>
                <table style="width: 100%; border-collapse: collapse;">
                    <thead>
                        <tr style="background: #f8f9fa;">
                            <th style="padding: 10px; text-align: left;">设备 ID</th>
                            <th style="padding: 10px; text-align: left;">状态</th>
                            <th style="padding: 10px; text-align: left;">绑定情况</th>
                            <th style="padding: 10px; text-align: left;">最后在线</th>
                            <th style="padding: 10px; text-align: left;">操作</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($devices as $dev): ?>
                            <tr style="border-bottom: 1px solid #eee;">
                                <td style="padding: 10px; font-family: monospace;"><?php echo htmlspecialchars($dev['id']); ?>
                                </td>
                                <td style="padding: 10px;">
                                    <?php if ($dev['status'] === 'online'): ?>
                                        <span style="color: green;">● 在线</span>
                                    <?php else: ?>
                                        <span style="color: gray;">● 离线</span>
                                    <?php endif; ?>
                                </td>
                                <td style="padding: 10px;">
                                    <?php if ($dev['bound_phone']): ?>
                                        <span style="color: #666;">
                                            已绑: <?php echo htmlspecialchars($dev['bound_user']); ?>
                                            (<?php echo htmlspecialchars($dev['bound_phone']); ?>)
                                        </span>
                                    <?php else: ?>
                                        <span
                                            style="color: #ff9800; background: #fff3e0; padding: 2px 6px; border-radius: 4px; font-size: 12px;">未绑定</span>
                                    <?php endif; ?>
                                </td>
                                <td style="padding: 10px; font-size: 12px; color: #999;">
                                    <?php echo $dev['last_seen'] ? date('H:i:s', strtotime($dev['last_seen'])) : '-'; ?>
                                </td>
                                <td style="padding: 10px;">
                                    <?php if (!$dev['bound_phone']): ?>
                                        <button onclick="fillBind('<?php echo htmlspecialchars($dev['id']); ?>')"
                                            style="cursor: pointer; background: #007bff; color: white; border: none; padding: 4px 8px; border-radius: 4px; font-size: 12px;">选择绑定</button>
                                    <?php else: ?>
                                        <button disabled
                                            style="background: #eee; color: #999; border: none; padding: 4px 8px; border-radius: 4px; font-size: 12px;">已占用</button>
                                    <?php endif; ?>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                        <?php if (empty($devices)): ?>
                            <tr>
                                <td colspan="5" style="text-align: center; color: #999; padding: 20px;">
                                    暂无设备。请启动 Moltbot 客户端并连接服务器以自动注册。
                                </td>
                            </tr>
                        <?php endif; ?>
                    </tbody>
                </table>
            </div>

            <!-- 绑定历史列表 (已有的) -->
            <div class="card">
                <div class="title" style="color: #666; font-size: 14px;">绑定历史记录</div>
                <!-- ... existing table code ... -->
                <table>
                    <!-- ... existing table content ... -->
                    <thead>
                        <tr>
                            <th>用户</th>
                            <th>手机号</th>
                            <th>设备 ID</th>
                            <th>绑定时间</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($bindings as $row): ?>
                            <tr>
                                <td><?php echo htmlspecialchars($row['nickname']); ?></td>
                                <td><?php echo htmlspecialchars($row['phone']); ?></td>
                                <td><?php echo htmlspecialchars($row['device_id']); ?></td>
                                <td><?php echo $row['bound_at']; ?></td>
                            </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>
            </div>

        <?php endif; ?>

    </div>

</body>

</html>