Spaces:
Running
Running
File size: 4,132 Bytes
f9e1174 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
import fs from 'fs';
import path from 'path';
// 日志文件路径
const LOG_FILE = './logs/app.log';
const LOG_DIR = './logs';
/**
* 确保日志目录存在
*/
function ensureLogDirectory() {
if (!fs.existsSync(LOG_DIR)) {
fs.mkdirSync(LOG_DIR, { recursive: true });
}
}
/**
* 写入日志到文件
* @param {string} level - 日志级别 (INFO, ERROR, WARN)
* @param {string} message - 日志消息
*/
export function writeLog(level, message) {
ensureLogDirectory();
const timestamp = new Date().toISOString();
const logEntry = `[${timestamp}] [${level}] ${message}\n`;
try {
fs.appendFileSync(LOG_FILE, logEntry);
} catch (error) {
console.error('写入日志文件失败:', error);
}
}
/**
* 增强的 console.log,同时输出到控制台和文件
* @param {...any} args - 要记录的参数
*/
export function log(...args) {
const message = args.map(arg =>
typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
).join(' ');
console.log(...args);
writeLog('INFO', message);
}
/**
* 增强的 console.error,同时输出到控制台和文件
* @param {...any} args - 要记录的参数
*/
export function logError(...args) {
const message = args.map(arg =>
typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
).join(' ');
console.error(...args);
writeLog('ERROR', message);
}
/**
* 读取最近的日志
* @param {number} lines - 要读取的行数,默认100行
* @returns {Array} 日志行数组
*/
export function getRecentLogs(lines = 100) {
try {
if (!fs.existsSync(LOG_FILE)) {
return [];
}
const content = fs.readFileSync(LOG_FILE, 'utf8');
const logLines = content.trim().split('\n').filter(line => line.length > 0);
// 返回最后 N 行
return logLines.slice(-lines);
} catch (error) {
console.error('读取日志文件失败:', error);
return [];
}
}
/**
* 创建人类可读的时间戳
* @returns {string} 格式化的时间戳 YYYY-MM-DD_HH-MM-SS
*/
export function getHumanReadableTimestamp() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
}
/**
* 确保截图目录存在
* @param {string} dir - 目录路径
*/
export function ensureScreenshotDirectory(dir) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
console.log(`创建截图目录: ${dir}`);
}
}
/**
* 检查 Cookie 文件是否存在
* @param {string} cookieFile - Cookie 文件路径
* @returns {boolean} 文件是否存在
*/
export function checkCookieFile(cookieFile) {
if (!fs.existsSync(cookieFile)) {
console.error(`Cookie文件不存在: ${cookieFile}`);
console.log('请先运行 npm run login 进行登录');
return false;
}
return true;
}
/**
* 读取并解析 Cookie 文件
* @param {string} cookieFile - Cookie 文件路径
* @returns {Array} Cookie 数组
*/
export function loadCookies(cookieFile) {
try {
const cookies = JSON.parse(fs.readFileSync(cookieFile, 'utf8'));
console.log(`已加载 ${cookies.length} 个cookies`);
return cookies;
} catch (error) {
console.error('读取 Cookie 文件失败:', error);
throw error;
}
}
/**
* 保存截图
* @param {Object} page - Playwright 页面对象
* @param {string} screenshotDir - 截图目录
* @param {string} prefix - 文件名前缀
* @returns {string} 截图文件路径
*/
export async function saveScreenshot(page, screenshotDir, prefix = 'screenshot') {
ensureScreenshotDirectory(screenshotDir);
const timestamp = getHumanReadableTimestamp();
const screenshotPath = path.join(screenshotDir, `${prefix}-${timestamp}.png`);
await page.screenshot({ path: screenshotPath });
console.log(`截图已保存: ${screenshotPath}`);
return screenshotPath;
}
|