Refresh the interface and clarify usage records

Adopt a white theme, add home-page shortcuts, and show usage metrics with color-coded details, automatic units, and explicit estimated-cost coverage. Update the README screenshots.
This commit is contained in:
lzt404 committed 2026-10-04 17:31:52 +08:00
1 parent 90364e91b4
commit d6bb29f79f
29 files changed
+954 -67

No files matched your search

+15 -11
View File
@@ -3,20 +3,24 @@ const assert = require('node:assert/strict');
const path = require('node:path');
(async () => {
const { createServer } = await import('vite');
const react = (await import('@vitejs/plugin-react')).default;
const root = path.resolve(__dirname, '..');
const server = await createServer({ configFile: false, root, plugins: [react()], logLevel: 'error', server: { host: '127.0.0.1', port: 1421, strictPort: false } });
let browser;
let server;
let base = 'http://127.0.0.1:1420/';
try {
const response = await fetch(base);
if (!response.ok) throw new Error(String(response.status));
} catch {
const { createServer } = await import('vite');
const react = (await import('@vitejs/plugin-react')).default;
const root = path.resolve(__dirname, '..');
server = await createServer({ configFile: false, root, plugins: [react()], logLevel: 'error', server: { host: '127.0.0.1', port: 1421, strictPort: false } });
await server.listen();
const address = server.httpServer.address();
const base = `http://127.0.0.1:${typeof address === 'object' && address ? address.port : 1421}/`;
const response = await fetch(base);
assert.equal(response.ok, true, `Vite server failed at ${base}`);
await response.text();
base = `http://127.0.0.1:${typeof address === 'object' && address ? address.port : 1421}/`;
}
let browser;
try {
const channel = process.env.PLAYWRIGHT_CHANNEL || (process.platform === 'win32' ? 'msedge' : undefined);
browser = await chromium.launch(channel ? { channel, headless: true } : { headless: true });
browser = await chromium.launch(channel ? { channel, headless: true, args: ['--no-proxy-server'] } : { headless: true, args: ['--no-proxy-server'] });
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
await page.goto(`${base}?mock=running`, { waitUntil: 'commit' });
await page.locator('.app-shell').waitFor();
@@ -68,7 +72,7 @@ const path = require('node:path');
console.log('PASS: page hierarchy, tabs, contextual filters, modal focus and compact shell.');
} finally {
if (browser) await browser.close();
await server.close();
if (server) await server.close();
}
})().catch((error) => {
console.error(error);
+1 -1
View File
@@ -26,7 +26,7 @@ const base = 'http://127.0.0.1:1421';
assert.equal(statInfo1213.cardCount, 6, 'There are 6 stat cards');
assert.equal(statInfo1213.cardRows, 1, 'At 1213px width, all 6 cards fit into a single row');
assert.equal(statInfo1213.metaCount, 0, 'Stat cards have no meta subtext displayed');
assert.equal(statInfo1213.metaCount, 6, 'Each stat card shows its supporting detail');
assert.ok(!statInfo1213.tpsValue.includes('TPS'), `TPS value should not contain TPS unit: ${statInfo1213.tpsValue}`);
assert.ok(/^\d+(\.\d+)?$/.test(statInfo1213.tpsValue), `TPS value should be numeric: ${statInfo1213.tpsValue}`);
+15 -3
View File
@@ -1,12 +1,24 @@
import { describe, expect, test } from 'bun:test';
import { formatUsageNumber } from '../src/services/usageNumber';
import { formatDuration, formatUsageNumber } from '../src/services/usageNumber';
describe('使用统计数量单位', () => {
test('百万以下保持普通数字格式', () => {
expect(formatUsageNumber(999_999, 'en-US')).toBe('999,999');
test('按数量级自动切换 K、M、B', () => {
expect(formatUsageNumber(999, 'en-US')).toBe('999');
expect(formatUsageNumber(1_000, 'en-US')).toBe('1K');
expect(formatUsageNumber(132_000, 'en-US')).toBe('132K');
expect(formatUsageNumber(486_500, 'en-US')).toBe('486.5K');
expect(formatUsageNumber(999_949, 'en-US')).toBe('999.9K');
expect(formatUsageNumber(999_950, 'en-US')).toBe('1M');
expect(formatUsageNumber(Number.NaN, 'en-US')).toBe('0');
});
test('延迟在毫秒和秒之间自动切换', () => {
expect(formatDuration(842, 'en-US')).toBe('842 ms');
expect(formatDuration(1_284, 'en-US')).toBe('1.28 s');
expect(formatDuration(12_840, 'en-US')).toBe('12.8 s');
expect(formatDuration(Number.NaN, 'en-US')).toBe('0 ms');
});
test('百万级使用 M 并在达到阈值时自动切换为 B', () => {
expect(formatUsageNumber(1_000_000, 'en-US')).toBe('1M');
expect(formatUsageNumber(12_340_000, 'en-US')).toBe('12.3M');