From 4f82325e45bc8be29725d2769b1559d0acc2c572 Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 13 Oct 2025 05:42:03 +0800 Subject: [PATCH 1/3] feat: Add Chinese-English language switching feature to RM-01 dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added language switcher button in the top-right corner of dashboard - Implemented comprehensive translation system with localStorage persistence - Added data-translate attributes to all text elements for internationalization - Created bilingual support for monitoring interface (Chinese/English) - Integrated language switching with existing scroll color transition system - Enhanced dynamic content generation to support multilingual display - Added professional IT hardware translation standards for technical terms Features: - 🌐 Language switcher with globe icon and current language indicator - 💾 Persistent language preference using localStorage - 🎨 Visual consistency with scroll-based color transitions - 📱 Mobile responsive design maintained - �� Comprehensive coverage including dynamic content and error messages --- sdcard/web/index.htm | 293 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 243 insertions(+), 50 deletions(-) diff --git a/sdcard/web/index.htm b/sdcard/web/index.htm index 71b8fe4..2084a82 100644 --- a/sdcard/web/index.htm +++ b/sdcard/web/index.htm @@ -52,6 +52,41 @@ .fixed-header-content { margin: 0; padding: 0; + position: relative; + } + + /* 语言切换按钮样式 */ + .language-switcher { + position: absolute; + top: 0; + right: 0; + background: rgba(255, 255, 255, 0.15); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 8px; + padding: 8px 12px; + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 6px; + font-size: 0.85rem; + color: white; + font-weight: 500; + } + + .language-switcher:hover { + background: rgba(255, 255, 255, 0.25); + border-color: rgba(255, 255, 255, 0.5); + transform: translateY(-1px); + } + + .language-switcher .lang-icon { + font-size: 1rem; + } + + .language-switcher .lang-text { + transition: color 0.3s ease; } .header { @@ -587,23 +622,29 @@
+ +
+ 🌐 + EN +
+
-

RM - 01 Dashboard

-

RobOS ( Rack on board ) 实时系统性能监控面板

+

RM - 01 Dashboard

+

RobOS ( Rack on board ) 实时系统性能监控面板

- 正在连接到 推理服务器... + 正在连接到 推理服务器...
- 正在连接到 应用服务器... + 正在连接到 应用服务器...
@@ -616,8 +657,8 @@

RM - 01 Dashboard

-

推理模组监控

-

NVIDIA 推理服务器系统状态

+

推理模组监控

+

NVIDIA 推理服务器系统状态

@@ -625,10 +666,10 @@

推理模组监控

-
CPU 监控
+
CPU 监控
-
等待数据...
+
等待数据...
@@ -636,10 +677,10 @@

推理模组监控

-
显存监控
+
显存监控
-
等待数据...
+
等待数据...
@@ -647,10 +688,10 @@

推理模组监控

-
温度监控
+
温度监控
-
等待数据...
+
等待数据...
@@ -658,10 +699,10 @@

推理模组监控

-
功耗监控
+
功耗监控
-
等待数据...
+
等待数据...
@@ -669,10 +710,10 @@

推理模组监控

-
GPU 监控
+
GPU 监控
-
等待数据...
+
等待数据...
@@ -680,20 +721,20 @@

推理模组监控

-
系统信息
+
系统信息
- 最后更新 + 最后更新 -
- 连接时间 + 连接时间 -
- 数据包 + 数据包 0
@@ -705,8 +746,8 @@

推理模组监控

-

应用模组监控

-

Intel X86 应用服务器系统状态

+

应用模组监控

+

Intel X86 应用服务器系统状态

@@ -716,10 +757,10 @@

应用模组监控

-
CPU 监控
+
CPU 监控
-
等待数据...
+
等待数据...
@@ -727,10 +768,10 @@

应用模组监控

-
内存监控
+
内存监控
-
等待数据...
+
等待数据...
@@ -738,20 +779,20 @@

应用模组监控

-
系统信息
+
系统信息
- 最后更新 + 最后更新 -
- 连接时间 + 连接时间 -
- 数据包 + 数据包 0
@@ -765,10 +806,10 @@

应用模组监控

-
温度监控
+
温度监控
-
等待数据...
+
等待数据...
@@ -779,10 +820,10 @@

应用模组监控

-
磁盘监控
+
磁盘监控
-
等待数据...
+
等待数据...
@@ -820,7 +861,8 @@

应用模组监控

if (this.isConnecting) return; this.isConnecting = true; - this.updateConnectionStatus('connecting', '正在连接到 推理服务器...'); + const connectingText = getTranslation('connecting-inference', '正在连接到 推理服务器...'); + this.updateConnectionStatus('connecting', connectingText); try { // 连接到 推理服务器 服务器的 WebSocket @@ -831,7 +873,8 @@

应用模组监控

this.isConnecting = false; this.reconnectAttempts = 0; this.connectionStartTime = new Date(); - this.updateConnectionStatus('connected', '已连接到 推理服务器 '); + const connectedText = getTranslation('connected-inference', '已连接到 推理服务器'); + this.updateConnectionStatus('connected', connectedText); // 发送初始连接消息 (Socket.IO 握手) this.ws.send('40'); @@ -845,20 +888,23 @@

应用模组监控

console.log('WebSocket 连接已关闭:', event.code, event.reason); this.isConnecting = false; this.connectionStartTime = null; - this.updateConnectionStatus('disconnected', '连接已断开'); + const disconnectedText = getTranslation('disconnected-inference', '连接已断开'); + this.updateConnectionStatus('disconnected', disconnectedText); this.scheduleReconnect(); }; this.ws.onerror = (error) => { console.error('WebSocket 错误:', error); this.isConnecting = false; - this.updateConnectionStatus('disconnected', '连接错误'); + const errorText = getTranslation('connection-error-inference', '连接错误'); + this.updateConnectionStatus('disconnected', errorText); }; } catch (error) { console.error('连接失败:', error); this.isConnecting = false; - this.updateConnectionStatus('disconnected', '连接失败'); + const errorText = getTranslation('connection-error-inference', '连接失败'); + this.updateConnectionStatus('disconnected', errorText); this.scheduleReconnect(); } } @@ -927,10 +973,11 @@

应用模组监控

cores.forEach(core => { const usage = parseFloat(core.usage) || 0; + const coreLabel = getTranslation('core', '核心'); html += `
-
核心 ${core.id}
+
${coreLabel} ${core.id}
${usage.toFixed(1)}%
@@ -1047,7 +1094,7 @@

应用模组监控

const powerItems = [ { label: 'GPU+SoC', data: powerData.gpu_soc }, { label: 'CPU', data: powerData.cpu_cv }, - { label: '系统 5V', data: powerData.sys_5v }, + { label: getTranslation('system-5v', '系统 5V'), data: powerData.sys_5v }, { label: 'RAM', data: powerData.ram } ]; @@ -1073,9 +1120,10 @@

应用模组监控

let html = '
'; if (gpuData.gr3d_freq !== undefined) { + const gpuFreqLabel = getTranslation('gpu-freq', '3D GPU 频率'); html += `
- 3D GPU 频率 + ${gpuFreqLabel} ${gpuData.gr3d_freq}%
@@ -1085,7 +1133,8 @@

应用模组监控

} html += '
'; - content.innerHTML = html || '
暂无 GPU 数据
'; + const noDataText = getTranslation('no-gpu-data', '暂无 GPU 数据'); + content.innerHTML = html || `
${noDataText}
`; } updateConnectionStatus(status, message) { @@ -1143,7 +1192,8 @@

应用模组监控

if (this.isConnecting) return; this.isConnecting = true; - this.updateConnectionStatus('connecting', '正在连接到 应用服务器...'); + const connectingText = getTranslation('connecting-application', '正在连接到 应用服务器...'); + this.updateConnectionStatus('connecting', connectingText); try { // 连接到 应用服务器 服务器的 WebSocket (Socket.IO) @@ -1154,7 +1204,8 @@

应用模组监控

this.isConnecting = false; this.reconnectAttempts = 0; this.connectionStartTime = new Date(); - this.updateConnectionStatus('connected', '已连接到 应用服务器 '); + const connectedText = getTranslation('connected-application', '已连接到 应用服务器'); + this.updateConnectionStatus('connected', connectedText); // 发送初始连接消息 (Socket.IO 握手) this.ws.send('40'); @@ -1168,20 +1219,23 @@

应用模组监控

console.log('应用服务器 WebSocket 连接已关闭:', event.code, event.reason); this.isConnecting = false; this.connectionStartTime = null; - this.updateConnectionStatus('disconnected', '应用服务器 连接已断开'); + const disconnectedText = getTranslation('disconnected-application', '应用服务器 连接已断开'); + this.updateConnectionStatus('disconnected', disconnectedText); this.scheduleReconnect(); }; this.ws.onerror = (error) => { console.error('应用服务器 WebSocket 错误:', error); this.isConnecting = false; - this.updateConnectionStatus('disconnected', '应用服务器 连接错误'); + const errorText = getTranslation('connection-error-application', '应用服务器 连接错误'); + this.updateConnectionStatus('disconnected', errorText); }; } catch (error) { console.error('应用服务器 连接失败:', error); this.isConnecting = false; - this.updateConnectionStatus('disconnected', '应用服务器 连接失败'); + const errorText = getTranslation('connection-error-application', '应用服务器 连接失败'); + this.updateConnectionStatus('disconnected', errorText); this.scheduleReconnect(); } } @@ -1247,10 +1301,11 @@

应用模组监控

cores.forEach(core => { const usage = parseFloat(core.usage) || 0; + const coreLabel = getTranslation('core', '核心'); html += `
-
核心 ${core.id}
+
${coreLabel} ${core.id}
${usage.toFixed(1)}%
@@ -1295,7 +1350,8 @@

应用模组监控

} html += '
'; - content.innerHTML = html || '
暂无内存数据
'; + const noDataText = getTranslation('no-memory-data', '暂无内存数据'); + content.innerHTML = html || `
${noDataText}
`; } updateTemperatureDisplay(tempData) { @@ -1414,8 +1470,139 @@

应用模组监控

// 添加滚动监听器来实现文字颜色渐变 initScrollColorTransition(); + + // 初始化语言系统 + initLanguageSystem(); }); + // 语言翻译系统 + const translations = { + 'zh': { + 'title': 'RM - 01 Dashboard', + 'subtitle': 'RobOS ( Rack on board ) 实时系统性能监控面板', + 'connecting-inference': '正在连接到 推理服务器...', + 'connecting-application': '正在连接到 应用服务器...', + 'connected-inference': '已连接到 推理服务器', + 'connected-application': '已连接到 应用服务器', + 'disconnected-inference': '推理服务器 连接已断开', + 'disconnected-application': '应用服务器 连接已断开', + 'connection-error-inference': '推理服务器 连接错误', + 'connection-error-application': '应用服务器 连接错误', + 'inference-monitoring': '推理模组监控', + 'application-monitoring': '应用模组监控', + 'nvidia-status': 'NVIDIA 推理服务器系统状态', + 'intel-status': 'Intel X86 应用服务器系统状态', + 'cpu-monitoring': 'CPU 监控', + 'memory-monitoring': '显存监控', + 'ram-monitoring': '内存监控', + 'temperature-monitoring': '温度监控', + 'power-monitoring': '功耗监控', + 'gpu-monitoring': 'GPU 监控', + 'disk-monitoring': '磁盘监控', + 'system-info': '系统信息', + 'waiting-data': '等待数据...', + 'last-update': '最后更新', + 'connection-time': '连接时间', + 'data-packets': '数据包', + 'core': '核心', + 'system-5v': '系统 5V', + 'gpu-freq': '3D GPU 频率', + 'no-gpu-data': '暂无 GPU 数据', + 'no-memory-data': '暂无内存数据' + }, + 'en': { + 'title': 'RM - 01 Dashboard', + 'subtitle': 'RobOS ( Rack on board ) Real-time System Performance Monitor', + 'connecting-inference': 'Connecting to Inference Server...', + 'connecting-application': 'Connecting to Application Server...', + 'connected-inference': 'Connected to Inference Server', + 'connected-application': 'Connected to Application Server', + 'disconnected-inference': 'Inference Server Disconnected', + 'disconnected-application': 'Application Server Disconnected', + 'connection-error-inference': 'Inference Server Connection Error', + 'connection-error-application': 'Application Server Connection Error', + 'inference-monitoring': 'Inference Module Monitor', + 'application-monitoring': 'Application Module Monitor', + 'nvidia-status': 'NVIDIA Inference Server System Status', + 'intel-status': 'Intel X86 Application Server System Status', + 'cpu-monitoring': 'CPU Monitor', + 'memory-monitoring': 'VRAM Monitor', + 'ram-monitoring': 'Memory Monitor', + 'temperature-monitoring': 'Temperature Monitor', + 'power-monitoring': 'Power Monitor', + 'gpu-monitoring': 'GPU Monitor', + 'disk-monitoring': 'Disk Monitor', + 'system-info': 'System Information', + 'waiting-data': 'Waiting for data...', + 'last-update': 'Last Update', + 'connection-time': 'Connection Time', + 'data-packets': 'Data Packets', + 'core': 'Core', + 'system-5v': 'System 5V', + 'gpu-freq': '3D GPU Frequency', + 'no-gpu-data': 'No GPU Data Available', + 'no-memory-data': 'No Memory Data Available' + } + }; + + let currentLanguage = 'zh'; + + function initLanguageSystem() { + // 从本地存储读取语言设置 + const savedLanguage = localStorage.getItem('dashboard-language'); + if (savedLanguage && translations[savedLanguage]) { + currentLanguage = savedLanguage; + } + + // 更新语言切换按钮显示 + updateLanguageSwitcher(); + + // 如果是英文,立即翻译 + if (currentLanguage === 'en') { + translatePage('en'); + } + } + + function switchLanguage() { + currentLanguage = currentLanguage === 'zh' ? 'en' : 'zh'; + localStorage.setItem('dashboard-language', currentLanguage); + updateLanguageSwitcher(); + translatePage(currentLanguage); + } + + function updateLanguageSwitcher() { + const langText = document.getElementById('langText'); + if (langText) { + langText.textContent = currentLanguage === 'zh' ? 'EN' : '中文'; + } + } + + function translatePage(language) { + const elements = document.querySelectorAll('[data-translate]'); + elements.forEach(element => { + const key = element.getAttribute('data-translate'); + if (translations[language] && translations[language][key]) { + element.textContent = translations[language][key]; + } + }); + + // 更新文档标题 + if (language === 'en') { + document.title = 'RM-01 Dashboard - RobOS Monitor'; + document.querySelector('meta[name="apple-mobile-web-app-title"]').content = 'RM - 01 Monitor Panel'; + } else { + document.title = 'Rob OS'; + document.querySelector('meta[name="apple-mobile-web-app-title"]').content = 'RM - 01 监控面板'; + } + } + + function getTranslation(key, fallback = '') { + if (translations[currentLanguage] && translations[currentLanguage][key]) { + return translations[currentLanguage][key]; + } + return fallback || key; + } + // 滚动颜色渐变功能 function initScrollColorTransition() { const header = document.querySelector('.header'); @@ -1423,6 +1610,8 @@

应用模组监控

const headerP = document.querySelector('.header p'); const connectionStatus = document.querySelector('.connection-status'); const connectionTexts = document.querySelectorAll('.connection-status span:not(.status-indicator)'); + const languageSwitcher = document.querySelector('.language-switcher'); + const langText = document.querySelector('.lang-text'); // 计算10%滚动距离 const maxScroll = window.innerHeight * 0.1; @@ -1457,6 +1646,10 @@

应用模组监控

if (headerP) headerP.style.color = colorValue; if (connectionStatus) connectionStatus.style.color = colorValue; + // 更新语言切换按钮颜色 + if (languageSwitcher) languageSwitcher.style.color = colorValue; + if (langText) langText.style.color = colorValue; + // 更新连接状态文字颜色 connectionTexts.forEach(text => { if (text) text.style.color = colorValue; From 9e48f43db4b5776fee5ef2f4c4e5cff85a5b5800 Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 13 Oct 2025 09:37:00 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=8C=9F=20RM-01=20Dashboard=20Complete?= =?UTF-8?q?=20Optimization=E2=9C=A8=20Features:-=20=F0=9F=8C=90=20Bilingua?= =?UTF-8?q?l=20support=20(Chinese/English)-=20=F0=9F=93=B1=20Mobile=20resp?= =?UTF-8?q?onsive=20design=20=20-=20=F0=9F=94=84=20Connection=20status=20p?= =?UTF-8?q?reservation=20during=20language=20switch=F0=9F=8E=A8=20UI=20Imp?= =?UTF-8?q?rovements:-=20=F0=9F=96=A5=EF=B8=8F=20Dual-column=20CPU=20layou?= =?UTF-8?q?t=20for=20AGX=20monitor-=20=F0=9F=93=8A=20Separated=20memory/GP?= =?UTF-8?q?U=20displays-=20=F0=9F=91=81=EF=B8=8F=20Enhanced=20CPU=20text?= =?UTF-8?q?=20visibility-=20=F0=9F=93=8B=20Mobile-optimized=20single=20col?= =?UTF-8?q?umn=20layout=F0=9F=94=A7=20Technical=20Enhancements:-=20?= =?UTF-8?q?=F0=9F=92=BE=20localStorage=20language=20persistence-=20?= =?UTF-8?q?=F0=9F=8E=AA=20Dynamic=20scroll=20color=20effects-=20=E2=9A=A1?= =?UTF-8?q?=20Mobile=20compatibility=20improvements-=20=F0=9F=94=84=20Smar?= =?UTF-8?q?t=20connection=20status=20refreshUser-tested=20and=20approved?= =?UTF-8?q?=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sdcard/web/index.htm | 318 +++++++++++++++++++++++++++++++------------ 1 file changed, 234 insertions(+), 84 deletions(-) diff --git a/sdcard/web/index.htm b/sdcard/web/index.htm index 2084a82..c14073d 100644 --- a/sdcard/web/index.htm +++ b/sdcard/web/index.htm @@ -63,16 +63,17 @@ background: rgba(255, 255, 255, 0.15); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.3); - border-radius: 8px; - padding: 8px 12px; + border-radius: 6px; + padding: 4px 8px; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; - gap: 6px; - font-size: 0.85rem; + gap: 4px; + font-size: 0.7rem; color: white; font-weight: 500; + z-index: 10; } .language-switcher:hover { @@ -82,7 +83,7 @@ } .language-switcher .lang-icon { - font-size: 1rem; + font-size: 0.8rem; } .language-switcher .lang-text { @@ -273,8 +274,8 @@ /* 推理服务器 CPU 柱状图样式 */ .cpu-chart { - display: flex; - flex-direction: column; + display: grid; + grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; padding: 10px; @@ -285,13 +286,13 @@ .cpu-bar-item { display: flex; align-items: center; - gap: 10px; - height: 30px; + gap: 8px; + height: 28px; } .cpu-bar-label { - width: 60px; - font-size: 0.85rem; + width: 50px; + font-size: 0.8rem; font-weight: 500; color: #666; text-align: left; @@ -300,9 +301,9 @@ .cpu-bar-container { flex: 1; - height: 20px; + height: 18px; background-color: #e0e0e0; - border-radius: 10px; + border-radius: 9px; overflow: hidden; position: relative; } @@ -310,22 +311,61 @@ .cpu-bar-fill { height: 100%; background: linear-gradient(90deg, #4CAF50, #45a049); - border-radius: 10px; + border-radius: 9px; transition: width 0.3s ease; position: relative; - min-width: 45px; /* 确保即使是0%也有最小宽度来显示文字 */ + min-width: 0; /* 移除最小宽度限制 */ } .cpu-bar-value { - font-size: 0.75rem; + font-size: 0.6rem; /* 缩小字体 */ font-weight: bold; color: white; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); position: absolute; - right: 8px; + right: 4px; /* 减小右边距 */ top: 50%; transform: translateY(-50%); z-index: 2; + white-space: nowrap; /* 防止文字换行 */ + min-width: max-content; /* 确保文字完整显示 */ + } + + /* 内存、显存、GPU监控专用样式 */ + .memory-chart { + display: flex; + flex-direction: column; + gap: 15px; + margin-top: 10px; + padding: 10px; + background: #f8f9fa; + border-radius: 10px; + } + + .memory-item { + display: flex; + flex-direction: column; + gap: 8px; + } + + .memory-metric { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 5px; + } + + .memory-metric-label { + font-size: 0.9rem; + font-weight: 500; + color: #666; + margin: 0 !important; + } + + .memory-metric-value { + font-size: 0.85rem; + font-weight: bold; + color: #323232; } /* 推理服务器 温度监控柱状图样式 */ @@ -543,6 +583,18 @@ padding: 0; } + /* 移动端语言切换按钮进一步缩小 */ + .language-switcher { + padding: 3px 6px; + font-size: 0.65rem; + gap: 3px; + border-radius: 4px; + } + + .language-switcher .lang-icon { + font-size: 0.7rem; + } + .header h1 { font-size: 1.8rem; } @@ -584,13 +636,14 @@ .system-header h2 { font-size: 1.3rem; } + + /* 移动端 CPU 图表单列显示 */ + .cpu-chart { + grid-template-columns: 1fr; + } } /* 监控卡片内容对齐样式 */ - .memory-metric-label, - .power-metric-label, - .gpu-metric-label, - .lpmu-memory-metric-label, .system-metric-label { margin-left: 0px !important; } @@ -724,18 +777,18 @@

推理模组监控

系统信息
-
-
- 最后更新 - - +
+
+ 最后更新 + -
-
- 连接时间 - - +
+ 连接时间 + -
-
- 数据包 - 0 +
+ 数据包 + 0
@@ -782,18 +835,18 @@

应用模组监控

系统信息
-
-
- 最后更新 - - +
+
+ 最后更新 + -
-
- 连接时间 - - +
+ 连接时间 + -
-
- 数据包 - 0 +
+ 数据包 + 0
@@ -975,11 +1028,14 @@

应用模组监控

const usage = parseFloat(core.usage) || 0; const coreLabel = getTranslation('core', '核心'); + // 确保进度条有足够宽度显示文字,减小最小宽度 + const barWidth = Math.max(usage, 15); // 减小到15%最小宽度 + html += `
${coreLabel} ${core.id}
-
+
${usage.toFixed(1)}%
@@ -995,17 +1051,19 @@

应用模组监控

if (!memoryData) return; const content = document.getElementById('memoryContent'); - let html = '
'; + let html = '
'; if (memoryData.ram) { const ramUsagePercent = ((memoryData.ram.used / memoryData.ram.total) * 100).toFixed(1); html += ` -
- RAM - ${memoryData.ram.used}/${memoryData.ram.total} MB -
-
-
${ramUsagePercent}%
+
+
+ RAM + ${memoryData.ram.used}/${memoryData.ram.total} MB +
+
+
${ramUsagePercent}%
+
`; } @@ -1014,12 +1072,14 @@

应用模组监控

const swapUsagePercent = memoryData.swap.total > 0 ? ((memoryData.swap.used / memoryData.swap.total) * 100).toFixed(1) : 0; html += ` -
- SWAP - ${memoryData.swap.used}/${memoryData.swap.total} MB -
-
-
${swapUsagePercent}%
+
+
+ SWAP + ${memoryData.swap.used}/${memoryData.swap.total} MB +
+
+
${swapUsagePercent}%
+
`; } @@ -1089,7 +1149,7 @@

应用模组监控

if (!powerData) return; const content = document.getElementById('powerContent'); - let html = '
'; + let html = '
'; const powerItems = [ { label: 'GPU+SoC', data: powerData.gpu_soc }, @@ -1101,9 +1161,11 @@

应用模组监控

powerItems.forEach(item => { if (item.data && item.data.current !== undefined) { html += ` -
- ${item.label} - ${item.data.current} ${item.data.unit || 'mW'} +
+
+ ${item.label} + ${item.data.current} ${item.data.unit || 'mW'} +
`; } @@ -1117,24 +1179,26 @@

应用模组监控

if (!gpuData) return; const content = document.getElementById('gpuContent'); - let html = '
'; + let html = '
'; if (gpuData.gr3d_freq !== undefined) { const gpuFreqLabel = getTranslation('gpu-freq', '3D GPU 频率'); html += ` -
- ${gpuFreqLabel} - ${gpuData.gr3d_freq}% -
-
-
${gpuData.gr3d_freq}%
+
+
+ ${gpuFreqLabel} + ${gpuData.gr3d_freq}% +
+
+
${gpuData.gr3d_freq}%
+
`; } html += '
'; const noDataText = getTranslation('no-gpu-data', '暂无 GPU 数据'); - content.innerHTML = html || `
${noDataText}
`; + content.innerHTML = html || `
${noDataText}
`; } updateConnectionStatus(status, message) { @@ -1143,6 +1207,37 @@

应用模组监控

indicator.className = `status-indicator status-${status}`; statusText.textContent = message; + + // 保存当前状态用于语言切换时刷新 + this.currentStatus = status; + } + + // 刷新连接状态显示(用于语言切换) + refreshConnectionStatus() { + if (this.currentStatus) { + let messageKey = ''; + let fallbackMessage = ''; + + switch(this.currentStatus) { + case 'connecting': + messageKey = 'connecting-inference'; + fallbackMessage = '正在连接到 推理服务器...'; + break; + case 'connected': + messageKey = 'connected-inference'; + fallbackMessage = '已连接到 推理服务器'; + break; + case 'disconnected': + messageKey = 'disconnected-inference'; + fallbackMessage = '推理服务器 连接已断开'; + break; + } + + if (messageKey) { + const message = getTranslation(messageKey, fallbackMessage); + document.getElementById('agxStatusText').textContent = message; + } + } } scheduleReconnect() { @@ -1303,11 +1398,14 @@

应用模组监控

const usage = parseFloat(core.usage) || 0; const coreLabel = getTranslation('core', '核心'); + // 确保进度条有足够宽度显示文字,减小最小宽度 + const barWidth = Math.max(usage, 15); // 减小到15%最小宽度 + html += `
${coreLabel} ${core.id}
-
+
${usage.toFixed(1)}%
@@ -1323,35 +1421,39 @@

应用模组监控

if (!memoryData) return; const content = document.getElementById('lpmuMemoryContent'); - let html = '
'; + let html = '
'; if (memoryData.ram) { html += ` -
- RAM - ${memoryData.ram.used}/${memoryData.ram.total} ${memoryData.ram.unit} -
-
-
${memoryData.ram.percent.toFixed(1)}%
+
+
+ RAM + ${memoryData.ram.used}/${memoryData.ram.total} ${memoryData.ram.unit} +
+
+
${memoryData.ram.percent.toFixed(1)}%
+
`; } if (memoryData.swap) { html += ` -
- SWAP - ${memoryData.swap.used}/${memoryData.swap.total} ${memoryData.swap.unit} -
-
-
${memoryData.swap.percent.toFixed(1)}%
+
+
+ SWAP + ${memoryData.swap.used}/${memoryData.swap.total} ${memoryData.swap.unit} +
+
+
${memoryData.swap.percent.toFixed(1)}%
+
`; } html += '
'; const noDataText = getTranslation('no-memory-data', '暂无内存数据'); - content.innerHTML = html || `
${noDataText}
`; + content.innerHTML = html || `
${noDataText}
`; } updateTemperatureDisplay(tempData) { @@ -1437,6 +1539,37 @@

应用模组监控

indicator.className = `status-indicator status-${status}`; statusText.textContent = message; + + // 保存当前状态用于语言切换时刷新 + this.currentStatus = status; + } + + // 刷新连接状态显示(用于语言切换) + refreshConnectionStatus() { + if (this.currentStatus) { + let messageKey = ''; + let fallbackMessage = ''; + + switch(this.currentStatus) { + case 'connecting': + messageKey = 'connecting-application'; + fallbackMessage = '正在连接到 应用服务器...'; + break; + case 'connected': + messageKey = 'connected-application'; + fallbackMessage = '已连接到 应用服务器'; + break; + case 'disconnected': + messageKey = 'disconnected-application'; + fallbackMessage = '应用服务器 连接已断开'; + break; + } + + if (messageKey) { + const message = getTranslation(messageKey, fallbackMessage); + document.getElementById('lpmuStatusText').textContent = message; + } + } } scheduleReconnect() { @@ -1465,8 +1598,9 @@

应用模组监控

// 页面加载完成后初始化监控 document.addEventListener('DOMContentLoaded', () => { - new 推理服务器Monitor(); - new 应用服务器Monitor(); + // 初始化监控类并保存为全局变量以便语言切换时使用 + window.agxMonitor = new 推理服务器Monitor(); + window.应用服务器Monitor = new 应用服务器Monitor(); // 添加滚动监听器来实现文字颜色渐变 initScrollColorTransition(); @@ -1582,10 +1716,26 @@

应用模组监控

elements.forEach(element => { const key = element.getAttribute('data-translate'); if (translations[language] && translations[language][key]) { + // 特殊处理连接状态文本,保持当前实际状态 + if (key === 'connecting-inference' || key === 'connecting-application' || + key === 'connected-inference' || key === 'connected-application' || + key === 'disconnected-inference' || key === 'disconnected-application' || + key === 'connection-error-inference' || key === 'connection-error-application') { + // 跳过连接状态文本的翻译,让Monitor类来管理这些状态 + return; + } element.textContent = translations[language][key]; } }); + // 刷新各个监控器的连接状态显示 + if (window.agxMonitor && typeof window.agxMonitor.refreshConnectionStatus === 'function') { + window.agxMonitor.refreshConnectionStatus(); + } + if (window.应用服务器Monitor && typeof window.应用服务器Monitor.refreshConnectionStatus === 'function') { + window.应用服务器Monitor.refreshConnectionStatus(); + } + // 更新文档标题 if (language === 'en') { document.title = 'RM-01 Dashboard - RobOS Monitor'; From 6dd2d140edf0e0bd723d17721ed189d35057a358 Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 13 Oct 2025 17:16:35 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=B1=20Mobile=20Spacing=20Optimizat?= =?UTF-8?q?ion=20for=20RM-01=20Dashboard=F0=9F=8E=AF=20Improvements:-=20?= =?UTF-8?q?=E2=9C=85=20Reduced=20main-panel=20top=20margin=20in=20mobile?= =?UTF-8?q?=20(100px=20=E2=86=92=2040px)-=20=E2=9C=85=20Optimized=20system?= =?UTF-8?q?=20section=20spacing=20(40px=20=E2=86=92=2025px)=20=20-=20?= =?UTF-8?q?=E2=9C=85=20Decreased=20panel=20padding=20for=20mobile=20(30px?= =?UTF-8?q?=20=E2=86=92=2020px)-=20=E2=9C=85=20Perfect=20spacing=20balance?= =?UTF-8?q?=20for=20iOS=20webapp=EF=BF=BD=20Technical=20Details:-=20Mobile?= =?UTF-8?q?-only=20CSS=20targeting=20(@media=20max-width:=20768px)-=20Desk?= =?UTF-8?q?top=20layout=20preserved=20unchanged-=20Maintains=20proper=20vi?= =?UTF-8?q?sual=20hierarchy-=20Improved=20mobile=20UX=20without=20affectin?= =?UTF-8?q?g=20desktop=E2=9C=A8=20Result:=20Compact=20mobile=20layout=20wi?= =?UTF-8?q?th=20optimal=20spacing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sdcard/web/index.htm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sdcard/web/index.htm b/sdcard/web/index.htm index c14073d..60ad0b7 100644 --- a/sdcard/web/index.htm +++ b/sdcard/web/index.htm @@ -615,6 +615,16 @@ grid-template-columns: 1fr; } + /* 移动端减少间距 */ + .main-panel { + margin: 40px 0 20px 0; /* 移动端减少上边距从100px到40px */ + padding: 20px; /* 移动端减少内边距 */ + } + + .system-section { + margin-bottom: 25px; /* 移动端减少系统区块间距从40px到25px */ + } + .lpmu-dashboard, .lpmu-row-1, .lpmu-row-2 {