文本对比

2025-01-12 15:06:05 | 前端Number of visitors 52
<template>
	<div class="compare-container">
		<div class="input-area">
			<el-input
				type="textarea"
				v-model="text1"
				placeholder="请输入第一段文本"
				:autosize="{ minRows: 10, maxRows: 10 }"
			></el-input>

			<el-input
				type="textarea"
				v-model="text2"
				placeholder="请输入第二段文本"
				:autosize="{ minRows: 10, maxRows: 10 }"
			></el-input>
		</div>
		<div class="button-area">
			<el-button type="primary" @click="compare" size="small"
				>比较文本</el-button
			>
			<el-button @click="reset" size="small">重置</el-button>
		</div>
		<div class="input-area">
			<div
				v-html="diffResult1"
				class="text-display"
				v-if="diffResult1"
			></div>
			<div
				v-html="diffResult2"
				class="text-display"
				v-if="diffResult2"
			></div>
		</div>
	</div>
</template>

<script>
export default {
	data() {
		return {
			text1: "",
			text2: "",
			diffResult1: "",
			diffResult2: "",
		};
	},
	methods: {
		compare() {
			if (!this.text1 || !this.text2) {
				this.$message.warning("请输入需要比较的文本");
				return;
			}

			const text1Arr = this.text1.split("");
			const text2Arr = this.text2.split("");
			let result1 = "";
			let result2 = "";

			// 使用动态规划找到最长公共子序列
			// 调用findLCS方法计算两段文本的最长公共子序列(Longest Common Subsequence)
			// 这个方法会返回两段文本中相同的字符序列
			// 例如 text1="ABCD", text2="ACBD", 最长公共子序列为"ABD"
			const lcs = this.findLCS(this.text1, this.text2);

			// 根据最长公共子序列标记差异
			let lcsIndex = 0;
			let i = 0,
				j = 0;

			while (i < text1Arr.length || j < text2Arr.length) {
				if (
					i < text1Arr.length &&
					j < text2Arr.length &&
					lcsIndex < lcs.length &&
					text1Arr[i] === lcs[lcsIndex] &&
					text2Arr[j] === lcs[lcsIndex]
				) {
					// 相同字符
					result1 += text1Arr[i];
					result2 += text2Arr[j];
					i++;
					j++;
					lcsIndex++;
				} else {
					// 差异字符
					if (
						i < text1Arr.length &&
						(lcsIndex >= lcs.length ||
							text1Arr[i] !== lcs[lcsIndex])
					) {
						result1 += `<span style="background-color: #ffd700">${text1Arr[i]}</span>`;
						i++;
					}
					if (
						j < text2Arr.length &&
						(lcsIndex >= lcs.length ||
							text2Arr[j] !== lcs[lcsIndex])
					) {
						result2 += `<span style="background-color: #ffd700">${text2Arr[j]}</span>`;
						j++;
					}
				}
			}

			this.diffResult1 = result1;
			this.diffResult2 = result2;
		},

		// 计算最长公共子序列
		findLCS(text1, text2) {
			const m = text1.length;
			const n = text2.length;
			const dp = Array(m + 1)
				.fill()
				.map(() => Array(n + 1).fill(""));

			for (let i = 1; i <= m; i++) {
				for (let j = 1; j <= n; j++) {
					if (text1[i - 1] === text2[j - 1]) {
						dp[i][j] = dp[i - 1][j - 1] + text1[i - 1];
					} else {
						dp[i][j] =
							dp[i - 1][j].length > dp[i][j - 1].length
								? dp[i - 1][j]
								: dp[i][j - 1];
					}
				}
			}

			return dp[m][n];
		},

		reset() {
			this.text1 = "";
			this.text2 = "";
			this.diffResult1 = "";
			this.diffResult2 = "";
		},
	},
};
</script>

<style scoped>
.compare-container {
	padding: 20px;
}

.input-area {
	display: flex;
	gap: 20px;
	margin-bottom: 20px;
}

.button-area {
	margin-bottom: 20px;
	text-align: center;
}

.result-area {
	padding: 10px;
	border: 1px solid #dcdfe6;
	border-radius: 4px;
	min-height: 100px;
	line-height: 1.5;
}

.text-display {
	width: 100%;
	min-height: 100px;
	border: 1px solid #dcdfe6;
	border-radius: 4px;
	padding: 5px 15px;
	line-height: 1.5;
	white-space: pre-wrap;
	color: #606266;
	font-size: 14px;
	font-family: monospace;
}
</style>



send发送