This is an automated email from the ASF dual-hosted git repository.

imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph-toolchain.git

commit aafe65745cd1e5ebe6e43e295a3377b1425d087a
Author: dark <[email protected]>
AuthorDate: Fri Aug 14 12:39:02 2026 +0800

    fix(hubble): improve result cards and graph labels
---
 .../src/i18n/resources/zh-CN/modules/analysis.json |  9 +++
 .../src/i18n/resources/zh-CN/modules/pages.json    | 52 +++++++++++--
 .../src/modules/component/NumberCard/index.js      | 86 +++++++++++++++++-----
 3 files changed, 123 insertions(+), 24 deletions(-)

diff --git 
a/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/analysis.json 
b/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/analysis.json
index 13ddc2b95..8d681f628 100644
--- a/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/analysis.json
+++ b/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/analysis.json
@@ -80,6 +80,15 @@
       "mode_2d": "2D 模式",
       "mode_3d": "3D 模式",
       "import_success": "导入成功",
+      "number_card": {
+        "paths": "路径",
+        "nodes": "节点",
+        "edges": "边",
+        "loading": "加载中",
+        "unavailable": "不可用",
+        "node_summary": "节点:当前结果 {{current}},全图 {{total}}",
+        "edge_summary": "边:当前结果 {{current}},全图 {{total}}"
+      },
       "import_failed": "导入失败",
       "export_json": "导出 JSON",
       "export_png": "导出图片",
diff --git 
a/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/pages.json 
b/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/pages.json
index a80f7f0d7..93a5ae2a8 100644
--- a/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/pages.json
+++ b/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/pages.json
@@ -226,10 +226,10 @@
       "clear_graph": "清空 Schema 与数据",
       "set_default": "设为默认",
       "view_schema": "查看schema",
-      "load_hlm_sample": "构建红楼梦 Demo 图",
-      "load_loader_sample": "构建人物与软件 Demo 图",
+      "load_hlm_sample": "红楼梦 Demo 图",
+      "load_loader_sample": "人物与软件 Demo 图",
       "sample_data": "示例数据与资源",
-      "load_rank_sample": "构建 Rank 迷你电影 Demo",
+      "load_rank_sample": "迷你电影 Rank Demo",
       "clone": "克隆图"
     },
     "sample": {
@@ -263,10 +263,18 @@
       "nickname_placeholder": "可选,例如:电影推荐图",
       "nickname_help": "可选的显示别名或备注名,不参与 URL 或权限匹配;留空时显示图名称。可使用中文、字母、数字和下划线,最长 
48 位",
       "schema": "Graph Schema",
+      "sample_hlm": "红楼梦 Demo 图",
+      "sample_rank": "迷你电影 Rank Demo",
+      "sample_loader": "人物与软件 Demo 图",
+      "sample_none": "不导入示例数据",
       "schema_placeholder": "选择已有 Schema 模板(可选)",
       "schema_load_failed": "Schema 模板暂时无法加载。",
       "schema_retry": "重试模板",
       "schema_optional_hint": "可选;不选择模板时将创建空 Schema 图",
+      "sample": "示例数据",
+      "sample_placeholder": "可选:创建图后自动导入一套示例数据",
+      "sample_hint": "选择后将创建图,并自动导入对应 Schema 和示例数据;若导入失败,可在已创建的图中重试",
+      "sample_apply_failed": "图已创建,但示例数据导入失败;可在图菜单中重试。",
       "schema_create": "点击创建 Graph Schema",
       "schema_create_failed": "内置 Graph Schema 创建失败,请检查模板列表后重试。",
       "schema_apply_failed": "图已创建,但内置 Schema 应用失败,请进入元数据页面重试。",
@@ -337,6 +345,7 @@
       "counts_tooltip": "来自图列表 API 的实际点边统计",
       "overview": "概览",
       "schema_info": "Schema 信息",
+      "view_schema": "查看 {{graph}} 的 Schema",
       "empty_schema": "尚未创建 Schema",
       "empty_schema_help": "可以先建立模型,或运行安全查询",
       "open_schema": "创建 Schema",
@@ -548,7 +557,7 @@
     "execute": "执行",
     "action": {
       "detail": "查看执行历史",
-      "config": "查看任务配置",
+      "config": "查看任务信息",
       "edit": "编辑任务",
       "pause": "暂停任务",
       "run": "运行任务",
@@ -568,6 +577,18 @@
       "realtime": "实时执行",
       "cron": "周期执行"
     },
+    "status": {
+      "pending": "待执行",
+      "running": "运行中",
+      "success": "已完成",
+      "failed": "失败",
+      "paused": "已暂停",
+      "stopped": "已停止",
+      "initializing": "初始化中",
+      "cancelling": "正在取消",
+      "cancelled": "已取消",
+      "unknown": "未知状态"
+    },
     "col": {
       "name": "任务名称",
       "source_type": "源数据类型",
@@ -611,14 +632,21 @@
       "other": "其它"
     },
     "view": {
-      "title": "查看任务",
+      "title": "任务信息",
       "unavailable": "无法加载当前任务详情。",
       "retry": "重试任务详情",
+      "unavailable_value": "未提供",
       "name": "任务名称",
       "source_type": "源数据类型",
       "target_space": "目标图空间",
       "target_graph": "目标图",
-      "sync_type": "同步类型"
+      "sync_type": "同步类型",
+      "status": "状态",
+      "data_size": "数据量",
+      "duration": "持续时间",
+      "create_time": "创建时间",
+      "update_time": "更新时间",
+      "technical_details": "技术详情"
     },
     "edit": {
       "name": "任务名称",
@@ -1188,6 +1216,8 @@
     "node_id_copied": "节点 ID 已复制",
     "node_id_copy_failed": "无法复制节点 ID",
     "leader_role": "Leader 角色",
+    "leader_shard": "{{count}} 个 Leader 分区",
+    "leader_shards": "{{count}} 个 Leader 分区",
     "node_profile": "节点概况",
     "node_detail": "节点详情",
     "node_metrics": "节点指标",
@@ -1199,6 +1229,10 @@
     "refresh": "刷新",
     "refreshing": "刷新中…",
     "stale": "数据已过期",
+    "stale_help": "指标采集未在最近一次观测窗口内成功完成;拓扑状态仍可用;请刷新或打开节点详情查看原因",
+    "status_unknown": "当前无法确认该来源的健康状态,请查看具体原因或刷新",
+    "status_degraded": "需关注",
+    "status_degraded_help": "部分来源或指标异常,核心服务可能仍可用;请查看下方来源原因",
     "unavailable": "不可用",
     "unsupported": "当前服务版本不支持",
     "metric_malformed": "指标响应格式异常",
@@ -1244,6 +1278,7 @@
     "search_nodes": "搜索节点名称",
     "node_type_filter": "按节点类型筛选",
     "node_status_filter": "按节点状态筛选",
+    "clear_filters": "清空筛选",
     "view_node_details": "查看 {{name}} 的详情",
     "view_details": "查看详情",
     "action": "操作",
@@ -1270,6 +1305,11 @@
     "metric_scope_backend": "后端指标由 Server 和 Store 节点提供,不会在 {{nodeType}} 节点采集。",
     "reason_upstream_timeout": "上游超时",
     "reason_upstream_unavailable": "上游不可用",
+    "reason_metrics_target_untrusted": "指标采集目标未通过信任校验,请检查 PD/Prometheus target 
配置",
+    "reason_metrics_target_missing": "未发现 Store 指标采集目标,请检查 target 配置",
+    "reason_upstream_deadline": "指标采集超时",
+    "reason_metrics_not_collected": "当前节点未采集该指标",
+    "reason_topology_fields_unavailable": "拓扑未提供该字段",
     "reason_partial_refresh_failed": "部分指标刷新失败",
     "reason_refresh_failed": "刷新失败",
     "reason_malformed_response": "响应格式异常",
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/component/NumberCard/index.js 
b/hugegraph-hubble/hubble-fe/src/modules/component/NumberCard/index.js
index 607b2252d..cd0eb168e 100644
--- a/hugegraph-hubble/hubble-fe/src/modules/component/NumberCard/index.js
+++ b/hugegraph-hubble/hubble-fe/src/modules/component/NumberCard/index.js
@@ -23,18 +23,48 @@
 import React from 'react';
 import c from './index.module.scss';
 import classnames from 'classnames';
+import {useTranslation} from 'react-i18next';
+
+const isLoadingCount = value => {
+    if (value === null || value === undefined
+        || (typeof value === 'string' && value.trim() === '')) {
+        return false;
+    }
+    const count = Number(value);
+    return Number.isFinite(count) && count < 0;
+};
+
+const getCountDisplay = (value, t) => {
+    if (isLoadingCount(value)) {
+        return t('analysis.canvas.number_card.loading');
+    }
+    if (value === null || value === undefined
+        || (typeof value === 'string' && value.trim() === '')) {
+        return t('analysis.canvas.number_card.unavailable');
+    }
+    const count = Number(value);
+    return Number.isFinite(count)
+        ? value
+        : t('analysis.canvas.number_card.unavailable');
+};
 
 const NumberCard = props => {
+    const {t} = useTranslation();
     const {pathNum, data, hasPadding} = props;
     const {currentGraphNodesNum, currentGraphEdgesNum, allGraphNodesNum, 
allGraphEdgesNum} = data;
 
-    let showLoading = false;
-    if (currentGraphNodesNum < 0 || currentGraphEdgesNum < 0 || 
+allGraphNodesNum < 0 || +allGraphEdgesNum < 0) {
-        showLoading = true;
-    }
-
-    const allGraphNodes = showLoading ? 'loading...' : allGraphNodesNum;
-    const allGraphEdges = showLoading ? 'loading...' : allGraphEdgesNum;
+    const currentGraphNodes = getCountDisplay(currentGraphNodesNum, t);
+    const currentGraphEdges = getCountDisplay(currentGraphEdgesNum, t);
+    const allGraphNodes = getCountDisplay(allGraphNodesNum, t);
+    const allGraphEdges = getCountDisplay(allGraphEdgesNum, t);
+    const nodeSummary = t('analysis.canvas.number_card.node_summary', {
+        current: currentGraphNodes,
+        total: allGraphNodes,
+    });
+    const edgeSummary = t('analysis.canvas.number_card.edge_summary', {
+        current: currentGraphEdges,
+        total: allGraphEdges,
+    });
 
     const graphClassName = classnames(
         c.numberCard,
@@ -45,28 +75,48 @@ const NumberCard = props => {
         <div className={graphClassName}>
             {pathNum && (
                 <div className={c.numberCardItem}>
-                    <div className={c.numberCardTitle}>Paths</div>
+                    <div className={c.numberCardTitle}>
+                        {t('analysis.canvas.number_card.paths')}
+                    </div>
                     <div className={c.numberCardInfo}>
                         <span className={c.numberCur}>{pathNum}</span>
                     </div>
                 </div>
             )}
             <div className={c.numberCardItem}>
-                <div className={c.numberCardTitle}>Nodes</div>
-                <div className={c.numberCardInfo}>
-                    <span className={c.numberCur}>{currentGraphNodesNum}</span>
-                    <span>/</span>
-                    <span className={c.numberAll}>
+                <div className={c.numberCardTitle}>
+                    {t('analysis.canvas.number_card.nodes')}
+                </div>
+                <div
+                    className={c.numberCardInfo}
+                    role='group'
+                    aria-label={nodeSummary}
+                    title={nodeSummary}
+                >
+                    <span className={c.numberCur} aria-hidden='true'>
+                        {currentGraphNodes}
+                    </span>
+                    <span aria-hidden='true'>/</span>
+                    <span className={c.numberAll} aria-hidden='true'>
                         {allGraphNodes}
                     </span>
                 </div>
             </div>
             <div className={c.numberCardItem}>
-                <div className={c.numberCardTitle}>Edges</div>
-                <div className={c.numberCardInfo}>
-                    <span className={c.numberCur}>{currentGraphEdgesNum}</span>
-                    <span>/</span>
-                    <span className={c.numberAll}>
+                <div className={c.numberCardTitle}>
+                    {t('analysis.canvas.number_card.edges')}
+                </div>
+                <div
+                    className={c.numberCardInfo}
+                    role='group'
+                    aria-label={edgeSummary}
+                    title={edgeSummary}
+                >
+                    <span className={c.numberCur} aria-hidden='true'>
+                        {currentGraphEdges}
+                    </span>
+                    <span aria-hidden='true'>/</span>
+                    <span className={c.numberAll} aria-hidden='true'>
                         {allGraphEdges}
                     </span>
                 </div>

Reply via email to