[优化] go 引用调整

This commit is contained in:
ryan
2026-06-06 10:26:20 +08:00
parent ee1110b752
commit 3cfefb4367
552 changed files with 1642 additions and 2185 deletions
+6
View File
@@ -0,0 +1,6 @@
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
+76
View File
@@ -0,0 +1,76 @@
const dateTimeFormatter = new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
});
const relativeTimeFormatter = new Intl.RelativeTimeFormat('zh-CN', {
numeric: 'auto',
});
function toDate(value: string | Date | null | undefined) {
if (!value) {
return null;
}
const normalizedValue =
typeof value === 'string' ? value.replace(' ', 'T') : value;
const date =
normalizedValue instanceof Date
? normalizedValue
: new Date(normalizedValue);
return Number.isNaN(date.getTime()) ? null : date;
}
export function formatDateTime(value: string | Date | null | undefined) {
const date = toDate(value);
if (!date) {
return '—';
}
return dateTimeFormatter.format(date).replace(/\//g, '-');
}
export function formatRelativeTime(value: string | Date | null | undefined) {
const date = toDate(value);
if (!date) {
return '—';
}
const diffMs = date.getTime() - Date.now();
const diffSeconds = Math.round(diffMs / 1000);
const absSeconds = Math.abs(diffSeconds);
if (absSeconds < 60) {
return relativeTimeFormatter.format(diffSeconds, 'second');
}
const diffMinutes = Math.round(diffSeconds / 60);
if (Math.abs(diffMinutes) < 60) {
return relativeTimeFormatter.format(diffMinutes, 'minute');
}
const diffHours = Math.round(diffMinutes / 60);
if (Math.abs(diffHours) < 24) {
return relativeTimeFormatter.format(diffHours, 'hour');
}
const diffDays = Math.round(diffHours / 24);
if (Math.abs(diffDays) < 30) {
return relativeTimeFormatter.format(diffDays, 'day');
}
const diffMonths = Math.round(diffDays / 30);
if (Math.abs(diffMonths) < 12) {
return relativeTimeFormatter.format(diffMonths, 'month');
}
const diffYears = Math.round(diffMonths / 12);
return relativeTimeFormatter.format(diffYears, 'year');
}
+83
View File
@@ -0,0 +1,83 @@
const compactNumberFormatter = new Intl.NumberFormat('zh-CN', {
maximumFractionDigits: 1,
});
type FormatBytesOptions = {
emptyText?: string;
zeroText?: string;
};
export function formatCompactNumber(value?: number | null) {
if (value === undefined || value === null || Number.isNaN(value)) {
return '—';
}
return compactNumberFormatter.format(value);
}
export function formatPercent(value?: number | null) {
if (value === undefined || value === null || Number.isNaN(value)) {
return '—';
}
return `${formatCompactNumber(value)}%`;
}
export function formatBytes(
value?: number | null,
options: FormatBytesOptions = {},
) {
const { emptyText = '—', zeroText = '0 B' } = options;
if (value === undefined || value === null || Number.isNaN(value)) {
return emptyText;
}
if (value <= 0) {
return zeroText;
}
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let current = value;
let index = 0;
while (current >= 1024 && index < units.length - 1) {
current /= 1024;
index += 1;
}
const digits = current >= 100 || index === 0 ? 0 : 1;
return `${new Intl.NumberFormat('zh-CN', {
maximumFractionDigits: digits,
minimumFractionDigits: 0,
}).format(current)} ${units[index]}`;
}
export function formatBytesPerSecond(
value?: number | null,
windowSeconds = 1,
options?: FormatBytesOptions,
) {
if (value === undefined || value === null || Number.isNaN(value)) {
return options?.emptyText ?? '—';
}
if (windowSeconds <= 0) {
return options?.emptyText ?? '—';
}
return `${formatBytes(value / windowSeconds, options)}/s`;
}
export function calculateNiceAxisMax(values: number[]) {
const rawMax = Math.max(
0,
...values.map((value) => (Number.isFinite(value) && value > 0 ? value : 0)),
);
if (rawMax <= 0) {
return 1;
}
const paddedMax = rawMax * 1.1;
const magnitude = 10 ** Math.floor(Math.log10(paddedMax));
const normalized = paddedMax / magnitude;
const steps = [1, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10];
const niceStep = steps.find((step) => normalized <= step) ?? 10;
return niceStep * magnitude;
}
@@ -0,0 +1,65 @@
import {dashboardNavigation} from '@/lib/constants/navigation';
import type {NavigationItem} from '@/types/navigation';
const navigationPathAliases: Record<string, string> = {
'/apply-log': '/node',
};
function normalizeNavigationPath(pathname: string) {
return navigationPathAliases[pathname] ?? pathname;
}
export function isPathActive(pathname: string, href: string) {
const normalizedPathname = normalizeNavigationPath(pathname);
if (href === '/') {
return normalizedPathname === '/';
}
return (
normalizedPathname === href || normalizedPathname.startsWith(`${href}/`)
);
}
export function isNavigationItemActive(
pathname: string,
item: NavigationItem,
): boolean {
return (
isPathActive(pathname, item.href) ||
item.children?.some((child) => isNavigationItemActive(pathname, child)) ||
false
);
}
export function flattenNavigationItems(
items: NavigationItem[],
): NavigationItem[] {
return items.flatMap((item) => [
item,
...(item.children ? flattenNavigationItems(item.children) : []),
]);
}
export function getCurrentNavigationItem(
pathname: string,
): NavigationItem | undefined {
const findMatch = (items: NavigationItem[]): NavigationItem | undefined => {
for (const item of items) {
if (item.children) {
const childMatch = findMatch(item.children);
if (childMatch) {
return childMatch;
}
}
if (isPathActive(pathname, item.href)) {
return item;
}
}
return undefined;
};
return findMatch(dashboardNavigation);
}