Compare commits
6 Commits
7cf87a75fe
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| bc6643a6c2 | |||
| ec6b72042e | |||
| 207e242696 | |||
| d74ddf4ba2 | |||
| 31879a511d | |||
| 5240b57c47 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -26,3 +26,8 @@ dist-ssr
|
||||
/.eslintrc-auto-import.json
|
||||
/components.d.ts
|
||||
/examples/auto-imports.d.ts
|
||||
|
||||
/CLAUDE.md
|
||||
/AGENTS.md
|
||||
/.claude
|
||||
|
||||
|
||||
@ -30,8 +30,8 @@ body {
|
||||
width: 100% !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-x: hidden !important;
|
||||
overflow-y: scroll !important;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
font-family: var(--tui-font);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
|
||||
|
||||
@ -69,12 +69,12 @@ export enum ImageType {
|
||||
PIXELATED = "ir-pixelated"
|
||||
}
|
||||
|
||||
export type KeyValue<T> = {
|
||||
key: string;
|
||||
value: T;
|
||||
export type KeyValue<V, K = string> = {
|
||||
key: K;
|
||||
value: V;
|
||||
}
|
||||
|
||||
export type LabelValue<T> = {
|
||||
label: string;
|
||||
value: T;
|
||||
export type LabelValue<L, V = string> = {
|
||||
label: L;
|
||||
value: V;
|
||||
}
|
||||
|
||||
@ -77,4 +77,96 @@ export default class IOSize {
|
||||
}
|
||||
return "0 B";
|
||||
}
|
||||
|
||||
/**
|
||||
* 将格式化的储存量字符串解析为字节量
|
||||
* <p>支持格式:10GB, 10 GB, 1TB, 1.24 KB 等(单位不区分大小写)</p>
|
||||
* <pre>
|
||||
* // 返回 102400
|
||||
* IOSize.parse("100 KB");
|
||||
* // 返回 1073741824
|
||||
* IOSize.parse("1GB");
|
||||
* </pre>
|
||||
*
|
||||
* @param sizeStr 格式化后的储存量字符串
|
||||
* @return 字节量
|
||||
* @throws Error 格式无效
|
||||
*/
|
||||
public static parse(sizeStr: string): number {
|
||||
if (!sizeStr || sizeStr.trim() === "") {
|
||||
throw new Error("not found sizeStr");
|
||||
}
|
||||
// 正则匹配:可选符号 + 数字(含小数点)+ 可选空格 + 单位
|
||||
const pattern = /([-+]?\d+(?:\.\d+)?)\s*([a-zA-Z]+)/;
|
||||
const matcher = pattern.exec(sizeStr.trim());
|
||||
if (matcher) {
|
||||
let value: number;
|
||||
try {
|
||||
value = parseFloat(matcher[1]);
|
||||
} catch (e) {
|
||||
throw new Error("invalid number format: " + matcher[1]);
|
||||
}
|
||||
if (value < 0) {
|
||||
throw new Error("size cannot be negative: " + value);
|
||||
}
|
||||
const unitStr = matcher[2].toUpperCase();
|
||||
let unit: Unit;
|
||||
|
||||
// 先尝试精确匹配枚举
|
||||
if (Object.values(Unit).includes(unitStr as Unit)) {
|
||||
unit = unitStr as Unit;
|
||||
} else {
|
||||
// 处理单字母单位缩写(K/M/G/T/P/E)
|
||||
switch (unitStr.charAt(0)) {
|
||||
case "K":
|
||||
unit = Unit.KB;
|
||||
break;
|
||||
case "M":
|
||||
unit = Unit.MB;
|
||||
break;
|
||||
case "G":
|
||||
unit = Unit.GB;
|
||||
break;
|
||||
case "T":
|
||||
unit = Unit.TB;
|
||||
break;
|
||||
case "P":
|
||||
unit = Unit.PB;
|
||||
break;
|
||||
case "E":
|
||||
unit = Unit.EB;
|
||||
break;
|
||||
case "B":
|
||||
unit = Unit.B;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unknown unit: " + unitStr);
|
||||
}
|
||||
}
|
||||
return IOSize.toBytes(value, unit);
|
||||
}
|
||||
// 尝试解析纯数字(无单位,默认字节)
|
||||
try {
|
||||
const bytes = parseInt(sizeStr.trim());
|
||||
if (bytes < 0) {
|
||||
throw new Error("size cannot be negative: " + bytes);
|
||||
}
|
||||
return bytes;
|
||||
} catch (e) {
|
||||
throw new Error("invalid size format: " + sizeStr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换值到字节量
|
||||
*
|
||||
* @param value 值
|
||||
* @param unit 单位
|
||||
* @return 字节量
|
||||
*/
|
||||
private static toBytes(value: number, unit: Unit): number {
|
||||
const units = Object.values(Unit);
|
||||
const ordinal = units.indexOf(unit);
|
||||
return Math.round(value * Math.pow(1024, ordinal));
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +69,26 @@ export default class Time {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将毫秒值转换为可读的时间字符串
|
||||
*
|
||||
* @param ms 毫秒值
|
||||
* @return 时间字符串,如 "10 天"、"5 小时"、"30 分钟"、"15 秒"、"500 毫秒"
|
||||
*/
|
||||
public static toString(ms: number): string {
|
||||
if (Time.D <= ms) {
|
||||
return `${Math.floor(ms / Time.D)} 天`;
|
||||
} else if (Time.H <= ms) {
|
||||
return `${Math.floor(ms / Time.H)} 小时`;
|
||||
} else if (Time.M <= ms) {
|
||||
return `${Math.floor(ms / Time.M)} 分钟`;
|
||||
} else if (Time.S <= ms) {
|
||||
return `${Math.floor(ms / Time.S)} 秒`;
|
||||
} else {
|
||||
return `${Math.floor(ms)} 毫秒`;
|
||||
}
|
||||
}
|
||||
|
||||
public static between(begin: Date, end?: Date) : any {
|
||||
if (!end) {
|
||||
end = new Date();
|
||||
@ -94,4 +114,58 @@ export default class Time {
|
||||
}
|
||||
return `${minutes.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将时间字符串解析为毫秒值
|
||||
*
|
||||
* <p>支持的格式示例:
|
||||
* <pre>
|
||||
* 10 = 10
|
||||
* 10ms = 10
|
||||
* 10s = 10,000
|
||||
* 10m = 600,000
|
||||
* 10h = 36,000,000
|
||||
* 10d = 10D = 10 d = 864,000,000
|
||||
* 10.5d = 907,200,000
|
||||
* </pre>
|
||||
*
|
||||
* @param timeStr 时间字符串
|
||||
* @return 毫秒
|
||||
* @throws Error 输入格式无效
|
||||
*/
|
||||
public static parseToMS(timeStr: string): number {
|
||||
if (!timeStr || timeStr.trim() === "") {
|
||||
throw new Error("not found timeStr");
|
||||
}
|
||||
const normalized = timeStr.replace(/\s+/g, "").toLowerCase();
|
||||
|
||||
const pattern = /^(\d+(?:\.\d+)?)(ms|[dhms])?$/;
|
||||
const matcher = pattern.exec(normalized);
|
||||
if (!matcher) {
|
||||
throw new Error("invalid format: " + timeStr);
|
||||
}
|
||||
const value = parseFloat(matcher[1]);
|
||||
const unit = matcher[2];
|
||||
if (!unit || unit === "ms") {
|
||||
return Math.round(value);
|
||||
}
|
||||
let multiplier: number;
|
||||
switch (unit) {
|
||||
case "s":
|
||||
multiplier = Time.S;
|
||||
break;
|
||||
case "m":
|
||||
multiplier = Time.M;
|
||||
break;
|
||||
case "h":
|
||||
multiplier = Time.H;
|
||||
break;
|
||||
case "d":
|
||||
multiplier = Time.D;
|
||||
break;
|
||||
default:
|
||||
throw new Error("invalid format unit: " + unit);
|
||||
}
|
||||
return Math.round(value * multiplier);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user