Fix land_api.php: add land_id to web_land_owner_changes INSERT, add perm_change sync for visitor perms

This commit is contained in:
ypsdf1
2026-06-24 13:09:47 +08:00
parent 02d2d95c9a
commit 06854054ca
2 changed files with 73 additions and 16 deletions
+62 -15
View File
@@ -65,6 +65,18 @@
.color-btn { width:30px; height:30px; border-radius:4px; cursor:pointer; border:2px solid transparent; transition:all 0.2s; }
.color-btn:hover { border-color:var(--accent); transform:scale(1.1); }
.color-input { padding:7px 10px; background:var(--bg); border:1px solid var(--border); border-radius:4px; color:var(--text); font-size:13px; flex:1; }
.glass-alert-overlay{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);z-index:5000;justify-content:center;align-items:center;animation:glassFadeIn 0.25s ease}
.glass-alert-overlay.show{display:flex}
.glass-alert-card{background:rgba(22,27,34,0.92);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:1px solid rgba(88,166,255,0.25);border-radius:16px;padding:28px 28px 20px;width:360px;max-width:88%;box-shadow:0 12px 48px rgba(0,0,0,0.5),inset 0 1px 0 rgba(255,255,255,0.05);animation:glassSlideUp 0.3s ease;text-align:center}
.glass-alert-card .alert-icon{font-size:36px;margin-bottom:12px}
.glass-alert-card .alert-msg{font-size:14px;color:#e6edf3;line-height:1.6;margin-bottom:20px;word-break:break-word}
.glass-alert-card .alert-btns{display:flex;gap:10px;justify-content:center}
.glass-alert-card .alert-btns button{padding:8px 24px;border:none;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;transition:all 0.2s}
.glass-alert-card .alert-btns .ag-ok{background:#58a6ff;color:#fff}
.glass-alert-card .alert-btns .ag-cancel{background:rgba(255,255,255,0.08);color:#8b949e}
.glass-alert-card .alert-btns button:hover{opacity:0.85;transform:scale(1.03)}
@keyframes glassFadeIn{from{opacity:0}to{opacity:1}}
@keyframes glassSlideUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
</style>
</head>
<body>
@@ -437,7 +449,7 @@ async function editStock(id, current) {
}
async function removeShop(id) {
if (!confirm('确定删除商品 '+id+'?')) return;
if (!await glassConfirm('确定删除商品 '+id+'?')) return;
const r = await postApi('shop_remove', {id});
toast(r.message, r.success?'ok':'err');
if (r.success) loadShop(document.getElementById('C'));
@@ -524,7 +536,7 @@ async function doBatchCDK() {
// ===== CDK撤销和删除 =====
async function undoRecentCDK() {
if (!confirm('确定要撤销最近3分钟内生成的CDK吗?')) return;
if (!await glassConfirm('确定要撤销最近3分钟内生成的CDK吗?')) return;
const r = await jsonApi('cdk.php?action=list');
const list = r.data || [];
@@ -564,7 +576,7 @@ async function undoRecentCDK() {
}
async function deleteCDK(code) {
if (!confirm(`确定要删除CDK ${code}吗?`)) return;
if (!await glassConfirm(`确定要删除CDK ${code}吗?`)) return;
const r = await postApi('cdk_delete', {code});
if (r.success) {
@@ -2018,8 +2030,8 @@ async function adminRejectTicket(id) {
url.searchParams.set('id', id);
const res = await fetch(url, {method:'POST', headers:{'Content-Type':'application/json'}, credentials:'same-origin', body: JSON.stringify({reason: reason})});
const data = await res.json();
if (data.success) { loadTicketList(document.getElementById('C')); } else { alert(data.message); }
} catch (e) { alert('操作失败: ' + e.message); }
if (data.success) { loadTicketList(document.getElementById('C')); } else { glassAlert(data.message); }
} catch (e) { glassAlert('操作失败: ' + e.message); }
}
async function adminCompleteTicket(id) {
@@ -2029,8 +2041,8 @@ async function adminCompleteTicket(id) {
url.searchParams.set('id', id);
const res = await fetch(url, {method:'POST', headers:{'Content-Type':'application/json'}, credentials:'same-origin'});
const data = await res.json();
if (data.success) { viewAdminTicket(id); } else { alert(data.message); }
} catch (e) { alert('操作失败: ' + e.message); }
if (data.success) { viewAdminTicket(id); } else { glassAlert(data.message); }
} catch (e) { glassAlert('操作失败: ' + e.message); }
}
async function adminAssignTicket(id) {
@@ -2378,7 +2390,7 @@ async function saveLandConfig() {
document.querySelector('.modal-close')?.click();
loadLands(document.getElementById('C'));
} catch(e) {
alert('保存失败: ' + e.message);
glassAlert('保存失败: ' + e.message);
}
}
@@ -2391,31 +2403,66 @@ function changeLandOwner(name, currentOwner) {
body: 'name=' + encodeURIComponent(name) + '&owner=' + encodeURIComponent(newOwner) + '&secret=sdf1_web_comm_2026_ypshidifu'
}).then(r => r.json()).then(d => {
if (d.success) loadLands(document.getElementById('C'));
else alert('失败: ' + (d.error||''));
else glassAlert('失败: ' + (d.error||''));
});
}
function deleteLand(name) {
if (!confirm('确定删除领地 [' + name + '] ?')) return;
async function deleteLand(name) {
if (!await glassConfirm('确定删除领地 [' + name + '] ?')) return;
fetch('api/land_api.php?action=delete_land', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'name=' + encodeURIComponent(name) + '&secret=sdf1_web_comm_2026_ypshidifu'
}).then(r => r.json()).then(d => {
if (d.success) loadLands(document.getElementById('C'));
else alert('失败: ' + (d.error||''));
else glassAlert('失败: ' + (d.error||''));
});
}
function deleteShopItem(id) {
if (!confirm('确定下架商品 #' + id + ' ?')) return;
async function deleteShopItem(id) {
if (!await glassConfirm('确定下架商品 #' + id + ' ?')) return;
fetch('api/land_api.php?action=delete_shop_item', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'id=' + id + '&secret=sdf1_web_comm_2026_ypshidifu'
}).then(r => r.json()).then(d => {
if (d.success) loadLands(document.getElementById('C'));
else alert('失败: ' + (d.error||''));
else glassAlert('失败: ' + (d.error||''));
});
}
</script>
<!-- 毛玻璃弹窗 -->
<div class="glass-alert-overlay" id="glassAlertOverlay" onclick="glassAlertResolve(false)">
<div class="glass-alert-card" onclick="event.stopPropagation()">
<div class="alert-icon" id="glassAlertIcon">⚠️</div>
<div class="alert-msg" id="glassAlertMsg"></div>
<div class="alert-btns" id="glassAlertBtns">
<button class="ag-ok" onclick="glassAlertResolve(true)">确定</button>
</div>
</div>
</div>
<script>
let _glassAlertResolve = null;
function glassAlertResolve(val) {
document.getElementById('glassAlertOverlay').classList.remove('show');
if (_glassAlertResolve) { _glassAlertResolve(val); _glassAlertResolve = null; }
}
function glassAlert(msg, icon = '⚠️') {
return new Promise(resolve => {
_glassAlertResolve = resolve;
document.getElementById('glassAlertIcon').textContent = icon;
document.getElementById('glassAlertMsg').textContent = msg;
document.getElementById('glassAlertBtns').innerHTML = '<button class="ag-ok" onclick="glassAlertResolve(true)">确定</button>';
document.getElementById('glassAlertOverlay').classList.add('show');
});
}
function glassConfirm(msg, icon = '❓') {
return new Promise(resolve => {
_glassAlertResolve = resolve;
document.getElementById('glassAlertIcon').textContent = icon;
document.getElementById('glassAlertMsg').textContent = msg;
document.getElementById('glassAlertBtns').innerHTML = '<button class="ag-cancel" onclick="glassAlertResolve(false)">取消</button><button class="ag-ok" onclick="glassAlertResolve(true)">确定</button>';
document.getElementById('glassAlertOverlay').classList.add('show');
});
}
</script>
+11 -1
View File
@@ -458,7 +458,9 @@ function handleUpdateLandOwner($db, $post) {
// 记录变更(用于同步到Java)
if ($oldOwner !== $owner) {
$stmt3 = $db->prepare("INSERT INTO web_land_owner_changes (land_name, old_owner, new_owner, created_at) VALUES (:name, :old, :new, :now)");
$landId = (int)($post['id'] ?? 0);
$stmt3 = $db->prepare("INSERT INTO web_land_owner_changes (land_id, land_name, old_owner, new_owner, created_at) VALUES (:lid, :name, :old, :new, :now)");
$stmt3->bindValue(':lid', $landId, SQLITE3_INTEGER);
$stmt3->bindValue(':name', $name, SQLITE3_TEXT);
$stmt3->bindValue(':old', $oldOwner, SQLITE3_TEXT);
$stmt3->bindValue(':new', $owner, SQLITE3_TEXT);
@@ -826,6 +828,14 @@ function handleUpdateVisitorPerm($db, $playerName, $post) {
$stmt2->bindValue(':now', time(), SQLITE3_INTEGER);
$stmt2->execute();
// ★ 写入web_admin_changes以便Java同步
$stmt4 = $db->prepare("INSERT INTO web_admin_changes (change_type, target_id, target_name, change_data, created_at) VALUES ('perm_change', :id, :name, :data, :now)");
$stmt4->bindValue(':id', (int)$land['id'], SQLITE3_INTEGER);
$stmt4->bindValue(':name', $visitor, SQLITE3_TEXT);
$stmt4->bindValue(':data', json_encode(['land_name' => $landName, 'permissions' => $permissions, 'role' => $role]), SQLITE3_TEXT);
$stmt4->bindValue(':now', time(), SQLITE3_INTEGER);
$stmt4->execute();
echo json_encode(['success' => true, 'message' => "已更新 $visitor 的权限"]);
}