<template>
  <div class="container-file-manager">
    <!-- 页面头部 -->
    <div class="page-header">
      <div class="header-left">
        <h2><el-icon class="header-icon"><Folder /></el-icon> 容器文件管理器</h2>
        <div class="container-info">
          <el-tag type="info" size="small">{{ containerId }}</el-tag>
        </div>
      </div>
      <div class="header-actions">
        <el-button size="default" @click="showUploadDialog = true" :icon="Upload">上传文件</el-button>
        <el-button size="default" @click="showCreateFileDialog = true" :icon="Document">新建文件</el-button>
        <el-button size="default" @click="showCreateFolderDialog = true" :icon="FolderAdd">新建文件夹</el-button>
        <el-button size="default" @click="refreshFileList" :icon="Refresh">刷新</el-button>
        <el-button size="default" @click="goBack" :icon="Back">返回</el-button>
      </div>
    </div>

    <!-- 路径导航 -->
    <div class="path-navigation">
      <div class="path-breadcrumb">
        <span class="path-label">当前路径:</span>
        <el-breadcrumb separator="/">
          <el-breadcrumb-item 
            v-for="(path, index) in breadcrumbPaths" 
            :key="index"
            @click="navigateToPath(index)"
            :class="{ 'breadcrumb-clickable': index < breadcrumbPaths.length - 1 }"
          >
            {{ path.name }}
          </el-breadcrumb-item>
        </el-breadcrumb>
      </div>
    </div>

      <div class="file-manager-container">
        <!-- 左侧文件树 -->
        <div class="file-sidebar">
          <div class="sidebar-header">
            <span class="sidebar-title">文件树</span>
            <div class="sidebar-actions">
              <el-tooltip content="刷新文件树">
                <el-button size="small" text @click="refreshFileList" :icon="Refresh" />
              </el-tooltip>
              <el-tooltip content="展开全部">
                <el-button size="small" text @click="expandAllNodes" :icon="DCaret" />
              </el-tooltip>
              <el-tooltip content="收起全部">
                <el-button size="small" text @click="collapseAllNodes" :icon="CaretRight" />
              </el-tooltip>
            </div>
          </div>
          <div class="file-tree-container">
            <el-scrollbar class="tree-scrollbar">
              <el-tree
                ref="fileTreeRef"
                :data="fileTreeData"
                :props="treeProps"
                :load="loadTreeNode"
                lazy
                :expand-on-click-node="false"
                @node-click="handleTreeNodeClick"
                @node-contextmenu="handleTreeContextMenu"
                node-key="id"
                class="file-tree"
              >
              <template #default="{ node, data }">
                <div class="tree-node-content">
                  <el-icon class="node-icon" :class="{ 'folder-icon': data.type === 'directory', 'file-icon': data.type === 'file' }">
                    <Folder v-if="data.type === 'directory'" />
                    <Document v-else />
                  </el-icon>
                  <span class="node-label">{{ node.label }}</span>
                  <div class="node-actions" v-if="hoveredNodeId === data.id">
                    <el-tooltip content="新建文件">
                      <el-button size="small" text @click.stop="createFileInNode(data)" :icon="DocumentAdd" />
                    </el-tooltip>
                    <el-tooltip content="新建文件夹">
                      <el-button size="small" text @click.stop="createFolderInNode(data)" :icon="FolderAdd" />
                    </el-tooltip>
                    <el-tooltip content="删除">
                      <el-button size="small" text @click.stop="handleDeleteFile(data)" :icon="Delete" />
                    </el-tooltip>
                  </div>
                </div>
              </template>
              </el-tree>
            </el-scrollbar>
          </div>
        </div>

        <!-- 右侧内容区域 -->
        <div class="content-area">
          <!-- 选项卡 -->
          <div class="content-tabs">
            <el-tabs
              v-model="activeTabName"
              type="border-card"
              @tab-click="handleContentTabClick"
              @tab-remove="handleTabClose"
              class="editor-tabs"
            >
              <el-tab-pane 
                v-for="tab in openTabs" 
                :key="tab.key"
                :name="tab.key"
                :closable="tab.closable"
              >
                <template #label>
                  <span :class="{ 'modified-tab': tab.modified }">
                    {{ tab.title }}
                    <span v-if="tab.modified" class="modified-indicator">●</span>
                  </span>
                </template>
                <!-- 文件编辑器 -->
                <div v-if="tab.type === 'file'" class="file-editor">
                  <div class="editor-toolbar">
                    <div class="toolbar-left">
                      <span class="file-info">{{ tab.title }}</span>
                      <el-tag v-if="tab.modified" type="warning" size="small">已修改</el-tag>
                      <el-tag type="info" size="small">{{ getFileExtension(tab.title) }}</el-tag>
                    </div>
                    <div class="toolbar-right">
                      <el-select 
                        v-model="editorTheme" 
                        size="small" 
                        style="width: 120px; margin-right: 8px;"
                        @change="handleThemeChange"
                      >
                        <el-option label="深色主题" value="custom-dark" />
                        <el-option label="浅色主题" value="custom-light" />
                        <el-option label="VS Dark" value="vs-dark" />
                        <el-option label="VS Light" value="vs" />
                      </el-select>
                      <el-button size="small" @click="saveCurrentFile" :disabled="!tab.modified">
                        <el-icon><DocumentChecked /></el-icon>
                        保存
                      </el-button>
                      <el-button size="small" @click="downloadCurrentFile">
                        <el-icon><Download /></el-icon>
                        下载
                      </el-button>
                    </div>
                  </div>
                  <div class="editor-content">
                    <MonacoEditor
                      v-model="tab.content"
                      :language="getFileLanguage(tab.title)"
                      :theme="editorTheme"
                      :height="600"
                      :options="editorOptions"
                      @change="markTabAsModified(tab.key)"
                      @save="saveCurrentFile"
                      ref="monacoEditorRef"
                    />
                  </div>
                </div>

                <!-- 文件夹内容视图 -->
                <div v-else-if="tab.type === 'directory'" class="directory-view">
                  <div class="directory-header">
                    <h3>{{ tab.title }}</h3>
                    <div class="view-actions">
                      <el-button size="small" @click="switchView('grid')" :type="viewMode === 'grid' ? 'primary' : ''" text>
                        <el-icon><Grid /></el-icon>
                      </el-button>
                      <el-button size="small" @click="switchView('list')" :type="viewMode === 'list' ? 'primary' : ''" text>
                        <el-icon><List /></el-icon>
                      </el-button>
                    </div>
                  </div>
                  
                  <!-- 网格视图 -->
                  <div v-if="viewMode === 'grid'" class="grid-view">
                    <div 
                      v-for="item in currentDirectoryItems" 
                      :key="item.id"
                      class="file-item"
                      @click="handleFileItemClick(item)"
                      @dblclick="handleFileItemDoubleClick(item)"
                      @contextmenu="handleFileContextMenu($event, item)"
                    >
                      <div class="file-icon-large">
                        <el-icon v-if="item.type === 'directory'" size="48" color="#409EFF">
                          <Folder />
                        </el-icon>
                        <el-icon v-else size="48" color="#67C23A">
                          <Document />
                        </el-icon>
                      </div>
                      <div class="file-name">{{ item.name }}</div>
                      <div class="file-details">
                        <span v-if="item.type === 'file'">{{ formatFileSize(item.size) }}</span>
                        <span v-else>文件夹</span>
                      </div>
                    </div>
                  </div>

                  <!-- 列表视图 -->
                  <div v-if="viewMode === 'list'" class="list-view">
                    <el-table
                      :data="currentDirectoryItems"
                      @row-click="handleFileItemClick"
                      @row-dblclick="handleFileItemDoubleClick"
                      @row-contextmenu="handleFileContextMenu"
                      class="directory-table"
                      :height="tableHeight"
                      :max-height="tableHeight"
                    >
                      <el-table-column width="50">
                        <template #default="scope">
                          <el-icon v-if="scope.row.type === 'directory'" color="#409EFF">
                            <Folder />
                          </el-icon>
                          <el-icon v-else color="#67C23A">
                            <Document />
                          </el-icon>
                        </template>
                      </el-table-column>
                      <el-table-column prop="name" label="名称" min-width="200" />
                      <el-table-column prop="size" label="大小" width="120">
                        <template #default="scope">
                          {{ scope.row.type === 'directory' ? '-' : formatFileSize(scope.row.size) }}
                        </template>
                      </el-table-column>
                      <el-table-column prop="modified_time" label="修改时间" width="180" />
                      <el-table-column prop="permissions" label="权限" width="120" />
                    </el-table>
                  </div>
                </div>

                <!-- 欢迎页 -->
                <div v-else-if="tab.type === 'welcome'" class="welcome-view">
                  <div class="welcome-container">
                    <div class="welcome-header">
                      <div class="welcome-icon">
                        <el-icon size="80" color="#409EFF"><Folder /></el-icon>
                      </div>
                      <h1 class="welcome-title">容器文件管理器</h1>
                      <p class="welcome-subtitle">高效管理您的容器文件，支持在线编辑和多种操作</p>
                    </div>
                    
                    <div class="welcome-features">
                      <div class="feature-grid">
                        <div class="feature-item">
                          <el-icon size="24" color="#67C23A"><DocumentChecked /></el-icon>
                          <span>代码编辑</span>
                          <small>Monaco Editor 语法高亮</small>
                        </div>
                        <div class="feature-item">
                          <el-icon size="24" color="#E6A23C"><FolderOpened /></el-icon>
                          <span>文件管理</span>
                          <small>创建、删除、上传下载</small>
                        </div>
                        <div class="feature-item">
                          <el-icon size="24" color="#F56C6C"><Document /></el-icon>
                          <span>多格式支持</span>
                          <small>支持多种文件格式</small>
                        </div>
                        <div class="feature-item">
                          <el-icon size="24" color="#909399"><Grid /></el-icon>
                          <span>多视图模式</span>
                          <small>网格和列表视图切换</small>
                        </div>
                      </div>
                    </div>
                    
                    <div class="quick-actions">
                      <h3 class="actions-title">快速操作</h3>
                      <div class="actions-grid">
                        <div class="action-card primary" @click="showCreateFileDialog = true">
                          <div class="action-icon">
                            <el-icon size="28"><DocumentAdd /></el-icon>
                          </div>
                          <div class="action-text">
                            <span class="action-name">新建文件</span>
                            <small class="action-desc">创建新的文本文件</small>
                          </div>
                        </div>
                        
                        <div class="action-card success" @click="showCreateFolderDialog = true">
                          <div class="action-icon">
                            <el-icon size="28"><FolderAdd /></el-icon>
                          </div>
                          <div class="action-text">
                            <span class="action-name">新建文件夹</span>
                            <small class="action-desc">创建新的目录</small>
                          </div>
                        </div>
                        
                        <div class="action-card warning" @click="showUploadDialog = true">
                          <div class="action-icon">
                            <el-icon size="28"><Upload /></el-icon>
                          </div>
                          <div class="action-text">
                            <span class="action-name">上传文件</span>
                            <small class="action-desc">从本地上传文件</small>
                          </div>
                        </div>
                      </div>
                    </div>
                    
                    <div class="welcome-tips">
                      <el-alert
                        title="使用提示"
                        type="info"
                        :closable="false"
                        show-icon
                      >
                        <template #default>
                          <ul class="tips-list">
                            <li>点击左侧文件树中的文件进行编辑</li>
                            <li>支持 Ctrl+S 快捷键保存文件</li>
                            <li>右键文件可进行更多操作</li>
                            <li>支持拖拽上传文件</li>
                          </ul>
                        </template>
                      </el-alert>
                    </div>
                  </div>
                </div>
              </el-tab-pane>
            </el-tabs>
          </div>
        </div>
      </div>

      <!-- 上传文件对话框 -->
      <el-dialog
        v-model="showUploadDialog"
        title="上传文件"
        width="600px"
        append-to-body
        :close-on-click-modal="false"
      >
        <div class="upload-container">
          <div class="upload-path-info">
            <el-alert
              :title="`上传到: ${currentPath}`"
              type="info"
              :closable="false"
              show-icon
            />
          </div>
          
          <el-upload
            ref="uploadRef"
            :action="uploadAction"
            :headers="uploadHeaders"
            :data="uploadData"
            :before-upload="beforeUpload"
            :on-remove="handleRemoveFile"
            :on-change="handleFileChange"
            drag
            multiple
            class="upload-area"
            :auto-upload="false"
            :file-list="displayFileList"
          >
            <el-icon class="el-icon--upload"><Upload /></el-icon>
            <div class="el-upload__text">
              将文件拖到此处，或<em>点击选择</em>
            </div>
            <template #tip>
              <div class="el-upload__tip">
                支持多文件上传，单个文件大小不超过100MB
              </div>
            </template>
          </el-upload>
          
          <!-- 上传按钮 -->
          <div class="upload-actions">
            <el-button 
              type="primary" 
              @click="handleManualUpload"
              :disabled="uploadFileList.length === 0"
            >
              开始上传 ({{ uploadFileList.length }} 个文件)
            </el-button>
            <el-button 
              @click="clearUploadList"
              :disabled="uploadFileList.length === 0"
            >
              清空列表
            </el-button>
          </div>
          
          <!-- 上传进度 -->
          <div v-if="uploadingFiles.length > 0" class="upload-progress">
            <h4>上传进度</h4>
            <div v-for="file in uploadingFiles" :key="file.name" class="file-progress">
              <div class="file-info">
                <span class="file-name">{{ file.name }}</span>
                <span class="file-status" :class="file.status">
                  {{ 
                    file.status === 'waiting' ? '等待中' : 
                    file.status === 'uploading' ? '上传中' : 
                    file.status === 'success' ? '成功' : '失败' 
                  }}
                </span>
              </div>
              <el-progress 
                :percentage="file.percentage" 
                :status="file.status === 'success' ? 'success' : file.status === 'error' ? 'exception' : ''"
              />
            </div>
          </div>
        </div>
      </el-dialog>

      <!-- 创建文件对话框 -->
      <el-dialog
        v-model="showCreateFileDialog"
        title="写入文件"
        width="600px"
        append-to-body
        @open="onCreateFileDialogOpen"
      >
        <el-form :model="createFileForm" label-width="100px">
          <el-form-item label="文件名" required>
            <el-input 
              v-model="createFileForm.filename" 
              placeholder="请输入文件名（如：myFile.txt）"
              @blur="validateFileNameInput"
            />
            <div v-if="fileNameError" class="error-message">
              {{ fileNameError }}
            </div>
            <div class="file-name-hint">
              <small>注意：文件名只能包含一个扩展名后缀（如：.txt、.js、.md等）</small>
            </div>
          </el-form-item>
          <el-form-item label="文件内容">
            <el-input
              v-model="createFileForm.content"
              type="textarea"
              :rows="10"
              placeholder="请输入文件内容"
            />
          </el-form-item>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="closeCreateFileDialog">取消</el-button>
            <el-button type="primary" @click="handleCreateFile" :disabled="!!fileNameError">
              确认创建
            </el-button>
          </div>
        </template>
      </el-dialog>

      <!-- 创建文件夹对话框 -->
      <el-dialog
        v-model="showCreateFolderDialog"
        title="创建文件夹"
        width="400px"
        append-to-body
      >
        <el-form :model="createFolderForm" label-width="100px">
          <el-form-item label="文件夹名" required>
            <el-input v-model="createFolderForm.foldername" placeholder="请输入文件夹名" />
          </el-form-item>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="showCreateFolderDialog = false">取消</el-button>
            <el-button type="primary" @click="handleCreateFolder">
              确认创建
            </el-button>
          </div>
        </template>
      </el-dialog>
      
      <!-- 压缩文件对话框 -->
      <el-dialog
        v-model="showCompressDialog"
        title="压缩文件"
        width="500px"
        append-to-body
      >
        <el-form :model="compressForm" label-width="100px">
          <el-form-item label="压缩包名称" required>
            <el-input v-model="compressForm.zipName" placeholder="请输入压缩包名称（含.zip后缀）" />
          </el-form-item>
          <el-form-item label="文件列表">
            <el-tag v-for="file in compressForm.fileList" :key="file" type="info" style="margin: 2px;">
              {{ file }}
            </el-tag>
          </el-form-item>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="showCompressDialog = false">取消</el-button>
            <el-button type="primary" @click="executeCompress">
              确认压缩
            </el-button>
          </div>
        </template>
      </el-dialog>
      
      <!-- 解压文件对话框 -->
      <el-dialog
        v-model="showDecompressDialog"
        title="解压文件"
        width="600px"
        append-to-body
        :close-on-click-modal="false"
      >
        <div class="decompress-container">
          <div class="decompress-info">
            <el-alert
              title="解压信息"
              type="info"
              :closable="false"
              show-icon
            >
              <template #default>
                <p><strong>压缩文件:</strong> {{ decompressForm.zipName }}</p>
                <p><strong>文件类型:</strong> {{ getArchiveType(decompressForm.zipName) }}</p>
              </template>
            </el-alert>
          </div>
          
          <el-form :model="decompressForm" label-width="100px" style="margin-top: 20px;">
            <el-form-item label="解压目录" required>
              <el-input 
                v-model="decompressForm.outputDir" 
                placeholder="请输入解压目录路径（如：home/user 或留空表示根目录）"
                :prefix-icon="Folder"
              >
                <template #append>
                  <el-button @click="setCurrentPathAsOutput" type="primary" text>
                    当前目录
                  </el-button>
                </template>
              </el-input>
              <div class="form-hint">
                <small>提示：解压目录不能以 / 开头，如 home/user 或留空表示根目录</small>
              </div>
            </el-form-item>
            
            <el-form-item label="解压选项">
              <el-checkbox v-model="decompressOptions.overwrite">覆盖已存在的文件</el-checkbox>
            </el-form-item>
          </el-form>
          
          <!-- 解压预览 -->
          <div class="decompress-preview">
            <el-alert
              :title="`将解压到: ${getDecompressPreviewPath()}`"
              type="success"
              :closable="false"
              show-icon
            />
          </div>
        </div>
        
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="closeDecompressDialog">取消</el-button>
            <el-button 
              type="primary" 
              @click="executeDecompress"
              :disabled="!decompressForm.outputDir.trim()"
            >
              <el-icon><FolderOpened /></el-icon>
              开始解压
            </el-button>
          </div>
        </template>
      </el-dialog>
      

      
      <!-- 右键菜单 -->
      <div 
        v-if="contextMenuVisible" 
        class="context-menu"
        :style="{ left: contextMenuPosition.x + 'px', top: contextMenuPosition.y + 'px' }"
        @click.stop
      >
        <div class="context-menu-item" @click="handleContextMenuAction('download')" v-if="contextMenuItem?.type === 'file'">
          <el-icon><Download /></el-icon>
          <span>下载</span>
        </div>
        <div class="context-menu-item" @click="handleContextMenuAction('compress')">
          <el-icon><Folder /></el-icon>
          <span>压缩</span>
        </div>
        <div class="context-menu-item" @click="handleContextMenuAction('decompress')" v-if="isArchiveFile(contextMenuItem?.name)">
          <el-icon><FolderOpened /></el-icon>
          <span>解压</span>
        </div>
        <div class="context-menu-divider"></div>
        <div class="context-menu-item danger" @click="handleContextMenuAction('delete')">
          <el-icon><Delete /></el-icon>
          <span>删除</span>
        </div>
      </div>
      
      <!-- 右键菜单遮罩 -->
      <div v-if="contextMenuVisible" class="context-menu-overlay" @click="contextMenuVisible = false"></div>
      
      <!-- 文件树右键菜单 -->
      <div 
        v-if="treeContextMenuVisible" 
        class="context-menu"
        :style="{ left: treeContextMenuPosition.x + 'px', top: treeContextMenuPosition.y + 'px' }"
        @click.stop
      >
        <div class="context-menu-item" @click="handleTreeContextMenuAction('download')" v-if="treeContextMenuItem?.type === 'file'">
          <el-icon><Download /></el-icon>
          <span>下载</span>
        </div>
        <div class="context-menu-item" @click="handleTreeContextMenuAction('compress')">
          <el-icon><Folder /></el-icon>
          <span>压缩</span>
        </div>
        <div class="context-menu-item" @click="handleTreeContextMenuAction('decompress')" v-if="isArchiveFile(treeContextMenuItem?.name)">
          <el-icon><FolderOpened /></el-icon>
          <span>解压</span>
        </div>
        <div class="context-menu-divider"></div>
        <div class="context-menu-item danger" @click="handleTreeContextMenuAction('delete')">
          <el-icon><Delete /></el-icon>
          <span>删除</span>
        </div>
      </div>
      
      <!-- 文件树右键菜单遮罩 -->
      <div v-if="treeContextMenuVisible" class="context-menu-overlay" @click="handleTreeContextMenuClose"></div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { ElMessage, ElMessageBox } from 'element-plus';
import {
  Folder,
  Document,
  Upload,
  FolderAdd,
  Back,
  DCaret,
  CaretRight,
  DocumentAdd,
  DocumentChecked,
  Download,
  Grid,
  List,
  Delete,
  Refresh,
  FolderOpened
} from '@element-plus/icons-vue';

import { FileName } from '@/utils/tool';
import MonacoEditor from '@/components/MonacoEditor.vue';

import { 
    getFileList,
    readFile,
    deleteFile,
    writeFile,
    createFolder,
    uploadFile,
    downloadFile,
    compressFile,
    decompressFile 
} from '@/utils/acs/file';

const router = useRouter();
const route = useRoute();

// 从URL参数获取容器ID
const containerId = ref(route.query.container_id || '');

// 如果没有容器ID，返回上一页
if (!containerId.value) {
  ElMessage.error('缺少容器ID参数');
  router.go(-1);
}

// 文件管理相关数据
const currentPath = ref('/');
const breadcrumbPaths = ref([{ name: 'root', path: '/' }]);

// 编辑器相关
const fileTreeRef = ref(null);
const fileTreeData = ref([]);
const treeProps = {
  children: 'children',
  label: 'name',
  isLeaf: 'isLeaf'
};
const hoveredNodeId = ref(null);

// 选项卡管理
const openTabs = ref([
  {
    key: 'welcome',
    title: '欢迎',
    type: 'welcome',
    closable: false,
    content: '',
    modified: false
  }
]);
const activeTabName = ref('welcome');

// 视图模式
const viewMode = ref('grid');
const currentDirectoryItems = ref([]);

// 文件操作对话框
const showUploadDialog = ref(false);
const showCreateFileDialog = ref(false);
const showCreateFolderDialog = ref(false);

// 文件名验证错误信息
const fileNameError = ref('');

// 文件操作表单
const createFileForm = reactive({
  filename: '',
  content: ''
});

const createFolderForm = reactive({
  foldername: ''
});

// 生成驼峰命名的默认文件名
const generateCamelCaseFileName = (extension = 'txt') => {
  // 获取当前时间戳的后6位作为唯一标识
  const timestamp = Date.now().toString().slice(-6);
  // 生成驼峰命名：newFile + 时间戳 + 扩展名
  return `newFile${timestamp}.${extension}`;
};

// 验证文件名是否只有一个后缀
const validateFileName = (filename) => {
  if (!filename || !filename.trim()) {
    return { valid: false, message: '文件名不能为空' };
  }
  
  const trimmedName = filename.trim();
  const dotCount = (trimmedName.match(/\./g) || []).length;
  
  if (dotCount === 0) {
    return { valid: false, message: '文件名必须包含扩展名（如：.txt、.js等）' };
  }
  
  if (dotCount > 1) {
    return { valid: false, message: '文件名只能包含一个扩展名后缀' };
  }
  
  // 检查是否以点开头或结尾
  if (trimmedName.startsWith('.') || trimmedName.endsWith('.')) {
    return { valid: false, message: '文件名格式不正确' };
  }
  
  // 检查扩展名部分是否为空
  const parts = trimmedName.split('.');
  if (parts.length !== 2 || !parts[0] || !parts[1]) {
    return { valid: false, message: '文件名和扩展名都不能为空' };
  }
  
  return { valid: true, message: '' };
};

// 上传相关
const uploadRef = ref(null);
const uploadAction = ref(''); // 不使用action，改用手动上传
const uploadHeaders = ref({});
const uploadData = ref({});

// 上传进度和状态
const uploadProgress = ref(0);
const uploadingFiles = ref([]);
const uploadFileList = ref([]);
const displayFileList = ref([]); // 用于 el-upload 组件显示的文件列表

// Monaco Editor 相关配置
const monacoEditorRef = ref(null);
const editorTheme = ref('custom-dark'); // 默认使用深色主题
const editorHeight = ref(500); // 编辑器高度
const editorOptions = ref({
  fontSize: 14,
  minimap: { enabled: true },
  wordWrap: 'on',
  automaticLayout: true,
  scrollBeyondLastLine: false,
  renderWhitespace: 'selection',
  tabSize: 2,
  insertSpaces: true,
  // 增强语法高亮配置
  semanticHighlighting: {
    enabled: true
  },
  colorDecorators: true,
  bracketPairColorization: {
    enabled: true,
    independentColorPoolPerBracketType: true
  },
  guides: {
    bracketPairs: true,
    bracketPairsHorizontal: true,
    highlightActiveBracketPair: true,
    indentation: true,
    highlightActiveIndentation: true
  },
  // 代码提示增强
  quickSuggestions: {
    other: true,
    comments: false,
    strings: false
  },
  parameterHints: {
    enabled: true,
    cycle: true
  },
  hover: {
    enabled: true,
    delay: 300
  },
  // 其他增强功能
  occurrencesHighlight: true,
  selectionHighlight: true,
  matchBrackets: 'always',
  foldingHighlight: true,
  links: true
});

// 计算表格高度（基于屏幕高度）
const tableHeight = computed(() => {
  return window.innerHeight - 360; // 屏幕高度减去页面头部、工具栏等空间
});

// 页面初始化
onMounted(() => {
  if (containerId.value) {
    initFileTree();
  }
  // 初始化编辑器主题
  initEditorTheme();
});

// ========== 核心功能函数 ==========

// 统一的路径处理函数
// 根据需求：根目录是 '/'，其他路径去掉前面的 '/'
const formatApiPath = (path, needsTrailingSlash = false) => {
  if (!path || path === '/') {
    return '/';
  }
  
  // 去掉前面的 '/'
  let formattedPath = path.startsWith('/') ? path.substring(1) : path;
  
  // 根据需要添加后面的 '/'
  if (needsTrailingSlash && !formattedPath.endsWith('/')) {
    formattedPath += '/';
  }
  
  return formattedPath;
};

// 转换API数据格式为树组件需要的格式
const convertApiDataToTreeData = (apiData, basePath = '/') => {
  const treeData = [];
  
  Object.keys(apiData).forEach(fileName => {
    const fileInfo = apiData[fileName];
    const filePath = basePath === '/' ? `/${fileName}` : `${basePath}/${fileName}`;
    
    const treeNode = {
      id: filePath, // 使用完整路径作为唯一ID
      name: fileName,
      type: fileInfo.type === 'dir' ? 'directory' : 'file',
      path: filePath,
      isLeaf: fileInfo.type !== 'dir',
      info: fileInfo.info, // 保存完整的文件信息
      children: fileInfo.type === 'dir' ? [] : undefined
    };
    
    // 如果是文件，添加大小信息
    if (fileInfo.type === 'file') {
      treeNode.size = fileInfo.info.st_size;
    }
    
    treeData.push(treeNode);
  });
  
  // 按类型和名称排序：目录在前，文件在后，同类型按名称排序
  treeData.sort((a, b) => {
    if (a.type !== b.type) {
      return a.type === 'directory' ? -1 : 1;
    }
    return a.name.localeCompare(b.name);
  });
  
  return treeData;
};

// 初始化文件树
const initFileTree = async () => {
  try {
    console.log('初始化文件树，请求根目录: /');
    
    const res = await getFileList({container_id: containerId.value, path: '/'});
    console.log('获取文件列表', res);
    
    if (res.data && res.data.code === 200) {
      const apiData = res.data.data.data;
      
      // 检查是否有数据
      if (!apiData || Object.keys(apiData).length === 0) {
        fileTreeData.value = [];
        ElMessage.info('根目录为空');
        return;
      }
      
      const treeData = convertApiDataToTreeData(apiData, '/');
      
      fileTreeData.value = treeData;
      currentPath.value = '/';
      updateBreadcrumb('/');
      
      ElMessage.success(`文件树初始化成功，加载了 ${treeData.length} 个项目`);
    } else {
      throw new Error(res.data?.msg || '获取文件列表失败');
    }
  } catch (error) {
    console.error('初始化文件树出错:', error);
    ElMessage.error(`初始化文件树出错: ${error.message || error}`);
  }
};

// 更新面包屑导航
const updateBreadcrumb = (path) => {
  const parts = path.split('/').filter(part => part !== '');
  breadcrumbPaths.value = [{ name: 'root', path: '/' }];
  
  let currentPath = '';
  parts.forEach(part => {
    currentPath += `/${part}`;
    breadcrumbPaths.value.push({ name: part, path: currentPath });
  });
};

// 导航到指定路径
const navigateToPath = (index) => {
  if (index < breadcrumbPaths.value.length - 1) {
    const targetPath = breadcrumbPaths.value[index].path;
    currentPath.value = targetPath;
    updateBreadcrumb(targetPath);
  }
};

// 懒加载树节点
const loadTreeNode = async (node, resolve) => {
  try {
    if (node.level === 0) {
      return resolve(fileTreeData.value);
    }
    
    // 只有目录类型才能懒加载子节点
    if (node.data.type !== 'directory') {
      return resolve([]);
    }
    
    // 使用统一的路径处理函数
    const requestPath = formatApiPath(node.data.path, true);
    
    console.log('懒加载请求路径:', requestPath);
    
    const res = await getFileList({
      container_id: containerId.value,
      path: requestPath
    });
    
    if (res.data && res.data.code === 200) {
      const apiData = res.data.data.data;
      
      // 如果没有数据或者数据为空，返回空数组
      if (!apiData || Object.keys(apiData).length === 0) {
        resolve([]);
        return;
      }
      
      const children = convertApiDataToTreeData(apiData, node.data.path);
      resolve(children);
    } else {
      console.error('获取子目录失败:', res.data?.msg);
      resolve([]);
    }
  } catch (error) {
    console.error('加载树节点出错:', error);
    ElMessage.error(`加载目录 ${node.data.name} 失败`);
    resolve([]);
  }
};

// 处理树节点点击
const handleTreeNodeClick = (data, node) => {
  currentPath.value = data.path;
  updateBreadcrumb(data.path);
  
  if (data.type === 'file') {
    openFileTab(data);
  } else {
    openDirectoryTab(data);
  }
};

// 树节点右键菜单
const treeContextMenuVisible = ref(false);
const treeContextMenuPosition = ref({ x: 0, y: 0 });
const treeContextMenuItem = ref(null);

// 处理树节点右键菜单
const handleTreeContextMenu = (event, data, node) => {
  event.preventDefault();
  treeContextMenuItem.value = data;
  treeContextMenuPosition.value = { x: event.clientX, y: event.clientY };
  treeContextMenuVisible.value = true;
  
  // 点击其他地方关闭菜单
  document.addEventListener('click', handleTreeContextMenuClose);
};

// 关闭树节点右键菜单
const handleTreeContextMenuClose = () => {
  treeContextMenuVisible.value = false;
  document.removeEventListener('click', handleTreeContextMenuClose);
};

// 处理树节点右键菜单操作
const handleTreeContextMenuAction = (action) => {
  const item = treeContextMenuItem.value;
  
  switch (action) {
    case 'compress':
      handleCompressFile(item);
      break;
    case 'decompress':
      if (isArchiveFile(item.name)) {
        handleDecompressFile(item);
      } else {
        ElMessage.warning('只能解压压缩文件');
      }
      break;
    case 'delete':
      handleDeleteFile(item);
      break;
    case 'download':
      handleDownloadFile(item);
      break;
    default:
      break;
  }
  
  handleTreeContextMenuClose();
};



// 打开文件选项卡
const openFileTab = async (fileData) => {
  const existingTab = openTabs.value.find(tab => tab.key === fileData.path);
  
  if (existingTab) {
    activeTabName.value = existingTab.key;
    return;
  }
  
  try {
    ElMessage.info(`正在读取文件: ${fileData.name}`);
    
    const res = await readFile({
      container_id: containerId.value,
      path: formatApiPath(fileData.path)
    });
    
    let fileContent = '';
    if (res.data && res.data.code === 200) {
      fileContent = res.data.data.data.content || '';
    } else {
      throw new Error(res.data?.data?.msg || '读取文件失败');
    }
    
    const newTab = {
      key: fileData.path,
      title: fileData.name,
      type: 'file',
      closable: true,
      content: atob(fileContent),
      originalContent: fileContent, // 保存原始内容用于比较是否修改
      modified: false,
      fileData: fileData
    };
    
    openTabs.value.push(newTab);
    activeTabName.value = newTab.key;
    
    ElMessage.success(`文件 ${fileData.name} 读取成功`);
  } catch (error) {
    console.error('打开文件出错:', error);
    ElMessage.error(`读取文件失败: ${error.message || error}`);
  }
};



// 打开目录选项卡
const openDirectoryTab = async (dirData) => {
  const existingTab = openTabs.value.find(tab => tab.key === dirData.path);
  
  if (existingTab) {
    activeTabName.value = existingTab.key;
    return;
  }
  
  try {
    await loadDirectoryItems(dirData.path);
    
    const newTab = {
      key: dirData.path,
      title: dirData.name,
      type: 'directory',
      closable: true,
      content: '',
      modified: false,
      dirData: dirData
    };
    
    openTabs.value.push(newTab);
    activeTabName.value = newTab.key;
  } catch (error) {
    console.error('打开目录出错:', error);
    ElMessage.error('打开目录出错');
  }
};

// 转换时间戳为可读格式
const formatTimestamp = (timestamp) => {
  const date = new Date(timestamp * 1000);
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  });
};

// 转换文件权限为可读格式
const formatPermissions = (mode) => {
  const permissions = [];
  // 文件类型判断
  const isDir = (mode & 0o040000) !== 0;
  permissions.push(isDir ? 'd' : '-');
  
  // 所有者权限
  permissions.push((mode & 0o400) ? 'r' : '-');
  permissions.push((mode & 0o200) ? 'w' : '-');
  permissions.push((mode & 0o100) ? 'x' : '-');
  
  // 组权限
  permissions.push((mode & 0o040) ? 'r' : '-');
  permissions.push((mode & 0o020) ? 'w' : '-');
  permissions.push((mode & 0o010) ? 'x' : '-');
  
  // 其他用户权限
  permissions.push((mode & 0o004) ? 'r' : '-');
  permissions.push((mode & 0o002) ? 'w' : '-');
  permissions.push((mode & 0o001) ? 'x' : '-');
  
  return permissions.join('');
};

// 加载目录项目
const loadDirectoryItems = async (path) => {
  try {
    // 使用统一的路径处理函数
    const requestPath = formatApiPath(path, true);
    
    console.log('加载目录项目请求路径:', requestPath);
    
    const res = await getFileList({
      container_id: containerId.value,
      path: requestPath
    });
    
    if (res.data && res.data.code === 200) {
      const apiData = res.data.data.data;
      const items = [];
      
      Object.keys(apiData).forEach(fileName => {
        const fileInfo = apiData[fileName];
        const item = {
          id: `${path}/${fileName}`,
          name: fileName,
          type: fileInfo.type === 'dir' ? 'directory' : 'file',
          size: fileInfo.info.st_size || 0,
          modified_time: formatTimestamp(fileInfo.info.st_mtime),
          permissions: formatPermissions(fileInfo.info.st_mode),
          info: fileInfo.info
        };
        items.push(item);
      });
      
      // 排序：目录在前，文件在后
      items.sort((a, b) => {
        if (a.type !== b.type) {
          return a.type === 'directory' ? -1 : 1;
        }
        return a.name.localeCompare(b.name);
      });
      
      currentDirectoryItems.value = items;
    } else {
      throw new Error(res.data?.msg || '获取目录内容失败');
    }
  } catch (error) {
    console.error('加载目录项目出错:', error);
    ElMessage.error(`加载目录内容失败: ${error.message || error}`);
    throw error;
  }
};

// 选项卡操作
const handleContentTabClick = (tab) => {
  activeTabName.value = tab.name;
};

const handleTabClose = (targetName) => {
  const tabs = openTabs.value;
  let activeName = activeTabName.value;
  
  if (activeName === targetName) {
    tabs.forEach((tab, index) => {
      if (tab.key === targetName) {
        const nextTab = tabs[index + 1] || tabs[index - 1];
        if (nextTab) {
          activeName = nextTab.key;
        }
      }
    });
  }
  
  activeTabName.value = activeName;
  openTabs.value = tabs.filter(tab => tab.key !== targetName);
};

// 标记选项卡为已修改
const markTabAsModified = (tabKey) => {
  const tab = openTabs.value.find(t => t.key === tabKey);
  if (tab && tab.type === 'file') {
    // 检查内容是否真的发生了变化
    tab.modified = tab.content !== tab.originalContent;
  }
};

// 保存当前文件
const saveCurrentFile = async () => {
  const currentTab = openTabs.value.find(tab => tab.key === activeTabName.value);
  if (!currentTab || currentTab.type !== 'file') return;
  
  if (!currentTab.modified) {
    ElMessage.info('文件内容未发生变化');
    return;
  }
  
  try {
    ElMessage.info('正在保存文件...');
    
    const res = await writeFile({
      container_id: containerId.value,
      path: formatApiPath(currentTab.fileData.path),
      content: currentTab.content
    });
    
    if (res.data && res.data.code === 200) {
      currentTab.modified = false;
      currentTab.originalContent = currentTab.content; // 更新原始内容
      ElMessage.success('文件保存成功');
    } else {
      throw new Error(res.data?.msg || '保存文件失败');
    }
  } catch (error) {
    console.error('保存文件出错:', error);
    ElMessage.error(`保存文件失败: ${error.message || error}`);
  }
};

// 下载当前文件
const downloadCurrentFile = async () => {
  const currentTab = openTabs.value.find(tab => tab.key === activeTabName.value);
  if (!currentTab || currentTab.type !== 'file') return;
  
  try {
    ElMessage.info('正在获取下载链接...');
    
    const res = await downloadFile({
      container_id: containerId.value,
      path: formatApiPath(currentTab.fileData.path)
    });
    console.log('下载文件', res);
    if (res.data && res.data.code === 200) {
      const downloadUrl = res.data.base_url;
      const filename = FileName(currentTab.fileData.name);
      const downloadFileUuid = res.data.data.data.downloadFileUuid
      const link = `${downloadUrl}?downloadFileUuid=${downloadFileUuid}&filename=${filename}`
      window.open(link, '_blank');
      ElMessage.success('文件下载已开始');
    } else {
      throw new Error(res.data?.msg || '获取下载链接失败');
    }
  } catch (error) {
    console.error('下载文件出错:', error);
    ElMessage.error(`下载文件失败: ${error.message || error}`);
  }
};

// 切换视图模式
const switchView = (mode) => {
  viewMode.value = mode;
};

// 文件项目操作
const handleFileItemClick = (item) => {
  console.log('点击文件项:', item.name);
};

const handleFileItemDoubleClick = (item) => {
  // 构建正确的路径
  let newPath;
  if (currentPath.value === '/') {
    newPath = `/${item.name}`;
  } else {
    newPath = `${currentPath.value}/${item.name}`;
  }
  
  if (item.type === 'directory') {
    const dirData = { ...item, path: newPath };
    openDirectoryTab(dirData);
  } else {
    const fileData = { ...item, path: newPath };
    openFileTab(fileData);
  }
};

// 右键菜单相关
const contextMenuVisible = ref(false);
const contextMenuPosition = ref({ x: 0, y: 0 });
const contextMenuItem = ref(null);

const handleFileContextMenu = (event, item) => {
  event.preventDefault();
  contextMenuItem.value = item;
  contextMenuPosition.value = { x: event.clientX, y: event.clientY };
  contextMenuVisible.value = true;
};

// 右键菜单操作
const handleContextMenuAction = (action) => {
  contextMenuVisible.value = false;
  const item = contextMenuItem.value;
  if (!item) return;
  
  switch (action) {
    case 'download':
      handleDownloadFile(item);
      break;
    case 'delete':
      handleDeleteFile(item);
      break;
    case 'compress':
      handleCompressFile(item);
      break;
    case 'decompress':
      handleDecompressFile(item);
      break;
    default:
      break;
  }
};

// 下载文件
const handleDownloadFile = async (file) => {
  try {
    ElMessage.info(`正在准备下载: ${file.name}`);
    
    const filePath = file.path || `${currentPath.value}/${file.name}`;
    const res = await downloadFile({
      container_id: containerId.value,
      path: formatApiPath(filePath)
    });
    
    if (res.data && res.data.code === 200) {
      const downloadUrl = res.data.base_url;
      const filename = FileName(file.name);
      const downloadFileUuid = res.data.data.data.downloadFileUuid;
      
      const link = `${downloadUrl}?downloadFileUuid=${downloadFileUuid}&filename=${filename}`;
      window.open(link, '_blank');
      
      ElMessage.success('文件下载已开始');
    } else {
      throw new Error(res.data?.msg || '获取下载链接失败');
    }
  } catch (error) {
    console.error('下载文件出错:', error);
    ElMessage.error(`下载文件失败: ${error.message || error}`);
  }
};

// 压缩文件相关数据
const showCompressDialog = ref(false);
const compressForm = reactive({
  zipName: '',
  fileList: []
});

// 压缩文件
const handleCompressFile = async (file) => {
  console.log('压缩文件111', file);
  try {
    // 打开压缩对话框
    compressForm.zipName = `${file.name}.zip`;
    compressForm.fileList = [file.name];
    showCompressDialog.value = true;
  } catch (error) {
    console.error('压缩文件出错:', error);
    ElMessage.error(`压缩失败: ${error.message || error}`);
  }
};

// 执行压缩
const executeCompress = async () => {
  if (!compressForm.zipName.trim()) {
    ElMessage.error('请输入压缩包名称');
    return;
  }
  
  try {
    ElMessage.info('正在压缩...');
    
    const res = await compressFile({
      container_id: containerId.value,
      file_list: JSON.stringify(compressForm.fileList),
      zip_name: compressForm.zipName.trim()
    });
    if(res.data.data.code === 500){
      ElMessage.error(res.data.data.msg);
      return;
    }
    
    if (res.data && res.data.code === 200) {
      ElMessage.success('压缩成功');
      showCompressDialog.value = false;
      compressForm.zipName = '';
      compressForm.fileList = [];
      refreshFileList();
    } else {
      throw new Error(res.data?.msg || '压缩失败');
    }
  } catch (error) {
    console.error('压缩文件出错:', error);
    ElMessage.error(`压缩失败: ${error.message || error}`);
  }
};

// 解压文件相关数据
const showDecompressDialog = ref(false);
const decompressForm = reactive({
  zipName: '',
  outputDir: ''
});

// 解压选项
const decompressOptions = reactive({
  overwrite: false
});



// 解压文件
const handleDecompressFile = async (file) => {
  try {
    // 验证是否为压缩文件
    if (!isArchiveFile(file.name)) {
      ElMessage.warning('只能解压压缩文件（.zip, .rar, .7z, .tar, .gz, .bz2, .xz）');
      return;
    }
    
    // 打开解压对话框
    decompressForm.zipName = file.path;
    
    // 设置解压目录为文件所在目录
    const filePath = file.path;
    const lastSlashIndex = filePath.lastIndexOf('/');
    const outputDir = lastSlashIndex > 0 ? filePath.substring(0, lastSlashIndex) : '/';
    
    // 根据新的路径规则设置解压目录
    if (outputDir === '/') {
      decompressForm.outputDir = ''; // 根目录用空字符串表示
    } else {
      // 去掉开头的 / 符号
      decompressForm.outputDir = outputDir.startsWith('/') ? outputDir.substring(1) : outputDir;
    }
    
    // 重置解压选项
    decompressOptions.overwrite = false;
    
    showDecompressDialog.value = true;
    
    ElMessage.info(`准备解压 ${file.name}`);
  } catch (error) {
    console.error('解压文件出错:', error);
    ElMessage.error(`解压失败: ${error.message || error}`);
  }
};

// 执行解压
const executeDecompress = async () => {
  // 验证解压目录格式
  const outputDir = decompressForm.outputDir.trim();
  
  // 检查路径是否以 / 开头（不允许）
  if (outputDir.startsWith('/')) {
    ElMessage.error('解压目录不能以 / 开头，请输入相对路径或留空表示根目录');
    return;
  }
  
  // 空字符串表示根目录，这是允许的
  // 非空字符串应该是相对路径，如 "home/user"
  
  try {
    ElMessage.info('正在解压...');
    // 处理解压目录路径：空字符串表示根目录 "/"，否则直接使用用户输入的路径
    const apiOutputDir = outputDir === '' ? '/' : outputDir;
    
    const res = await decompressFile({
      container_id: containerId.value,
      zip_name: formatApiPath(decompressForm.zipName),
      output_dir: apiOutputDir
    });
    
    console.log('解压响应:', res);
    
    // 处理不同的响应格式
    if (res.data && res.data.code === 200) {
      const displayPath = apiOutputDir === '/' ? '根目录' : apiOutputDir;
      ElMessage.success(`解压成功！文件已解压到 ${displayPath}`);
      closeDecompressDialog();
      refreshFileList();
    } else if (res.data && res.data.data && res.data.data.code === 500) {
      // 处理内部错误
      ElMessage.error(res.data.data.msg || '解压失败');
      return;
    } else {
      throw new Error(res.data?.msg || res.data?.data?.msg || '解压失败');
    }
  } catch (error) {
    console.error('解压文件出错:', error);
    ElMessage.error(`解压失败: ${error.message || error}`);
  }
};

// 树操作
const expandAllNodes = () => {
  if (fileTreeRef.value && fileTreeRef.value.store) {
    try {
      // 获取所有已加载的目录节点
      const allDirectoryKeys = [];
      
      // 递归收集所有目录节点的key
      const collectDirectoryKeys = (store, nodeKey = null) => {
        const nodes = nodeKey ? store.getNode(nodeKey)?.childNodes || [] : store.root.childNodes;
        
        nodes.forEach(node => {
          if (node.data && node.data.type === 'directory') {
            allDirectoryKeys.push(node.key);
            // 如果节点已经加载了子节点，继续递归
            if (node.childNodes && node.childNodes.length > 0) {
              collectDirectoryKeys(store, node.key);
            }
          }
        });
      };
      
      collectDirectoryKeys(fileTreeRef.value.store);
      
      // 展开所有找到的目录节点
      allDirectoryKeys.forEach(key => {
        const node = fileTreeRef.value.store.getNode(key);
        if (node && !node.expanded) {
          node.expand();
        }
      });
      
      ElMessage.success(`已展开 ${allDirectoryKeys.length} 个文件夹`);
    } catch (error) {
      console.error('展开文件夹出错:', error);
      ElMessage.error('展开文件夹失败');
    }
  }
};

const collapseAllNodes = () => {
  if (fileTreeRef.value && fileTreeRef.value.store) {
    try {
      // 获取所有已展开的目录节点
      const expandedDirectoryKeys = [];
      
      // 递归收集所有已展开的目录节点
      const collectExpandedKeys = (store, nodeKey = null) => {
        const nodes = nodeKey ? store.getNode(nodeKey)?.childNodes || [] : store.root.childNodes;
        
        nodes.forEach(node => {
          if (node.data && node.data.type === 'directory' && node.expanded) {
            expandedDirectoryKeys.push(node.key);
            // 继续递归子节点
            if (node.childNodes && node.childNodes.length > 0) {
              collectExpandedKeys(store, node.key);
            }
          }
        });
      };
      
      collectExpandedKeys(fileTreeRef.value.store);
      
      // 收起所有已展开的目录节点
      expandedDirectoryKeys.forEach(key => {
        const node = fileTreeRef.value.store.getNode(key);
        if (node && node.expanded) {
          node.collapse();
        }
      });
      
      ElMessage.success(`已收起 ${expandedDirectoryKeys.length} 个文件夹`);
    } catch (error) {
      console.error('收起文件夹出错:', error);
      ElMessage.error('收起文件夹失败');
    }
  }
};

// 在节点中创建文件/文件夹
const createFileInNode = (nodeData) => {
  currentPath.value = nodeData.path;
  showCreateFileDialog.value = true;
};

const createFolderInNode = (nodeData) => {
  currentPath.value = nodeData.path;
  showCreateFolderDialog.value = true;
};

// 创建文件对话框打开时的处理
const onCreateFileDialogOpen = () => {
  // 生成默认的驼峰命名文件名
  createFileForm.filename = generateCamelCaseFileName('txt');
  createFileForm.content = '';
  fileNameError.value = '';
};

// 验证文件名输入
const validateFileNameInput = () => {
  const validation = validateFileName(createFileForm.filename);
  fileNameError.value = validation.valid ? '' : validation.message;
};

// 关闭创建文件对话框
const closeCreateFileDialog = () => {
  showCreateFileDialog.value = false;
  createFileForm.filename = '';
  createFileForm.content = '';
  fileNameError.value = '';
};

// 创建文件
const handleCreateFile = async () => {
  // 验证文件名
  const validation = validateFileName(createFileForm.filename);
  if (!validation.valid) {
    fileNameError.value = validation.message;
    ElMessage.error(validation.message);
    return;
  }

  // 构建文件路径
  const filePath = currentPath.value === '/' 
    ? `/${createFileForm.filename.trim()}`
    : `${currentPath.value}/${createFileForm.filename.trim()}`;

  try {
    ElMessage.info('正在创建文件...');
    
    const res = await writeFile({
      container_id: containerId.value,
      path: formatApiPath(filePath),
      content: createFileForm.content || ''
    });
    
    if (res.data && res.data.code === 200) {
      ElMessage.success('文件创建成功');
      closeCreateFileDialog(); // 使用统一的关闭函数
      refreshFileList();
    } else {
      throw new Error(res.data?.msg || '创建文件失败');
    }
  } catch (error) {
    console.error('创建文件出错:', error);
    ElMessage.error(`创建文件失败: ${error.message || error}`);
  }
};

// 创建文件夹
const handleCreateFolder = async () => {
  if (!createFolderForm.foldername.trim()) {
    ElMessage.error('请输入文件夹名');
    return;
  }

  // 构建文件夹路径
  const folderPath = currentPath.value === '/' 
    ? `/${createFolderForm.foldername.trim()}`
    : `${currentPath.value}/${createFolderForm.foldername.trim()}`;

  try {
    ElMessage.info('正在创建文件夹...');
    
    const res = await createFolder({
      container_id: containerId.value,
      path: formatApiPath(folderPath)
    });
    
    if (res.data && res.data.code === 200) {
      ElMessage.success('文件夹创建成功');
      showCreateFolderDialog.value = false;
      createFolderForm.foldername = '';
      refreshFileList();
    } else {
      throw new Error(res.data?.msg || '创建文件夹失败');
    }
  } catch (error) {
    console.error('创建文件夹出错:', error);
    ElMessage.error(`创建文件夹失败: ${error.message || error}`);
  }
};

// 删除文件/文件夹
const handleDeleteFile = async (file) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除 ${file.type === 'directory' ? '文件夹' : '文件'} "${file.name}" 吗？`,
      '确认删除',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: true,
        message: `
          <div style="margin-top: 10px;">
            <p><strong>文件路径:</strong> ${file.path}</p>
            <p style="color: #f56c6c; margin-top: 8px;"><strong>注意:</strong> 此操作不可恢复！</p>
          </div>
        `
      }
    );

    ElMessage.info('正在删除...');
    
    const res = await deleteFile({
      container_id: containerId.value,
      path: formatApiPath(file.path)
    });
    
    if (res.data && res.data.code === 200) {
      ElMessage.success('删除成功');
      
      // 如果删除的文件在编辑器中打开，关闭对应的选项卡
      const openTab = openTabs.value.find(tab => tab.key === file.path);
      if (openTab) {
        handleTabClose(openTab.key);
      }
      
      refreshFileList();
    } else {
      throw new Error(res.data?.msg || '删除失败');
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除文件出错:', error);
      ElMessage.error(`删除失败: ${error.message || error}`);
    }
  }
};

// 刷新文件列表
const refreshFileList = async () => {
  try {
    await initFileTree();
    // 如果当前有打开的目录选项卡，也刷新其内容
    const currentTab = openTabs.value.find(tab => tab.key === activeTabName.value);
    if (currentTab && currentTab.type === 'directory') {
      await loadDirectoryItems(currentTab.dirData.path);
    }
    ElMessage.success('文件列表刷新成功');
  } catch (error) {
    console.error('刷新文件列表失败:', error);
    ElMessage.error('刷新文件列表失败');
  }
};

// 返回上一页
const goBack = () => {
  router.go(-1);
};

// 文件选择变化处理
const handleFileChange = (file, fileList) => {
  console.log('handleFileChange', file, fileList);
  
  if (file.status === 'ready') {
    // 检查文件大小（限制为100MB）
    const maxSize = 100 * 1024 * 1024;
    if (file.size > maxSize) {
      ElMessage.error('文件大小不能超过100MB');
      // 从文件列表中移除这个文件
      const index = fileList.findIndex(f => f.uid === file.uid);
      if (index > -1) {
        fileList.splice(index, 1);
      }
      return;
    }
    
    // 添加到我们的上传列表
    uploadFileList.value.push(file.raw);
    uploadingFiles.value.push({
      name: file.name,
      status: 'waiting',
      percentage: 0,
      file: file.raw,
      uid: file.uid
    });
  }
  
  // 更新显示的文件列表
  displayFileList.value = fileList.filter(f => f.status === 'ready');
};

// 上传前检查（这个现在主要用于阻止自动上传）
const beforeUpload = (file) => {
  console.log('beforeUpload', file);
  return false; // 阻止自动上传
};

// 手动上传所有文件
const handleManualUpload = async () => {
  if (uploadFileList.value.length === 0) {
    ElMessage.warning('请选择要上传的文件');
    return;
  }
  
  for (const file of uploadFileList.value) {
    await uploadSingleFile(file);
  }
  
  // 检查是否所有文件都上传完成
  const allCompleted = uploadingFiles.value.every(f => f.status === 'success' || f.status === 'error');
  if (allCompleted) {
    const successCount = uploadingFiles.value.filter(f => f.status === 'success').length;
    const errorCount = uploadingFiles.value.filter(f => f.status === 'error').length;
    
    if (errorCount === 0) {
      ElMessage.success(`所有文件上传成功 (${successCount}/${uploadingFiles.value.length})`);
    } else {
      ElMessage.warning(`上传完成: 成功 ${successCount} 个，失败 ${errorCount} 个`);
    }
    
    showUploadDialog.value = false;
    clearUploadList();
    refreshFileList();
  }
};

// 上传单个文件
const uploadSingleFile = async (file) => {
  const fileItem = uploadingFiles.value.find(f => f.name === file.name);
  if (!fileItem) return;
  
  try {
    fileItem.status = 'uploading';
    fileItem.percentage = 0;
    
    const formData = new FormData();
    formData.append('file', file);
    formData.append('container_id', containerId.value);
    // 根目录是 '/'，其他路径去掉前面的 '/' 并添加后面的 '/'
    const uploadPath = currentPath.value === '/' ? '/' : currentPath.value.substring(1) + '/';
    formData.append('path', uploadPath);
    formData.append('filename', file.name);
    const res = await uploadFile(formData);
    
    if (res.data && res.data.code === 200) {
      fileItem.status = 'success';
      fileItem.percentage = 100;
      ElMessage.success(`文件 ${file.name} 上传成功`);
    } else {
      throw new Error(res.data?.msg || '上传失败');
    }
  } catch (error) {
    fileItem.status = 'error';
    console.error('上传失败:', error);
    ElMessage.error(`文件 ${file.name} 上传失败: ${error.message || '未知错误'}`);
  }
};

// 移除文件
const handleRemoveFile = (file) => {
  console.log('handleRemoveFile', file);
  
  // 从 uploadFileList 中移除
  const index = uploadFileList.value.findIndex(f => f.name === file.name);
  if (index > -1) {
    uploadFileList.value.splice(index, 1);
  }
  
  // 从 uploadingFiles 中移除
  const fileIndex = uploadingFiles.value.findIndex(f => f.uid === file.uid || f.name === file.name);
  if (fileIndex > -1) {
    uploadingFiles.value.splice(fileIndex, 1);
  }
  
  // 从 displayFileList 中移除
  const displayIndex = displayFileList.value.findIndex(f => f.uid === file.uid);
  if (displayIndex > -1) {
    displayFileList.value.splice(displayIndex, 1);
  }
};

// 清空上传列表
const clearUploadList = () => {
  uploadFileList.value = [];
  uploadingFiles.value = [];
  displayFileList.value = [];
  uploadProgress.value = 0;
  
  // 清空 el-upload 组件的文件列表
  if (uploadRef.value) {
    uploadRef.value.clearFiles();
  }
};

// 工具函数
const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 B';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

const getFileExtension = (filename) => {
  const ext = filename.split('.').pop();
  return ext ? ext.toUpperCase() : 'TXT';
};

// 判断是否为压缩文件
const isArchiveFile = (filename) => {
  if (!filename) return false;
  const ext = filename.split('.').pop()?.toLowerCase();
  const archiveExtensions = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz'];
  return archiveExtensions.includes(ext);
};

// 获取压缩文件类型
const getArchiveType = (filename) => {
  if (!filename) return '未知';
  const ext = filename.split('.').pop()?.toLowerCase();
  
  const typeMap = {
    'zip': 'ZIP 压缩文件',
    'rar': 'RAR 压缩文件',
    '7z': '7-Zip 压缩文件',
    'tar': 'TAR 归档文件',
    'gz': 'GZIP 压缩文件',
    'bz2': 'BZIP2 压缩文件',
    'xz': 'XZ 压缩文件'
  };
  
  return typeMap[ext] || '压缩文件';
};

// 设置当前路径为解压目录
const setCurrentPathAsOutput = () => {
  // 如果当前路径是根目录，设置为空字符串
  if (currentPath.value === '/') {
    decompressForm.outputDir = '';
  } else {
    // 去掉开头的 / 符号
    decompressForm.outputDir = currentPath.value.startsWith('/') ? currentPath.value.substring(1) : currentPath.value;
  }
};

// 获取解压预览路径
const getDecompressPreviewPath = () => {
  const outputDir = decompressForm.outputDir.trim();
  if (outputDir === '') {
    return '根目录 (/)';
  } else if (outputDir.startsWith('/')) {
    return '❌ 路径不能以 / 开头';
  } else {
    return outputDir;
  }
};

// 关闭解压对话框
const closeDecompressDialog = () => {
  showDecompressDialog.value = false;
  decompressForm.zipName = '';
  decompressForm.outputDir = '';
  decompressOptions.overwrite = false;
};

// 根据文件名获取编程语言
const getFileLanguage = (filename) => {
  if (!filename) return 'plaintext';
  
  const ext = filename.split('.').pop()?.toLowerCase();
  
  const languageMap = {
    // Web 技术
    'js': 'javascript',
    'jsx': 'javascript',
    'ts': 'typescript',
    'tsx': 'typescript',
    'html': 'html',
    'htm': 'html',
    'css': 'css',
    'scss': 'scss',
    'sass': 'sass',
    'less': 'less',
    'vue': 'html', // Vue SFC 使用 HTML 语法高亮
    'json': 'json',
    'xml': 'xml',
    
    // 编程语言
    'py': 'python',
    'java': 'java',
    'c': 'c',
    'cpp': 'cpp',
    'cxx': 'cpp',
    'cc': 'cpp',
    'h': 'c',
    'hpp': 'cpp',
    'cs': 'csharp',
    'php': 'php',
    'rb': 'ruby',
    'go': 'go',
    'rs': 'rust',
    'swift': 'swift',
    'kt': 'kotlin',
    'scala': 'scala',
    'r': 'r',
    'pl': 'perl',
    'lua': 'lua',
    
    // Shell 和配置
    'sh': 'shell',
    'bash': 'shell',
    'zsh': 'shell',
    'fish': 'shell',
    'ps1': 'powershell',
    'bat': 'bat',
    'cmd': 'bat',
    'dockerfile': 'dockerfile',
    'yaml': 'yaml',
    'yml': 'yaml',
    'toml': 'toml',
    'ini': 'ini',
    'conf': 'ini',
    'cfg': 'ini',
    
    // 数据格式
    'sql': 'sql',
    'md': 'markdown',
    'markdown': 'markdown',
    'tex': 'latex',
    
    // 其他
    'log': 'plaintext',
    'txt': 'plaintext'
  };
  
  return languageMap[ext] || 'plaintext';
};

// 处理主题切换
const handleThemeChange = (theme) => {
  editorTheme.value = theme;
  // 保存主题设置到本地存储
  localStorage.setItem('monaco-editor-theme', theme);
};

// 初始化时加载保存的主题
const initEditorTheme = () => {
  const savedTheme = localStorage.getItem('monaco-editor-theme');
  if (savedTheme) {
    editorTheme.value = savedTheme;
  }
};
</script>

<style scoped>
/* 文件管理页面样式 */
.container-file-manager {
  padding: 24px;
  background-color: #f5f7fa;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* 页面头部样式 */
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  background: #fff;
  padding: 16px 24px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}

.page-header h2 {
  margin: 0;
  font-size: 22px;
  color: #303133;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.page-header h2::before {
  content: '';
  display: inline-block;
  width: 4px;
  height: 22px;
  background-color: #409EFF;
  margin-right: 10px;
  border-radius: 2px;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 16px;
}

.header-icon {
  font-size: 20px;
  color: #409EFF;
}

.container-info {
  display: flex;
  align-items: center;
}

.header-actions {
  display: flex;
  gap: 12px;
}

/* 路径导航样式 */
.path-navigation {
  margin-bottom: 24px;
  background: #fff;
  padding: 12px 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}

.path-breadcrumb {
  display: flex;
  align-items: center;
  gap: 12px;
}

.path-label {
  font-size: 14px;
  color: #606266;
  font-weight: 500;
  white-space: nowrap;
}

.breadcrumb-clickable {
  cursor: pointer;
  color: #409EFF;
}

.breadcrumb-clickable:hover {
  text-decoration: underline;
}

.file-manager-container {
  flex: 1;
  display: flex;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
  overflow: hidden;
  height: calc(100vh - 180px); /* 固定为屏幕高度减去页面头部和导航 */
  max-height: calc(100vh - 180px);
}

/* 左侧文件树 */
.file-sidebar {
  width: 300px;
  background: #ffffff;
  border-right: 1px solid #e9ecef;
  display: flex;
  flex-direction: column;
  height: 100%; /* 使用父容器的完整高度 */
  max-height: calc(100vh - 180px); /* 最大高度限制为屏幕高度 */
  overflow: hidden;
}

.sidebar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  background: #f8f9fa;
  border-bottom: 1px solid #ebeef5;
  font-weight: 600;
  color: #303133;
}

.sidebar-title {
  font-size: 14px;
}

.sidebar-actions {
  display: flex;
  gap: 4px;
}

.file-tree-container {
  flex: 1;
  overflow: hidden;
  padding: 0;
  min-height: 0; /* 允许flex子项目缩小 */
}

/* 文件树滚动条样式 */
.tree-scrollbar {
  height: 100%;
  padding: 8px;
}

.tree-scrollbar :deep(.el-scrollbar__view) {
  height: calc(100vh - 280px); /* 屏幕高度减去页面头部等空间 */
  max-height: calc(100vh - 280px);
  overflow-y: auto;
}

.tree-scrollbar :deep(.el-scrollbar__bar.is-vertical) {
  right: 2px;
  width: 6px;
}

.tree-scrollbar :deep(.el-scrollbar__thumb) {
  background-color: rgba(144, 147, 153, 0.3);
  border-radius: 3px;
}

.tree-scrollbar :deep(.el-scrollbar__thumb:hover) {
  background-color: rgba(144, 147, 153, 0.5);
}

.file-tree {
  background: transparent;
}

.file-tree .el-tree-node__content {
  height: 36px;
  line-height: 36px;
  padding-right: 8px;
}

.file-tree .el-tree-node__content:hover {
  background-color: #f8f9fa;
}

.file-tree .el-tree-node:focus > .el-tree-node__content {
  background-color: #e3f2fd;
}

.tree-node-content {
  display: flex;
  align-items: center;
  flex: 1;
  padding-right: 8px;
}

.node-icon {
  margin-right: 8px;
  font-size: 16px;
}

.folder-icon {
  color: #ffd54f;
}

.file-icon {
  color: #90a4ae;
}

.node-label {
  flex: 1;
  font-size: 14px;
  color: #495057;
}

.node-actions {
  display: flex;
  gap: 2px;
  opacity: 0.8;
}

/* 右侧内容区域 */
.content-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: #ffffff;
  height: calc(100vh - 200px); /* 固定为屏幕高度减去页面头部等空间 */
  max-height: calc(100vh - 200px);
  overflow: hidden;
}

.content-tabs {
  height: 100%;
}

.editor-tabs {
  height: 100%;
}

.editor-tabs .el-tabs__content {
  height: calc(100% - 40px);
  overflow: hidden;
}

.editor-tabs .el-tab-pane {
  height: 100%;
}

/* 文件编辑器 */
.file-editor {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.editor-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #f8f9fa;
  border-bottom: 1px solid #e9ecef;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.file-info {
  font-weight: 600;
  color: #495057;
}

.toolbar-right {
  display: flex;
  gap: 8px;
}

.editor-content {
  flex: 1;
  padding: 0;
  height: calc(100% - 60px); 
  display: flex;
  flex-direction: column;
  /* height: 600px; */
}

.editor-content :deep(.monaco-editor-container) {
  flex: 1;
  border: none;
  border-radius: 0;
}

.code-editor {
  height: 100%;
}

.code-editor .el-textarea__inner {
  font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.6;
  border: none;
  border-radius: 0;
  resize: none;
  background: #ffffff;
  color: #212529;
}

.code-editor .el-textarea__inner:focus {
  box-shadow: none;
}

/* 目录视图 */
.directory-view {
  height: calc(100vh - 240px); /* 基于屏幕高度 */
  max-height: calc(100vh - 240px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.directory-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  background: #f8f9fa;
  border-bottom: 1px solid #e9ecef;
}

.directory-header h3 {
  margin: 0;
  color: #495057;
  font-size: 18px;
}

.view-actions {
  display: flex;
  gap: 4px;
}

/* 网格视图 */
.grid-view {
  padding: 20px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 16px;
  height: calc(100vh - 320px); /* 基于屏幕高度 */
  max-height: calc(100vh - 320px);
  overflow-y: auto;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}

.file-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 16px 8px;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
  border: 2px solid transparent;
}

.file-item:hover {
  background: #f8f9fa;
  border-color: #dee2e6;
}

.file-item:active {
  background: #e9ecef;
}

.file-icon-large {
  margin-bottom: 8px;
}

.file-name {
  text-align: center;
  font-size: 12px;
  color: #495057;
  word-break: break-all;
  line-height: 1.3;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
}



.file-details {
  font-size: 11px;
  color: #6c757d;
  margin-top: 4px;
}

/* 列表视图 */
.list-view {
  padding: 0 20px 20px;
  height: calc(100vh - 320px); /* 基于屏幕高度 */
  max-height: calc(100vh - 320px);
  overflow: hidden;
}

.list-view .directory-table {
  border: 1px solid #ebeef5;
  border-radius: 4px;
}

.directory-table .el-table__row {
  cursor: pointer;
}

.directory-table .el-table__row:hover {
  background: #f8f9fa;
}

/* 欢迎页 */
.welcome-view {
  height: calc(100vh - 240px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  overflow-y: auto;
  padding: 20px;
}

.welcome-container {
  width: 100%;
  max-width: 900px;
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  padding: 40px;
  margin-top: 20px;
}

.welcome-header {
  text-align: center;
  margin-bottom: 40px;
  padding-bottom: 30px;
  border-bottom: 1px solid #ebeef5;
}

.welcome-icon {
  margin-bottom: 20px;
}

.welcome-title {
  margin: 0 0 16px;
  color: #303133;
  font-size: 32px;
  font-weight: 600;
  letter-spacing: -0.5px;
}

.welcome-subtitle {
  color: #606266;
  font-size: 16px;
  margin: 0;
  line-height: 1.6;
}

.welcome-features {
  margin-bottom: 40px
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

.feature-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 20px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
  transition: all 0.3s ease;
}

.feature-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  border-color: #409EFF;
}

.feature-item span {
  font-weight: 600;
  color: #303133;
  margin: 8px 0 4px;
  font-size: 14px;
}

.feature-item small {
  color: #909399;
  font-size: 12px;
  line-height: 1.4;
}

.quick-actions {
  margin-bottom: 30px;
}

.actions-title {
  margin: 0 0 20px;
  color: #303133;
  font-size: 18px;
  font-weight: 600;
}

.actions-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}

.action-card {
  display: flex;
  align-items: center;
  padding: 20px;
  background: #ffffff;
  border: 2px solid #e4e7ed;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}

.action-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
}

.action-card.primary:hover {
  border-color: #409EFF;
  background: linear-gradient(135deg, #ecf5ff 0%, #ffffff 100%);
}

.action-card.success:hover {
  border-color: #67C23A;
  background: linear-gradient(135deg, #f0f9ff 0%, #ffffff 100%);
}

.action-card.warning:hover {
  border-color: #E6A23C;
  background: linear-gradient(135deg, #fdf6ec 0%, #ffffff 100%);
}

.action-icon {
  margin-right: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 8px;
  background: #f8f9fa;
}

.action-card.primary .action-icon {
  color: #409EFF;
  background: #ecf5ff;
}

.action-card.success .action-icon {
  color: #67C23A;
  background: #f0f9ff;
}

.action-card.warning .action-icon {
  color: #E6A23C;
  background: #fdf6ec;
}

.action-text {
  flex: 1;
}

.action-name {
  display: block;
  font-weight: 600;
  color: #303133;
  font-size: 16px;
  margin-bottom: 4px;
}

.action-desc {
  color: #909399;
  font-size: 13px;
  line-height: 1.4;
}

.welcome-tips {
  margin-top: 30px;
}

.welcome-tips :deep(.el-alert) {
  border-radius: 8px;
  background: #f0f9ff;
  border-color: #b3d8ff;
}

.tips-list {
  margin: 0;
  padding-left: 20px;
  color: #606266;
}

.tips-list li {
  margin-bottom: 8px;
  line-height: 1.6;
}

.tips-list li:last-child {
  margin-bottom: 0;
}

.breadcrumb-clickable {
  cursor: pointer;
  color: rgba(255, 255, 255, 0.9);
}

.breadcrumb-clickable:hover {
  color: white;
  text-decoration: underline;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.el-upload__text em {
  color: #409EFF;
}

/* 上传相关样式 */
.upload-container {
  padding: 10px 0;
}

.upload-path-info {
  margin-bottom: 20px;
}

.upload-area {
  margin-bottom: 20px;
}

.upload-actions {
  margin-bottom: 20px;
  padding: 12px;
  background: #f8f9fa;
  border-radius: 6px;
  text-align: center;
}

.upload-progress {
  margin-top: 20px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 6px;
}

.upload-progress h4 {
  margin: 0 0 16px 0;
  color: #303133;
  font-size: 16px;
}

.file-progress {
  margin-bottom: 16px;
}

.file-progress:last-child {
  margin-bottom: 0;
}

.file-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.file-name {
  color: #303133;
  font-weight: 500;
}

.file-status {
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 4px;
}

.file-status.waiting {
  background: #f4f4f5;
  color: #909399;
}

.file-status.uploading {
  background: #e6f7ff;
  color: #1890ff;
}

.file-status.success {
  background: #f6ffed;
  color: #52c41a;
}

.file-status.error {
  background: #fff1f0;
  color: #ff4d4f;
}

/* 右键菜单样式 */
.context-menu-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2000;
}

.context-menu {
  position: fixed;
  background: #ffffff;
  border: 1px solid #ebeef5;
  border-radius: 6px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  padding: 6px 0;
  min-width: 120px;
  z-index: 2001;
}

.context-menu-item {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  cursor: pointer;
  transition: background-color 0.3s;
  color: #606266;
  font-size: 14px;
}

.context-menu-item:hover {
  background-color: #f5f7fa;
  color: #409EFF;
}

.context-menu-item.danger {
  color: #f56c6c;
}

.context-menu-item.danger:hover {
  background-color: #fef0f0;
  color: #f56c6c;
}

.context-menu-item .el-icon {
  margin-right: 8px;
  font-size: 16px;
}

.context-menu-divider {
  height: 1px;
  background-color: #ebeef5;
  margin: 6px 0;
}

/* 响应式设计 */
@media screen and (max-width: 1200px) {
  .file-sidebar {
    width: 250px;
  }
}

@media screen and (max-width: 768px) {
  .container-file-manager {
    padding: 16px;
  }
  
  .page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
    padding: 16px 20px;
  }
  
  .header-left {
    width: 100%;
  }
  
  .header-actions {
    width: 100%;
    flex-wrap: wrap;
    gap: 8px;
  }
  
  .header-actions .el-button {
    flex: 1;
    min-width: auto;
  }
  
  .path-navigation {
    padding: 12px 16px;
  }
  
  .path-breadcrumb {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
  
  .file-manager-container {
    flex-direction: column;
    height: calc(100vh - 150px); /* 移动端调整高度 */
  }
  
  .file-sidebar {
    width: 100%;
    height: 250px; /* 固定高度，不随内容增长 */
    max-height: 100vh; /* 移动端最大高度限制为一倍屏幕高度 */
    border-right: none;
    border-bottom: 1px solid #ebeef5;
  }
  
  .tree-scrollbar {
    padding: 4px;
  }
  
  .tree-scrollbar :deep(.el-scrollbar__view) {
    max-height: calc(100vh - 100px); /* 移动端限制为一倍屏幕高度 */
  }
  
  .content-area {
    height: calc(100vh - 400px);
    min-height: 300px;
    flex: 1;
  }
  
  .grid-view {
    grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
    gap: 12px;
    padding: 16px;
  }
}

/* 标签页样式 */
.modified-indicator {
  color: #F56C6C;
  margin-left: 4px;
}

/* 文件名验证样式 */
.error-message {
  color: #f56c6c;
  font-size: 12px;
  margin-top: 4px;
  line-height: 1.4;
}

.file-name-hint {
  margin-top: 4px;
}

.file-name-hint small {
  color: #909399;
  font-size: 12px;
  line-height: 1.4;
}

/* 解压对话框样式 */
.decompress-container {
  padding: 10px 0;
}

.decompress-info {
  margin-bottom: 20px;
}

.decompress-info :deep(.el-alert__content) p {
  margin: 4px 0;
  color: #606266;
}

.form-hint {
  margin-top: 8px;
}

.form-hint small {
  color: #909399;
  font-size: 12px;
  line-height: 1.4;
}

.decompress-preview {
  margin-top: 20px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e9ecef;
}

.decompress-preview :deep(.el-alert) {
  background: transparent;
  border: none;
  padding: 0;
}

.decompress-preview :deep(.el-alert__title) {
  color: #67C23A;
  font-weight: 500;
}




</style>
