#!/usr/bin/env node const fs = require('fs') const path = require('path') const { execSync } = require('child_process') // 创建报告目录 const reportDir = path.resolve(process.cwd(), 'quality-report') if (!fs.existsSync(reportDir)) { fs.mkdirSync(reportDir, { recursive: true }) } // 生成时间戳 const timestamp = new Date().toISOString().replace(/[:.]/g, '-') const reportFile = path.join(reportDir, `quality-report-${timestamp}.html`) // 报告模板 const reportTemplate = ` 代码质量报告

代码质量报告

生成时间: ${new Date().toLocaleString('zh-CN')}

概览

测试覆盖率

-

代码行覆盖率

ESLint 问题

-

代码风格问题

类型错误

-

TypeScript 类型错误

安全漏洞

-

npm audit 结果

测试覆盖率

代码风格检查

类型检查

安全检查

` // 写入报告文件 fs.writeFileSync(reportFile, reportTemplate) console.log(`✅ 代码质量报告已生成: ${reportFile}`) // 运行各种检查并更新报告 async function generateQualityReport() { try { // 1. 运行测试覆盖率 console.log('🔍 运行测试覆盖率...') try { execSync('npm run test:unit:coverage', { stdio: 'pipe' }) const coverageSummary = JSON.parse(fs.readFileSync('coverage/coverage-summary.json', 'utf8')) updateTestCoverage(coverageSummary) } catch (error) { console.error('❌ 测试覆盖率检查失败:', error.message) updateTestCoverage(null, error.message) } // 2. 运行 ESLint console.log('🔍 运行 ESLint...') try { const eslintOutput = execSync('npm run lint -- --format=json', { stdio: 'pipe' }).toString() const eslintResults = JSON.parse(eslintOutput) updateESLintResults(eslintResults) } catch (error) { console.error('❌ ESLint 检查失败:', error.message) updateESLintResults(null, error.message) } // 3. 运行类型检查 console.log('🔍 运行类型检查...') try { execSync('npm run type-check', { stdio: 'pipe' }) updateTypeCheckResults(true) } catch (error) { console.error('❌ 类型检查失败:', error.message) updateTypeCheckResults(false, error.message) } // 4. 运行安全审计 console.log('🔍 运行安全审计...') try { const auditOutput = execSync('npm audit --json', { stdio: 'pipe' }).toString() const auditResults = JSON.parse(auditOutput) updateSecurityResults(auditResults) } catch (error) { console.error('❌ 安全审计失败:', error.message) updateSecurityResults(null, error.message) } console.log('✅ 代码质量报告更新完成') } catch (error) { console.error('❌ 生成代码质量报告时出错:', error) } } // 更新测试覆盖率信息 function updateTestCoverage(coverageSummary, error) { let html = '' if (error) { html = `
状态 检查失败
${error}
` } else { const { lines, functions, branches, statements } = coverageSummary.total const linesPercent = parseFloat(lines.pct) html = `
行覆盖率 ${lines.pct}%
函数覆盖率 ${functions.pct}%
分支覆盖率 ${branches.pct}%
语句覆盖率 ${statements.pct}%
` // 更新概览 updateOverview('test-coverage', lines.pct + '%', linesPercent >= 80 ? 'success' : linesPercent >= 60 ? 'warning' : 'error') } updateReportSection('coverage-details', html) } // 更新 ESLint 结果 function updateESLintResults(eslintResults, error) { let html = '' if (error) { html = `
状态 检查失败
${error}
` } else { let totalErrors = 0 let totalWarnings = 0 eslintResults.forEach(file => { totalErrors += file.errorCount totalWarnings += file.warningCount }) const status = totalErrors === 0 && totalWarnings === 0 ? 'success' : totalErrors === 0 ? 'warning' : 'error' html = `
错误 ${totalErrors}
警告 ${totalWarnings}
状态 ${totalErrors === 0 && totalWarnings === 0 ? '通过' : totalErrors === 0 ? '警告' : '失败'}
` // 更新概览 updateOverview('eslint-issues', totalErrors + totalWarnings, status) } updateReportSection('eslint-details', html) } // 更新类型检查结果 function updateTypeCheckResults(success, error) { let html = '' if (success) { html = `
状态 通过
类型错误 0
` // 更新概览 updateOverview('type-errors', '0', 'success') } else { html = `
状态 失败
${error}
` // 更新概览 updateOverview('type-errors', '>', 'error') } updateReportSection('type-check-details', html) } // 更新安全检查结果 function updateSecurityResults(auditResults, error) { let html = '' if (error) { html = `
状态 检查失败
${error}
` // 更新概览 updateOverview('security-vulnerabilities', '?', 'error') } else { const { vulnerabilities } = auditResults.metadata const { low, moderate, high, critical } = vulnerabilities const totalVulns = low + moderate + high + critical const status = critical > 0 || high > 0 ? 'error' : moderate > 0 ? 'warning' : 'success' html = `
严重 ${critical}
高危 ${high}
中危 ${moderate}
低危 ${low}
总计 ${totalVulns}
` // 更新概览 updateOverview('security-vulnerabilities', totalVulns, status) } updateReportSection('security-details', html) } // 更新概览 function updateOverview(id, value, status) { const elementId = id const className = status === 'success' ? 'success' : status === 'warning' ? 'warning' : 'error' // 这里需要使用 DOM 操作,但在 Node.js 环境中无法直接操作 HTML // 实际实现中可以使用 cheerio 或其他 HTML 解析库 console.log(`更新概览 ${id}: ${value} (${status})`) } // 更新报告部分 function updateReportSection(id, html) { // 这里需要使用 DOM 操作,但在 Node.js 环境中无法直接操作 HTML // 实际实现中可以使用 cheerio 或其他 HTML 解析库 console.log(`更新报告部分 ${id}`) } // 运行报告生成 generateQualityReport() module.exports = { generateQualityReport }