const fs = require('fs'); const path = require('path'); const yaml = require('js-yaml'); const WorkflowEngine = require('./workflow-engine'); /** * 站点适配器基类 - 所有网站的基类 */ class SiteAdapter { constructor(context, siteName) { this.context = context; this.siteName = siteName; this.useConfig = true; // 默认使用配置文件 // 快捷访问 this.page = context.page; this.logger = context.logger; // 加载配置 if (this.useConfig) { this.config = this.loadConfig(siteName); this.context.siteName = this.config.site?.name || siteName; } } /** * 加载站点配置 * @param {string} siteName - 站点名称 * @returns {Object} */ loadConfig(siteName) { const configPath = path.join(__dirname, '../configs/sites', `${siteName}.yaml`); if (!fs.existsSync(configPath)) { throw new Error(`配置文件不存在: ${configPath}`); } const configContent = fs.readFileSync(configPath, 'utf8'); return yaml.load(configContent); } /** * 生命周期钩子 - 工作流执行前 */ async beforeWorkflow() { this.log('debug', '执行 beforeWorkflow 钩子'); // 子类可以重写 } /** * 生命周期钩子 - 工作流执行后 */ async afterWorkflow() { this.log('debug', '执行 afterWorkflow 钩子'); // 子类可以重写 } /** * 生命周期钩子 - 错误处理 * @param {Error} error - 错误对象 */ async onError(error) { this.log('error', `工作流执行失败: ${error.message}`); // 截图 if (this.page) { try { const screenshotPath = path.join( __dirname, '../../logs', `error-${Date.now()}.png` ); await this.page.screenshot({ path: screenshotPath, fullPage: true }); this.log('info', `错误截图已保存: ${screenshotPath}`); } catch (e) { this.log('warn', `截图失败: ${e.message}`); } } // 子类可以重写 } /** * 执行入口 * @returns {Promise} */ async execute() { try { // 执行前钩子 await this.beforeWorkflow(); // 创建工作流引擎 const engine = new WorkflowEngine(this.context, this.config); this.context.engine = engine; this.context.adapter = this; // 执行工作流 const result = await engine.execute(); // 执行后钩子 await this.afterWorkflow(); return result; } catch (error) { await this.onError(error); throw error; } } /** * 记录日志 */ log(level, message) { if (this.logger && this.logger[level]) { this.logger[level](this.siteName, message); } else { console.log(`[${level.toUpperCase()}] ${message}`); } } } module.exports = SiteAdapter;