fix: render workbench time from yaml config
This commit is contained in:
+3
-1
@@ -346,7 +346,9 @@ lanes:
|
||||
- internal/dev-entrypoint/cloud-web-routes.mjs
|
||||
- tools/src/hwlab-cli/trace-renderer.ts
|
||||
env:
|
||||
TZ: Asia/Shanghai
|
||||
HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE: Asia/Shanghai
|
||||
HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE: zh-CN
|
||||
HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL: 北京时间
|
||||
observable: true
|
||||
hwlab-gateway:
|
||||
runtimeKind: bun-command
|
||||
|
||||
@@ -125,12 +125,45 @@ function injectCloudWebRuntimeConfig(body) {
|
||||
}
|
||||
|
||||
function runtimeConfigFromEnv() {
|
||||
const config = {};
|
||||
const config = { displayTime: displayTimeConfigFromEnv() };
|
||||
const workbench = workbenchRuntimeConfigFromEnv();
|
||||
if (workbench) config.workbench = workbench;
|
||||
return config;
|
||||
}
|
||||
|
||||
function displayTimeConfigFromEnv() {
|
||||
const timeZone = requiredRuntimeConfigEnv("HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE");
|
||||
const locale = requiredRuntimeConfigEnv("HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE");
|
||||
const label = requiredRuntimeConfigEnv("HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL");
|
||||
validateDisplayTimeZone(timeZone);
|
||||
validateDisplayLocale(locale);
|
||||
return { timeZone, locale, label };
|
||||
}
|
||||
|
||||
function requiredRuntimeConfigEnv(name) {
|
||||
const value = process.env[name];
|
||||
if (typeof value !== "string" || value.trim().length === 0) {
|
||||
throw new Error(`missing required Cloud Web runtime config env: ${name}`);
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
function validateDisplayTimeZone(timeZone) {
|
||||
try {
|
||||
new Intl.DateTimeFormat("en-US", { timeZone }).format(new Date(0));
|
||||
} catch {
|
||||
throw new Error(`invalid HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE: ${timeZone}`);
|
||||
}
|
||||
}
|
||||
|
||||
function validateDisplayLocale(locale) {
|
||||
try {
|
||||
new Intl.DateTimeFormat(locale).format(new Date(0));
|
||||
} catch {
|
||||
throw new Error(`invalid HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE: ${locale}`);
|
||||
}
|
||||
}
|
||||
|
||||
function workbenchRuntimeConfigFromEnv() {
|
||||
const traceTimeline = {};
|
||||
const autoExpandRunning = parseEnvBoolean(process.env.HWLAB_WORKBENCH_TRACE_AUTO_EXPAND_RUNNING);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { computed, ref } from "vue";
|
||||
import { useWorkbenchStore } from "@/stores/workbench";
|
||||
import { useClipboard } from "@/composables/useClipboard";
|
||||
import LoadingState from "@/components/common/LoadingState.vue";
|
||||
import { formatDisplayDateTime } from "@/config/runtime";
|
||||
import { workbenchSessionPath } from "@/utils";
|
||||
|
||||
const workbench = useWorkbenchStore();
|
||||
@@ -91,7 +92,7 @@ function formatSessionUpdatedTime(value: string | null | undefined): string {
|
||||
if (delta < 3_600_000) return `${Math.max(1, Math.round(delta / 60_000))} 分`;
|
||||
if (delta < 86_400_000) return `${Math.max(1, Math.round(delta / 3_600_000))} 时`;
|
||||
if (delta < 604_800_000) return `${Math.max(1, Math.round(delta / 86_400_000))} 天`;
|
||||
return date.toLocaleString(undefined, { month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
||||
return formatDisplayDateTime(date, { month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,5 +1,55 @@
|
||||
import type { WorkbenchTraceTimelinePolicy } from "@/components/workbench/trace-lifecycle";
|
||||
|
||||
export interface DisplayTimeConfig {
|
||||
timeZone: string;
|
||||
locale: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export function displayTimeConfig(): DisplayTimeConfig {
|
||||
const config = window.HWLAB_CLOUD_WEB_CONFIG?.displayTime;
|
||||
const timeZone = requiredDisplayTimeField(config?.timeZone, "timeZone");
|
||||
const locale = requiredDisplayTimeField(config?.locale, "locale");
|
||||
const label = requiredDisplayTimeField(config?.label, "label");
|
||||
validateDisplayTimeZone(timeZone);
|
||||
validateDisplayLocale(locale);
|
||||
return { timeZone, locale, label };
|
||||
}
|
||||
|
||||
export function displayTimeLabel(): string {
|
||||
return displayTimeConfig().label;
|
||||
}
|
||||
|
||||
export function formatDisplayDateTime(value: string | Date, options: Intl.DateTimeFormatOptions = {}): string {
|
||||
const date = value instanceof Date ? value : new Date(value);
|
||||
if (!Number.isFinite(date.getTime())) return String(value);
|
||||
const config = displayTimeConfig();
|
||||
return new Intl.DateTimeFormat(config.locale, { hour12: false, ...options, timeZone: config.timeZone }).format(date);
|
||||
}
|
||||
|
||||
function requiredDisplayTimeField(value: unknown, field: string): string {
|
||||
if (typeof value !== "string" || value.trim().length === 0) {
|
||||
throw new Error(`HWLAB Cloud Web displayTime.${field} is required`);
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
function validateDisplayTimeZone(timeZone: string): void {
|
||||
try {
|
||||
new Intl.DateTimeFormat("en-US", { timeZone }).format(new Date(0));
|
||||
} catch {
|
||||
throw new Error(`HWLAB Cloud Web displayTime.timeZone is invalid: ${timeZone}`);
|
||||
}
|
||||
}
|
||||
|
||||
function validateDisplayLocale(locale: string): void {
|
||||
try {
|
||||
new Intl.DateTimeFormat(locale).format(new Date(0));
|
||||
} catch {
|
||||
throw new Error(`HWLAB Cloud Web displayTime.locale is invalid: ${locale}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function workbenchTraceTimelinePolicy(): WorkbenchTraceTimelinePolicy {
|
||||
const config = window.HWLAB_CLOUD_WEB_CONFIG?.workbench?.traceTimeline;
|
||||
return {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { displayTimeLabel, formatDisplayDateTime } from "@/config/runtime";
|
||||
import type { ApiResult, HwpodNodeOpsResponse, HwpodSpecsResponse, LiveProbePayload, LiveSurface, Tone } from "@/types";
|
||||
import { asRecord, firstNonEmptyString, statusTone } from "@/utils";
|
||||
|
||||
@@ -148,7 +149,7 @@ export function formatTimestamp(value: unknown): string {
|
||||
if (!text) return "未观测";
|
||||
const date = new Date(text);
|
||||
if (!Number.isFinite(date.getTime())) return text;
|
||||
return date.toLocaleString("zh-CN", { hour12: false, timeZone: "Asia/Shanghai" });
|
||||
return formatDisplayDateTime(date, { hour12: false });
|
||||
}
|
||||
|
||||
export function shortToken(value: unknown, size = 12): string | null {
|
||||
@@ -224,7 +225,7 @@ function rowFromLiveHealth(payload: LiveProbePayload | null): BuildRow {
|
||||
}
|
||||
|
||||
function latestBuildText(row: BuildRow): string {
|
||||
const time = row.builtAt ? `${formatTimestamp(row.builtAt)} 北京时间` : "构建时间不可用";
|
||||
const time = row.builtAt ? `${formatTimestamp(row.builtAt)} ${displayTimeLabel()}` : "构建时间不可用";
|
||||
return `最新镜像构建时间:${time} · ${row.label} · tag ${row.tag ?? "unknown"} · commit ${row.commitShort ?? "unknown"} · env ${row.envImageTag ?? row.envCommitShort ?? "unknown"} · revision ${row.revisionShort ?? "unknown"}`;
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -2,6 +2,11 @@ declare global {
|
||||
interface Window {
|
||||
HWLAB_CLOUD_WEB_CONFIG?: {
|
||||
auth?: { mode?: "auto" | "manual"; username?: string; password?: string };
|
||||
displayTime?: {
|
||||
timeZone?: string;
|
||||
locale?: string;
|
||||
label?: string;
|
||||
};
|
||||
workbench?: {
|
||||
traceTimeline?: {
|
||||
autoExpandRunning?: boolean;
|
||||
|
||||
Reference in New Issue
Block a user