单值设置从常驻输入框改成 InlineEdit(纯文本加铅笔,Enter 或失焦提交, 失焦无效直接放弃——失焦是「我走了」,不该把人拽回来)。测速地址加恢复 默认按钮;内核参数逐项提交,不再攒一个保存按钮。 资源一节按文件展开:四类 GEO 文件的大小和更新时间由服务端 stat 内核 工作目录得来(GET /api/geo;文件名和大小写不敏感匹配照 constant/ path.go:18-20,193-224),下载地址可改(geox-url,config.go:363-368, 默认值 578-583)。行内的更新按钮仍是全量更新——内核只有这一个口子, 没变化的文件靠内容哈希跳过。 上传拆成两个入口:恢复只认带 Patchbay 标记的文件,导入收任意配置; 新增恢复策略(兼容只搬接管段落 listeners/proxy-groups/rules/ proxy-providers/rule-providers,覆盖整份替换)。平时是按钮,拖着文件 进窗口时整行变成投放区。
45 lines
2.0 KiB
TypeScript
45 lines
2.0 KiB
TypeScript
/**
|
|
* 流量数字显示成人读的样子。连接页和仪表盘共用。
|
|
*
|
|
* 1024 进制。B 一档不带小数;其余不满 100 的保留一位小数,够 100 的取整——
|
|
* 「23.4 MB」有信息量,「234.7 MB」的小数就只是噪音了。
|
|
*/
|
|
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB'] as const
|
|
|
|
export function formatBytes(bytes: number): string {
|
|
if (!Number.isFinite(bytes) || bytes < 0) return '0 B'
|
|
let value = bytes
|
|
let unit = 0
|
|
while (value >= 1024 && unit < UNITS.length - 1) {
|
|
value /= 1024
|
|
unit += 1
|
|
}
|
|
const digits = unit === 0 || value >= 100 ? 0 : 1
|
|
// Number() 去掉无意义的尾零:1.0 KB → 1 KB
|
|
return `${String(Number(value.toFixed(digits)))} ${UNITS[unit]}`
|
|
}
|
|
|
|
/**
|
|
* 一个过去时刻距今多久,「21 分钟前」的形态。now 由调用方传,纯函数才测得了。
|
|
* 超过 30 天相对时间就没有信息量了,直接给日期。
|
|
*/
|
|
export function formatAgo(at: Date, now: Date): string {
|
|
const seconds = Math.max(0, (now.getTime() - at.getTime()) / 1000)
|
|
if (seconds < 60) return '刚刚'
|
|
if (seconds < 3600) return `${String(Math.floor(seconds / 60))} 分钟前`
|
|
if (seconds < 86400) return `${String(Math.floor(seconds / 3600))} 小时前`
|
|
if (seconds < 30 * 86400) return `${String(Math.floor(seconds / 86400))} 天前`
|
|
const p = (n: number) => String(n).padStart(2, '0')
|
|
return `${String(at.getFullYear())}-${p(at.getMonth() + 1)}-${p(at.getDate())}`
|
|
}
|
|
|
|
/** 运行时长。一小时内说分钟,一天内说时分,再长说天和小时;秒级抖动没有信息量。 */
|
|
export function formatUptime(seconds: number): string {
|
|
if (!Number.isFinite(seconds) || seconds < 0) return '—'
|
|
const minutes = Math.floor(seconds / 60)
|
|
if (minutes < 60) return `${String(minutes)} 分钟`
|
|
const hours = Math.floor(minutes / 60)
|
|
if (hours < 24) return `${String(hours)} 小时 ${String(minutes % 60)} 分`
|
|
return `${String(Math.floor(hours / 24))} 天 ${String(hours % 24)} 小时`
|
|
}
|