
关键代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>代码对比工具</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(135deg,
color:
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
header {
text-align: center;
padding: 30px 0;
margin-bottom: 20px;
}
h1 {
font-size: 2.8rem;
margin-bottom: 10px;
background: linear-gradient(90deg,
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
.subtitle {
font-size: 1.2rem;
color:
max-width: 800px;
margin: 0 auto;
line-height: 1.6;
}
.main-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 25px;
margin-bottom: 30px;
}
.panel {
background: rgba(25, 40, 65, 0.85);
border-radius: 12px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(100, 150, 255, 0.2);
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(100, 150, 255, 0.3);
}
.panel-title {
font-size: 1.4rem;
color:
display: flex;
align-items: center;
gap: 10px;
}
.code-input {
width: 100%;
height: 300px;
background: rgba(15, 30, 50, 0.7);
border: 1px solid rgba(100, 150, 255, 0.3);
border-radius: 8px;
padding: 15px;
color:
font-family: 'Consolas', 'Courier New', monospace;
font-size: 15px;
line-height: 1.5;
resize: vertical;
transition: all 0.3s;
}
.code-input:focus {
outline: none;
border-color:
box-shadow: 0 0 0 3px rgba(79, 195, 247, 0.2);
}
.controls {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
margin: 20px 0;
}
.btn {
padding: 14px 20px;
border: none;
border-radius: 8px;
background: linear-gradient(135deg,
color: white;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
}
.btn:hover {
transform: translateY(-3px);
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
}
.btn:active {
transform: translateY(1px);
}
.btn-compare {
background: linear-gradient(135deg,
}
.btn-export {
background: linear-gradient(135deg,
}
.btn-clear {
background: linear-gradient(135deg,
}
.comparison-title {
text-align: center;
font-size: 1.5rem;
margin: 30px 0 20px;
color:
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
}
.comparison-container {
display: flex;
gap: 20px;
margin-bottom: 30px;
}
.comparison-panel {
flex: 1;
background: rgba(25, 40, 65, 0.85);
border-radius: 12px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.comparison-header {
padding: 15px 20px;
background: rgba(30, 50, 80, 0.9);
font-weight: bold;
color:
display: flex;
justify-content: space-between;
align-items: center;
}
.comparison-content {
padding: 15px;
overflow-x: auto;
font-family: 'Consolas', 'Courier New', monospace;
font-size: 15px;
line-height: 1.5;
min-height: 350px;
max-height: 500px;
}
.line {
padding: 5px 8px;
border-radius: 4px;
margin-bottom: 3px;
display: flex;
min-height: 24px;
transition: background 0.2s;
}
.line:hover {
background: rgba(255, 255, 255, 0.05);
}
.line-number {
min-width: 35px;
padding-right: 12px;
text-align: right;
color:
user-select: none;
}
.line-content {
flex: 1;
overflow-x: auto;
white-space: pre;
word-break: break-word;
padding-left: 8px;
border-left: 1px solid rgba(255, 255, 255, 0.1);
}
.unchanged { color:
.inserted { background: rgba(46, 204, 113, 0.25); }
.deleted { background: rgba(231, 76, 60, 0.25); }
.changed { background: rgba(241, 196, 15, 0.3); }
.legend {
display: flex;
justify-content: center;
gap: 30px;
padding: 18px;
background: rgba(30, 50, 80, 0.8);
border-radius: 12px;
margin-top: 25px;
flex-wrap: wrap;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 15px;
}
.legend-color {
width: 24px;
height: 24px;
border-radius: 4px;
}
.legend-unchanged { background: transparent; border: 1px solid
.legend-inserted { background: rgba(46, 204, 113, 0.25); }
.legend-deleted { background: rgba(231, 76, 60, 0.25); }
.legend-changed { background: rgba(241, 196, 15, 0.3); }
.stats {
text-align: center;
padding: 20px;
background: rgba(30, 50, 80, 0.8);
border-radius: 12px;
margin-top: 25px;
font-size: 18px;
display: flex;
justify-content: center;
gap: 40px;
flex-wrap: wrap;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
min-width: 120px;
}
.stat-value {
font-size: 2rem;
font-weight: bold;
margin-top: 8px;
}
.added { color:
.removed { color:
.modified { color:
.instructions {
background: rgba(30, 50, 80, 0.8);
padding: 25px;
border-radius: 12px;
margin: 30px 0;
font-size: 16px;
line-height: 1.7;
}
.instructions h3 {
color:
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.instructions ul {
padding-left: 30px;
margin: 15px 0;
}
.instructions li {
margin-bottom: 12px;
}
footer {
text-align: center;
padding: 25px 0;
color:
font-size: 15px;
border-top: 1px solid rgba(100, 150, 255, 0.2);
margin-top: 30px;
}
@media (max-width: 1100px) {
.main-content {
grid-template-columns: 1fr;
}
.controls {
grid-template-columns: 1fr;
}
.comparison-container {
flex-direction: column;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1><i class="fas fa-code-compare"></i> 代码对比工具</h1>
<p class="subtitle">可视化比较两段代码的差异,支持多种编程语言,快速识别代码变化</p>
</header>
<div class="instructions">
<h3><i class="fas fa-info-circle"></i> 使用说明</h3>
<ul>
<li>在左侧输入原始代码,在右侧输入修改后的代码</li>
<li>点击"对比代码"按钮查看差异分析结果</li>
<li>绿色背景表示新增的代码行</li>
<li>红色背景表示删除的代码行</li>
<li>黄色背景表示修改的代码行</li>
<li>使用"导出结果"按钮将对比结果保存为HTML文件</li>
</ul>
</div>
<div class="main-content">
<div class="panel">
<div class="panel-header">
<h2 class="panel-title"><i class="fas fa-file-code"></i> 原始代码</h2>
</div>
<textarea id="original-code" class="code-input" placeholder="在此输入原始代码...">function factorial(n) {
if (n === 0) {
return 1;
}
return n * factorial(n - 1);
}
console.log(factorial(5));</textarea>
</div>
<div class="panel">
<div class="panel-header">
<h2 class="panel-title"><i class="fas fa-file-code"></i> 修改后代码</h2>
</div>
<textarea id="modified-code" class="code-input" placeholder="在此输入修改后的代码...">function factorial(n) {
// 基本情况:0的阶乘为1
if (n <= 0) {
return 1;
}
// 递归计算阶乘
return n * factorial(n - 1);
}
// 测试多个数字
[5, 6, 7].forEach(num => {
console.log(`阶乘(${num}) = ${factorial(num)}`);
});</textarea>
</div>
</div>
<div class="controls">
<button class="btn btn-compare" onclick="compareCode()">
<i class="fas fa-exchange-alt"></i> 对比代码
</button>
<button class="btn btn-export" onclick="exportResults()">
<i class="fas fa-download"></i> 导出结果
</button>
<button class="btn btn-clear" onclick="clearCode()">
<i class="fas fa-trash-alt"></i> 清除代码
</button>
</div>
<h2 class="comparison-title"><i class="fas fa-chart-bar"></i> 代码差异分析</h2>
<div class="comparison-container">
<div class="comparison-panel">
<div class="comparison-header">
<span><i class="fas fa-file-alt"></i> 原始代码版本</span>
<span>行数: <span id="original-lines">0</span></span>
</div>
<div id="original-comparison" class="comparison-content">
<div class="line unchanged">
<div class="line-number">1</div>
<div class="line-content">代码对比结果将显示在这里</div>
</div>
</div>
</div>
<div class="comparison-panel">
<div class="comparison-header">
<span><i class="fas fa-file-code"></i> 修改后代码版本</span>
<span>行数: <span id="modified-lines">0</span></span>
</div>
<div id="modified-comparison" class="comparison-content">
<div class="line unchanged">
<div class="line-number">1</div>
<div class="line-content">代码对比结果将显示在这里</div>
</div>
</div>
</div>
</div>
<div class="legend">
<div class="legend-item">
<div class="legend-color legend-unchanged"></div>
<span>未更改的行</span>
</div>
<div class="legend-item">
<div class="legend-color legend-inserted"></div>
<span>新增的行</span>
</div>
<div class="legend-item">
<div class="legend-color legend-deleted"></div>
<span>删除的行</span>
</div>
<div class="legend-item">
<div class="legend-color legend-changed"></div>
<span>修改的行</span>
</div>
</div>
<div class="stats">
<div class="stat-item">
<span>新增行数</span>
<div class="stat-value added" id="added-lines">0</div>
</div>
<div class="stat-item">
<span>删除行数</span>
<div class="stat-value removed" id="removed-lines">0</div>
</div>
<div class="stat-item">
<span>修改行数</span>
<div class="stat-value modified" id="modified-lines">0</div>
</div>
<div class="stat-item">
<span>总差异</span>
<div class="stat-value" id="total-changes">0</div>
</div>
</div>
<footer>
<p>代码对比工具 © 2023 | 纯前端实现,无需服务器支持</p>
<p>使用JavaScript实现代码差异分析算法</p>
</footer>
</div>
<script>
// 代码对比函数
function compareCode() {
const originalCode = document.getElementById('original-code').value;
const modifiedCode = document.getElementById('modified-code').value;
// 分割代码为行数组
const originalLines = originalCode.split('\n');
const modifiedLines = modifiedCode.split('\n');
// 更新行数统计
document.getElementById('original-lines').textContent = originalLines.length;
document.getElementById('modified-lines').textContent = modifiedLines.length;
// 计算差异
const diff = calculateDiff(originalLines, modifiedLines);
// 渲染结果
renderComparison(diff);
}
// 计算代码差异
function calculateDiff(original, modified) {
const diff = [];
let i = 0, j = 0;
let added = 0, removed = 0, modifiedCount = 0;
while (i < original.length || j < modified.length) {
if (i < original.length && j < modified.length && original[i] === modified[j]) {
// 未更改的行
diff.push({
type: 'unchanged',
original: original[i],
modified: modified[j],
originalLine: i+1,
modifiedLine: j+1
});
i++;
j++;
} else {
// 检查是否有删除
let found = false;
for (let k = i + 1; k <= original.length; k++) {
if (j < modified.length && k < original.length && original[k] === modified[j]) {
for (let m = i; m < k; m++) {
diff.push({
type: 'deleted',
original: original[m],
modified: null,
originalLine: m+1,
modifiedLine: null
});
removed++;
}
i = k;
found = true;
break;
}
}
// 检查是否有添加
if (!found) {
for (let k = j + 1; k <= modified.length; k++) {
if (i < original.length && k < modified.length && modified[k] === original[i]) {
for (let m = j; m < k; m++) {
diff.push({
type: 'inserted',
original: null,
modified: modified[m],
originalLine: null,
modifiedLine: m+1
});
added++;
}
j = k;
found = true;
break;
}
}
}
// 检查是否有修改
if (!found && i < original.length && j < modified.length) {
diff.push({
type: 'changed',
original: original[i],
modified: modified[j],
originalLine: i+1,
modifiedLine: j+1
});
modifiedCount++;
i++;
j++;
}
// 处理末尾行
if (!found && i >= original.length && j < modified.length) {
diff.push({
type: 'inserted',
original: null,
modified: modified[j],
originalLine: null,
modifiedLine: j+1
});
added++;
j++;
} else if (!found && j >= modified.length && i < original.length) {
diff.push({
type: 'deleted',
original: original[i],
modified: null,
originalLine: i+1,
modifiedLine: null
});
removed++;
i++;
}
}
}
// 更新统计信息
document.getElementById('added-lines').textContent = added;
document.getElementById('removed-lines').textContent = removed;
document.getElementById('modified-lines').textContent = modifiedCount;
document.getElementById('total-changes').textContent = added + removed + modifiedCount;
return diff;
}
// 渲染对比结果
function renderComparison(diff) {
const originalContainer = document.getElementById('original-comparison');
const modifiedContainer = document.getElementById('modified-comparison');
originalContainer.innerHTML = '';
modifiedContainer.innerHTML = '';
diff.forEach(item => {
// 原始代码列
if (item.original !== null) {
const originalLine = document.createElement('div');
originalLine.className = `line ${item.type}`;
originalLine.innerHTML = `
<div class="line-number">${item.originalLine}</div>
<div class="line-content">${escapeHtml(item.original)}</div>
`;
originalContainer.appendChild(originalLine);
} else {
// 空行占位
const emptyLine = document.createElement('div');
emptyLine.className = 'line';
emptyLine.innerHTML = `
<div class="line-number"></div>
<div class="line-content"></div>
`;
originalContainer.appendChild(emptyLine);
}
// 修改后代码列
if (item.modified !== null) {
const modifiedLine = document.createElement('div');
modifiedLine.className = `line ${item.type}`;
modifiedLine.innerHTML = `
<div class="line-number">${item.modifiedLine}</div>
<div class="line-content">${escapeHtml(item.modified)}</div>
`;
modifiedContainer.appendChild(modifiedLine);
} else {
// 空行占位
const emptyLine = document.createElement('div');
emptyLine.className = 'line';
emptyLine.innerHTML = `
<div class="line-number"></div>
<div class="line-content"></div>
`;
modifiedContainer.appendChild(emptyLine);
}
});
}
// 导出结果
function exportResults() {
const originalCode = document.getElementById('original-code').value;
const modifiedCode = document.getElementById('modified-code').value;
if (!originalCode && !modifiedCode) {
alert('请输入要比较的代码');
return;
}
// 创建导出内容
const exportContent = `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>代码对比结果</title>
<style>
body {
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
background:
color:
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
header {
text-align: center;
padding: 20px 0;
margin-bottom: 20px;
border-bottom: 1px solid
}
h1 {
color:
margin-bottom: 10px;
}
.comparison-container {
display: flex;
gap: 20px;
margin-bottom: 30px;
}
.comparison-panel {
flex: 1;
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.comparison-header {
padding: 12px 15px;
background:
color: white;
font-weight: bold;
}
.comparison-content {
padding: 15px;
font-family: 'Consolas', monospace;
font-size: 14px;
line-height: 1.5;
}
.line {
padding: 4px 6px;
display: flex;
margin-bottom: 2px;
}
.line-number {
min-width: 30px;
padding-right: 10px;
text-align: right;
color:
}
.line-content {
flex: 1;
}
.inserted { background:
.deleted { background:
.changed { background:
</style>
</head>
<body>
<div class="container">
<header>
<h1>代码对比结果</h1>
<p>生成时间: ${new Date().toLocaleString()}</p>
</header>
<div class="comparison-container">
<div class="comparison-panel">
<div class="comparison-header">原始代码</div>
<div class="comparison-content">
${document.getElementById('original-comparison').innerHTML}
</div>
</div>
<div class="comparison-panel">
<div class="comparison-header">修改后代码</div>
<div class="comparison-content">
${document.getElementById('modified-comparison').innerHTML}
</div>
</div>
</div>
</div>
</body>
</html>
`;
// 创建下载链接
const blob = new Blob([exportContent], {type: 'text/html'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = '代码对比结果.html';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
alert('导出成功!文件已保存为 "代码对比结果.html"');
}
// 清除代码
function clearCode() {
document.getElementById('original-code').value = '';
document.getElementById('modified-code').value = '';
document.getElementById('original-comparison').innerHTML = '';
document.getElementById('modified-comparison').innerHTML = '';
document.getElementById('original-lines').textContent = '0';
document.getElementById('modified-lines').textContent = '0';
document.getElementById('added-lines').textContent = '0';
document.getElementById('removed-lines').textContent = '0';
document.getElementById('modified-lines').textContent = '0';
document.getElementById('total-changes').textContent = '0';
}
// HTML转义函数
function escapeHtml(unsafe) {
if (!unsafe) return '';
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "&
}
// 页面加载时自动对比示例代码
window.onload = function() {
setTimeout(compareCode, 500);
};
</script>
</body>
</html>
源码链接:
通过网盘分享的文件:代码对比工具
链接: https://pan.baidu.com/s/1ENpyCEf2tZDnSyB61YDVCA
提取码: 9bcb