feat: 添加父目录跟踪功能,优化目录和文件的路径构建逻辑
This commit is contained in:
1 parent
6431049d05
commit
de7af2f650
2 files changed
+146
-21
No files matched your search
@@ -14,6 +14,7 @@
|
||||
activatable
|
||||
open-on-click
|
||||
:return-object="false"
|
||||
:hoverable="true"
|
||||
>
|
||||
<template #prepend="{ item }">
|
||||
<v-icon
|
||||
@@ -202,12 +203,14 @@ const emit = defineEmits([
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Tree node styling */
|
||||
:deep(.v-treeview-node__root),
|
||||
:deep(.v-treeview-node__children .v-treeview-node__root) {
|
||||
padding: 4px;
|
||||
margin: 2px 0;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:deep(.v-treeview-node__root:hover),
|
||||
@@ -215,7 +218,47 @@ const emit = defineEmits([
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
/* Indentation guides to show hierarchy */
|
||||
:deep(.v-treeview-node__level) {
|
||||
margin-right: 4px;
|
||||
margin-right: 8px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Vertical connector lines */
|
||||
:deep(.v-treeview-node) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Add connector lines */
|
||||
:deep(.v-treeview-node::before) {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 12px;
|
||||
width: 1px;
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Horizontal connector lines for children */
|
||||
:deep(.v-treeview-node__children) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:deep(.v-treeview-node__children::before) {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -16px;
|
||||
width: 16px;
|
||||
height: 1px;
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
/* Hide connector for root level */
|
||||
:deep(.v-treeview > .v-treeview-node > .v-treeview-node__root::before),
|
||||
:deep(.v-treeview > .v-treeview-node > .v-treeview-node__children::before) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -336,6 +336,7 @@ const newDirectoryPath = ref('')
|
||||
const newFilePath = ref('')
|
||||
const editingFile = ref<{ path: string; content: string } | null>(null)
|
||||
const editingFileContent = ref('')
|
||||
const parentDirectoryForNewItems = ref<string | null>(null) // Track parent context
|
||||
|
||||
// Tree state
|
||||
const expandedNodes = ref<string[]>([])
|
||||
@@ -356,28 +357,84 @@ const files = ref<{ path: string; content: string }[]>([])
|
||||
// Computed
|
||||
const isEditMode = computed(() => !!route.params.id)
|
||||
const treeItems = computed<TreeItem[]>(() => {
|
||||
const items: TreeItem[] = []
|
||||
|
||||
// Add directories
|
||||
directories.value.forEach((dir) => {
|
||||
items.push({
|
||||
id: `dir-${dir.path}`,
|
||||
name: dir.path,
|
||||
// Create root structure
|
||||
const root: TreeItem = {
|
||||
id: 'root',
|
||||
name: 'root',
|
||||
type: 'directory',
|
||||
children: []
|
||||
})
|
||||
}
|
||||
|
||||
// Process each directory
|
||||
directories.value.forEach((dir) => {
|
||||
const pathParts = dir.path.split('/').filter(part => part !== '') // Split path and remove empty parts
|
||||
let currentLevel = root.children || []
|
||||
|
||||
// Navigate/create the directory structure
|
||||
for (let i = 0; i < pathParts.length; i++) {
|
||||
const part = pathParts[i]
|
||||
const isLastPart = i === pathParts.length - 1
|
||||
|
||||
// Check if this part already exists in the current level
|
||||
let existingItem = currentLevel.find(item => item.name === part)
|
||||
|
||||
if (!existingItem) {
|
||||
// Create new directory item
|
||||
const newDir: TreeItem = {
|
||||
id: `dir-${part}-${Date.now()}-${Math.random()}`, // Unique ID
|
||||
name: part,
|
||||
type: 'directory',
|
||||
children: []
|
||||
}
|
||||
currentLevel.push(newDir)
|
||||
existingItem = newDir
|
||||
}
|
||||
|
||||
// Move to the next level if not the last part
|
||||
if (!isLastPart && existingItem.children) {
|
||||
currentLevel = existingItem.children
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Add files
|
||||
// Process each file and add to the appropriate directory
|
||||
files.value.forEach((file) => {
|
||||
items.push({
|
||||
id: `file-${file.path}`,
|
||||
name: file.path,
|
||||
const pathParts = file.path.split('/').filter(part => part !== '')
|
||||
const fileName = pathParts.pop() // Get the last part as filename
|
||||
|
||||
if (!fileName) return // Skip if no filename
|
||||
|
||||
let currentLevel = root.children || []
|
||||
|
||||
// Navigate to the appropriate directory for the file
|
||||
for (let i = 0; i < pathParts.length; i++) {
|
||||
const part = pathParts[i]
|
||||
const dirItem = currentLevel.find(item => item.name === part && item.type === 'directory')
|
||||
|
||||
if (dirItem && dirItem.children) {
|
||||
currentLevel = dirItem.children
|
||||
} else {
|
||||
// If the directory doesn't exist, create it
|
||||
const newDir: TreeItem = {
|
||||
id: `dir-${part}-${Date.now()}-${Math.random()}`,
|
||||
name: part,
|
||||
type: 'directory',
|
||||
children: []
|
||||
}
|
||||
currentLevel.push(newDir)
|
||||
currentLevel = newDir.children || []
|
||||
}
|
||||
}
|
||||
|
||||
// Add the file to the current level
|
||||
currentLevel.push({
|
||||
id: `file-${fileName}-${Date.now()}-${Math.random()}`,
|
||||
name: fileName,
|
||||
type: 'file'
|
||||
})
|
||||
})
|
||||
|
||||
return items
|
||||
return root.children || []
|
||||
})
|
||||
|
||||
// Validation rules
|
||||
@@ -459,21 +516,24 @@ const addRootFile = () => {
|
||||
const addDirectory = (parentItem: TreeItem | null = null) => {
|
||||
showContextMenuVar.value = false
|
||||
currentContextItem.value = parentItem
|
||||
newDirectoryPath.value = parentItem ? `${parentItem.name}/` : ''
|
||||
parentDirectoryForNewItems.value = parentItem ? parentItem.name : null // Store parent context
|
||||
newDirectoryPath.value = '' // Don't pre-fill the path
|
||||
showDirectoryDialog.value = true
|
||||
autoFocusDirectoryInput()
|
||||
}
|
||||
|
||||
const addFile = (parentItem: TreeItem | null = null) => {
|
||||
showContextMenuVar.value = false
|
||||
newFilePath.value = parentItem ? `${parentItem.name}/` : ''
|
||||
parentDirectoryForNewItems.value = parentItem ? parentItem.name : null // Store parent context
|
||||
newFilePath.value = '' // Don't pre-fill the path
|
||||
showFileDialog.value = true
|
||||
autoFocusFileInput()
|
||||
}
|
||||
|
||||
const addNewItemToCurrentDirectory = (directoryItem: TreeItem) => {
|
||||
currentContextItem.value = directoryItem
|
||||
newDirectoryPath.value = directoryItem ? `${directoryItem.name}/` : ''
|
||||
parentDirectoryForNewItems.value = directoryItem.name // Store parent context
|
||||
newDirectoryPath.value = '' // Don't pre-fill the path
|
||||
showDirectoryDialog.value = true
|
||||
autoFocusDirectoryInput()
|
||||
}
|
||||
@@ -481,9 +541,19 @@ const addNewItemToCurrentDirectory = (directoryItem: TreeItem) => {
|
||||
const confirmAddDirectory = () => {
|
||||
if (!newDirectoryPath.value.trim()) return
|
||||
|
||||
// Construct the full path if there's a parent directory
|
||||
let fullPath = newDirectoryPath.value
|
||||
if (parentDirectoryForNewItems.value) {
|
||||
// Make sure parent directory ends with a slash before appending
|
||||
const parentPath = parentDirectoryForNewItems.value.endsWith('/')
|
||||
? parentDirectoryForNewItems.value
|
||||
: parentDirectoryForNewItems.value + '/'
|
||||
fullPath = parentPath + newDirectoryPath.value
|
||||
}
|
||||
|
||||
// Check for duplicates
|
||||
const exists = directories.value.some(
|
||||
(d) => d.path === newDirectoryPath.value
|
||||
(d) => d.path === fullPath
|
||||
)
|
||||
if (exists) {
|
||||
showSnackbar('该目录路径已存在!')
|
||||
@@ -491,26 +561,37 @@ const confirmAddDirectory = () => {
|
||||
}
|
||||
|
||||
directories.value.push({
|
||||
path: newDirectoryPath.value
|
||||
path: fullPath
|
||||
})
|
||||
|
||||
showDirectoryDialog.value = false
|
||||
newDirectoryPath.value = ''
|
||||
parentDirectoryForNewItems.value = null // Clear parent context after creation
|
||||
currentContextItem.value = null
|
||||
}
|
||||
|
||||
const confirmAddFile = () => {
|
||||
if (!newFilePath.value.trim()) return
|
||||
|
||||
// Construct the full path if there's a parent directory
|
||||
let fullPath = newFilePath.value
|
||||
if (parentDirectoryForNewItems.value) {
|
||||
// Make sure parent directory ends with a slash before appending
|
||||
const parentPath = parentDirectoryForNewItems.value.endsWith('/')
|
||||
? parentDirectoryForNewItems.value
|
||||
: parentDirectoryForNewItems.value + '/'
|
||||
fullPath = parentPath + newFilePath.value
|
||||
}
|
||||
|
||||
// Check for duplicates
|
||||
const exists = files.value.some((f) => f.path === newFilePath.value)
|
||||
const exists = files.value.some((f) => f.path === fullPath)
|
||||
if (exists) {
|
||||
showSnackbar('该文件路径已存在!')
|
||||
return
|
||||
}
|
||||
|
||||
const newFile = {
|
||||
path: newFilePath.value,
|
||||
path: fullPath,
|
||||
content: ''
|
||||
}
|
||||
|
||||
@@ -521,6 +602,7 @@ const confirmAddFile = () => {
|
||||
|
||||
showFileDialog.value = false
|
||||
newFilePath.value = ''
|
||||
parentDirectoryForNewItems.value = null // Clear parent context after creation
|
||||
currentContextItem.value = null
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user