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