修复Java删除成员后PHP不同步删除的问题:移除syncPermissions中导致删除永远不生效的120秒宽限期,改为检查web_admin_changes待处理变更保护

This commit is contained in:
ypsdf1
2026-07-12 11:20:11 +08:00
parent 8645c57839
commit 0760cc1d2e
+52 -10
View File
@@ -757,22 +757,63 @@ function syncPermissions() {
// ★ 删除Java端已移除的成员(同步清理)
// 对于每个有incoming数据的land_id,删除不在incoming列表中的旧记录
// 但保留最近120秒内被PHP端添加/修改的记录(防止PHP刚添加、Java还没处理就被删)
// 但如果该玩家有待处理的PHP变更(add_visitor/perm_change),则跳过删除
// (防止PHP刚添加、Java还没处理就被删;同时避免旧120秒宽限期导致删除永远不生效)
$deleted = 0;
$skipped = 0;
// 先收集所有待处理的PHP变更的(land_name, player_name)对
$pendingChanges = [];
$pcStmt = $db->prepare("SELECT change_data FROM web_admin_changes WHERE change_type IN ('perm_change','add_visitor') AND acknowledged = 0");
$pcRes = $pcStmt->execute();
while ($pcRow = $pcRes->fetchArray(SQLITE3_ASSOC)) {
$pcData = json_decode($pcRow['change_data'] ?? '{}', true);
if (is_array($pcData)) {
$pcLand = $pcData['land_name'] ?? '';
$pcPlayer = $pcData['player'] ?? '';
if ($pcLand !== '' && $pcPlayer !== '') {
$pendingChanges[$pcLand][] = $pcPlayer;
}
}
}
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);
// 查出待删除的玩家名单
$selStmt = $db->prepare("SELECT player_name, land_name FROM web_area_permissions
WHERE land_id = ? AND player_name NOT IN ($placeholders)");
$selStmt->bindValue(1, $lid, SQLITE3_INTEGER);
$idx = 2;
foreach ($players as $p) {
$delStmt->bindValue($idx++, $p, SQLITE3_TEXT);
$selStmt->bindValue($idx++, $p, SQLITE3_TEXT);
}
$selRes = $selStmt->execute();
$toDelete = [];
while ($selRow = $selRes->fetchArray(SQLITE3_ASSOC)) {
$dPlayer = $selRow['player_name'];
$dLand = $selRow['land_name'] ?? '';
// 检查是否有待处理的PHP变更保护该玩家
$isProtected = false;
if (isset($pendingChanges[$dLand])) {
$isProtected = in_array($dPlayer, $pendingChanges[$dLand]);
}
if ($isProtected) {
$skipped++;
debugLog("[syncPermissions] 跳过删除(有待处理PHP变更)", ['land' => $dLand, 'player' => $dPlayer]);
} else {
$toDelete[] = $dPlayer;
}
}
if (!empty($toDelete)) {
$delPlaceholders = implode(',', array_fill(0, count($toDelete), '?'));
$delStmt = $db->prepare("DELETE FROM web_area_permissions
WHERE land_id = ? AND player_name IN ($delPlaceholders)");
$delStmt->bindValue(1, $lid, SQLITE3_INTEGER);
$dIdx = 2;
foreach ($toDelete as $dp) {
$delStmt->bindValue($dIdx++, $dp, SQLITE3_TEXT);
}
$delStmt->execute();
$deleted += $db->changes();
}
$delStmt->bindValue($idx, $cutoff, SQLITE3_INTEGER);
$delStmt->execute();
$deleted += $db->changes();
}
// ★ 清理与Java同步状态冲突的待处理PHP变更(防止 stale pending 覆盖Java最新状态)
@@ -824,6 +865,7 @@ function syncPermissions() {
$msg = "访客权限同步成功: {$count}个";
if ($deleted > 0) $msg .= ", 清理{$deleted}个已移除成员";
if ($skipped > 0) $msg .= ", 跳过{$skipped}个待处理变更保护";
if ($conflictCleaned > 0) $msg .= ", 忽略{$conflictCleaned}个冲突待处理变更";
success($msg);
}