mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-06-28 19:21:30 +08:00
fix: pairing required(metadata-upgrade) + agents 骨架屏
pairing.rs: - platform 改用 std::env::consts::OS (windows/macos/linux), 新增 deviceFamily=desktop,与 device.rs connect frame 保持一致 - 已配对设备若 platform 字段不匹配,自动覆盖更新,避免 Gateway 因 metadata-upgrade 拒绝静默自动配对 agents.js + components.css: - loadAgents 调用前先渲染 3 条骨架屏占位,消除空白等待期 - 添加 .skeleton 闪光动画样式
This commit is contained in:
@@ -47,8 +47,32 @@ pub fn auto_pair_device() -> Result<String, String> {
|
||||
// 无论是否已配对,都确保 gateway.controlUi.allowedOrigins 已写入
|
||||
patch_gateway_origins();
|
||||
|
||||
// 检查设备是否已配对
|
||||
if paired.get(&device_id).is_some() {
|
||||
let os_platform = std::env::consts::OS; // "windows" | "macos" | "linux"
|
||||
|
||||
// 如果已配对,档查 platform 字段是否正确;不正确则覆盖更新,
|
||||
// 避免 Gateway 因 metadata-upgrade 拒绝静默自动配对
|
||||
if let Some(existing) = paired.get_mut(&device_id) {
|
||||
let current_platform = existing
|
||||
.get("platform")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("");
|
||||
if current_platform != os_platform {
|
||||
if let Some(obj) = existing.as_object_mut() {
|
||||
obj.insert(
|
||||
"platform".to_string(),
|
||||
serde_json::Value::String(os_platform.to_string()),
|
||||
);
|
||||
obj.insert(
|
||||
"deviceFamily".to_string(),
|
||||
serde_json::Value::String("desktop".to_string()),
|
||||
);
|
||||
}
|
||||
let new_content = serde_json::to_string_pretty(&paired)
|
||||
.map_err(|e| format!("序列化 paired.json 失败: {e}"))?;
|
||||
std::fs::write(&paired_path, new_content)
|
||||
.map_err(|e| format!("更新 paired.json 失败: {e}"))?;
|
||||
return Ok("设备已配对(已修正平台字段)".into());
|
||||
}
|
||||
return Ok("设备已配对".into());
|
||||
}
|
||||
|
||||
@@ -61,7 +85,8 @@ pub fn auto_pair_device() -> Result<String, String> {
|
||||
paired[&device_id] = serde_json::json!({
|
||||
"deviceId": device_id,
|
||||
"publicKey": public_key,
|
||||
"platform": "desktop",
|
||||
"platform": os_platform,
|
||||
"deviceFamily": "desktop",
|
||||
"clientId": "openclaw-control-ui",
|
||||
"clientMode": "ui",
|
||||
"role": "operator",
|
||||
|
||||
@@ -34,8 +34,23 @@ export async function render() {
|
||||
return page
|
||||
}
|
||||
|
||||
function renderSkeleton(container) {
|
||||
const item = () => `
|
||||
<div class="agent-card" style="pointer-events:none">
|
||||
<div class="agent-card-header">
|
||||
<div class="skeleton" style="width:40px;height:40px;border-radius:50%"></div>
|
||||
<div style="flex:1;display:flex;flex-direction:column;gap:6px">
|
||||
<div class="skeleton" style="width:45%;height:16px;border-radius:4px"></div>
|
||||
<div class="skeleton" style="width:60%;height:12px;border-radius:4px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
container.innerHTML = [item(), item(), item()].join('')
|
||||
}
|
||||
|
||||
async function loadAgents(page, state) {
|
||||
const container = page.querySelector('#agents-list')
|
||||
renderSkeleton(container)
|
||||
try {
|
||||
state.agents = await api.listAgents()
|
||||
renderAgents(page, state)
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
/* 骨架屏 */
|
||||
.skeleton {
|
||||
background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--bg-tertiary, var(--bg-card-hover)) 50%, var(--bg-secondary) 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-shine 1.4s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes skeleton-shine {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
/* 卡片 */
|
||||
.card {
|
||||
background: var(--bg-card);
|
||||
|
||||
Reference in New Issue
Block a user