☰
Engram Cloud Dashboard UI 组件规范:页面、卡片、指标与关联导航的实战指南
2026/10/9 5:06:05 网站建设 项目流程
  • 人工智能
  • AI Agent
  • Agent记忆
  • MCP服务

【免费下载链接】engram

Persistent memory system for AI coding agents. Agent-agnostic Go binary with SQLite + FTS5, MCP server, HTTP API, CLI, and TUI.

项目地址:https://gitcode.com/gh_mirrors/engra/engram
点击查看免费下载

Engram 是一个面向 AI 编码代理的持久记忆系统,其云控制面(Cloud Dashboard)是一套基于 Go templ 服务端渲染 + HTMX 局部刷新的浏览器 UI。本文以仓库中的 skills/ui-elements/SKILL.md 为骨架,结合 internal/cloud/dashboard 的真实组件与测试实现,系统讲解在 Engram Dashboard 中新增页面、卡片、指标、表格与详情流时应遵守的设计规则和落地方式。读完本文,你将掌握:何时该用这套规范、五条 UX 铁律与四条组合规则的含义、每条规则对应的 templ/HTMX 组件证据,以及如何通过测试守护"UI 不能撒谎"这一核心不变式。

何时使用这套规范

按 skills/ui-elements/SKILL.md 的When to Use定义,以下场景应当套用本规范:

  • 为 Dashboard 新增一个页面或 partial(局部片段);
  • 创建卡片(card)、指标(metric)、表格(table)、列表(list)或详情视图(detail view);
  • 设计相关实体之间的关联导航(connected navigation)。

在 Engram 中,这些 UI 元素全部落在internal/cloud/dashboard包内,通过 templ 模板(.templ+ 生成的*_templ.go)与 HTMX 属性(hx-get、hx-target、hx-swap、hx-include)组合实现,具体挂载路径可参考 docs/codebase/dashboard.md 中的架构说明:Browser → cloudserver(认证/会话/管理员边界)→ dashboard(handlers + templ + 静态资源)→ DashboardStore 接口 → cloudstore(Postgres 读模型)。

UX 五条铁律:每条都有源码佐证

原文档定义了五条 UX 规则,它们不是空泛的审美建议,而是可以在 components.templ 中逐条对号入座的实现约束。

1. 每条列表项都应通向有用之处

Every list item should lead somewhere useful when domain relationships exist.

当实体之间存在领域关系时,任何列表项都必须是可点击的入口,而不是死胡同。代码中最直接的体现是列表 partial 用<a class="card-link">包裹整张卡片:

  • ObservationsPartial(components.templ#L328-L352)把每条 observation 包成<a href="/dashboard/observations/{project}/{sessionID}/{syncID}">;
  • PromptsPartial同样把每条 prompt 包成指向详情页的卡片链接;
  • ProjectsListPartial(components.templ#L500-L539)把每个项目包成指向/dashboard/projects/{project}的card-link。

对应测试 dashboard_test.go#L257-L321(TestBrowserObservationsAreClickable、TestBrowserSessionsAreClickable、TestBrowserPromptsAreClickable)逐一断言这些 href 确实存在。

2. 优先使用连接流:project → session → observation → full detail

Prefer connected flows: project -> session -> observation -> full detail.

这是 Engram Dashboard 关联导航的黄金链路,在 URL 结构上体现得尤为清晰(这也是 SKILL 中"connected navigation"的核心实现):

  • 项目卡片 →/dashboard/projects/{project}(ProjectDetailPage);
  • 项目详情页内通过#project-tabs三个子标签继续下钻到该项目的 observations / sessions / prompts;
  • Session 行 →/dashboard/sessions/{project}/{sessionID}(SessionDetailPage),页面展示会话元数据 + 该会话内的 observations 与 prompts;
  • Observation 卡片 →/dashboard/observations/{project}/{sessionID}/{syncID}(ObservationDetailPage),详情页除完整内容外,还带LINKED SESSION面板与"More from this Session"相关列表。

值得注意的细节:observation/prompt 详情 URL 使用syncID而非纯数据库自增 ID,测试TestObservationDetailURLUsesSyncID(dashboard_test.go#L1907)与TestPromptDetailURLUsesSyncID(dashboard_test.go#L1947)专门守护这一约定,确保详情地址与同步合同保持一致。

3. 空状态必须说明缺什么、以及什么能解锁数据

Empty states must explain what is missing and what unlocks data.

EmptyState是 Dashboard 的共享组件(components.templ#L41-L48),渲染NO SIGNAL YET小标题 + 主标题 + 说明文案,配合 styles.css#L856-L871 的居中空状态样式。它在整个界面中大量复用,并且文案始终在回答"缺什么 / 怎么解锁":

  • 首页无同步项目时:"Project metrics will show up here after the first successful sync."——明确指出数据从首次同步解锁;
  • 无匹配的 observation:"No observations match the current project, search text, or type filter."——指出是过滤条件导致为空;
  • 无托管用户:"Create the first managed user above. Every managed user is deny-by-default and cannot sync any project until an admin grants one explicitly."——既说明缺什么,也说明解锁路径(管理员显式授权项目);
  • 无项目授权:"This user is deny-by-default: it cannot sync any project until an admin grants one explicitly above."。

4. 指标必须反映真实系统状态,而不是装饰性计数器

Metrics must reflect real system state, not decorative counters.

首页指标条由DashboardStatsPartial(components.templ#L146-L222)渲染,四个指标卡(Sessions / Observations / Prompts / Projects Synced)全部来自cloudstore.DashboardProjectRow的真实聚合值,汇总函数totalStatSessions、totalStatObservations、totalStatPrompts定义在 helpers.go#L207-L233。每个指标卡同时是stat-card-link,点击直接跳转到对应的过滤视图——指标不仅"真实",还承担导航职责。

Admin 侧同样如此:AdminPage与AdminHealthPage展示的 DB 连接状态、Contributors、Sessions、Observations、Prompts、Projects、Paused Projects 均来自DashboardSystemHealth读模型(components.templ#L755-L802),其中数据库连接直接渲染Connected / Disconnected徽章。

5. 详情页应展示元数据、内容与下一步相关链接

Detail pages should show metadata, content, and the next relevant links.

ObservationDetailPage是标准范本:元数据表(Chunk ID / Session / Created / Tool / Topic Key)→CONTENT区块(结构化内容渲染)→LINKED SESSION面板 →More from this Session相关列表。PromptDetailPage(components.templ#L423-L461)同样在元数据后追加LINKED SESSION与"Other Prompts from this Session"。SessionDetailPage则在会话元数据(Session ID / Project / Directory / Started / Ended / Summary)之外,下钻展示该会话的 Observations 与 Prompts 两组列表。

结构化内容渲染逻辑在 helpers.go#L343-L492:自动识别**What/Why/Where/Learned**结构字段或##标题分节,转成structured-block区块;列表预览则通过renderInlineStructuredPreview压成单行摘要。

组合规则:什么时候用什么元素

原文档给出四条组合规则,配合DashboardStore接口(dashboard.go#L59-L96)能看清每种元素的适用场景:

  1. 指标用于定位,而不是替代核心内容:metric-strip/stat-card只承担概览与导航(点击后进入真实内容页),详情本身由 card / table / detail 承载;
  2. 可浏览实体用卡片,密集对比的管理数据用表格:observations 与 prompts 用.card列表(有标题、预览、时间戳 footer);而 sessions、contributors、admin projects、managed users、audit log 等"密集行数据"统一用.data-table(styles.css#L819-L848),会话表还包在.table-scroll中应对横向溢出(测试TestSessionsTableWrappedInScrollContainer守护);
  3. 避免嵌套框架框:数据面板使用.data-frame/.browser-content-frame单层边框,.structured-block仅用于表达内容内部层级;
  4. 操作控件要紧贴其作用的实体:项目同步开关直接放在项目行内(AdminProjectsPage的switch-form,components.templ#L807-L882),启用/禁用按钮紧挨目标项目;托管用户的 Enable/Disable、Revoke 按钮同样各自贴在所属行内。

关联导航的工程化:分页与局部刷新

导航不止是链接,还包括列表翻页体验。Pagination结构(helpers.go#L33-L38)提供Offset/HasPrev/HasNext/ShowPagination/Start/End/PageNumbers全套能力,parsePagination负责把?page=&pageSize=参数钳制在合法范围:默认每页 10 条、最小 10、最大 100,UI 提供{10, 25, 50, 100}四种档位(helpers.go#L21-L30)。

两种分页条分工明确:

  • PaginationBar(components.templ#L53-L86):完整页面跳转,paginationURL保留现有查询参数(project / q / type 等);
  • HtmxPaginationBar(components.templ#L92-L125):以hx-get向指定 endpoint 发起局部请求,hx-target指向内容容器、hx-include携带现有筛选条件,翻页不刷新整页。注释特别强调 URL 使用?page=而非&page=以避免产生畸形的?&URL。

对应测试TestBrowserPaginationHonorsPageParam、TestBrowserPaginationBeyondTotalClampsToLastPage、TestBrowserPartialRendersPaginationBar(dashboard_test.go)覆盖了页码越界钳制与局部刷新渲染。

核心不变式:UI 不能撒谎

skills/ui-elements/SKILL.md 的精神内核在 docs/codebase/dashboard.md#L45-L47 中被总结为一条硬性架构约束:

The UI cannot lie. If it shows "sync paused", every push path must be blocked server-side.

落实到实现上:

  • 项目卡片上的Paused徽章(ProjectsListPartial)读取的是cloudstore.ProjectSyncControl.SyncEnabled,而真正的执行阻断在cloudserver/cloudstore层(如POST /sync/push、POST /sync/mutations/push的服务器端策略),不是 templ/HTMX 里的摆设;
  • Admin 项目控制页(AdminProjectsPage)的每个开关都 POST 到/dashboard/admin/projects/{project}/sync,由 cloudserver 强制执行并审计;
  • 托管用户(managed users)页面的所有变更表单(create / enable / disable / tokens / grants)也全部指向 cloudserver 拥有的路由,dashboard包只渲染状态与结果、绝不自行决定授权(见 dashboard.go#L98-L108 的ManagedUsersStore只读边界注释);
  • 非管理员访问 Admin 面返回 403(AdminForbidden),测试TestAdminProjectsRequires403ForNonAdmin、TestAdminUsersRequires403ForNonAdmin等一整套 403 用例守护此不变式。

视觉系统:TUI 对齐的设计令牌

static/styles.css 顶部定义了与 TUI 视觉对齐的 CSS 变量:--engram-base: #191724、--engram-surface: #1f1d2e、--engram-primary: #c4a7e7、--engram-success: #9ccfd8、--engram-warning: #f6c177、--engram-danger: #eb6f92等(styles.css#L3-L20)。语义化徽章(StatusBadge)据此着色:decision/architecture → success、bugfix → danger、discovery/learning → warning(helpers.go#L571-L583),头部与按钮使用等宽显示字体族营造终端气质,section-kicker的大写字母间距排版用于区分层级。设计一个"看起来属于 Engram"的新组件,应当复用这些令牌而不是另起一套色板。

用测试守护这套规范

internal/cloud/dashboard/dashboard_test.go是这套 UI 规范最完整的"验收清单",值得在新增组件时对照阅读:

  • 可点击性:TestContributorDetailPageRendersDrillDown、TestBrowserObservationsAreClickable、TestDashboardHomeStatCardsAreClickable(断言 metric-card 必须包在<a>中且 href 指向有意义的钻取视图);
  • URL 约定:TestObservationDetailURLUsesSyncID、TestPromptDetailURLUsesSyncID、TestObservationCardHrefIsNotMalformed;
  • HTMX 接线:TestMountAddsHTMXNavigationWiringForBrowserProjectsAndAdmin、TestDashboardHomeHTMXWiring、TestBrowserPageHTMXWiring、TestProjectsPageHTMXWiring、TestMountHTMXAndProjectDetailParity;
  • 空状态与降级:TestMountStoreErrorsReturnDegradedNon200Responses(store 出错时 htmx 路由返回独立 503 片段而非整页);
  • 管理权限:一整套 403 用例,以及TestAdminSyncToggleHTMXPostIncludesFormFields(HTMX 表单必须携带enabled字段)。

这些测试把"每条列表项通向有用之处""指标反映真实状态""详情页带元数据与相关链接"等抽象规则,翻译成了可断言的机器行为——这正是 Engram UI 元素规范能长期不被架空的根本原因。后续新增页面或 partial 时,遵循本文的规则,并参照TestMount...系列测试补齐路由、认证、HTMX partial 与边缘用例即可。

  • 人工智能
  • AI Agent
  • Agent记忆
  • MCP服务

【免费下载链接】engram

Persistent memory system for AI coding agents. Agent-agnostic Go binary with SQLite + FTS5, MCP server, HTTP API, CLI, and TUI.

项目地址:https://gitcode.com/gh_mirrors/engra/engram
点击查看免费下载
上一篇:WXT 国际化(I18n)完全指南:从原生 browser.i18n 到 @wxt-dev/i18n 的类型安全方案
下一篇:XGP存档提取终极指南:简单三步实现游戏进度无损迁移

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询