mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-06-14 20:48:00 +08:00
216 lines
5.7 KiB
TypeScript
216 lines
5.7 KiB
TypeScript
import { debounce } from 'lodash-es';
|
|
import logInfo from './logger.json';
|
|
|
|
export const enum LogLevel {
|
|
/** 输出所有,包括日志 */
|
|
LOG,
|
|
/** 报错、严重警告和警告 */
|
|
WARNING,
|
|
/** 仅报错 */
|
|
ERROR
|
|
}
|
|
|
|
interface LoggerCatchInfo {
|
|
code?: number;
|
|
level: LogLevel;
|
|
message: string;
|
|
}
|
|
|
|
interface LoggerCatchReturns<T> {
|
|
ret: T;
|
|
info: LoggerCatchInfo[];
|
|
}
|
|
|
|
let logTip: HTMLSpanElement;
|
|
if (!main.replayChecking) {
|
|
const tip = document.createElement('span');
|
|
logTip = tip;
|
|
tip.style.position = 'fixed';
|
|
tip.style.right = '0';
|
|
tip.style.bottom = '0';
|
|
tip.style.height = '20px';
|
|
tip.style.width = 'auto';
|
|
tip.style.textAlign = 'right';
|
|
tip.style.padding = '0 5px';
|
|
tip.style.fontSize = '16px';
|
|
tip.style.fontFamily = 'Arial';
|
|
tip.style.display = 'none';
|
|
tip.style.margin = '2px';
|
|
document.body.appendChild(tip);
|
|
}
|
|
|
|
const hideTipText = debounce(() => {
|
|
if (main.replayChecking) return;
|
|
logTip.style.display = 'none';
|
|
}, 5000);
|
|
|
|
const nums = new Set('1234567890');
|
|
|
|
export interface ILoggerInfo {
|
|
error: Record<number, string>;
|
|
warn: Record<number, string>;
|
|
}
|
|
|
|
export class Logger {
|
|
enabled: boolean = true;
|
|
|
|
private catching: boolean = false;
|
|
private catchedInfo: LoggerCatchInfo[] = [];
|
|
|
|
private catchStack: LoggerCatchInfo[][] = [];
|
|
|
|
constructor(
|
|
public readonly level: LogLevel,
|
|
public readonly info: ILoggerInfo
|
|
) {}
|
|
|
|
private parseInfo(text: string, ...params: string[]) {
|
|
let pointer = -1;
|
|
let str = '';
|
|
|
|
let inParam = false;
|
|
let paramNum = '';
|
|
while (++pointer < text.length) {
|
|
const char = text[pointer];
|
|
|
|
if (char === '$' && text[pointer - 1] !== '\\') {
|
|
inParam = true;
|
|
continue;
|
|
}
|
|
|
|
if (inParam) {
|
|
if (nums.has(char)) {
|
|
paramNum += char;
|
|
}
|
|
if (!nums.has(text[pointer + 1])) {
|
|
inParam = false;
|
|
const num = Number(paramNum);
|
|
paramNum = '';
|
|
str += params[num - 1] ?? '[not delivered]';
|
|
}
|
|
continue;
|
|
}
|
|
|
|
str += char;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* 输出报错信息
|
|
* @param code 错误代码,每个错误都应当使用唯一的错误代码
|
|
* @param params 参数
|
|
*/
|
|
error(code: number, ...params: string[]) {
|
|
const info = this.info.error[code];
|
|
if (!info) {
|
|
logger.error(16, 'error', code.toString());
|
|
return;
|
|
}
|
|
|
|
const text = this.parseInfo(info, ...params);
|
|
if (this.catching) {
|
|
this.catchedInfo.push({
|
|
level: LogLevel.ERROR,
|
|
message: text,
|
|
code
|
|
});
|
|
}
|
|
if (this.level <= LogLevel.ERROR && this.enabled) {
|
|
if (!main.replayChecking) {
|
|
logTip.style.color = 'lightcoral';
|
|
logTip.style.display = 'block';
|
|
logTip.textContent = `Error thrown, please check in console.`;
|
|
hideTipText();
|
|
}
|
|
const n = Math.floor(code / 50) + 1;
|
|
const n2 = code % 50;
|
|
const url = `${location.origin}/_docs/logger/error/error${n}.html#error-code-${n2}`;
|
|
console.error(`[ERROR Code ${code}] ${text} See ${url}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 输出警告信息
|
|
* @param code 警告代码
|
|
* @param text 警告信息
|
|
*/
|
|
warn(code: number, ...params: string[]) {
|
|
const info = this.info.warn[code];
|
|
if (!info) {
|
|
logger.error(16, 'warn', code.toString());
|
|
return;
|
|
}
|
|
const text = this.parseInfo(info, ...params);
|
|
|
|
if (this.catching) {
|
|
this.catchedInfo.push({
|
|
level: LogLevel.ERROR,
|
|
message: text,
|
|
code
|
|
});
|
|
}
|
|
if (this.level <= LogLevel.WARNING && this.enabled) {
|
|
if (!main.replayChecking) {
|
|
logTip.style.color = 'gold';
|
|
logTip.style.display = 'block';
|
|
logTip.textContent = `Warning thrown, please check in console.`;
|
|
hideTipText();
|
|
}
|
|
const n = Math.floor(code / 50) + 1;
|
|
const n2 = code % 50;
|
|
const url = `${location.origin}/_docs/logger/warn/warn${n}.html#warn-code-${n2}`;
|
|
console.warn(`[WARNING Code ${code}] ${text}. See ${url}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 输出日志
|
|
* @param text 日志信息
|
|
*/
|
|
log(text: string) {
|
|
if (this.catching) {
|
|
this.catchedInfo.push({
|
|
level: LogLevel.ERROR,
|
|
message: text
|
|
});
|
|
}
|
|
if (this.level <= LogLevel.LOG && this.enabled) {
|
|
console.log(`[LOG] ${text}`);
|
|
}
|
|
}
|
|
|
|
catch<T>(fn: () => T): LoggerCatchReturns<T> {
|
|
const before = this.enabled;
|
|
this.catchedInfo = [];
|
|
this.catchStack.push(this.catchedInfo);
|
|
this.disable();
|
|
this.catching = true;
|
|
const ret = fn();
|
|
if (this.catchStack.length === 0) {
|
|
this.catching = false;
|
|
} else {
|
|
this.catching = true;
|
|
}
|
|
if (before) this.enable();
|
|
|
|
this.catchStack.pop();
|
|
const last = this.catchStack?.at(-1);
|
|
const info = this.catchedInfo;
|
|
this.catchedInfo = last ?? [];
|
|
|
|
return { ret, info };
|
|
}
|
|
|
|
disable() {
|
|
this.enabled = false;
|
|
}
|
|
|
|
enable() {
|
|
this.enabled = true;
|
|
}
|
|
}
|
|
|
|
export const logger = new Logger(LogLevel.LOG, logInfo);
|