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:
@@ -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
@@ -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 的权限"]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user