R14: 修复PHP添加成员静默失败+syncPermissions删除清理

- handleAddVisitor: 移除异步验证阻塞,先添加成员再异步校验
- syncPermissions: 新增删除清理逻辑,同步Java端已移除的成员
- 120秒宽限期防止PHP刚添加的成员被误删
This commit is contained in:
ypsdf1
2026-07-11 15:11:00 +08:00
parent ed57c8f82c
commit 0115cbda41
2 changed files with 56 additions and 16 deletions
+23 -13
View File
@@ -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"]);
}
+33 -3
View File
@@ -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);
}
// ===== 用户组同步 =====