zhilian-auto-hi
Version:
智联招聘自动打招呼工具 - 自动化招聘流程的命令行工具
356 lines (355 loc) • 16 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.logger = void 0;
const chalk_1 = __importDefault(require("chalk"));
const boxen_1 = __importDefault(require("boxen"));
const index_1 = require("../types/index");
// 定义日志级别样式
const styles = {
info: chalk_1.default.blue,
success: chalk_1.default.green,
warning: chalk_1.default.yellow,
error: chalk_1.default.red.bold,
highlight: chalk_1.default.cyan.bold,
dim: chalk_1.default.gray,
title: chalk_1.default.magenta.bold,
stats: chalk_1.default.white.bold
};
// 定义图标
const icons = {
info: '🔍',
success: '✅',
warning: '⚠️',
error: '❌',
loading: '⏳',
rocket: '🚀',
target: '🎯',
chart: '📊',
page: '📄',
robot: '🤖',
handshake: '🤝',
camera: '📸',
book: '📖'
};
class Logger {
// 基础日志方法
info(message, icon) {
console.log(`${icon || icons.info} ${styles.info(message)}`);
}
success(message, icon) {
console.log(`${icon || icons.success} ${styles.success(message)}`);
}
warning(message, icon) {
console.log(`${icon || icons.warning} ${styles.warning(message)}`);
}
error(message, icon) {
console.log(`${icon || icons.error} ${styles.error(message)}`);
}
// 高亮显示重要信息
highlight(message, icon) {
console.log(`${icon || icons.target} ${styles.highlight(message)}`);
}
// 显示标题
title(message) {
console.log('\n' + (0, boxen_1.default)(styles.title(message), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: 'magenta'
}));
}
// 显示分隔线
separator(title) {
const line = '='.repeat(50);
if (title) {
console.log(`\n${styles.dim(line)} ${styles.highlight(title)} ${styles.dim(line)}`);
}
else {
console.log(`\n${styles.dim(line)}`);
}
}
// 显示统计信息
stats(stats) {
const matchRate = stats.totalProcessed > 0 ?
((stats.matchedCount / stats.totalProcessed) * 100).toFixed(1) : '0';
const greetRate = stats.matchedCount > 0 ?
((stats.greetedCount / stats.matchedCount) * 100).toFixed(1) : '0';
const statsBox = (0, boxen_1.default)([
`${icons.chart} ${styles.stats('处理统计信息')}`,
'',
`${icons.page} 总处理页数: ${styles.highlight(stats.currentPage.toString())}`,
`📋 总处理简历数: ${styles.highlight(stats.totalProcessed.toString())}`,
`${icons.success} 匹配简历数: ${styles.highlight(stats.matchedCount.toString())}`,
`${icons.handshake} 成功打招呼数: ${styles.highlight(stats.greetedCount.toString())}`,
`📈 匹配率: ${styles.highlight(matchRate + '%')}`,
`${icons.target} 打招呼成功率: ${styles.highlight(greetRate + '%')}`
].join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: 'green'
});
console.log('\n' + statsBox);
}
// 显示配置信息
config(config) {
const configItems = [
`${icons.target} ${styles.stats('配置信息')}`,
''
];
// 如果有运行模式信息,显示在最前面
if (config.runMode) {
configItems.push(`🚀 运行模式: ${styles.highlight(config.runMode)}`);
}
configItems.push(`🔍 筛选关键字: ${styles.highlight(config.keywords.join(', '))}`, `📅 年龄限制: ${styles.highlight((config.minAge || '无限制') + ' - ' + (config.maxAge || '无限制') + ' 岁')}`, `⚧️ 性别筛选: ${styles.highlight(config.gender === 'male' ? '仅男性' : config.gender === 'female' ? '仅女性' : '不限制')}`, `📋 最大页数: ${styles.highlight(config.maxPages.toString())}`, `⏱️ 翻页延迟: ${styles.highlight(config.pageDelay + 'ms')}`);
// 添加优雅关闭配置显示
configItems.push(`📊 显示统计: ${styles.highlight(config.gracefulShutdown.showStats ? '是' : '否')}`);
const configBox = (0, boxen_1.default)(configItems.join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: 'cyan'
});
console.log('\n' + configBox);
}
// 显示简历筛选结果
resumeResult(isMatch, matchedKeywords, age, gender) {
const genderText = gender === 'male' ? '男性' : gender === 'female' ? '女性' : '未知';
const resultBox = (0, boxen_1.default)([
`${icons.target} ${styles.stats('简历筛选结果')}`,
'',
`${isMatch ? icons.success : icons.error} 筛选结果: ${isMatch ? styles.success('匹配成功') : styles.error('不匹配')}`,
`🎯 匹配到的关键字: ${styles.highlight(matchedKeywords.join(', ') || '无')}`,
`📅 候选人年龄: ${styles.highlight(age !== undefined ? age + '岁' : '未知')}`,
`⚧️ 候选人性别: ${styles.highlight(genderText)}`
].join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: isMatch ? 'green' : 'red'
});
console.log('\n' + resultBox);
}
// 显示页面处理信息
pageInfo(pageNum) {
console.log(`\n${icons.page} ${styles.highlight(`正在处理第 ${pageNum} 页...`)}`);
}
// 显示简历详情
resumeDetails(resumeText) {
console.log('\n' + (0, boxen_1.default)([
`${icons.info} ${styles.stats('简历详情信息')}`,
'',
styles.dim(resumeText.trim())
].join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'single',
borderColor: 'blue'
}));
}
// 浏览模式专用方法
// 显示浏览模式页面进度
browsePageInfo(pageNum) {
console.log(`\n${icons.book} ${styles.highlight(`正在浏览第 ${pageNum} 页...`)}`);
}
// 显示浏览模式统计信息
browseStats(stats) {
const duration = stats.endTime ?
Math.round((stats.endTime.getTime() - stats.startTime.getTime()) / 1000) :
Math.round((new Date().getTime() - stats.startTime.getTime()) / 1000);
const statsItems = [
`${icons.book} ${styles.stats('浏览统计信息')}`,
'',
`${icons.page} 当前页数: ${styles.highlight(stats.currentPage.toString())}`,
`${icons.camera} 已浏览页面数: ${styles.highlight(stats.totalBrowsed.toString())}`,
`⏱️ 浏览时长: ${styles.highlight(duration + '秒')}`,
`📈 平均浏览速度: ${stats.totalBrowsed > 0 ? styles.highlight((duration / stats.totalBrowsed).toFixed(1) + '秒/页') : styles.highlight('0秒/页')}`
];
// 如果有筛选统计信息,添加筛选相关的统计
if (stats.totalFiltered !== undefined && stats.matchedCount !== undefined) {
statsItems.push('', `🔍 筛选统计信息:`, `📋 已筛选简历数: ${styles.highlight(stats.totalFiltered.toString())}`, `✅ 匹配简历数: ${styles.highlight(stats.matchedCount.toString())}`);
if (stats.totalFiltered > 0) {
const matchRate = ((stats.matchedCount / stats.totalFiltered) * 100).toFixed(1);
statsItems.push(`📊 匹配率: ${styles.highlight(matchRate + '%')}`);
}
}
const statsBox = (0, boxen_1.default)(statsItems.join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: 'blue'
});
console.log('\n' + statsBox);
}
// 显示浏览模式进度更新
browseProgress(currentPage, totalBrowsed) {
console.log(`${icons.camera} ${styles.info(`页面 ${currentPage} 浏览完成,累计浏览: ${totalBrowsed} 页`)}`);
}
// 显示浏览模式开始信息
browseStart() {
console.log(`\n${icons.rocket} ${styles.success('开始浏览模式...')}`);
}
// 显示浏览模式完成信息
browseComplete(totalBrowsed) {
console.log(`\n${icons.success} ${styles.success(`浏览模式完成!总共浏览了 ${totalBrowsed} 页`)}`);
}
// 显示浏览模式错误但继续执行
browseError(error, currentPage) {
console.log(`${icons.warning} ${styles.warning(`第 ${currentPage} 页浏览出错,继续下一页: ${error}`)}`);
}
// 显示浏览模式筛选结果(简化版,不显示详细简历信息)
browseFilterResult(pageNum, isMatch, matchedKeywords, age, gender) {
const genderText = gender === 'male' ? '男性' : gender === 'female' ? '女性' : '未知';
const statusIcon = isMatch ? '✅' : '❌';
const statusText = isMatch ? styles.success('匹配') : styles.dim('不匹配');
console.log(`${statusIcon} 第${pageNum}页 - ${statusText} | 年龄: ${styles.highlight(age !== undefined ? age + '岁' : '未知')} | 性别: ${styles.highlight(genderText)} | 关键字: ${styles.highlight(matchedKeywords.join(', ') || '无')}`);
}
// 优雅关闭相关方法
// 显示关闭开始信息
shutdownStart(signal) {
const shutdownBox = (0, boxen_1.default)([
`🛑 ${styles.warning('正在关闭程序...')}`,
'',
`📡 接收信号: ${styles.highlight(signal)}`,
`⏰ 开始时间: ${styles.dim(new Date().toLocaleString('zh-CN'))}`,
'',
`${styles.info('正在安全清理资源,请稍候...')}`
].join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: 'yellow'
});
console.log('\n' + shutdownBox);
}
// 显示清理进度
cleanupProgress(step) {
console.log(`🧹 ${styles.info(step)}`);
}
// 显示清理步骤开始
cleanupStepStart(stepName) {
console.log(`🔄 ${styles.info(`开始清理: ${stepName}`)}`);
}
// 显示清理步骤完成
cleanupStepComplete(stepName) {
console.log(`✅ ${styles.success(`完成清理: ${stepName}`)}`);
}
// 显示清理步骤失败
cleanupStepFailed(stepName, error) {
console.log(`❌ ${styles.warning(`清理失败: ${stepName} - ${error}`)}`);
}
// 显示关闭完成信息(带详细统计)
shutdownComplete(shutdownStats) {
if (!shutdownStats) {
// 简单的关闭完成消息
const simpleBox = (0, boxen_1.default)([
`✅ ${styles.success('程序已安全退出')}`,
'',
`🕐 退出时间: ${styles.dim(new Date().toLocaleString('zh-CN'))}`
].join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: 'green'
});
console.log('\n' + simpleBox);
return;
}
// 计算关闭耗时
const duration = shutdownStats.endTime ?
Math.round((shutdownStats.endTime.getTime() - shutdownStats.startTime.getTime()) / 1000) : 0;
// 构建统计信息内容
const statsContent = [
`✅ ${styles.success('程序已安全退出')}`,
''
];
// 基本信息
statsContent.push(`📡 触发信号: ${styles.highlight(shutdownStats.signal)}`, `🕐 关闭耗时: ${styles.highlight(duration + '秒')}`, `📊 关闭阶段: ${styles.highlight(this.getPhaseDisplayName(shutdownStats.phase))}`);
// 清理步骤信息
if (shutdownStats.cleanupSteps.length > 0) {
statsContent.push('', `🧹 完成的清理步骤 (${shutdownStats.cleanupSteps.length}个):`);
shutdownStats.cleanupSteps.forEach(step => {
statsContent.push(` • ${styles.dim(step)}`);
});
}
// 错误信息
if (shutdownStats.errors.length > 0) {
statsContent.push('', `⚠️ 清理过程中的错误 (${shutdownStats.errors.length}个):`);
shutdownStats.errors.forEach(error => {
statsContent.push(` • ${styles.warning(error)}`);
});
}
// 处理统计信息
if (shutdownStats.processingStats) {
const stats = shutdownStats.processingStats;
const matchRate = stats.totalProcessed > 0 ?
((stats.matchedCount / stats.totalProcessed) * 100).toFixed(1) : '0';
statsContent.push('', `📈 执行统计信息:`, ` • 处理页数: ${styles.highlight(stats.currentPage.toString())}`, ` • 处理简历: ${styles.highlight(stats.totalProcessed.toString())}`, ` • 匹配简历: ${styles.highlight(stats.matchedCount.toString())}`, ` • 成功打招呼: ${styles.highlight(stats.greetedCount.toString())}`, ` • 匹配率: ${styles.highlight(matchRate + '%')}`, ` • 完成状态: ${stats.isCompleted ? styles.success('正常完成') : styles.warning('提前终止')}`);
if (stats.shutdownReason) {
statsContent.push(` • 终止原因: ${styles.highlight(stats.shutdownReason)}`);
}
}
const completionBox = (0, boxen_1.default)(statsContent.join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: shutdownStats.errors.length > 0 ? 'yellow' : 'green'
});
console.log('\n' + completionBox);
}
// 显示强制关闭警告
forceShutdownWarning(reason = 'repeated_signal') {
const warningMessage = reason === 'timeout'
? '清理超时,正在强制关闭程序...'
: '检测到重复信号,正在强制关闭程序...';
const warningBox = (0, boxen_1.default)([
`⚡ ${styles.error('强制关闭警告')}`,
'',
`${styles.warning(warningMessage)}`,
'',
`${styles.dim('注意: 强制关闭可能导致资源未完全清理')}`
].join('\n'), {
padding: 1,
margin: 1,
borderStyle: 'double',
borderColor: 'red'
});
console.log('\n' + warningBox);
}
// 显示超时提示
shutdownTimeoutWarning(timeoutSeconds) {
console.log(`⏰ ${styles.warning(`清理操作将在 ${timeoutSeconds} 秒后超时`)}`);
}
// 显示关闭进度概览
shutdownProgress(completedSteps, totalSteps, currentStep) {
const progress = totalSteps > 0 ? Math.round((completedSteps / totalSteps) * 100) : 0;
const progressBar = '█'.repeat(Math.floor(progress / 5)) + '░'.repeat(20 - Math.floor(progress / 5));
console.log(`📊 ${styles.info(`关闭进度: [${progressBar}] ${progress}% (${completedSteps}/${totalSteps})`)}`);
if (currentStep) {
console.log(`🔄 ${styles.dim(`当前步骤: ${currentStep}`)}`);
}
}
// 获取阶段显示名称
getPhaseDisplayName(phase) {
switch (phase) {
case index_1.ShutdownPhase.RUNNING:
return '运行中';
case index_1.ShutdownPhase.INITIATED:
return '开始关闭';
case index_1.ShutdownPhase.CLEANING_UP:
return '清理中';
case index_1.ShutdownPhase.COMPLETED:
return '正常完成';
case index_1.ShutdownPhase.FORCED:
return '强制关闭';
default:
return '未知状态';
}
}
}
// 导出单例实例
exports.logger = new Logger();
exports.default = exports.logger;