分享一个实用的代码对比工具

分享一个实用的代码对比工具_第1张图片

关键代码如下:

<!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, #1e3c72, #2a5298);
            color: #f0f8ff;
            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, #ff7e5f, #feb47b);
            -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: #c0d6e4;
            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: #4fc3f7;
            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: #e0f7fa;
            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: #4fc3f7;
            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, #3498db, #1abc9c);
            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, #ff7e5f, #feb47b);
        }
        
        .btn-export {
            background: linear-gradient(135deg, #9c27b0, #673ab7);
        }
        
        .btn-clear {
            background: linear-gradient(135deg, #e74c3c, #c0392b);
        }
        
        .comparison-title {
            text-align: center;
            font-size: 1.5rem;
            margin: 30px 0 20px;
            color: #feb47b;
            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: #4fc3f7;
            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: #95a5a6;
            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: #e0f7fa; }
        .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 #3498db; }
        .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: #2ecc71; }
        .removed { color: #e74c3c; }
        .modified { color: #f1c40f; }
        
        .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: #4fc3f7;
            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: #a0c4e0;
            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>代码对比工具 &copy; 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: #f5f7fa;
                        color: #333;
                        padding: 20px;
                    }
                    .container {
                        max-width: 1400px;
                        margin: 0 auto;
                    }
                    header {
                        text-align: center;
                        padding: 20px 0;
                        margin-bottom: 20px;
                        border-bottom: 1px solid #ddd;
                    }
                    h1 {
                        color: #2c3e50;
                        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: #3498db;
                        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: #7f8c8d;
                    }
                    .line-content {
                        flex: 1;
                    }
                    .inserted { background: #e8f5e9; }
                    .deleted { background: #ffebee; }
                    .changed { background: #fff8e1; }
                </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 = '
1
请在上方输入代码并点击对比按钮
'
; document.getElementById('modified-comparison').innerHTML = '
1
请在上方输入代码并点击对比按钮
'
; 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, "&quot;") .replace(/'/g, "&#039;"); } // 页面加载时自动对比示例代码 window.onload = function() { setTimeout(compareCode, 500); }; </script> </body> </html>

源码链接:

通过网盘分享的文件:代码对比工具
链接: https://pan.baidu.com/s/1ENpyCEf2tZDnSyB61YDVCA 
提取码: 9bcb

你可能感兴趣的:(css,css3,javascript)