31
This commit is contained in:
@@ -100,6 +100,93 @@ function getNodeSourceText(source, node) {
|
||||
return source.substring(start, end)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将元素移动到目标元素内部
|
||||
* 如果目标已有子元素,则放到最后
|
||||
*/
|
||||
function moveElementInside(templateContent, sourceNode, targetNode, sourcePath, targetPath) {
|
||||
const sourceStart = sourceNode.loc.start.offset
|
||||
const sourceEnd = sourceNode.loc.end.offset
|
||||
const sourceText = templateContent.substring(sourceStart, sourceEnd)
|
||||
|
||||
// 找到源元素行的开始位置(用于删除整行)
|
||||
const sourceLineStart = templateContent.lastIndexOf('\n', sourceStart - 1) + 1
|
||||
|
||||
// 获取目标元素的缩进(子元素需要比父元素多一层缩进)
|
||||
const targetLineStart = templateContent.lastIndexOf('\n', targetNode.loc.start.offset - 1) + 1
|
||||
const targetIndent = templateContent.substring(targetLineStart, targetNode.loc.start.offset)
|
||||
const childIndent = targetIndent + ' ' // 子元素缩进
|
||||
|
||||
// 找到目标元素的结束标签位置
|
||||
// 目标元素内容的结束位置(结束标签前)
|
||||
const targetText = templateContent.substring(targetNode.loc.start.offset, targetNode.loc.end.offset)
|
||||
const targetTag = targetNode.tag // 'el-row' 或 'el-col'
|
||||
const closeTagPattern = `</${targetTag}>`
|
||||
const closeTagIndex = targetText.lastIndexOf(closeTagPattern)
|
||||
|
||||
if (closeTagIndex === -1) {
|
||||
console.error('[moveElementInside] 未找到结束标签:', targetTag)
|
||||
return templateContent
|
||||
}
|
||||
|
||||
// 计算插入位置(在结束标签之前)
|
||||
const insertPositionInTarget = closeTagIndex
|
||||
const insertPositionInTemplate = targetNode.loc.start.offset + insertPositionInTarget
|
||||
|
||||
// 调整源元素的缩进
|
||||
const sourceLines = sourceText.split('\n')
|
||||
const adjustedSourceLines = sourceLines.map((line, index) => {
|
||||
if (index === 0) {
|
||||
return childIndent + line.trimStart()
|
||||
}
|
||||
// 保持相对缩进
|
||||
return childIndent + line.trimStart()
|
||||
})
|
||||
const adjustedSourceText = adjustedSourceLines.join('\n')
|
||||
|
||||
// 根据源和目标的位置关系进行操作
|
||||
if (sourceStart < targetNode.loc.start.offset) {
|
||||
// 源在目标前面:先删除源,再插入
|
||||
|
||||
// 删除源元素
|
||||
const beforeSource = templateContent.substring(0, sourceLineStart)
|
||||
const afterSource = templateContent.substring(sourceEnd)
|
||||
let afterSourceTrimmed = afterSource.startsWith('\n') ? afterSource.substring(1) : afterSource
|
||||
const withoutSource = beforeSource + afterSourceTrimmed
|
||||
|
||||
// 计算新的插入位置
|
||||
const removedLength = templateContent.length - withoutSource.length
|
||||
const newInsertPosition = insertPositionInTemplate - removedLength
|
||||
|
||||
// 插入到目标内部
|
||||
const insertText = adjustedSourceText + '\n' + targetIndent
|
||||
|
||||
return withoutSource.substring(0, newInsertPosition) +
|
||||
insertText +
|
||||
withoutSource.substring(newInsertPosition)
|
||||
} else {
|
||||
// 源在目标后面:先插入,再删除
|
||||
|
||||
// 插入到目标内部
|
||||
const insertText = adjustedSourceText + '\n' + targetIndent
|
||||
const withInsert = templateContent.substring(0, insertPositionInTemplate) +
|
||||
insertText +
|
||||
templateContent.substring(insertPositionInTemplate)
|
||||
|
||||
// 计算源元素新位置
|
||||
const insertedLength = insertText.length
|
||||
const newSourceLineStart = sourceLineStart + insertedLength
|
||||
const newSourceEnd = sourceEnd + insertedLength
|
||||
|
||||
// 删除源元素
|
||||
const beforeNewSource = withInsert.substring(0, newSourceLineStart)
|
||||
const afterNewSource = withInsert.substring(newSourceEnd)
|
||||
let afterTrimmed = afterNewSource.startsWith('\n') ? afterNewSource.substring(1) : afterNewSource
|
||||
|
||||
return beforeNewSource + afterTrimmed
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动元素
|
||||
*
|
||||
@@ -107,7 +194,7 @@ function getNodeSourceText(source, node) {
|
||||
* @param {Object} options - 移动选项
|
||||
* @param {string} options.sourcePath - 源元素路径,如 "r1c1"
|
||||
* @param {string} options.targetPath - 目标元素路径,如 "r1c2"
|
||||
* @param {string} options.direction - 移动方向: 'top' | 'bottom' | 'left' | 'right'
|
||||
* @param {string} options.direction - 移动方向: 'top' | 'bottom' | 'left' | 'right' | 'inside'
|
||||
* @returns {Object} - { success: boolean, content?: string, error?: string }
|
||||
*/
|
||||
export function moveElement(vueContent, options) {
|
||||
@@ -194,9 +281,16 @@ export function moveElement(vueContent, options) {
|
||||
const targetLineStart = templateContent.lastIndexOf('\n', targetStart - 1) + 1
|
||||
const targetIndent = templateContent.substring(targetLineStart, targetStart)
|
||||
|
||||
// 判断是否需要先删除源,再插入
|
||||
// 关键:需要考虑源和目标的相对位置
|
||||
if (sourceStart < targetStart) {
|
||||
// 处理 'inside' 方向(放入目标元素内部)
|
||||
if (direction === 'inside') {
|
||||
newTemplateContent = moveElementInside(
|
||||
templateContent,
|
||||
sourceNode,
|
||||
targetNode,
|
||||
sourcePath,
|
||||
targetPath
|
||||
)
|
||||
} else if (sourceStart < targetStart) {
|
||||
// 源在目标前面:先处理目标位置,再删除源
|
||||
const insertPosition = (direction === 'bottom' || direction === 'right')
|
||||
? targetEnd
|
||||
|
||||
Reference in New Issue
Block a user