mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-19 17:16:08 +08:00
192 lines
4.9 KiB
TypeScript
192 lines
4.9 KiB
TypeScript
import { debounce } from 'lodash-es';
|
|
import logInfo from '../../data/logger.json';
|
|
|
|
// todo: 使用格式化输出?
|
|
|
|
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(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']);
|
|
|
|
const logError = logInfo.error as Record<number, string>;
|
|
const logWarn = logInfo.warn as Record<number, string>;
|
|
|
|
export class Logger {
|
|
level: LogLevel = LogLevel.LOG;
|
|
enabled: boolean = true;
|
|
|
|
private catching: boolean = false;
|
|
private catchedInfo: LoggerCatchInfo[] = [];
|
|
|
|
constructor(logLevel: LogLevel) {
|
|
this.level = logLevel;
|
|
}
|
|
|
|
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;
|
|
} else {
|
|
inParam = false;
|
|
const num = Number(paramNum);
|
|
str += params[num] ?? '[not delivered]';
|
|
}
|
|
continue;
|
|
}
|
|
|
|
str += char;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* 设置该日志类的输出等级
|
|
* @param level 要设置为的输出等级
|
|
*/
|
|
setLogLevel(level: LogLevel) {
|
|
this.level = level;
|
|
}
|
|
|
|
/**
|
|
* 输出报错信息
|
|
* @param code 错误代码,每个错误都应当使用唯一的错误代码
|
|
* @param params 参数
|
|
*/
|
|
error(code: number, ...params: string[]) {
|
|
const text = this.parseInfo(logError[code], ...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();
|
|
}
|
|
console.error(`[ERROR Code ${code}] ${text}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 输出警告信息
|
|
* @param code 警告代码
|
|
* @param text 警告信息
|
|
*/
|
|
warn(code: number, ...params: string[]) {
|
|
const text = this.parseInfo(logWarn[code], ...params);
|
|
if (this.catching) {
|
|
this.catchedInfo.push({
|
|
level: LogLevel.ERROR,
|
|
message: text,
|
|
code
|
|
});
|
|
}
|
|
if (this.level <= LogLevel.WARNING && this.enabled) {
|
|
console.warn(`[WARNING Code ${code}] ${text}`);
|
|
if (!main.replayChecking) {
|
|
logTip.style.color = 'gold';
|
|
logTip.style.display = 'block';
|
|
logTip.textContent = `Warning thrown, please check in console.`;
|
|
hideTipText();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 输出日志
|
|
* @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.disable();
|
|
this.catching = true;
|
|
const ret = fn();
|
|
this.catching = false;
|
|
if (before) this.enable();
|
|
|
|
return { ret, info: this.catchedInfo };
|
|
}
|
|
|
|
disable() {
|
|
this.enabled = false;
|
|
}
|
|
|
|
enable() {
|
|
this.enabled = true;
|
|
}
|
|
}
|
|
|
|
export const logger = new Logger(LogLevel.LOG);
|