@form-create/vant-designer
Version:
基于Vant的移动端低代码可视化表单设计器,可以通过拖拽的方式快速创建表单,提高开发者对表单的开发效率。
174 lines (151 loc) • 5.18 kB
JavaScript
/**
* JSON 差异比较工具
* 用于比较两个 JSON 对象并生成差异信息
*/
/**
* 计算最长公共子序列(LCS)
* @param {Array} oldLines - 旧的行数组
* @param {Array} newLines - 新的行数组
* @returns {Array} LCS 矩阵
*/
function computeLCS(oldLines, newLines) {
const m = oldLines.length;
const n = newLines.length;
const lcs = Array(m + 1)
.fill(null)
.map(() => Array(n + 1).fill(0));
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (oldLines[i - 1] === newLines[j - 1]) {
lcs[i][j] = lcs[i - 1][j - 1] + 1;
} else {
lcs[i][j] = Math.max(lcs[i - 1][j], lcs[i][j - 1]);
}
}
}
return lcs;
}
/**
* 根据 LCS 矩阵生成差异操作序列
* @param {Array} lcs - LCS 矩阵
* @param {Array} oldLines - 旧的行数组
* @param {Array} newLines - 新的行数组
* @param {number} i - 当前旧行索引
* @param {number} j - 当前新行索引
* @returns {Array} 差异操作数组
*/
function generateDiffOps(lcs, oldLines, newLines, i = oldLines.length, j = newLines.length) {
if (i === 0 && j === 0) {
return [];
}
if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
const ops = generateDiffOps(lcs, oldLines, newLines, i - 1, j - 1);
ops.push({
type: 'unchanged',
oldLine: oldLines[i - 1],
newLine: newLines[j - 1],
oldLineIndex: i - 1,
newLineIndex: j - 1,
});
return ops;
}
if (j > 0 && (i === 0 || lcs[i][j - 1] >= lcs[i - 1][j])) {
const ops = generateDiffOps(lcs, oldLines, newLines, i, j - 1);
ops.push({
type: 'added',
oldLine: '',
newLine: newLines[j - 1],
oldLineIndex: -1,
newLineIndex: j - 1,
});
return ops;
}
if (i > 0 && (j === 0 || lcs[i][j - 1] < lcs[i - 1][j])) {
const ops = generateDiffOps(lcs, oldLines, newLines, i - 1, j);
ops.push({
type: 'removed',
oldLine: oldLines[i - 1],
newLine: '',
oldLineIndex: i - 1,
newLineIndex: -1,
});
return ops;
}
return [];
}
/**
* 生成行级别的差异显示
* @param {Object} oldJson - 旧的 JSON 对象
* @param {Object} newJson - 新的 JSON 对象
* @param {number} contextLines - 上下文行数,默认5行
* @returns {Array} 行级别的差异数组
*/
export function generateLineDiff(oldJson, newJson, contextLines = 5) {
const oldStr = JSON.stringify(oldJson, null, 2);
const newStr = JSON.stringify(newJson, null, 2);
const oldLines = oldStr.split('\n');
const newLines = newStr.split('\n');
// 使用 LCS 算法计算差异
const lcs = computeLCS(oldLines, newLines);
const diffOps = generateDiffOps(lcs, oldLines, newLines);
// 找出所有有差异的行的索引
const changedIndices = new Set();
diffOps.forEach((op, index) => {
if (op.type !== 'unchanged') {
changedIndices.add(index);
}
});
// 如果没有差异,返回空数组
if (changedIndices.size === 0) {
return [];
}
// 找出需要显示的行(差异行 + 上下文)
const showIndices = new Set();
// 将连续的差异行合并为块
const changeBlocks = [];
const sortedChangedIndices = Array.from(changedIndices).sort((a, b) => a - b);
let currentBlock = { start: sortedChangedIndices[0], end: sortedChangedIndices[0] };
for (let i = 1; i < sortedChangedIndices.length; i++) {
if (sortedChangedIndices[i] === currentBlock.end + 1) {
currentBlock.end = sortedChangedIndices[i];
} else {
changeBlocks.push(currentBlock);
currentBlock = { start: sortedChangedIndices[i], end: sortedChangedIndices[i] };
}
}
changeBlocks.push(currentBlock);
// 为每个差异块添加上下文
changeBlocks.forEach(block => {
// 添加差异行本身
for (let i = block.start; i <= block.end; i++) {
showIndices.add(i);
}
// 添加上下文行
for (let i = 1; i <= contextLines; i++) {
// 前面的上下文
if (block.start - i >= 0) {
showIndices.add(block.start - i);
}
// 后面的上下文
if (block.end + i < diffOps.length) {
showIndices.add(block.end + i);
}
}
});
// 生成最终结果,只包含需要显示的行
const result = [];
const sortedIndices = Array.from(showIndices).sort((a, b) => a - b);
sortedIndices.forEach(index => {
const op = diffOps[index];
result.push({
type: op.type,
oldLine: op.oldLine,
newLine: op.newLine,
lineNumber: index + 1,
originalIndex: index,
isSame: op.type === 'unchanged',
isContext: op.type === 'unchanged' && !changedIndices.has(index),
});
});
return result;
}