mirror of
https://gitee.com/czh-dev/upload-hub
synced 2026-09-05 23:47:46 +08:00
feat:集成vue-diff-view完善FileDiff功能
This commit is contained in:
@@ -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>
|
||||||
Reference in New Issue
Block a user