From 0115cbda41f7b3c95022c26077a651d2c3761c5c Mon Sep 17 00:00:00 2001 From: ypsdf1 Date: Sat, 11 Jul 2026 15:11:00 +0800 Subject: [PATCH] =?UTF-8?q?R14:=20=E4=BF=AE=E5=A4=8DPHP=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=88=90=E5=91=98=E9=9D=99=E9=BB=98=E5=A4=B1=E8=B4=A5+syncPerm?= =?UTF-8?q?issions=E5=88=A0=E9=99=A4=E6=B8=85=E7=90=86=20-=20handleAddVisi?= =?UTF-8?q?tor:=20=E7=A7=BB=E9=99=A4=E5=BC=82=E6=AD=A5=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E9=98=BB=E5=A1=9E=EF=BC=8C=E5=85=88=E6=B7=BB=E5=8A=A0=E6=88=90?= =?UTF-8?q?=E5=91=98=E5=86=8D=E5=BC=82=E6=AD=A5=E6=A0=A1=E9=AA=8C=20-=20sy?= =?UTF-8?q?ncPermissions:=20=E6=96=B0=E5=A2=9E=E5=88=A0=E9=99=A4=E6=B8=85?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C=E5=90=8C=E6=AD=A5Java?= =?UTF-8?q?=E7=AB=AF=E5=B7=B2=E7=A7=BB=E9=99=A4=E7=9A=84=E6=88=90=E5=91=98?= =?UTF-8?q?=20-=20120=E7=A7=92=E5=AE=BD=E9=99=90=E6=9C=9F=E9=98=B2?= =?UTF-8?q?=E6=AD=A2PHP=E5=88=9A=E6=B7=BB=E5=8A=A0=E7=9A=84=E6=88=90?= =?UTF-8?q?=E5=91=98=E8=A2=AB=E8=AF=AF=E5=88=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/land_api.php | 36 +++++++++++++++++++++++------------- api/sync.php | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/api/land_api.php b/api/land_api.php index b6daa47..d916271 100644 --- a/api/land_api.php +++ b/api/land_api.php @@ -1115,18 +1115,7 @@ function handleAddVisitor($db, $playerName, $req) { return; } - // ★ 校验玩家是否存在于login.db(异步验证) - $visitorValid = validatePlayerViaJava($db, $visitor, 'add_visitor', ['land' => $landName]); - if ($visitorValid === null) { - echo json_encode(['success' => true, 'pending' => true, 'message' => "玩家 {$visitor} 的验证请求已提交,系统将在1-2分钟内自动完成验证"]); - return; - } - if (!$visitorValid) { - echo json_encode(['success' => false, 'error' => "玩家 {$visitor} 尚未注册,请确认玩家名是否正确"]); - return; - } - - // 获取领地 + // ★ 先获取领地(先校验,再添加) $stmt = $db->prepare("SELECT * FROM web_area_lands WHERE name = :name"); $stmt->bindValue(':name', $landName, SQLITE3_TEXT); $result = $stmt->execute(); @@ -1142,7 +1131,18 @@ function handleAddVisitor($db, $playerName, $req) { return; } - // 插入访客 + // ★ 检查是否已是成员 + $checkStmt = $db->prepare("SELECT COUNT(*) as cnt FROM web_area_permissions WHERE land_id = :lid AND player_name = :player"); + $checkStmt->bindValue(':lid', (int)$land['id'], SQLITE3_INTEGER); + $checkStmt->bindValue(':player', $visitor, SQLITE3_TEXT); + $checkResult = $checkStmt->execute(); + $checkRow = $checkResult->fetchArray(SQLITE3_ASSOC); + if ($checkRow && $checkRow['cnt'] > 0) { + echo json_encode(['success' => false, 'error' => "玩家 {$visitor} 已是该领地成员"]); + return; + } + + // ★ 直接插入访客(先执行操作,再异步验证) $stmt2 = $db->prepare("INSERT OR REPLACE INTO web_area_permissions (land_id, land_name, player_name, role, permissions, granted_at, expires_at, synced_at) VALUES (:land_id, :land_name, :player, 'visitor', '', :now, 0, :now)"); @@ -1164,6 +1164,16 @@ function handleAddVisitor($db, $playerName, $req) { // 非致命 } + // ★ 异步验证玩家是否存在(仅记录日志,不阻塞操作) + try { + $visitorValid = validatePlayerViaJava($db, $visitor, 'add_visitor', ['land' => $landName]); + if ($visitorValid === false) { + error_log("[访客管理] 警告: 玩家 {$visitor} 可能不存在于login.db,但已添加为访客"); + } + } catch (\Throwable $e) { + // 验证失败不阻塞 + } + echo json_encode(['success' => true, 'message' => "已添加访客: $visitor"]); } diff --git a/api/sync.php b/api/sync.php index c5345f6..c997141 100644 --- a/api/sync.php +++ b/api/sync.php @@ -735,10 +735,14 @@ function syncPermissions() { ELSE excluded.role END"); $count = 0; + // 收集所有incoming的(land_id, player_name)对,用于后续删除清理 + $incomingKeys = []; foreach ($perms as $p) { - $stmt->bindValue(':land_id', (int)($p['land_id'] ?? 0), SQLITE3_INTEGER); + $lid = (int)($p['land_id'] ?? 0); + $player = $p['player_name'] ?? ''; + $stmt->bindValue(':land_id', $lid, SQLITE3_INTEGER); $stmt->bindValue(':land_name', $p['land_name'] ?? '', SQLITE3_TEXT); - $stmt->bindValue(':player', $p['player_name'] ?? '', SQLITE3_TEXT); + $stmt->bindValue(':player', $player, SQLITE3_TEXT); $stmt->bindValue(':role', $p['role'] ?? 'visitor', SQLITE3_TEXT); $stmt->bindValue(':perms', $p['permissions'] ?? '', SQLITE3_TEXT); $stmt->bindValue(':granted', (int)($p['granted_at'] ?? 0), SQLITE3_INTEGER); @@ -746,8 +750,34 @@ function syncPermissions() { $stmt->bindValue(':synced', $now, SQLITE3_INTEGER); $stmt->execute(); $count++; + if ($lid > 0 && !empty($player)) { + $incomingKeys[$lid][] = $player; + } } - success("访客权限同步成功: {$count}个"); + + // ★ 删除Java端已移除的成员(同步清理) + // 对于每个有incoming数据的land_id,删除不在incoming列表中的旧记录 + // 但保留最近120秒内被PHP端添加/修改的记录(防止PHP刚添加、Java还没处理就被删) + $deleted = 0; + foreach ($incomingKeys as $lid => $players) { + $placeholders = implode(',', array_fill(0, count($players), '?')); + $cutoff = $now - 120; // 120秒宽限期 + $delStmt = $db->prepare("DELETE FROM web_area_permissions + WHERE land_id = ? AND player_name NOT IN ($placeholders) + AND synced_at < ?"); + $delStmt->bindValue(1, $lid, SQLITE3_INTEGER); + $idx = 2; + foreach ($players as $p) { + $delStmt->bindValue($idx++, $p, SQLITE3_TEXT); + } + $delStmt->bindValue($idx, $cutoff, SQLITE3_INTEGER); + $delStmt->execute(); + $deleted += $db->changes(); + } + + $msg = "访客权限同步成功: {$count}个"; + if ($deleted > 0) $msg .= ", 清理{$deleted}个已移除成员"; + success($msg); } // ===== 用户组同步 =====