From 6bf98ed00e87e5ca99c75a3dbe9ba3fcd7004a18 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 3 Jun 2026 00:18:23 +0800 Subject: [PATCH] fix(web): standardize UI icon language --- apps/web/messages/en.json | 6 +- apps/web/messages/zh-TW.json | 6 +- .../src/app/[locale]/knowledge-base/page.tsx | 13 +++-- .../components/ai/openclaw-state-machine.tsx | 11 ++-- .../neural-command/NeuralLiveCenter.tsx | 56 +++++++++++-------- .../components/neural-command/NeuralStats.tsx | 24 +++++--- docs/LOGBOOK.md | 25 +++++++++ 7 files changed, 94 insertions(+), 47 deletions(-) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 24955526..df54bea6 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -1871,7 +1871,7 @@ }, "neuralCommand": { "title": "神經指揮中心", - "subtitle": "SSH_COMMAND 指揮權鏈 · OpenClaw 🦞 × NemoTron ⚡", + "subtitle": "SSH_COMMAND 指揮權鏈 · OpenClaw × NemoTron", "lastRefresh": "更新於 {time}", "refresh": "重新整理", "preFlightAudit": "Pre-Flight 審查", @@ -1962,8 +1962,8 @@ "noApprovals": "目前無待審核項目", "noApprovalsDesc": "所有授權請求已處理完畢", "chainAlert": "告警觸發", - "chainRAG": "🦞 OpenClaw RAG 診斷", - "chainDecide": "⚡ NemoTron 決策", + "chainRAG": "OpenClaw RAG 診斷", + "chainDecide": "NemoTron 決策", "chainExec": "Executor 路由", "chainIdleSub": "等待新告警進入...", "backToList": "返回列表", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 24955526..df54bea6 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -1871,7 +1871,7 @@ }, "neuralCommand": { "title": "神經指揮中心", - "subtitle": "SSH_COMMAND 指揮權鏈 · OpenClaw 🦞 × NemoTron ⚡", + "subtitle": "SSH_COMMAND 指揮權鏈 · OpenClaw × NemoTron", "lastRefresh": "更新於 {time}", "refresh": "重新整理", "preFlightAudit": "Pre-Flight 審查", @@ -1962,8 +1962,8 @@ "noApprovals": "目前無待審核項目", "noApprovalsDesc": "所有授權請求已處理完畢", "chainAlert": "告警觸發", - "chainRAG": "🦞 OpenClaw RAG 診斷", - "chainDecide": "⚡ NemoTron 決策", + "chainRAG": "OpenClaw RAG 診斷", + "chainDecide": "NemoTron 決策", "chainExec": "Executor 路由", "chainIdleSub": "等待新告警進入...", "backToList": "返回列表", diff --git a/apps/web/src/app/[locale]/knowledge-base/page.tsx b/apps/web/src/app/[locale]/knowledge-base/page.tsx index cf66bd1a..a883488c 100644 --- a/apps/web/src/app/[locale]/knowledge-base/page.tsx +++ b/apps/web/src/app/[locale]/knowledge-base/page.tsx @@ -17,7 +17,7 @@ import { useTranslations } from 'next-intl' import { cn } from '@/lib/utils' import { Search, BookOpen, FileText, Shield, Cpu, - Server, Eye, Bot, ChevronRight, Plus, Sparkles, + Server, Eye, Bot, ChevronRight, Plus, Sparkles, ClipboardList, TriangleAlert, } from 'lucide-react' import ReactMarkdown from 'react-markdown' import remarkGfm from 'remark-gfm' @@ -493,13 +493,15 @@ export default function KnowledgeBasePage({ {/* Related links */} {selectedEntry.related_playbook_id && ( -
- 📋 {t('relatedPlaybook')}: {selectedEntry.related_playbook_id} +
+
)} {selectedEntry.related_incident_id && ( -
- ⚠️ {t('relatedIncident')}: {selectedEntry.related_incident_id} +
+
)} @@ -534,4 +536,3 @@ export default function KnowledgeBasePage({ ) } - diff --git a/apps/web/src/components/ai/openclaw-state-machine.tsx b/apps/web/src/components/ai/openclaw-state-machine.tsx index 79b78f49..7ba4489e 100644 --- a/apps/web/src/components/ai/openclaw-state-machine.tsx +++ b/apps/web/src/components/ai/openclaw-state-machine.tsx @@ -436,7 +436,7 @@ export function OpenClawStateMachine({ setSelectedIndex(null) setProcessedApproval(null) }} - title={processedApproval ? (processedApproval.action === 'approved' ? '✅ 已批准' : '❌ 已拒絕') : '審核詳情'} + title={processedApproval ? (processedApproval.action === 'approved' ? '已批准' : '已拒絕') : '審核詳情'} onPrev={processedApproval ? undefined : handlePrevApproval} onNext={processedApproval ? undefined : handleNextApproval} current={selectedIndex !== null && !processedApproval ? selectedIndex + 1 : undefined} @@ -458,9 +458,12 @@ export function OpenClawStateMachine({ ? "bg-status-healthy/20 text-status-healthy" : "bg-status-critical/20 text-status-critical" )}> -
- {processedApproval.action === 'approved' ? '✅' : '❌'} -
+
+ {processedApproval.action === 'approved' + ?
{processedApproval.action === 'approved' ? '已批准執行' : '已拒絕執行'}
diff --git a/apps/web/src/components/neural-command/NeuralLiveCenter.tsx b/apps/web/src/components/neural-command/NeuralLiveCenter.tsx index e4ac700c..68416e0f 100644 --- a/apps/web/src/components/neural-command/NeuralLiveCenter.tsx +++ b/apps/web/src/components/neural-command/NeuralLiveCenter.tsx @@ -11,7 +11,7 @@ import { useTranslations } from 'next-intl' import { cn } from '@/lib/utils' -import { CheckCircle2, Clock, XCircle, Loader2, Inbox } from 'lucide-react' +import { Bot, CheckCircle2, Clock, Cpu, Inbox, Loader2, Server, Settings, XCircle } from 'lucide-react' import type { AutoRepairStats, RepairHistoryItem, UriScheme, RepairStatus, ActiveIncident } from './types' interface Props { @@ -41,6 +41,13 @@ const NODE_STATE_STYLES = { waiting: 'border-border opacity-40', } +const SEVERITY_DOT_STYLES: Record = { + P0: 'bg-red-500 ring-red-500/20', + P1: 'bg-orange-500 ring-orange-500/20', + P2: 'bg-yellow-500 ring-yellow-500/20', + P3: 'bg-green-500 ring-green-500/20', +} + // 從最新一筆 history 衍生鏈路狀態 function deriveChainNodes(latestItem: RepairHistoryItem | null, t: ReturnType) { if (!latestItem) { @@ -72,14 +79,8 @@ function computeAvgDuration(history: RepairHistoryItem[]): string { return `${(avg / 1000).toFixed(1)}s` } -// 嚴重度 → emoji 對應 -function severityEmoji(severity: string): string { - switch (severity) { - case 'P0': return '🔴' - case 'P1': return '🟠' - case 'P2': return '🟡' - default: return '🟢' - } +function severityDotClass(severity: string): string { + return SEVERITY_DOT_STYLES[severity] ?? SEVERITY_DOT_STYLES.P3 } export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents = [] }: Props) { @@ -101,7 +102,9 @@ export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents {/* OpenClaw */}
-
🦞
+
+

OpenClaw

{t('agentRoleOC')}

@@ -118,7 +121,9 @@ export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents {/* NemoTron */}
-
+
+

NemoTron

{t('agentRoleNemo')}

@@ -142,7 +147,11 @@ export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents 'flex items-center gap-2 px-2 py-1.5 rounded-lg cursor-pointer transition-colors', i === 0 ? 'bg-orange-500/8 border border-orange-500/20' : 'hover:bg-muted', )}> - {severityEmoji(inc.severity)} +

{inc.incident_id}

{inc.affected_services.join(', ') || inc.status}

@@ -187,16 +196,19 @@ export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents
{[ - { scheme: 'kubectl://', icon: '☸️', label: 'kubectl', cls: 'border-blue-500/25 bg-blue-500/5' }, - { scheme: 'openclaw://', icon: '🦞', label: 'OpenClaw', cls: 'border-orange-500/25 bg-orange-500/5' }, - { scheme: 'ansible://', icon: '⚙️', label: 'Ansible .188', cls: 'border-purple-500/25 bg-purple-500/5' }, - ].map(b => ( -
-

{b.icon}

-

{b.label}

-

{b.scheme}

-
- ))} + { scheme: 'kubectl://', Icon: Server, label: 'kubectl', cls: 'border-blue-500/25 bg-blue-500/5', iconCls: 'text-blue-500' }, + { scheme: 'openclaw://', Icon: Bot, label: 'OpenClaw', cls: 'border-orange-500/25 bg-orange-500/5', iconCls: 'text-orange-500' }, + { scheme: 'ansible://', Icon: Settings, label: 'Ansible .188', cls: 'border-purple-500/25 bg-purple-500/5', iconCls: 'text-purple-500' }, + ].map(b => { + const BranchIcon = b.Icon + return ( +
+
+ ) + })}
diff --git a/apps/web/src/components/neural-command/NeuralStats.tsx b/apps/web/src/components/neural-command/NeuralStats.tsx index cff607ab..70ab7473 100644 --- a/apps/web/src/components/neural-command/NeuralStats.tsx +++ b/apps/web/src/components/neural-command/NeuralStats.tsx @@ -12,7 +12,8 @@ import { useMemo } from 'react' import { useTranslations } from 'next-intl' import { cn } from '@/lib/utils' -import { Inbox } from 'lucide-react' +import { Bot, Inbox, Server, Settings } from 'lucide-react' +import type { LucideIcon } from 'lucide-react' import type { AutoRepairStats, PlaybookItem, RepairHistoryItem } from './types' interface DispositionSummary { @@ -38,10 +39,10 @@ const TYPE_BADGE: Record = { openclaw: 'bg-orange-500/10 text-orange-500 border border-orange-500/25', } -const SCHEME_ICON: Record = { - 'kubectl://': { icon: '☸️', color: 'bg-blue-500', textColor: 'text-blue-500', bg: 'bg-blue-500/10' }, - 'openclaw://': { icon: '🦞', color: 'bg-orange-500', textColor: 'text-orange-500', bg: 'bg-orange-500/10' }, - 'ansible://': { icon: '⚙️', color: 'bg-purple-500', textColor: 'text-purple-500', bg: 'bg-purple-500/10' }, +const SCHEME_STYLE: Record = { + 'kubectl://': { Icon: Server, color: 'bg-blue-500', textColor: 'text-blue-500', bg: 'bg-blue-500/10' }, + 'openclaw://': { Icon: Bot, color: 'bg-orange-500', textColor: 'text-orange-500', bg: 'bg-orange-500/10' }, + 'ansible://': { Icon: Settings, color: 'bg-purple-500', textColor: 'text-purple-500', bg: 'bg-purple-500/10' }, } export function NeuralStats({ stats, playbooks, history, pendingCount, disposition }: Props) { @@ -59,7 +60,7 @@ export function NeuralStats({ stats, playbooks, history, pendingCount, dispositi const total = history.length || 1 return Object.entries(counts).map(([scheme, { count, successCount }]) => ({ scheme, - ...(SCHEME_ICON[scheme] ?? SCHEME_ICON['kubectl://']), + ...(SCHEME_STYLE[scheme] ?? SCHEME_STYLE['kubectl://']), count, rate: count > 0 ? Math.round((successCount / count) * 100) : 0, pct: Math.round((count / total) * 100), @@ -145,9 +146,13 @@ export function NeuralStats({ stats, playbooks, history, pendingCount, dispositi

{t('schemeBreakdown')}

{schemeStats.length > 0 ? (
- {schemeStats.map(s => ( + {schemeStats.map(s => { + const SchemeIcon = s.Icon + return (
- {s.icon} + + {s.scheme}
@@ -155,7 +160,8 @@ export function NeuralStats({ stats, playbooks, history, pendingCount, dispositi {s.count} {s.rate}%
- ))} + ) + })}
) : (
diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index b5d40767..b09819cd 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,28 @@ +## 2026-06-03|前端 UI/UX 與素材治理同步盤點啟動 + +**背景**:統帥追問前端是否也需要同步盤點 UI/UX 與素材。結論:需要,而且必須和 AI 自動化飛輪、AwoooP 操作台、告警流程呈現一起治理;目前問題不只是文案,而是過多文字牆、流程/拓樸/圖表不足、正式 UI 仍混用 emoji 作為產品圖示、可復用素材庫薄弱,導致使用者難以快速判斷「現在跑到哪個階段、誰主責、是否自動修復、何時要人工介入」。 + +**本次盤點結果**: +- `apps/web/public` 目前可復用產品素材極少,主要只有 `favicon.svg` 與 DSEG7 字型;缺少正式產品截圖、拓樸圖、架構圖、流程圖素材入口與治理清單。 +- 前端已有 `lucide-react`、`recharts`、`@xyflow/react` 等基礎能力,可以支撐專業圖示、趨勢圖、流程圖與狀態機視覺化;下一步應優先把大量文字段落改成「流程節點、狀態表、時間軸、拓樸關係、風險分佈」。 +- 正式頁仍有 emoji 扮演狀態或服務圖示,會削弱操作台專業感,也不利於建立一致設計語言。 +- `apps/web/src/components/aiops/timeline/mock-data.ts` 仍是前端假資料風險候選,後續要確認是否僅開發殘留,不能讓產品頁誤讀為真實自動化證據。 + +**本次低風險可見修正**: +- `NeuralLiveCenter`:告警雷達嚴重度由 emoji 改為一致狀態點;OpenClaw / NemoTron 與 kubectl / OpenClaw / Ansible 分支改用 lucide 圖示。 +- `NeuralStats`:URI scheme 分佈由 emoji 改為一致的圖示膠囊與進度條,保留真實 history 聚合邏輯。 +- `Knowledge Base`:related Playbook / Incident 連結改用 lucide 圖示,避免正式知識頁出現 emoji 標記。 +- `OpenClawStateMachine`:approval 處理結果 modal 移除 `✅ / ❌`,改用 lucide 成功/警示圖示。 +- `neuralCommand` i18n:副標題與鏈路節點文案移除 emoji,`zh-TW` / `en` 鏡像保持一致。 + +**後續治理方向**: +- Wave A:全站掃描 emoji-as-icon、硬編碼圖示、文字牆區塊,優先處理 AwoooP Runs / Approvals / Alerts / KM / Monitoring。 +- Wave B:建立 reusable visual primitives:狀態點、流程節點、拓樸節點、證據表、空狀態、資料品質徽章,避免每頁重做。 +- Wave C:補正式素材庫:AI 飛輪架構圖、MCP/Agent 拓樸圖、告警到修復 swimlane、資料來源與證據鏈圖;素材必須對應真實系統與 DB/API 證據,禁止用假圖暗示已完成。 +- Wave D:首頁與核心操作頁改為圖表/表格優先,文字只保留決策摘要與例外原因。 + +**進度更新**:前端設計系統/i18n/素材治理由 `46%` 上修至 `49%`;首頁產品化入口維持 `80%`;AwoooP/HITL 維持 `99.2%`;完整 AI 自動化飛輪仍維持約 `66%`,本輪 UI 素材治理不代表自動修復能力已新增。 + ## 2026-06-02|IwoooS 進度誠實儀表正式落地 **背景**:統帥持續要求 IwoooS 不要只堆文字,且要讓使用者能理解「為什麼資安網有明顯框架進展,但整體進度不應假性跳點」。本輪延續低摩擦資安框架策略,不提高 enforcement、不啟動 Kali 掃描 / SSH 修復 / 主機更新 / repo mutation,只在首屏新增小型圖表化儀表,明確呈現只讀納管、S4.9 待補證據與執行閘門 0。