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
+2
View File
@@ -8,6 +8,7 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@jafri/vue-diff-view": "^0.7.0",
"axios": "^1.8.1", "axios": "^1.8.1",
"axios-extra": "^0.0.8", "axios-extra": "^0.0.8",
"core-js": "^3.8.3", "core-js": "^3.8.3",
@@ -28,6 +29,7 @@
"@babel/core": "^7.12.16", "@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16", "@babel/eslint-parser": "^7.12.16",
"@babel/plugin-transform-class-properties": "^7.25.9", "@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/plugin-transform-private-methods": "^7.25.9",
"@babel/preset-env": "^7.26.9", "@babel/preset-env": "^7.26.9",
"@vue/cli-plugin-babel": "~5.0.0", "@vue/cli-plugin-babel": "~5.0.0",
@@ -1,4 +1,3 @@
<!-- Toolbox.vue -->
<template> <template>
<div class="toolbox-container"> <div class="toolbox-container">
<el-row :gutter="20" class="tools-grid"> <el-row :gutter="20" class="tools-grid">
@@ -7,6 +6,7 @@
class="tool-card" class="tool-card"
@click.native="openTool(tool)" @click.native="openTool(tool)"
shadow="hover" shadow="hover"
:style="{ '--tool-color': tool.color }"
> >
<div class="tool-item"> <div class="tool-item">
<i :class="tool.icon" class="tool-icon"></i> <i :class="tool.icon" class="tool-icon"></i>
@@ -136,7 +136,7 @@ export default {
left: 0; left: 0;
width: 100%; width: 100%;
height: 4px; height: 4px;
background: v-bind('tools[$index].color'); background: var(--tool-color);
} }
/* 自定义模态框样式 */ /* 自定义模态框样式 */
@@ -161,4 +161,12 @@ export default {
padding: 20px; padding: 20px;
background: #ffffff; background: #ffffff;
} }
:deep(.el-card.is-hover-shadow:hover)::before {
display: none;
}
:deep(.el-card.is-hover-shadow)::before {
display: none;
}
</style> </style>
@@ -1,61 +1,180 @@
<template> <template>
<div class="file-diff"> <div id="app" class="app">
<el-row :gutter="20"> <div v-if="!showDiff">
<el-col :span="12"> <div class="input-container">
<el-input type="textarea" v-model="text1" placeholder="输入第一个文件内容" :rows="8"></el-input> <div class="text-area-wrapper">
</el-col> <label>原始文本</label>
<el-col :span="12"> <textarea v-model="oldStr" rows="30" class="text-area"></textarea>
<el-input type="textarea" v-model="text2" placeholder="输入第二个文件内容" :rows="8"></el-input> </div>
</el-col> <div class="text-area-wrapper">
</el-row> <label>新文本</label>
<textarea v-model="newStr" rows="30" class="text-area"></textarea>
<el-button type="primary" @click="compare" class="action-btn">比较</el-button> </div>
</div>
<div v-if="diffHtml" v-html="diffHtml" class="diff-container"></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> </div>
</template> </template>
<script> <script>
import { createTwoFilesPatch } from 'diff'; import CodeDiffViewer from '@jafri/vue-diff-view';
import { Diff2Html } from 'diff2html'; import 'highlight.js/styles/github.css';
import 'diff2html/bundles/css/diff2html.min.css';
export default { export default {
name: 'FileDiff', name: 'FileDiff',
components: {
CodeDiffViewer
},
data() { data() {
return { return {
text1: '', showDiff: false,
text2: '', oldStr: '',
diffHtml: '' newStr: '',
processedOldStr: '',
processedNewStr: ''
}; };
}, },
methods: { methods: {
compare() { processText(text) {
// 生成 Diff // 确保文本以换行符结尾
const diff = createTwoFilesPatch('File1', 'File2', this.text1, this.text2); return text.trim() + '\n';
},
// 解析 Diff 并生成 HTML handleCompare() {
this.diffHtml = Diff2Html.getPrettyHtml(diff, { this.processedOldStr = this.processText(this.oldStr);
inputFormat: 'diff', this.processedNewStr = this.processText(this.newStr);
outputFormat: 'side-by-side', // 或 "line-by-line" this.showDiff = true;
drawFileList: false
});
} }
} }
}; };
</script> </script>
<style scoped> <style scoped>
.file-diff { .app {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
padding: 10px; 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 { .diff-container {
margin-top: 20px; height: 100%;
border: 1px solid #ddd; display: flex;
padding: 10px; flex-direction: column;
background: #f8f8f8; min-height: 0;
}
.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> </style>