feat:集成vue-diff-view完善FileDiff功能

This commit is contained in:
czhqwer
2025-04-04 00:25:56 +08:00
parent de1768381e
commit 570e4edf4d
3 changed files with 168 additions and 39 deletions

View File

@@ -8,6 +8,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@jafri/vue-diff-view": "^0.7.0",
"axios": "^1.8.1",
"axios-extra": "^0.0.8",
"core-js": "^3.8.3",
@@ -28,6 +29,7 @@
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@babel/plugin-transform-class-properties": "^7.25.9",
"@babel/plugin-transform-class-static-block": "^7.26.0",
"@babel/plugin-transform-private-methods": "^7.25.9",
"@babel/preset-env": "^7.26.9",
"@vue/cli-plugin-babel": "~5.0.0",

View File

@@ -1,4 +1,3 @@
<!-- Toolbox.vue -->
<template>
<div class="toolbox-container">
<el-row :gutter="20" class="tools-grid">
@@ -7,6 +6,7 @@
class="tool-card"
@click.native="openTool(tool)"
shadow="hover"
:style="{ '--tool-color': tool.color }"
>
<div class="tool-item">
<i :class="tool.icon" class="tool-icon"></i>
@@ -136,7 +136,7 @@ export default {
left: 0;
width: 100%;
height: 4px;
background: v-bind('tools[$index].color');
background: var(--tool-color);
}
/* 自定义模态框样式 */
@@ -161,4 +161,12 @@ export default {
padding: 20px;
background: #ffffff;
}
:deep(.el-card.is-hover-shadow:hover)::before {
display: none;
}
:deep(.el-card.is-hover-shadow)::before {
display: none;
}
</style>

View File

@@ -1,61 +1,180 @@
<template>
<div class="file-diff">
<el-row :gutter="20">
<el-col :span="12">
<el-input type="textarea" v-model="text1" placeholder="输入第一个文件内容" :rows="8"></el-input>
</el-col>
<el-col :span="12">
<el-input type="textarea" v-model="text2" placeholder="输入第二个文件内容" :rows="8"></el-input>
</el-col>
</el-row>
<el-button type="primary" @click="compare" class="action-btn">比较</el-button>
<div v-if="diffHtml" v-html="diffHtml" class="diff-container"></div>
<div id="app" class="app">
<div v-if="!showDiff">
<div class="input-container">
<div class="text-area-wrapper">
<label>原始文本</label>
<textarea v-model="oldStr" rows="30" class="text-area"></textarea>
</div>
<div class="text-area-wrapper">
<label>新文本</label>
<textarea v-model="newStr" rows="30" class="text-area"></textarea>
</div>
</div>
<div class="button-container">
<button @click="handleCompare" class="compare-button">开始比对</button>
</div>
</div>
<div v-else class="diff-container">
<div class="diff-header">
<button @click="showDiff = false" class="back-button">返回编辑</button>
</div>
<div class="diff-content">
<code-diff-viewer
:new-content="processedNewStr"
:old-content="processedOldStr"
title="文本比对结果"
:language="'javascript'"
:theme="'light'"
:show-line-numbers="true"
:split-view="true"
:hide-line-numbers="false"
:context="3"
/>
</div>
</div>
</div>
</template>
<script>
import { createTwoFilesPatch } from 'diff';
import { Diff2Html } from 'diff2html';
import 'diff2html/bundles/css/diff2html.min.css';
import CodeDiffViewer from '@jafri/vue-diff-view';
import 'highlight.js/styles/github.css';
export default {
name: 'FileDiff',
components: {
CodeDiffViewer
},
data() {
return {
text1: '',
text2: '',
diffHtml: ''
showDiff: false,
oldStr: '',
newStr: '',
processedOldStr: '',
processedNewStr: ''
};
},
methods: {
compare() {
// 生成 Diff
const diff = createTwoFilesPatch('File1', 'File2', this.text1, this.text2);
// 解析 Diff 并生成 HTML
this.diffHtml = Diff2Html.getPrettyHtml(diff, {
inputFormat: 'diff',
outputFormat: 'side-by-side', // 或 "line-by-line"
drawFileList: false
});
processText(text) {
// 确保文本以换行符结尾
return text.trim() + '\n';
},
handleCompare() {
this.processedOldStr = this.processText(this.oldStr);
this.processedNewStr = this.processText(this.newStr);
this.showDiff = true;
}
}
};
</script>
<style scoped>
.file-diff {
.app {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
padding: 10px;
box-sizing: border-box;
}
.action-btn {
margin-top: 15px;
.input-container {
display: flex;
gap: 20px;
margin-bottom: 20px;
min-height: 0;
}
.text-area-wrapper {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
}
.text-area {
width: 100%;
padding: 10px;
border: 1px solid #dcdfe6;
border-radius: 4px;
font-family: monospace;
resize: vertical;
max-height: 300px;
min-height: 100px;
flex: 1;
}
.button-container {
text-align: center;
margin: 10px 0;
flex-shrink: 0;
}
.compare-button, .back-button {
padding: 8px 16px;
background-color: #409eff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.compare-button:hover, .back-button:hover {
background-color: #66b1ff;
}
.diff-header {
margin-bottom: 10px;
flex-shrink: 0;
}
label {
display: block;
margin-bottom: 4px;
font-weight: bold;
flex-shrink: 0;
}
.diff-container {
margin-top: 20px;
border: 1px solid #ddd;
padding: 10px;
background: #f8f8f8;
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
}
</style>
.diff-content {
flex: 1;
overflow: auto;
max-height: calc(100vh - 300px);
border: 1px solid #dcdfe6;
border-radius: 4px;
min-height: 0;
padding-bottom: 20px;
}
:deep(.diff-viewer) {
height: 100%;
overflow: visible;
border: none !important;
margin-bottom: 0 !important;
}
:deep(.diff-viewer .diff-content) {
max-height: none;
padding-bottom: 20px;
}
:deep(.diff-viewer .diff-line) {
min-height: 20px;
line-height: 20px;
}
:deep(.diff-viewer .diff-line-content) {
padding: 2px 0;
}
:deep(.container) {
height: 400px;
border: none;
}
</style>