微信小程序页面迁移校验之前 P5任务处理之前

This commit is contained in:
Neo
2026-03-09 01:19:21 +08:00
parent 263bf96035
commit 6e20987d2f
1112 changed files with 153824 additions and 219694 deletions

View File

@@ -0,0 +1,130 @@
/**
* 任务日志解析与分组工具函数。
*
* 解析 TaskLogBuffer 输出的日志格式:[TASK_CODE] timestamp level message
* 将扁平日志行按任务代码分组,提取时间线信息。
*/
/** 单条解析后的日志条目 */
export interface ParsedLogEntry {
/** 原始行文本 */
raw: string;
/** 任务代码(如 ODS_MEMBER */
taskCode: string;
/** 时间戳字符串(原始格式) */
timestamp: string;
/** 日志级别INFO / WARNING / ERROR / DEBUG */
level: string;
/** 日志消息正文 */
message: string;
}
/** 按任务分组后的日志集合 */
export interface TaskLogGroup {
taskCode: string;
entries: ParsedLogEntry[];
/** 该任务第一条日志的时间戳 */
startTime: string | null;
/** 该任务最后一条日志的时间戳 */
endTime: string | null;
/** 推断的任务状态success / failed / running / unknown */
status: "success" | "failed" | "running" | "unknown";
/** 各级别日志计数 */
counts: { info: number; warning: number; error: number; debug: number };
}
/**
* 匹配 TaskLogBuffer 输出格式:[TASK_CODE] 2024-01-01 12:00:00 INFO 消息内容
* 也兼容:[TASK_CODE] 2024-01-01 12:00:00,123 INFO 消息内容
*/
const LOG_LINE_REGEX =
/^\[([A-Z][A-Z0-9_]*)\]\s+(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}(?:[.,]\d+)?)\s+(DEBUG|INFO|WARNING|ERROR|CRITICAL)\s+(.*)$/;
/**
* 解析单行日志。无法解析时返回 null。
*/
export function parseLogLine(line: string): ParsedLogEntry | null {
const match = LOG_LINE_REGEX.exec(line.trim());
if (!match) return null;
return {
raw: line,
taskCode: match[1],
timestamp: match[2],
level: match[3],
message: match[4],
};
}
/**
* 将日志行数组按任务代码分组。
* 无法解析的行归入 "_UNKNOWN" 分组。
*/
export function groupLogsByTask(lines: string[]): TaskLogGroup[] {
const groupMap = new Map<string, ParsedLogEntry[]>();
for (const line of lines) {
if (!line.trim()) continue;
const parsed = parseLogLine(line);
const code = parsed?.taskCode ?? "_UNKNOWN";
const entry: ParsedLogEntry = parsed ?? {
raw: line,
taskCode: "_UNKNOWN",
timestamp: "",
level: "INFO",
message: line,
};
const arr = groupMap.get(code);
if (arr) {
arr.push(entry);
} else {
groupMap.set(code, [entry]);
}
}
const groups: TaskLogGroup[] = [];
for (const [taskCode, entries] of groupMap) {
const counts = { info: 0, warning: 0, error: 0, debug: 0 };
for (const e of entries) {
const lvl = e.level.toLowerCase();
if (lvl === "info") counts.info++;
else if (lvl === "warning" || lvl === "critical") counts.warning++;
else if (lvl === "error") counts.error++;
else if (lvl === "debug") counts.debug++;
}
// 推断状态:有 ERROR 级别 → failed否则看最后一条消息
let status: TaskLogGroup["status"] = "unknown";
if (counts.error > 0) {
status = "failed";
} else if (entries.length > 0) {
const lastMsg = entries[entries.length - 1].message.toLowerCase();
if (lastMsg.includes("完成") || lastMsg.includes("success") || lastMsg.includes("finished")) {
status = "success";
}
}
const timestamps = entries.map((e) => e.timestamp).filter(Boolean);
groups.push({
taskCode,
entries,
startTime: timestamps[0] ?? null,
endTime: timestamps.length > 0 ? timestamps[timestamps.length - 1] : null,
status,
counts,
});
}
return groups;
}
/**
* 按任务代码过滤分组。空关键词返回全部。
*/
export function filterTaskGroups(
groups: TaskLogGroup[],
keyword: string,
): TaskLogGroup[] {
const kw = keyword.trim().toUpperCase();
if (!kw) return groups;
return groups.filter((g) => g.taskCode.toUpperCase().includes(kw));
}