Bytebase 时间戳显示设计:工作队列 vs 历史视图的展示规范
【免费下载链接】bytebaseDatabase governance built for humans and agents — controlling changes and access across every major database.项目地址: https://gitcode.com/GitHub_Trending/by/bytebase
本文系统梳理 Bytebase 前端的时间戳显示设计文档(docs/design/timestamp-display.md)——该文档定义了一条贯穿全产品的核心原则:一个界面要么是工作队列(Work Queue),要么是历史视图(History View),这一分类直接决定它的时间展示方式。工作队列采用 GitHub 风格的相对时间(30 天上限),历史视图始终显示绝对日期时间,而面向未来的“操作时间”(计划发布、到期时间)则强制显示带显式时区的绝对时间。读完本文,你将理解这一设计决策的完整推演过程、全站调用点分类清单、各模式的渲染规范与实现形态,并能直接对照 HumanizeTs.tsx 等源码继续深入。
背景与问题:HumanizeTs的“永久相对化”
Bytebase 产品中规范的时间戳组件是HumanizeTs(frontend/src/components/HumanizeTs.tsx),它支撑着 issue 列表、plan 列表以及十余个其他界面。当前实现是相对时间永无止境:从"45 seconds ago"一路走到"12 minutes ago"→"7 hours ago"→"N days ago",没有任何上限。一份一年前的 issue 会显示为"365 days ago"——对审计阅读而言,这个字符串携带的有效信息量几乎为零,无法与事件时间窗、changelog 条目或外部审计请求做关联。
绝对时间只存在于 hover 提示(tooltip)中,且只能逐行恢复。而产品其余部分并非一个统一的反例模型,而是“大杂烩”:
- 审计日志和少数详情视图渲染完整的绝对日期时间;
- 若干界面手工拼接固定、非 locale 感知的字符串(下文“现状清点”给出全部调用点)。
该设计文档由两个真实用户反馈驱动:
- BYT-10140:相对时间戳("x days ago")恰恰隐藏了审计阅读所需的精确性;
- BYT-10023:一位客户为当晚的生产发布排期时,无人能从产品上判断排期使用的是哪个时区——两个猜测(UTC+0 与服务器时区)都是错的(实际是操作者浏览器时区),若按 UTC+0 执行将提前 7 小时触发发布。
核心原则:工作队列 vs 历史视图
文档落地的原则是一句话:
A surface is either a work queue or a history view, and that classification decides its time display.
| 界面类型 | 阅读目的 | 首要时间问题 | 显示方式 |
|---|---|---|---|
| 工作队列(Work queue) | 决定现在需要处理什么 | 新鲜度(freshness) | GitHub 风格相对时间 + 30 天上限,之后切换为绝对日期 |
| 历史视图(History view) | 作为已经发生的事件的记录 | 精确时间(exactly when) | 始终显示绝对日期时间 |
既不是队列也不是记录的界面(活动流、"created N ago"元信息、同步新鲜度、Agent 聊天)属于新鲜度优先阅读,沿用工作队列的渲染方式。
在“队列/历史”二分法之外还存在第三类时间:
- 操作时间(Operational time)——计划发布(scheduled rollout)或到期时间(expiration),阅读目的是采取行动:"这到底会在何时触发或失效"。显示方式:带显式时区的绝对日期时间,绝不只显示相对时间。相对措辞("in 7 hours")会隐藏时区问题的存在——这正是 BYT-10023 事故的证据。
范围界定:本文只讨论显示(frontend display),不涉及后端、API 或存储偏好;时间输入(排期与到期 picker)明确不在当前范围内。
竞品研究:成熟产品按“阅读模式”而非全局约定选择显示方式
文档对主流产品的默认显示、切换机制、逃生通道(escape hatch)和用户设置做了横向对比(✔ 表示 2026-08-26 已对一手来源核实):
| 产品/界面 | 界面类型 | 默认显示 | 切换机制 | 逃生通道 | 用户设置 |
|---|---|---|---|---|---|
| GitHubissues/PRs/commits ✔ | 工作队列/流 | 相对("3 days ago") | 30 天后→绝对仅日期(同一年省略年份) | Tooltip:完整日期时间 | 无 |
| GitLab✔ | 工作队列/流 | 处处相对 | 无 | Tooltip | 按用户的"Use relative times"开关 + 12/24 小时制 |
| Linearissue 列表 | 工作队列 | 紧凑相对("3d") | 无 | Tooltip | 无 |
| Jiraissue 视图 | 工作队列 | 近期相对 | 旧条目绝对 | Tooltip | 无 |
| Slack消息 | 流 | 情境式("Today at 2:31 PM") | 更早的日期显示日期 | Hover | 12/24 小时制 |
| Sentryissue 流 | 队列/流 | 相对年龄 | 流内无;详情页为绝对 | 详情页 | 无 |
| Stripe Dashboard支付 | 历史/审计表 | 绝对("Jul 3, 2:35 PM") | — | — | 无 |
| AWS CloudTrail | 审计日志 | 绝对、统一列 | — | — | UTC/local |
| Datadog日志 | 记录/可观测 | 绝对(毫秒精度) | — | — | 时区 |
规律:成熟产品不选择单一全局约定,而是按阅读模式分别选择。队列和流用相对时间(GitHub 额外加了 30 天年龄上限);记录与审计表用绝对、统一、可整列扫描的时间。GitLab 是用“用户偏好”解决的特例——且其默认仍是相对时间,审计读者必须自己发现那个开关。Bytebase 的原则与行业二分一致,但默认就把两边都做对,而不引入设置项。
注意:原始诉求(绝对、始终、带秒)比 GitHub 的模式更强。下述决议(D1–D7)在历史视图上完全满足它;在工作队列上则有意识地为了队列可扫描性(D1)做了取舍。
设计决议 D1–D7
D1 — 机制:队列采用 GitHub 风格的年龄切换,而非绝对始终、也非偏好设置。issue 列表是工作队列,plan 列表也正在成为队列。新鲜度是主导问题,因此上限内的相对时间是正确的。被否决的选项:队列上绝对始终(扼杀新鲜度阅读);GitLab 式用户偏好(设置机制复杂,且未切换者的默认值就是错的);什么都不做("365 days ago"的抱怨是真实存在的)。
D2 — 切换后的绝对形式:仅日期(GitHub 对齐)。"Jul 12, 2026";同年行省略年份("Jul 12")。时间保留在 tooltip 中。优先保证队列密度;接受在队列界面“精确到秒”的诉求只能通过 hover 满足(在历史视图上则完全满足——那个阅读场景才真正需要它)。
D3 — 阈值:30 天(GitHub 对齐)。与 GitHub 完全一致,并且匹配现有常量RELATIVE_THRESHOLD_MS = 30d(源码见 frontend/src/utils/datetime.ts)。接受后果:年龄 1–29 天的队列行仍显示"x days ago"。否决了 24 小时与 7 天阈值(能更早消除被抱怨的字符串,但偏离用户熟悉的 GitHub 行为)。
D4 — 范围:全站切换 + 历史视图豁免。HumanizeTs自身获得 30 天切换,因此每个新鲜度优先界面都呈现 GitHub 风格。历史视图——数据库 changelog、revision 表、task-run 历史——切换为始终绝对日期时间,与审计日志保持一致:它们是执行的记录,不是队列。
D5(提案)— 操作时间:绝对 + 显式时区,分钟精度。计划发布与到期时间的墙钟渲染显示带短时区名的绝对日期时间:"Sep 15, 2026, 9:00 AM GMT+8"。评审后的两个细化:(a) 预设写出的到期时间(now() + N days)带有真实的亚分钟尾巴,分钟显示会将强制截止时间向下取整 ≤59 秒——处于安全方向,精确值在 D6 tooltip 中;备选方案是为到期保留秒,或归一化预设写入(写路径改动,超出范围)。(b) 规则只针对墙钟字符串——纯倒计时("expires in 3h20m")跨时区不会被误读,仍允许保留(配合 D6 tooltip)。由 BYT-10023 驱动,处于提案待确认状态;写入这些值的 picker 被推迟。
D6 — 每个缩减显示的完整日期时间 tooltip。任何未显示完整形式的时间戳——相对时间、切换后的仅日期、或紧凑历史层级——都在 tooltip 中携带带秒和时区的完整绝对日期时间。这是通用的逃生通道,保证每个缩减单元格都可恢复。推论:无法承载 tooltip 的上下文——i18n 插值字符串、导出、标题——本身必须携带完整精度字符串。
D7(提案)— 历史视图携带两个精度层级。历史行用于定位;历史记录用于见证。当时间本身就是证据时用完整精度(秒 + 时区,formatAbsoluteDateTime):审计日志(可导出,且导出必须在不低于屏幕的精度下保留同一时刻——导出写 RFC 3339 UTC 而屏幕显示浏览器本地时间;等价性指时刻 + 精度而非字符串同一性)与单条记录详情视图。当行被扫描以在某个资源的历史中定位记录时用紧凑精度(日期 + hh:mm,无秒、无时区):嵌入式列表——宽度被争用,D6 保证完整精度一次 hover 即可获得。客观划分线:可作为证据导出或详情视图 → 完整;可扫描的嵌入式列表 → 紧凑。
全站界面分类清单
文档将当前每一个HumanizeTs调用点按上述原则分类(以下文件均可在仓库中直接核对):
| 界面 | 文件 | 分类 | 新显示 |
|---|---|---|---|
| Issue 列表 | components/IssueTable.tsx | 工作队列 | 30d 切换 |
| Plan 列表 | routes/project/ProjectPlanDashboardPage.tsx | 工作队列 | 30d 切换 |
| Release 列表/详情元信息 | routes/project/ProjectReleaseDashboardPage.tsx、ProjectReleaseDetailPage.tsx、components/release/ReleaseInfoCard.tsx(今日为固定字符串——改用HumanizeTs) | 工作队列/元信息 | 30d 切换 |
| Issue 评论与活动 | components/issue-activity/IssueCommentActivity.tsx、routes/project/issue-detail/components/IssueDetailCommentList.tsx | 流 | 30d 切换 |
| 评审时间线/拒绝横幅 | routes/project/plan-detail/components/review/ReviewActivityTimeline.tsx、ReviewRejectionBanner.tsx | 流 | 30d 切换 |
| Plan 详情"created" | routes/project/plan-detail/components/PlanDetailMeta.tsx | 元信息 | 30d 切换 |
| Deploy 当前状态(最近运行时间) | routes/project/plan-detail/components/deploy/DeployTaskHeader.tsx、DeployLatestTaskRunInfo.tsx | 新鲜度 | 30d 切换 |
| 计划发布 pill | DeployTaskHeader.tsx(任务钉住运行时间) | 操作时间 | 绝对 + 时区 |
| Schema 同步状态 | modules/sql-editor/components/SchemaPane/SyncSchemaButton.tsx、routes/project/ProjectSyncSchemaPage.tsx、components/database/DatabaseOverviewInfo.tsx | 新鲜度 | 30d 切换 |
| Agent 聊天 | modules/agent/components/AgentWindow.tsx | 流 | 30d 切换 |
| Plan-check 运行时间 | components/plan-check/PlanCheckSection.tsx(今日为裸toLocaleString()——改用HumanizeTs) | 新鲜度 | 30d 切换 |
| Access-grant 创建时间 | routes/project/ProjectAccessGrantsPage.tsx(AccessGrantRow;今日为完整绝对——改用HumanizeTs)。管理花名册上的创建元信息;该 grant 的操作性事实是它的到期,后者保持操作模式 | 工作队列/元信息 | 30d 切换 |
| 数据库 changelog | routes/project/database-detail/changelog/DatabaseChangelogTable.tsx | 历史视图 | 始终绝对——紧凑层级(D7) |
| 数据库 revisions | routes/project/database-detail/revision/DatabaseRevisionTable.tsx | 历史视图 | 始终绝对——紧凑层级(D7) |
| Task-run 历史 | routes/project/plan-detail/components/deploy/DeployTaskRunHistorySheet.tsx、routes/project/issue-detail/components/IssueDetailTaskRunTable.tsx | 历史视图 | 始终绝对——紧凑层级(D7) |
| 审计日志 | components/AuditLogTable.tsx | 历史视图 | 已是绝对——不变 |
操作时间现状(BYT-10023)与修复
触发第三类时间的事故前文已述:产品行为正确,缺陷在于没有任何可见表面说明适用哪个时区。文档侧已在 bytebase.com#125 修复,本文档覆盖显示侧;picker(输入侧)有意不在本文档设计。
当前操作时间的展示位置与差距:
| 界面 | 文件 | 今日 | 差距 |
|---|---|---|---|
| 计划发布 pill | routes/project/plan-detail/components/deploy/DeployTaskHeader.tsx(任务钉住运行时间) | HumanizeTs——相对("in 7 hours"),时区仅在 tooltip | BYT-10023 显示缺口:唯一显示发布何时触发的界面却完全隐藏了时区问题 |
| Task-run 等待消息 | frontend/src/lib/taskRun.ts("enqueued, will run at …") | i18n 字符串中的formatAbsoluteDateTime | 无——纯字符串上下文,保持完整精度(D6 推论) |
| SQL 编辑器 access grant 项,<24h 剩余 | modules/sql-editor/components/AccessGrantItem.tsx | 仅时长("expires in 3h20m"),无 tooltip | 倒计时保留(D5 范围注);增加 D6 tooltip |
| Access-grant 到期,issue 详情 | routes/project/issue-detail/components/IssueDetailAccessGrantDetails.tsx | 经getAccessGrantExpirationText的formatAbsoluteDateTime,位于 JSX | 今日无;D5 下采用操作模式 |
| Masking 豁免到期 | routes/project/ProjectMaskingExemptionPage.tsx | dayjsYYYY-MM-DD HH:mm | 无时区、无秒、非 locale 感知 |
| 角色授权到期详情 | routes/project/issue-detail/components/IssueDetailRoleGrantDetails.tsx | dayjsLLL | 无时区 |
| 成员到期预览 | routes/workspace/MembersPage.tsx(formatExpirationDate) | i18n 字符串中的toLocaleDateString+ 时/分 | 无时区/秒;纯字符串上下文 → 完整精度字符串(D6 推论) |
| 成员到期表、access grants、IAM 提醒对话框、示例到期、订阅到期 | MembersPage.tsx、ProjectAccessGrantsPage.tsx、utils/accessGrant.ts、IAMRemindDialog.tsx、SampleExpirationAlert.tsx、stores/app/workspace.ts | formatAbsoluteDateTime | 今日无;D5 下 JSX 位置采用操作模式,字符串插值位置(横幅、示例提醒)保持完整精度(D6 推论) |
D5 下的修复:计划发布 pill、masking 豁免到期、角色授权到期统一收敛到操作格式——绝对日期时间 + 时区,分钟精度("Sep 15, 2026, 9:00 AM GMT+8"),相对年龄可移入 tooltip。成员到期预览是 i18n 插值字符串,按纯字符串推论保持完整精度字符串。
当前绝对时间显示现状清点
文档还清点了产品中已存在的三族不一致的绝对时间显示(作为参考基线):
formatAbsoluteDateTime—— locale 感知,秒 + 短时区名("GMT+8")。主导族:审计日志、changelog 详情页、revision 详情面板、access grants、成员到期表、IAM 提醒对话框、示例到期提醒、订阅到期、task-run 排期时间消息、SQL 编辑器结果面板、Monaco 心跳、Agent 聊天 tooltip。- 固定的 dayjs 字符串—— 有时间无时区、非 locale 感知:masking 豁免(
YYYY-MM-DD HH:mm)、角色授权详情(LLL)、SQL 编辑器查询历史行与标签页标题(YYYY-MM-DD HH:mm:ss——HistoryPane.tsx 中的titleOfQueryHistory,加上 SQLEditorRouteShell.tsx 中独立构建的深链标签页标题)、以及嵌入式 release 元信息(components/release/ReleaseInfoCard.tsx,YYYY-MM-DD HH:mm:ss)。 - 临时
toLocale*—— 成员页到期预览(toLocaleDateString+ 时/分,无秒无时区)与 plan-check 运行时间(PlanCheckSection.tsx 中的裸toLocaleString(),locale 默认、无 tooltip)。
该设计还有两个已存在的半成品死代码:utils/util.ts中未被使用的humanizeTs()30 天切换(frontend/src/utils/util.ts),以及IssueDetailTaskRunTable.tsx中从未传过的format="absolute"分支(frontend/src/routes/project/issue-detail/components/IssueDetailTaskRunTable.tsx)。两者都证明这个需求早已被感知;两者都将被新设计吸收。
值得注意,产品当前的模式是列表相对、详情绝对——changelog 详情页与 revision 详情面板已渲染formatAbsoluteDateTime,而其列表视图渲染相对时间。D4 让每个列表与它自己的详情视图一致。
渲染规范
工作队列/新鲜度界面(经HumanizeTs,组件将获得切换):
| 行年龄 | 渲染 | 示例(en) | 示例(zh) |
|---|---|---|---|
| < 10 s | "now" | now | 现在 |
| < 1 min | 相对秒 | 45 seconds ago | 45秒钟前 |
| < 1 h | 相对分钟 | 12 minutes ago | 12分钟前 |
| < 24 h | 相对小时 | 7 hours ago | 7小时前 |
| < 30 d | 相对天数 | 6 days ago | 6天前 |
| ≥ 30 d,同年 | 绝对日期,无年 | Jul 12 | 7月12日 |
| ≥ 30 d,其他年份 | 绝对日期带年 | Jul 12, 2025 | 2025年7月12日 |
- Tooltip(两种形式,契约不变):带秒和时区的完整绝对日期时间——"Aug 26, 2026, 2:03:22 PM GMT+8" / zh "2026年8月26日 14:03:22 GMT+8"。
- 未来时间戳按 |age| 镜像处理(
Intl.RelativeTimeFormat已正确带符号;≥30d 分支显示日期)。 - 所有字符串经
Intl使用活动 i18n locale——无硬编码格式,无需新增 locale key。
历史视图:始终绝对;精度在 D7 下分两个层级(分配为提案):
| 历史视图出现位置 | 空间 | 层级 |
|---|---|---|
| 审计日志(工作区 + 项目页) | 专用页面,可导出 | 完整——保持现状 |
| Changelog 详情页 | 详情视图 | 完整——保持现状 |
| Revision 详情面板 | 详情视图 | 完整——保持现状 |
| 数据库 changelog 列表 | 全宽表格 | 紧凑 |
| 数据库 revision 列表 | 全宽表格 | 紧凑 |
| Task-run 历史 sheet | 704px sheet——空间受限情形 | 紧凑 |
| Issue 详情 task-run 表 | 嵌入式表格 | 紧凑 |
| SQL 编辑器查询历史行(HistoryPane.tsx) | 窄侧栏列表;今日为固定非 localeYYYY-MM-DD HH:mm:ss | 紧凑 |
- 完整=
formatAbsoluteDateTime:"Aug 26, 2026, 2:03:22 PM GMT+8" / zh "2026年8月26日 14:03:22 GMT+8"(约 30 字符)。 - 紧凑= 日期 + hh:mm,locale 感知:"Aug 26, 2026, 2:03 PM" / zh "2026年8月26日 14:03"(约 21 字符)。秒和时区按 D6 一次 hover 即可获得。
Task-run 日志条目(task-run-log/model.ts::formatTime,HH:mm:ss.SSS):保留高密度纯时间格式——父级运行头携带日期——并加上携带完整日期时间的 D6 tooltip(同时覆盖跨午夜运行)。
操作时间(计划发布、到期时间):formatOperationalDateTime——日期 + hh:mm + 短时区名,locale 感知:"Sep 15, 2026, 9:00 AM GMT+8" / zh "2026年9月15日 09:00 GMT+8"。时区位于可见字符串中,因为读者即将基于该值采取行动;按 D5 无秒。相对年龄可随附在 tooltip 中。
实现形态与源码佐证
实现要点:
HumanizeTs获得 30 天切换(逻辑已作为死代码存在——utils/util.ts 中的humanizeTs(),utils/datetime.ts 中的RELATIVE_THRESHOLD_MS/formatAbsoluteDate;在此处合并并删除这对死代码)外加三个绝对模式,每个都内置 D6 tooltip:compact(新增formatCompactDateTime)、datetime(现有formatAbsoluteDateTime)、operational(新增formatOperationalDateTime)。- 逐站点的工作就是上文的清点表:每个列出的调用点采用其所属类的模式;纯字符串上下文按 D6 推论保持完整精度字符串。同时喂养 JSX 与字符串上下文的辅助函数保持为完整精度字符串构建器——其 JSX 消费者改为渲染组件。
- 陈旧性(staleness):任何随时间变化的显示(相对桶、倒计时、
isExpired派生)在挂载期间不得过期;从不随时间变化的显示零成本。机制——共享时钟、节奏、订阅者,整合今日各组件临时的 per-component 定时器——是实现 PR 的设计空间,由渲染期Date.now()扫描与 fake-timer 测试守护。GitHub 的relative-time元素(在下一个边界调度更新)是参考行为。 - 测试:阈值边界(29d/31d)、年份处理、zh locale、三个模式、亚分钟尾到期时的操作标签/tooltip 契约、<24h 倒计时豁免、fake-timer 陈旧性;更新现有断言相对字符串的
*.test.tsx文件。
源码佐证(当前仓库现状):
- frontend/src/components/HumanizeTs.tsx 今日契约:
formatRelativeTime渲染相对标签,formatAbsoluteDateTime在 tooltip 中展示完整日期时间——与文档描述的“相对永远、绝对只存在于 hover”一致。 - frontend/src/utils/datetime.ts 已定义
RELATIVE_THRESHOLD_MS = 30 * 24 * 60 * 60 * 1000(30 天)与DEFAULT_NOW_THRESHOLD_MS = 10_000,formatRelativeTime的桶结构与渲染规范中的表格(<10s / <1min / <1h / <24h / ≥1d)逐项对应;formatAbsoluteDate已实现同年省略年份的逻辑。 - frontend/src/utils/util.ts#L29-L36 中的
humanizeTs()是文档所称的“死代码 30 天切换”——判断diff > RELATIVE_THRESHOLD_MS后转formatAbsoluteDate。 - frontend/src/routes/project/issue-detail/components/IssueDetailTaskRunTable.tsx#L188-L198 存在从未被调用的
format?: "absolute" | "humanized"分支。 - frontend/src/components/HumanizeTs.test.tsx 与 frontend/src/utils/datetime.test.ts 验证了相对/绝对契约与阈值行为(后者含 31 天前的用例);frontend/src/routes/project/plan-detail/components/deploy/DeployTaskHeader.tsx 展示了“计划发布 pill”当前以
HumanizeTs渲染scheduledTimeTs的调用点。
哪些不变
- 审计日志(已正确)。
- 时长显示(
humanizeDurationV1,"4.2s"):时长是已流逝的量,不涉日历或时区问题。 - 30 天以内的相对措辞。
- 无用户或工作区偏好(GitLab 的模式是若客户将来要求时的已知形态)。
- 无后端或 proto 改动。
- 时间picker:BYT-10023 的输入侧,推迟到其自己的设计(文档侧修复已在 bytebase.com#125)。
- 按类型排除范围——有了这些,
frontend/src下每一个dayjs/Intl/toLocale*调用点在本文档中都有处置:SQL 结果单元格值(utils/v1/sql.ts 中的数据本身)、嵌入生成内容中的时间(issue 标题、CEL 描述——重排格式属于数据变更)、导出/下载文件名、以及 picker 值回显/API 线上字符串。
客户成果检查
- 历史工单(> 30 天):issue 列表显示真实日期——对真正久远的历史,投诉已解决。
- Changelog / revisions / task-run 历史:默认绝对日期时间到分钟(紧凑层级,D7);秒与时区一次 hover 即得(D6)。完整秒仍作为证据界面的默认——审计日志与 changelog/revision 详情视图——因此“年月日时分秒”诉求在记录列表上满足到分钟、在记录详情上完全满足。若客户特别坚持可见秒,升级路径是把这些列表切换到完整层级——一行 D7 分配变更,无需模型改动。
- 1–29 天队列行:仍显示"x days ago"(D1/D3 取舍,作为队列阅读被接受)。风险:若被报告的"工单历史"阅读包含近期的 issue 列表行,则部分投诉依然存在。缓解:tooltip;若复发,升级路径是降低阈值(D3)或引入 GitLab 式偏好(D1 暂被否决)。
待裁决的开放事项
自初稿以来已确认:release 列表 = 工作队列;评论/活动时间线 = 流;D6(每个缩减显示上的完整日期时间 tooltip)。仍开放:
- D7 层级分配/格式——嵌入式历史列表用紧凑(日期 + hh:mm)还是完整。changelog 表与 704px task-run sheet 已有两种选项的 mockup;按 orient/testify 原则推荐紧凑。
- D5 精度细化——操作时间用分钟精度(无秒)。Picker 写入分钟,但天/秒计数预设写入
now() + offset且带亚分钟尾巴,因此分钟显示将强制截止时间向下取整 ≤59 秒(安全方向;完整值在 tooltip 中)。备选:到期值保留完整秒,或将预设写入归一化到分钟(写路径变更,超出本范围)。 - 计划发布 pill 内联显示操作格式("Sep 15, 2026, 9:00 AM GMT+8");相对年龄移入 tooltip。
- 裸格式的到期显示在本工作中修复而非作为后续清理单:masking 豁免与角色授权详情采用操作模式;成员预览——i18n 插值字符串——按推论获得完整精度字符串(若此处偏好分钟显示,则做
Trans-slot 重构)。 - 完整单元格上的 tooltip 可以显示相对年龄(反向 tooltip)。备选:重复完整字符串(GitHub 对齐)。
总结:Bytebase 的时间戳显示设计以一个二元分类(工作队列/历史视图)+ 一个操作时间类别为骨架,通过 D1–D7 七项决议把 GitHub 式 30 天切换、历史视图绝对显示、操作时间显式时区落实为可执行的渲染规范与逐站点改造清单。实现上以HumanizeTs组件与 utils/datetime.ts 工具函数为汇聚点,最终达到“队列可扫描、记录可审计、操作不歧义”的产品目标。
【免费下载链接】bytebaseDatabase governance built for humans and agents — controlling changes and access across every major database.项目地址: https://gitcode.com/GitHub_Trending/by/bytebase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考