mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-29 20:30:00 +08:00
feat: new pages + dashboard enhancements + backend improvements
New pages: - Plugin Hub: grid cards, search, install/toggle/enable plugins - Route Map: SVG visualization of channels→agents bindings with legends - Diagnose: gateway connectivity diagnosis with step-by-step checks Dashboard enhancements: - WebSocket status indicator (connected/handshaking/reconnecting/disconnected) - Connected channels overview with platform icons - Colored log level badges (ERROR/WARN/INFO/DEBUG) with timestamps - Channels data loading in dashboard secondary fetch Splash screen: - Multi-stage boot detection (JS not loaded vs boot slow vs timeout) - 15s: WebView2/resource load failure - 20s: "initializing..." hint with elapsed counter - 90s: true timeout error Backend (Rust): - diagnose.rs: gateway connectivity diagnosis command - messaging.rs: plugin management commands - service.rs: improvements - lib.rs: register new commands Frontend libs: - feature-gates.js: feature flag system - ws-client.js: reconnect state tracking - tauri-api.js: new API bindings - model-presets.js: provider fixes - Remove gateway-guardian-policy.js (unused) Dev API (scripts/dev-api.js): - list_all_plugins, toggle_plugin, install_plugin handlers - probe_gateway_port, diagnose_gateway_connection handlers i18n: dashboard, sidebar, diagnose, extensions, routeMap locale modules CSS: plugin-hub cards, route-map SVG styles
This commit is contained in:
@@ -8,6 +8,7 @@ import { api } from '../lib/tauri-api.js'
|
||||
import { toast } from './toast.js'
|
||||
import { version as APP_VERSION } from '../../package.json'
|
||||
import { t, getLang, setLang, getAvailableLangs } from '../lib/i18n.js'
|
||||
import { isFeatureAvailable } from '../lib/feature-gates.js'
|
||||
|
||||
function NAV_ITEMS_FULL() { return [
|
||||
{
|
||||
@@ -16,6 +17,7 @@ function NAV_ITEMS_FULL() { return [
|
||||
{ route: '/dashboard', label: t('sidebar.dashboard'), icon: 'dashboard' },
|
||||
{ route: '/assistant', label: t('sidebar.assistant'), icon: 'assistant' },
|
||||
{ route: '/chat', label: t('sidebar.chat'), icon: 'chat' },
|
||||
{ route: '/route-map', label: t('sidebar.routeMap'), icon: 'route-map' },
|
||||
{ route: '/services', label: t('sidebar.services'), icon: 'services' },
|
||||
{ route: '/logs', label: t('sidebar.logs'), icon: 'logs' },
|
||||
]
|
||||
@@ -34,23 +36,24 @@ function NAV_ITEMS_FULL() { return [
|
||||
{
|
||||
section: t('sidebar.sectionData'),
|
||||
items: [
|
||||
{ route: '/memory', label: t('sidebar.memory'), icon: 'memory' },
|
||||
{ route: '/dreaming', label: t('sidebar.dreaming'), icon: 'dreaming' },
|
||||
{ route: '/cron', label: t('sidebar.cron'), icon: 'clock' },
|
||||
{ route: '/memory', label: t('sidebar.memory'), icon: 'memory', gate: 'memory' },
|
||||
{ route: '/dreaming', label: t('sidebar.dreaming'), icon: 'dreaming', gate: 'dreaming' },
|
||||
{ route: '/cron', label: t('sidebar.cron'), icon: 'clock', gate: 'cron' },
|
||||
{ route: '/usage', label: t('sidebar.usage'), icon: 'bar-chart' },
|
||||
]
|
||||
},
|
||||
{
|
||||
section: t('sidebar.sectionExtension'),
|
||||
items: [
|
||||
{ route: '/skills', label: t('sidebar.skills'), icon: 'skills' },
|
||||
{ route: '/skills', label: t('sidebar.skills'), icon: 'skills', gate: 'skills' },
|
||||
{ route: '/plugin-hub', label: t('sidebar.pluginHub'), icon: 'extensions' },
|
||||
]
|
||||
},
|
||||
{
|
||||
section: '',
|
||||
items: [
|
||||
{ route: '/settings', label: t('sidebar.settings'), icon: 'settings' },
|
||||
{ route: '/chat-debug', label: t('sidebar.chatDebug'), icon: 'debug' },
|
||||
{ route: '/chat-debug', label: t('sidebar.checkRepair'), icon: 'diagnose' },
|
||||
{ route: '/about', label: t('sidebar.about'), icon: 'about' },
|
||||
]
|
||||
}
|
||||
@@ -95,6 +98,8 @@ const ICONS = {
|
||||
'bar-chart': '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/></svg>',
|
||||
settings: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>',
|
||||
debug: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/><circle cx="12" cy="12" r="3"/></svg>',
|
||||
'route-map': '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="5" cy="6" r="2"/><circle cx="19" cy="6" r="2"/><circle cx="5" cy="18" r="2"/><circle cx="19" cy="18" r="2"/><path d="M7 6h10M7 18h10M5 8v8M19 8v8"/></svg>',
|
||||
diagnose: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>',
|
||||
}
|
||||
|
||||
let _delegated = false
|
||||
@@ -162,6 +167,7 @@ export function renderSidebar(el) {
|
||||
<div class="nav-section-title">${section.section}</div>`
|
||||
|
||||
for (const item of section.items) {
|
||||
if (item.gate && !isFeatureAvailable(item.gate)) continue
|
||||
const active = current === item.route ? ' active' : ''
|
||||
html += `<div class="nav-item${active}" data-route="${item.route}">
|
||||
${ICONS[item.icon] || ''}
|
||||
|
||||
Reference in New Issue
Block a user