<template>
  <div class="setting-manage-container">
    <el-card class="main-container" shadow="never">
      <!-- 搜索和操作栏 -->
      <div class="filter-section">
        <div class="filter-content">
          <el-form :inline="true" :model="queryParams" class="search-form">
            <el-form-item label="关键词筛选">
              <el-input v-model="queryParams.key" placeholder="请输入关键词" clearable style="width: 200px" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleQuery">
                <el-icon><Search /></el-icon>查询
              </el-button>
              <el-button @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
          <div class="action-bar">
            <el-button type="primary" @click="handleAddGroup">
              <el-icon><Plus /></el-icon>新增配置组
            </el-button>
            <el-button type="primary" @click="handleAddSetting">
              <el-icon><Plus /></el-icon>新增配置
            </el-button>
            <el-button type="success" @click="handleBatchImport">
              <el-icon><UploadFilled /></el-icon>一键导入配置
            </el-button>
            <el-button type="danger" :disabled="selectedRows.length === 0" @click="handleBatchDelete">
              <el-icon><Delete /></el-icon>批量删除 ({{ selectedRows.length }})
            </el-button>
          </div>
        </div>
      </div>

      <!-- 树状图显示区域 -->
      <div class="tree-section">
        <!-- 树形表格视图 -->
        <el-table
          ref="treeTableRef"
          :data="treeDisplayData"
          style="width: 100%"
          row-key="id"
          :header-cell-style="{ background: '#fafafa', color: '#333', fontWeight: 600 }"
          class="setting-tree-table"
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="55" />
          <el-table-column label="名称" min-width="300">
            <template #default="{ row }">
              <div class="tree-item-content" :style="{ paddingLeft: (row.level - 1) * 24 + 'px' }">
                <!-- 展开/收起按钮 -->
                <span 
                  v-if="row.type === 'group' && row.hasChildren" 
                  class="expand-icon"
                  @click="toggleExpand(row)"
                >
                  <el-icon v-if="row._loading"><Loading /></el-icon>
                  <el-icon v-else :class="{ 'is-expanded': row._expanded }"><ArrowRight /></el-icon>
                </span>
                <span v-else class="expand-placeholder"></span>
                <div class="tree-node">
                  <el-icon class="tree-icon" v-if="row.type === 'group'">
                    <Folder />
                  </el-icon>
                  <el-icon class="tree-icon" v-else-if="row.type === 'setting'">
                    <Document />
                  </el-icon>
                  <span class="tree-label">{{ row.label }}</span>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="类型" width="100">
            <template #default="{ row }">
              <el-tag v-if="row.type === 'group'" type="primary" size="small">配置组</el-tag>
              <el-tag v-else-if="row.type === 'setting'" :type="getTypeColor(row.data.type)" size="small">
                {{ row.data.type }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="值" min-width="200">
            <template #default="{ row }">
              <span v-if="row.type === 'group'" style="cursor: default;">{{ row.data.note || '-' }}</span>
              <span v-else-if="row.type === 'setting'" style="cursor: pointer;" @click="handleEditSetting(row.data)">
                <span v-if="row.data.type === 'bool'">{{ row.data.value ? '是' : '否' }}</span>
                <span v-else-if="row.data.type === 'file'">
                  <el-link v-if="row.data.value" type="primary" @click.stop="previewFile(row.data.value)">
                    文件ID: {{ row.data.value }}
                  </el-link>
                  <span v-else>-</span>
                </span>
                <span v-else-if="row.data.type === 'file_list'">
                  <div v-if="row.data.value" class="file-list-summary">
                    <el-tag type="primary" size="small" @click.stop="handleEditSetting(row.data)" style="cursor: pointer;">
                      <el-icon><Folder /></el-icon>
                      共 {{ getFileList(row.data.value).length }} 个文件
                    </el-tag>
                  </div>
                  <span v-else>-</span>
                </span>
                <span v-else-if="row.data.type === 'string_list'">
                  <div v-if="row.data.value" class="string-list-summary">
                    <el-tag type="success" size="small" @click.stop="handleEditSetting(row.data)" style="cursor: pointer;">
                      <el-icon><Document /></el-icon>
                      共 {{ getStringList(row.data.value).length }} 条字符串
                    </el-tag>
                  </div>
                  <span v-else>-</span>
                </span>
                <span v-else>
                  <span class="text-value" :title="row.data.value">{{ truncateText(row.data.value, 30) }}</span>
                </span>
              </span>
            </template>
          </el-table-column>
          <el-table-column label="状态" width="100">
            <template #default="{ row }">
              <el-tag v-if="row.type === 'group'" type="success" size="small">正常</el-tag>
              <el-tag v-else-if="row.type === 'setting'" :type="row.data.open ? 'success' : 'info'" size="small">
                {{ row.data.open ? '开放' : '私有' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="创建时间" width="180">
            <template #default="{ row }">
              {{ formatDate(row.data.CreatedAt) }}
            </template>
          </el-table-column>
          <el-table-column label="备注" min-width="150" show-overflow-tooltip>
            <template #default="{ row }">
              <span v-if="row.type === 'group'">{{ row.data.note || '-' }}</span>
              <span v-else-if="row.type === 'setting'">{{ row.data.note || '-' }}</span>
              <span v-else>-</span>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="320" fixed="right">
            <template #default="{ row }">
              <el-button v-if="row.type === 'group'" type="primary" link size="small" @click="handleEditGroup(row.data)">
                编辑
              </el-button>
              <el-button v-if="row.type === 'group'" type="success" link size="small" @click="handleAddSettingToGroup(row.data)">
                新增配置
              </el-button>
              <el-button v-if="row.type === 'group'" type="warning" link size="small" @click="handleCopyGroupSettings(row)">
                一键复制
              </el-button>
              <el-button v-if="row.type === 'group'" type="success" link size="small" @click="handleImportToGroup(row.data)">
                一键导入
              </el-button>
              <el-button v-if="row.type === 'setting'" type="primary" link size="small" @click="handleEditSetting(row.data)">
                编辑
              </el-button>
              <el-button type="danger" link size="small" @click="handleDelete(row)">
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <!-- 详细信息面板 -->
      <div class="detail-section" v-if="selectedNode">
        <el-divider content-position="left">{{ selectedNode.type === 'group' ? '配置组详情' : '配置详情' }}</el-divider>
        <div class="detail-content">
          <template v-if="selectedNode.type === 'group'">
            <el-descriptions :column="2" border>
              <el-descriptions-item label="ID">{{ selectedNode.data.id }}</el-descriptions-item>
              <el-descriptions-item label="名称">{{ selectedNode.data.name }}</el-descriptions-item>
              <el-descriptions-item label="备注" :span="2">{{ selectedNode.data.note || '-' }}</el-descriptions-item>
              <el-descriptions-item label="创建时间">{{ formatDate(selectedNode.data.CreatedAt) }}</el-descriptions-item>
              <el-descriptions-item label="更新时间">{{ formatDate(selectedNode.data.UpdatedAt) }}</el-descriptions-item>
            </el-descriptions>
          </template>
          <template v-else-if="selectedNode.type === 'setting'">
            <el-descriptions :column="2" border>
              <el-descriptions-item label="ID">{{ selectedNode.data.id }}</el-descriptions-item>
              <el-descriptions-item label="名称">{{ selectedNode.data.name }}</el-descriptions-item>
              <el-descriptions-item label="类型">
                <el-tag :type="getTypeColor(selectedNode.data.type)">{{ selectedNode.data.type }}</el-tag>
              </el-descriptions-item>
              <el-descriptions-item label="配置组">{{ selectedNode.data.settingGroupID || '-' }}</el-descriptions-item>
              <el-descriptions-item label="值" :span="2" class="value-descriptions-item">
                <div class="value-content">
                  <span v-if="selectedNode.data.type === 'bool'">{{ selectedNode.data.value ? '是' : '否' }}</span>
                  <span v-else-if="selectedNode.data.type === 'file'">
                    <el-link v-if="selectedNode.data.value" type="primary" @click="previewFile(selectedNode.data.value)">
                      文件ID: {{ selectedNode.data.value }}
                    </el-link>
                    <span v-else>-</span>
                  </span>
                  <span v-else-if="selectedNode.data.type === 'file_list'">
                    <div v-if="selectedNode.data.value" class="table-file-list">
                      <div 
                        v-for="(fileId, index) in getFileList(selectedNode.data.value)" 
                        :key="fileId"
                        class="table-file-item"
                      >
                        <div class="file-preview-mini">
                          <img 
                            v-if="selectedNode.data.parsedValue && selectedNode.data.parsedValue[index]"
                            :src="processImageUrl(selectedNode.data.parsedValue[index])" 
                            :alt="`文件${index + 1}`"
                            class="preview-mini-image"
                            @click="previewImage(selectedNode.data.parsedValue[index])"
                            @error="handleImageError"
                          />
                          <div v-else class="file-placeholder-mini">
                            <el-icon><Document /></el-icon>
                          </div>
                        </div>
                        <div class="file-info-mini">
                          <div class="file-name-mini" :title="`文件${index + 1}: ${fileId}`">
                            文件{{ index + 1 }}
                          </div>
                          <div class="file-id-mini">ID: {{ fileId }}</div>
                        </div>
                      </div>
                    </div>
                    <span v-else>-</span>
                  </span>
                  <span v-else-if="selectedNode.data.type === 'string_list'">
                    <div class="editable-string-list">
                      <div class="string-list-header">
                        <span class="list-title">字符串列表 ({{ getStringList(selectedNode.data.value).length }} 项)</span>
                        <el-button type="primary" size="small" @click="addEditableStringItem">添加项目</el-button>
                      </div>
                      <div class="string-list-items">
                        <div
                          v-for="(item, index) in getEditableStringList()"
                          :key="`editable-${index}`"
                          class="string-list-item"
                          draggable="true"
                          @dragstart="handleDragStart($event, index)"
                          @dragover.prevent
                          @drop="handleDrop($event, index)"
                        >
                          <div class="drag-handle">
                            <el-icon><Rank /></el-icon>
                          </div>
                          <div class="item-content">
                            <el-input
                              v-if="item.editing"
                              v-model="item.value"
                              size="small"
                              @blur="finishEditItem(index)"
                              @keyup.enter="finishEditItem(index)"
                              ref="editInput"
                              @mounted="focusEditInput"
                            />
                            <span v-else class="item-text" @dblclick="startEditItem(index)">
                              {{ truncateFileName(item.value, 40) }}
                            </span>
                          </div>
                          <div class="item-actions">
                            <el-button type="text" size="small" @click="startEditItem(index)" :icon="Edit" />
                            <el-button type="text" size="small" @click="removeEditableStringItem(index)" :icon="Delete" class="danger-btn" />
                          </div>
                        </div>
                      </div>
                    </div>
                  </span>
                  <span v-else class="text-value">
                    {{ selectedNode.data.value }}
                  </span>
                </div>
              </el-descriptions-item>
              <el-descriptions-item label="是否开放">
                <el-tag :type="selectedNode.data.open ? 'success' : 'info'">
                  {{ selectedNode.data.open ? '开放' : '私有' }}
                </el-tag>
              </el-descriptions-item>
              <el-descriptions-item label="备注" :span="2">{{ selectedNode.data.note || '-' }}</el-descriptions-item>
              <el-descriptions-item label="创建时间">{{ formatDate(selectedNode.data.CreatedAt) }}</el-descriptions-item>
              <el-descriptions-item label="更新时间">{{ formatDate(selectedNode.data.UpdatedAt) }}</el-descriptions-item>
            </el-descriptions>
          </template>
        </div>
      </div>
    </el-card>

    <!-- 配置组表单对话框 -->
    <el-dialog
      v-model="groupDialogVisible"
      :title="groupDialogTitle"
      width="500px"
      destroy-on-close
      class="dialog-scrollable"
    >
      <el-form
        ref="groupFormRef"
        :model="groupForm"
        :rules="groupRules"
        label-width="100px"
      >
        <el-form-item label="名称" prop="name">
          <el-input v-model="groupForm.name" placeholder="请输入配置组名称" />
        </el-form-item>
        <el-form-item label="备注" prop="note">
          <el-input
            v-model="groupForm.note"
            type="textarea"
            :rows="3"
            placeholder="请输入备注信息"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="groupDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitGroupForm">确定</el-button>
      </template>
    </el-dialog>

    <!-- 配置表单对话框 -->
    <el-dialog
      v-model="settingDialogVisible"
      :title="settingDialogTitle"
      width="1000px"
      destroy-on-close
      class="dialog-scrollable"
    >
      <el-form
        ref="settingFormRef"
        :model="settingForm"
        :rules="settingRules"
        label-width="120px"
      >
        <el-form-item label="配置组" prop="settingGroupID">
          <el-select v-model="settingForm.settingGroupID" placeholder="请选择配置组" style="width: 100%">
            <el-option
              v-for="group in allGroupList"
              :key="group.id"
              :label="group.name"
              :value="group.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="名称" prop="name">
          <el-input v-model="settingForm.name" placeholder="请输入配置名称" />
        </el-form-item>
        <el-form-item label="类型" prop="type">
          <el-select v-model="settingForm.type" placeholder="请选择类型" style="width: 100%" @change="handleTypeChange">
            <el-option label="字符串 (string)" value="string" />
            <el-option label="整数 (int)" value="int" />
            <el-option label="浮点数 (float)" value="float" />
            <el-option label="布尔值 (bool)" value="bool" />
            <el-option label="文件 (file)" value="file" />
            <el-option label="多文件 (file_list)" value="file_list" />
            <el-option label="字符串列表 (string_list)" value="string_list" />
          </el-select>
        </el-form-item>
        <el-form-item label="值" prop="value">
          <div v-if="settingForm.type === 'string'" style="width: 100%">
            <div v-if="isJsonValue" class="json-toolbar">
              <el-tag size="small" type="success">JSON</el-tag>
              <el-button size="small" @click="formatJson">格式化</el-button>
              <el-button size="small" @click="compressJson">压缩</el-button>
            </div>
            <el-input
              v-model="settingForm.value"
              type="textarea"
              :rows="isJsonValue ? 12 : 3"
              placeholder="请输入配置值"
              :input-style="isJsonValue ? { fontFamily: 'Consolas, Monaco, monospace', fontSize: '13px', lineHeight: '1.5' } : {}"
            />
          </div>
          <el-input-number
            v-else-if="settingForm.type === 'int'"
            v-model="settingForm.value"
            :controls="false"
            placeholder="请输入整数"
            style="width: 100%"
          />
          <el-input-number
            v-else-if="settingForm.type === 'float'"
            v-model="settingForm.value"
            :controls="false"
            :precision="2"
            placeholder="请输入浮点数"
            style="width: 100%"
          />
          <el-switch
            v-else-if="settingForm.type === 'bool'"
            v-model="settingForm.value"
          />
          <div v-else-if="settingForm.type === 'file'" class="file-upload-section">
            <div class="file-info-display" v-if="settingForm.value && fileInfo">
              <div class="file-item" :class="{ 'uploading': fileUploading && fileInfo.isLocal }">
                <!-- 图片预览 -->
                <div class="file-preview" v-if="fileInfo.url || fileInfo.localUrl" @click="openImageSelector" style="cursor: pointer;">
                  <img :src="fileInfo.localUrl || processImageUrl(fileInfo.url)" :alt="fileInfo.realName" class="preview-image" @click.stop="previewImage(fileInfo.localUrl || fileInfo.url)" @error="handleImageError" />
                  <!-- 上传状态指示器 -->
                  <div v-if="fileUploading && fileInfo.isLocal" class="upload-overlay">
                    <el-icon class="is-loading"><Loading /></el-icon>
                    <span>上传中...</span>
                  </div>
                </div>
                <!-- 图片加载失败占位符 -->
                <div class="file-preview" v-else @click="openImageSelector" style="cursor: pointer;">
                  <div class="file-placeholder">
                    <el-icon><Document /></el-icon>
                  </div>
                </div>
                
                <!-- 文件信息 -->
                <div class="file-details">
                  <span class="file-name" :title="fileInfo.realName || fileInfo.saveName">{{ truncateFileName(fileInfo.realName || fileInfo.saveName) }}</span>
                  <span class="file-id">文件ID: {{ settingForm.value }}</span>
                  <span class="file-size">{{ formatFileSize(fileInfo.size) }}</span>
                  <!-- 非图片文件预览链接 -->
                  
                </div>
                
                <!-- 操作按钮 -->
                <div class="file-actions">
                  <el-button type="primary" size="small" @click="openImageSelector" :icon="Picture">
                    修改图片
                  </el-button>
                  <el-button type="danger" size="small" @click="clearFile">删除</el-button>
                </div>
              </div>
            </div>
            <div v-else class="file-upload-options">
              <div class="upload-methods">
                <el-button 
                  type="primary" 
                  @click="openImageSelector"
                  :icon="Picture"
                  class="image-selector-btn"
                >
                  从文件库选择图片
                </el-button>
              </div>
            </div>
          </div>
          <div v-else-if="settingForm.type === 'file_list'" class="file-list-section">
            <div class="editable-file-list">
              <div class="file-list-header">
                <span class="list-title">文件列表 ({{ getEditableFormFileList().length }} 项)</span>
                <div class="header-actions">
                  <el-button size="small" @click="openImageSelectorForList" :icon="Picture">
                    从文件库选择
                  </el-button>
                </div>
              </div>
              <div class="file-list-items">
                <div
                  v-for="(fileInfo, index) in getEditableFormFileList()"
                  :key="`form-file-${index}`"
                  class="file-list-item"
                  draggable="true"
                  @dragstart="handleFormFileDragStart($event, index)"
                  @dragover.prevent
                  @drop="handleFormFileDrop($event, index)"
                >
                  <div class="drag-handle">
                    <el-icon><Rank /></el-icon>
                  </div>
                  <div class="file-preview">
                    <img 
                      v-if="fileInfo.url || fileInfo.localUrl" 
                      :src="fileInfo.localUrl || processImageUrl(fileInfo.url)" 
                      :alt="fileInfo.realName" 
                      class="preview-image" 
                      @click="previewImage(fileInfo.localUrl || fileInfo.url)" 
                      @error="handleImageError" 
                    />
                    <div v-else class="file-placeholder">
                      <el-icon><Document /></el-icon>
                    </div>
                    <div v-if="fileInfo.uploading" class="upload-overlay">
                      <el-icon class="is-loading"><Loading /></el-icon>
                      <span>上传中...</span>
                    </div>
                  </div>
                  <div class="file-info">
                    <div class="file-name" :title="fileInfo.realName || fileInfo.saveName">
                      {{ truncateFileName(fileInfo.realName || fileInfo.saveName, 30) }}
                    </div>
                    <div class="file-id">ID: {{ fileInfo.id || '上传中' }}</div>
                    <div class="file-size">{{ formatFileSize(fileInfo.size) }}</div>
                  </div>
                  <div class="file-actions">
                    <el-button type="text" size="small" @click="openImageSelectorForListItem(index)" :icon="Edit" title="替换文件" />
                    <el-button type="text" size="small" @click="removeFormEditableFileItem(index)" :icon="Delete" class="danger-btn" title="删除文件" />
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div v-else-if="settingForm.type === 'string_list'" class="string-list-section">
            <div class="editable-string-list">
              <div class="string-list-header">
                <span class="list-title">字符串列表 ({{ getEditableFormStringList().length }} 项)</span>
                <el-button type="primary" size="small" @click="addFormEditableStringItem">添加项目</el-button>
              </div>
              <div class="string-list-items">
                <div
                  v-for="(item, index) in getEditableFormStringList()"
                  :key="`form-editable-${index}`"
                  class="string-list-item"
                  draggable="true"
                  @dragstart="handleFormDragStart($event, index)"
                  @dragover.prevent
                  @drop="handleFormDrop($event, index)"
                >
                  <div class="drag-handle">
                    <el-icon><Rank /></el-icon>
                  </div>
                  <div class="item-content">
                    <el-input
                      v-if="item.editing"
                      v-model="item.value"
                      size="small"
                      @blur="finishFormEditItem(index)"
                      @keyup.enter="finishFormEditItem(index)"
                      ref="formEditInput"
                      @mounted="focusFormEditInput"
                    />
                    <span v-else class="item-text" @dblclick="startFormEditItem(index)">
                      {{ truncateFileName(item.value, 40) }}
                    </span>
                  </div>
                  <div class="item-actions">
                    <el-button type="text" size="small" @click="startFormEditItem(index)" :icon="Edit" />
                    <el-button type="text" size="small" @click="removeFormEditableStringItem(index)" :icon="Delete" class="danger-btn" />
                  </div>
                </div>
              </div>
            </div>
          </div>
          <el-input
            v-else
            v-model="settingForm.value"
            placeholder="请输入配置值"
          />
        </el-form-item>
        <el-form-item label="是否开放访问">
          <el-switch v-model="settingForm.open" />
          <span style="margin-left: 10px; color: #909399; font-size: 12px;">
            开启后允许公开访问
          </span>
        </el-form-item>
        <el-form-item label="备注" prop="note">
          <el-input
            v-model="settingForm.note"
            type="textarea"
            :rows="3"
            placeholder="请输入备注信息"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="settingDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitSettingForm">确定</el-button>
      </template>
    </el-dialog>

    <!-- 一键导入配置对话框 -->
    <el-dialog
      v-model="batchImportDialogVisible"
      title="一键导入配置"
      width="900px"
      destroy-on-close
      class="dialog-scrollable"
      :close-on-click-modal="!batchImportLoading"
      :close-on-press-escape="!batchImportLoading"
      :show-close="!batchImportLoading"
    >
      <el-alert
        title="使用说明"
        type="info"
        :closable="false"
        show-icon
        style="margin-bottom: 16px"
      >
        <template #default>
          <div style="line-height: 1.8">
            粘贴通过「一键复制」导出的内容即可自动导入。系统会自动识别配置组名称，不存在则自动创建。<br />
            格式示例：<br />
            <code>[配置组] 移动端-全局配置</code><br />
            <code>| 配置名 | 类型 | 默认值 | 说明 |</code><br />
            <code>|--------|------|--------|------|</code><br />
            <code>| `移动端_主题主色` | `string` | `#2B7EFB` | 按钮、链接、选中态主色 |</code>
          </div>
        </template>
      </el-alert>

      <!-- 导入进度面板 -->
      <div v-if="batchImportLoading" class="import-progress-panel">
        <div class="progress-header">
          <el-icon class="is-loading" :size="20" color="#409eff"><Loading /></el-icon>
          <span style="font-weight: 600; font-size: 15px; color: #303133">正在导入...</span>
        </div>
        <div class="progress-info">
          <div v-if="batchImportStatusText" style="margin-bottom: 12px; color: #606266; font-size: 13px;">
            {{ batchImportStatusText }}
          </div>
          <el-progress
            :percentage="batchImportTotal > 0 ? Math.round(batchImportProgress / batchImportTotal * 100) : 0"
            :stroke-width="18"
            :text-inside="true"
            striped
            striped-flow
          />
          <div style="margin-top: 8px; color: #909399; font-size: 12px; text-align: center;">
            {{ batchImportProgress }} / {{ batchImportTotal }}
          </div>
        </div>
      </div>

      <!-- 非导入中时显示表单 -->
      <template v-if="!batchImportLoading">
        <el-form label-width="100px">
          <!-- 自动识别的配置组 -->
          <el-form-item label="配置组">
            <div v-if="batchImportGroupName" style="display: flex; align-items: center; gap: 8px; width: 100%;">
              <el-tag :type="batchImportGroupExists ? 'success' : 'warning'" size="large" style="font-size: 14px;">
                <el-icon style="margin-right: 4px;"><Folder /></el-icon>
                {{ batchImportGroupName }}
              </el-tag>
              <span v-if="batchImportGroupExists" style="color: #67c23a; font-size: 12px;">已存在，将导入到此配置组</span>
              <span v-else style="color: #e6a23c; font-size: 12px;">不存在，将自动创建后导入</span>
            </div>
            <span v-else style="color: #c0c4cc; font-size: 13px;">粘贴内容后自动识别（首行 <code>[配置组] 名称</code>）</span>
          </el-form-item>
          <el-form-item label="默认公开">
            <el-switch v-model="batchImportOpen" />
            <span style="margin-left: 8px; color: #909399; font-size: 13px">导入的配置项是否默认对外公开</span>
          </el-form-item>
          <el-form-item label="导入内容">
            <el-input
              v-model="batchImportText"
              type="textarea"
              :rows="10"
              placeholder="粘贴通过「一键复制」导出的内容..."
              style="font-family: monospace"
            />
          </el-form-item>
        </el-form>

        <!-- 解析预览 -->
        <div v-if="batchImportParsed.length > 0" style="margin-top: 8px">
          <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px">
            <span style="font-weight: 600; font-size: 14px; color: #303133">
              解析预览（共 {{ batchImportParsed.length }} 条）
            </span>
            <el-button type="primary" link @click="parseBatchImportText">
              <el-icon><Search /></el-icon>重新解析
            </el-button>
          </div>
          <el-table :data="batchImportParsed" border size="small" max-height="300">
            <el-table-column type="index" label="#" width="50" />
            <el-table-column prop="name" label="配置名" min-width="180">
              <template #default="{ row }">
                <span :style="{ color: row._duplicate ? '#F56C6C' : '' }">
                  {{ row.name }}
                  <el-tag v-if="row._duplicate" type="danger" size="small" style="margin-left: 4px">重复</el-tag>
                </span>
              </template>
            </el-table-column>
            <el-table-column prop="type" label="类型" width="120">
              <template #default="{ row }">
                <el-tag size="small">{{ row.type }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="value" label="默认值" min-width="160">
              <template #default="{ row }">
                <span class="text-value">{{ row.value }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="note" label="说明" min-width="200" />
            <el-table-column label="操作" width="70" fixed="right">
              <template #default="{ $index }">
                <el-button link type="danger" size="small" @click="batchImportParsed.splice($index, 1)">移除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </template>

      <template #footer>
        <el-button @click="batchImportDialogVisible = false" :disabled="batchImportLoading">取消</el-button>
        <el-button type="primary" @click="parseBatchImportText" :disabled="!batchImportText.trim() || batchImportLoading">
          解析预览
        </el-button>
        <el-button
          type="success"
          :loading="batchImportLoading"
          :disabled="batchImportParsed.length === 0 || !batchImportGroupName"
          @click="submitBatchImport"
        >
          确认导入 ({{ batchImportParsed.length }})
        </el-button>
      </template>
    </el-dialog>

    <!-- 图片查看器 -->
    <el-dialog v-model="imageViewerVisible" width="auto" destroy-on-close>
      <img :src="currentViewImage" style="max-width: 100%; max-height: 80vh;" />
    </el-dialog>

    <!-- 图片选择器 -->
    <ImageSelector 
      v-model="imageSelectorVisible" 
      :current-file-id="currentImageSelectorFileId"
      :multiple="imageSelectorMode === 'list'"
      @confirm="handleImageSelectorConfirm"
    />
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, watch, nextTick, computed } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Plus, Delete, UploadFilled, Folder, Document, ArrowRight, Loading, Picture, Edit, Rank } from '@element-plus/icons-vue'
import {
  getSettingGroupList,
  getSettingGroupInfo,
  createSettingGroup,
  updateSettingGroup,
  deleteSettingGroup,
  getSettingList,
  getSettingInfo,
  createSetting,
  updateSetting,
  setSettingOpen,
  deleteSetting
} from '@/api/admin/setting'
import { uploadFile, getFileDetail, downloadFile } from '@/api/admin/file'
import ImageSelector from '@/components/admin/ImageSelector.vue'

const route = useRoute()

// 树状图相关状态
const treeTableRef = ref(null)
const treeData = ref([])
const allGroupList = ref([]) // 存储所有已加载的配置组
const treeDataMap = ref(new Map()) // 存储树形数据，key为group_id
const selectedNode = ref(null)
const editableStringList = ref([]) // 弹窗中可编辑的字符串列表
const draggedIndex = ref(-1) // 拖拽的索引

// 表单相关可编辑列表
const editableFormStringList = ref([]) // 表单中可编辑的字符串列表
const editableFormFileList = ref([]) // 表单中可编辑的文件列表
const formDraggedIndex = ref(-1) // 表单拖拽索引
const formFileDraggedIndex = ref(-1) // 表单文件拖拽索引

// 查询参数
const queryParams = reactive({
  key: '',
  page: 1,
  count: 10
})

// 树状图配置
const treeProps = {
  children: 'children',
  label: 'label',
  hasChildren: 'hasChildren'
}

// 树形显示数据（扁平化用于表格显示）
const treeDisplayData = computed(() => {
  const result = []
  const rootItems = treeData.value || []
  
  const flatten = (items, parentExpanded = true) => {
    if (!parentExpanded) return
    items.forEach(item => {
      result.push(item)
      if (item._expanded && item._children && item._children.length > 0) {
        flatten(item._children, true)
      }
    })
  }
  
  flatten(rootItems)
  return result
})

// ==================== 配置组相关 ====================
const groupForm = reactive({
  id: undefined,
  name: '',
  note: ''
})

const groupRules = {
  name: [
    { required: true, message: '请输入配置组名称', trigger: 'blur' }
  ]
}

const groupLoading = ref(false)
const groupList = ref([])
const groupTotal = ref(0)
const groupDialogVisible = ref(false)
const groupDialogTitle = ref('新增配置组')
const groupFormRef = ref(null)

// 添加缺失的变量
const groupQueryParams = reactive({
  key: '',
  page: 1,
  count: 10
})

const settingQueryParams = reactive({
  group_id: undefined,
  key: '',
  page: 1,
  count: 10
})

// ==================== 配置相关 ====================
const settingForm = reactive({
  id: undefined,
  name: '',
  value: '',
  type: 'string',
  settingGroupID: undefined,
  open: false,
  note: ''
})

const settingRules = {
  name: [
    { required: true, message: '请输入配置名称', trigger: 'blur' }
  ],
  type: [
    { required: true, message: '请选择配置类型', trigger: 'change' }
  ],
  settingGroupID: [
    { required: true, message: '请选择配置组', trigger: 'change' }
  ]
}

const settingLoading = ref(false)
const settingList = ref([])
const settingTotal = ref(0)
const settingDialogVisible = ref(false)
const settingDialogTitle = ref('新增配置')
const settingFormRef = ref(null)
const toggleLoading = ref(null)
const fileInfo = ref(null)
const fileUploading = ref(false)
const fileListInfo = ref([])
const newStringItem = ref('')
const imageViewerVisible = ref(false)
const currentViewImage = ref('')
const imageSelectorVisible = ref(false)
const currentImageSelectorFileId = ref('')
const imageSelectorMode = ref('single') // 'single' 或 'list'

// 批量选择相关
const selectedRows = ref([])

// 格式化日期时间
const formatDate = (dateString) => {
  if (!dateString) return '-'
  const date = new Date(dateString)
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  const seconds = String(date.getSeconds()).padStart(2, '0')
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}

// ==================== 树状图方法 ====================

// 相近字排序函数
const sortBySimilarity = (settings) => {
  if (!settings || settings.length <= 1) return settings
  
  // 提取所有配置项的名称
  const names = settings.map(item => item.name || '')
  
  // 按名称排序，相近的名称会排在一起
  return settings.sort((a, b) => {
    const nameA = (a.name || '').toLowerCase()
    const nameB = (b.name || '').toLowerCase()
    
    // 先按前缀分组排序
    const prefixA = nameA.substring(0, 2)
    const prefixB = nameB.substring(0, 2)
    
    if (prefixA !== prefixB) {
      return prefixA.localeCompare(prefixB, 'zh-CN')
    }
    
    // 前缀相同则按完整名称排序
    return nameA.localeCompare(nameB, 'zh-CN')
  })
}

// 加载配置项子节点
const loadChildren = async (row) => {
  if (!row || row.type !== 'group') return
  
  row._loading = true
  try {
    const groupId = row.data.id
    console.log('Loading children for group:', groupId)
    const res = await getSettingList({ group_id: groupId, page: 1, count: 10 })
    console.log('getSettingList response:', res.data)
    if (res.data.code === 200) {
      let settings = res.data.data.data || []
      console.log('settings loaded:', settings)
      
      // 应用相近字排序
      settings = sortBySimilarity(settings)
      console.log('settings after sorting:', settings)
      
      const settingNodes = settings.map(setting => ({
        id: `setting_${setting.id}`,
        label: setting.name,
        type: 'setting',
        data: setting,
        level: row.level + 1,
        hasChildren: false, // 配置项没有子节点
        _expanded: false,
        _children: [],
        _loading: false
      }))
      console.log('settingNodes created:', settingNodes)
      
      row._children = settingNodes
      console.log('updated row with children:', row)
    }
  } catch (error) {
    console.error('加载配置列表失败:', error)
    ElMessage.error('加载配置列表失败')
  } finally {
    row._loading = false
  }
}

// 切换展开状态
const toggleExpand = async (row) => {
  if (row._loading) return
  
  if (row._expanded) {
    // 收起
    row._expanded = false
  } else {
    // 展开 - 如果还没加载子级，先加载
    if (row.type === 'group' && (!row._children || row._children.length === 0)) {
      await loadChildren(row)
    }
    row._expanded = true
  }
}

// 初始化加载配置组
const loadGroups = async () => {
  try {
    const res = await getSettingGroupList({ page: 1, count: 10 })
    console.log('getSettingGroupList response:', res.data)
    if (res.data.code === 200) {
      const groups = res.data.data.data || []
      console.log('groups loaded:', groups)
      const treeNodes = groups.map(group => ({
        id: `group_${group.id}`,
        label: group.name,
        type: 'group',
        data: group,
        level: 1,
        hasChildren: true, // 标记有子节点
        _expanded: false,
        _children: [],
        _loading: false
      }))
      console.log('treeNodes created:', treeNodes)
      treeData.value = treeNodes
      allGroupList.value = groups
      console.log('data set to reactive refs')
    }
  } catch (error) {
    console.error('加载配置组失败:', error)
    ElMessage.error('加载配置组失败')
  }
}

// 节点点击事件
const handleNodeClick = (row) => {
  selectedNode.value = row
  
  // 如果是字符串列表类型，初始化可编辑列表
  if (row.data.type === 'string_list') {
    initEditableStringList()
  }
}

// 查询处理
const handleQuery = () => {
  // 重新加载树
  treeData.value = []
  selectedNode.value = null
  
  // 重新加载配置组
  loadGroups()
}

// 重置查询
const resetQuery = () => {
  queryParams.key = ''
  handleQuery()
}

// 批量删除
const handleBatchDelete = () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning('请先选择要删除的项目')
    return
  }
  
  // 分离配置组和配置项
  const groups = selectedRows.value.filter(row => row.type === 'group')
  const settings = selectedRows.value.filter(row => row.type === 'setting')
  
  let confirmMessage = ''
  if (groups.length > 0 && settings.length > 0) {
    confirmMessage = `确认删除选中的 ${groups.length} 个配置组和 ${settings.length} 个配置项吗？删除配置组将同时删除其下的所有配置项。`
  } else if (groups.length > 0) {
    confirmMessage = `确认删除选中的 ${groups.length} 个配置组吗？删除配置组将同时删除其下的所有配置项。`
  } else {
    confirmMessage = `确认删除选中的 ${settings.length} 个配置项吗？`
  }
  
  ElMessageBox.confirm(confirmMessage, '批量删除警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    const deletePromises = []
    
    // 删除配置组
    groups.forEach(row => {
      deletePromises.push(deleteSettingGroup({ setting_group_id: row.data.id }))
    })
    
    // 删除配置项
    settings.forEach(row => {
      deletePromises.push(deleteSetting({ id: row.data.id }))
    })
    
    try {
      const results = await Promise.all(deletePromises)
      const successCount = results.filter(res => res.data.code === 200).length
      
      if (successCount === selectedRows.value.length) {
        ElMessage.success('批量删除成功')
      } else {
        ElMessage.warning(`成功删除 ${successCount} 项，失败 ${selectedRows.value.length - successCount} 项`)
      }
      
      // 清空选择
      selectedRows.value = []
      handleQuery()
    } catch (error) {
      console.error('批量删除失败:', error)
      ElMessage.error('批量删除失败')
    }
  }).catch(() => {})
}

// 删除节点
const handleDelete = (data) => {
  const type = data.type
  const rowData = data.data
  
  if (type === 'group') {
    ElMessageBox.confirm(`确认删除配置组 "${rowData.name}" 吗？`, '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(async () => {
      try {
        const res = await deleteSettingGroup({ setting_group_id: rowData.id })
        if (res.data.code === 200) {
          ElMessage.success('删除成功')
          handleQuery()
        }
      } catch (error) {
        console.error('删除失败:', error)
        ElMessage.error(error.response?.data?.message || '删除失败')
      }
    }).catch(() => {})
  } else if (type === 'setting') {
    ElMessageBox.confirm(`确认删除配置 "${rowData.name}" 吗？`, '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(async () => {
      try {
        const res = await deleteSetting({ id: rowData.id })
        if (res.data.code === 200) {
          ElMessage.success('删除成功')
          handleQuery()
        }
      } catch (error) {
        console.error('删除失败:', error)
        ElMessage.error(error.response?.data?.message || '删除失败')
      }
    }).catch(() => {})
  }
}

// 处理表格选择变化
const handleSelectionChange = (selection) => {
  selectedRows.value = selection
}

// ==================== 配置组方法 ====================

// 新增配置组
const handleAddGroup = () => {
  groupDialogTitle.value = '新增配置组'
  Object.assign(groupForm, {
    id: undefined,
    name: '',
    note: ''
  })
  groupDialogVisible.value = true
}

// 编辑配置组
const handleEditGroup = async (row) => {
  groupDialogTitle.value = '编辑配置组'
  try {
    const res = await getSettingGroupInfo({ setting_group_id: row.id })
    if (res.data.code === 200) {
      Object.assign(groupForm, {
        id: res.data.data.id,
        name: res.data.data.name || '',
        note: res.data.data.note || ''
      })
      groupDialogVisible.value = true
    }
  } catch (error) {
    console.error('获取配置组详情失败:', error)
    ElMessage.error('获取配置组详情失败')
  }
}

// 提交配置组表单
const submitGroupForm = () => {
  groupFormRef.value?.validate(async (valid) => {
    if (valid) {
      try {
        const submitData = {
          name: groupForm.name,
          note: groupForm.note
        }
        if (groupForm.id) {
          submitData.id = groupForm.id
        }
        const res = groupForm.id 
          ? await updateSettingGroup(submitData)
          : await createSettingGroup(submitData)
        if (res.data.code === 200) {
          ElMessage.success(groupForm.id ? '修改成功' : '创建成功')
          groupDialogVisible.value = false
          handleQuery()
        }
      } catch (error) {
        console.error('提交失败:', error)
        ElMessage.error(error.response?.data?.message || '提交失败')
      }
    }
  })
}

// ==================== 配置方法 ====================

// 新增配置
const handleAddSetting = () => {
  settingDialogTitle.value = '新增配置'
  Object.assign(settingForm, {
    id: undefined,
    name: '',
    value: '',
    type: 'string',
    settingGroupID: selectedNode.value?.type === 'group' ? selectedNode.value.data.id : undefined,
    open: true,
    note: ''
  })
  fileInfo.value = null
  fileListInfo.value = []
  newStringItem.value = ''
  settingDialogVisible.value = true
}

// 为指定配置组新增配置
const handleAddSettingToGroup = (groupData) => {
  settingDialogTitle.value = '新增配置'
  Object.assign(settingForm, {
    id: undefined,
    name: '',
    value: '',
    type: 'string',
    settingGroupID: groupData.id,
    open: true,
    note: ''
  })
  fileInfo.value = null
  fileListInfo.value = []
  newStringItem.value = ''
  settingDialogVisible.value = true
}

// 编辑配置
const handleEditSetting = async (row) => {
  settingDialogTitle.value = '编辑配置'
  try {
    const res = await getSettingInfo({ id: row.id })
    if (res.data.code === 200) {
      const data = res.data.data
      Object.assign(settingForm, {
        id: data.id,
        name: data.name || '',
        value: data.value,
        type: data.type || 'string',
        settingGroupID: data.settingGroupID,
        open: data.open || false,
        note: data.note || ''
      })
      if (data.type === 'bool') {
        settingForm.value = data.value === true || data.value === 'true' || data.value === 1
      } else if (data.type === 'int') {
        settingForm.value = parseInt(data.value) || 0
      } else if (data.type === 'float') {
        settingForm.value = parseFloat(data.value) || 0
      } else if (data.type === 'file') {
        // 处理单个文件类型，获取文件信息
        if (data.parsedValue && typeof data.parsedValue === 'string') {
          fileInfo.value = {
            id: data.value,
            url: processImageUrl(data.parsedValue), // 使用processImageUrl处理URL
            realName: '文件',
            saveName: 'file',
            size: 0
          }
        } else {
          fileInfo.value = null
        }
      } else if (data.type === 'string_list') {
        // 处理字符串列表类型，对每个字符串进行截断
        if (data.parsedValue && Array.isArray(data.parsedValue)) {
          const truncatedValues = data.parsedValue.map(item => truncateFileName(item, 25))
          settingForm.value = truncatedValues.join(',')
          initEditableFormStringList() // 初始化表单可编辑字符串列表
        } else {
          settingForm.value = ''
          editableFormStringList.value = []
        }
        newStringItem.value = ''
      } else if (data.type === 'file_list') {
        // 处理文件列表类型，使用parsedValue来获取文件信息
        if (data.parsedValue && Array.isArray(data.parsedValue)) {
          fileListInfo.value = data.parsedValue.map((url, index) => {
            const fileIds = getFileList(data.value)
            return {
              id: fileIds[index] || `file_${index}`,
              url: processImageUrl(url), // 使用processImageUrl处理URL
              realName: `文件${index + 1}`,
              saveName: `file_${index}`,
              size: 0
            }
          })
          // 确保在设置fileListInfo后再初始化表单可编辑文件列表
          nextTick(() => {
            initEditableFormFileList()
          })
        } else {
          fileListInfo.value = []
          editableFormFileList.value = []
        }
      }
      settingDialogVisible.value = true
    }
  } catch (error) {
    console.error('获取配置详情失败:', error)
    ElMessage.error('获取配置详情失败')
  }
}

// 获取类型颜色
const getTypeColor = (type) => {
  const colorMap = {
    'string': 'primary',
    'int': 'success',
    'float': 'warning',
    'bool': 'info',
    'file': 'danger',
    'file_list': 'danger',
    'string_list': 'primary'
  }
  return colorMap[type] || ''
}

// 添加缺失的辅助函数
const fetchGroupList = async () => {
  groupLoading.value = true
  try {
    const res = await getSettingGroupList(groupQueryParams)
    if (res.data.code === 200) {
      groupList.value = res.data.data.data || []
      groupTotal.value = res.data.data.all_count || 0
    }
  } catch (error) {
    console.error('获取配置组列表失败:', error)
    ElMessage.error('获取配置组列表失败')
  } finally {
    groupLoading.value = false
  }
}

const fetchAllGroupList = async () => {
  try {
    const res = await getSettingGroupList({ page: 1, count: 10 })
    if (res.data.code === 200) {
      allGroupList.value = res.data.data.data || []
    }
  } catch (error) {
    console.error('获取配置组列表失败:', error)
  }
}

// JSON 值检测与格式化
const isJsonValue = computed(() => {
  if (settingForm.type !== 'string' || !settingForm.value) return false
  const v = settingForm.value.trim()
  return (v.startsWith('{') && v.endsWith('}')) || (v.startsWith('[') && v.endsWith(']'))
})

const formatJson = () => {
  try {
    const parsed = JSON.parse(settingForm.value)
    settingForm.value = JSON.stringify(parsed, null, 2)
  } catch (e) {
    ElMessage.warning('JSON 格式不合法，无法格式化')
  }
}

const compressJson = () => {
  try {
    const parsed = JSON.parse(settingForm.value)
    settingForm.value = JSON.stringify(parsed)
  } catch (e) {
    ElMessage.warning('JSON 格式不合法，无法压缩')
  }
}

// 类型切换处理 - 重置值和相关状态
const handleTypeChange = (newType) => {
  // 重置表单值为对应类型的默认值
  if (newType === 'bool') {
    settingForm.value = false
  } else if (newType === 'int') {
    settingForm.value = 0
  } else if (newType === 'float') {
    settingForm.value = 0.0
  } else {
    settingForm.value = ''
  }
  
  // 重置所有相关状态
  fileInfo.value = null
  fileListInfo.value = []
  editableFormStringList.value = []
  editableFormFileList.value = []
  newStringItem.value = ''
}

// 文件相关函数
const handleFileChange = async (file) => {
  fileUploading.value = true
  
  // 创建本地预览URL
  const localUrl = URL.createObjectURL(file.raw)
  const isImage = file.raw.type.startsWith('image/')
  
  // 立即显示本地预览
  fileInfo.value = {
    id: '', // 暂时为空，上传成功后会更新
    url: isImage ? localUrl : '',
    realName: file.name,
    saveName: file.name,
    size: file.size,
    isLocal: true // 标记为本地文件
  }
  
  try {
    const formData = new FormData()
    formData.append('file_names', file.name)
    formData.append('files', file.raw)
    formData.append('update_type','cover')
    formData.append('open_down','true')
    
    const res = await uploadFile(formData)
    if (res.data.code === 200 && res.data.data && res.data.data.length > 0) {
      const uploadedFile = res.data.data[0]
      settingForm.value = String(uploadedFile.id || '')
      
      // 释放本地URL（暂时不释放，保留用于渲染）
      // if (fileInfo.value?.isLocal) {
      //   URL.revokeObjectURL(fileInfo.value.url)
      // }
      
      // 更新为服务器返回的文件信息，但保留本地URL用于渲染
      fileInfo.value = {
        id: uploadedFile.id || '',
        url: processImageUrl(uploadedFile.url || uploadedFile.realName || ''),
        localUrl: fileInfo.value?.url || '', // 保留本地URL用于渲染
        realName: uploadedFile.realName || '文件',
        saveName: uploadedFile.saveName || 'file',
        size: uploadedFile.size || 0,
        isLocal: false // 标记为已上传，但保留本地渲染
      }
      ElMessage.success('文件上传成功')
    } else {
      // 上传失败，保留本地预览，但显示错误消息
      ElMessage.error(res.data.message || '文件上传失败')
      // 注意：不清理本地预览，让用户可以重新上传或删除
    }
  } catch (error) {
    console.error('文件上传失败:', error)
    ElMessage.error('文件上传失败')
  } finally {
    fileUploading.value = false
  }
}

const clearFile = () => {
  // 释放本地URL
  if (fileInfo.value?.localUrl) {
    URL.revokeObjectURL(fileInfo.value.localUrl)
  }
  if (fileInfo.value?.isLocal && fileInfo.value?.url) {
    URL.revokeObjectURL(fileInfo.value.url)
  }
  
  settingForm.value = ''
  fileInfo.value = null
}

const formatFileSize = (bytes) => {
  if (!bytes) 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 truncateFileName = (fileName, maxLength = 25) => {
  if (!fileName) return ''
  if (fileName.length <= maxLength) return fileName
  
  const extension = fileName.includes('.') ? '.' + fileName.split('.').pop() : ''
  const nameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.'))
  
  if (nameWithoutExt.length <= maxLength) {
    return fileName
  }
  
  const truncatedName = nameWithoutExt.substring(0, maxLength - 3) // 留3个字符给"...和扩展名"
  console.log('111',truncatedName + '...' + extension)
  return truncatedName + '...' + extension
}

// ==================== 可编辑字符串列表功能 ====================

// 获取可编辑的字符串列表
const getEditableStringList = () => {
  if (!selectedNode.value || selectedNode.value.data.type !== 'string_list') {
    return []
  }
  return editableStringList.value
}

// 初始化可编辑字符串列表
const initEditableStringList = () => {
  if (!selectedNode.value || selectedNode.value.data.type !== 'string_list') {
    editableStringList.value = []
    return
  }
  
  const stringItems = getStringList(selectedNode.value.data.value)
  editableStringList.value = stringItems.map(item => ({
    value: item,
    editing: false
  }))
}

// 开始拖拽
const handleDragStart = (event, index) => {
  draggedIndex.value = index
  event.dataTransfer.effectAllowed = 'move'
  event.dataTransfer.setData('text/html', event.target.outerHTML)
  event.target.style.opacity = '0.5'
}

// 拖拽放下
const handleDrop = (event, dropIndex) => {
  event.preventDefault()
  const dragIndex = draggedIndex.value
  
  if (dragIndex === dropIndex) return
  
  // 重新排列数组
  const newList = [...editableStringList.value]
  const [draggedItem] = newList.splice(dragIndex, 1)
  newList.splice(dropIndex, 0, draggedItem)
  
  editableStringList.value = newList
  draggedIndex.value = -1
  
  // 更新selectedNode中的数据
  const updatedValues = newList.map(item => item.value)
  selectedNode.value.data.value = updatedValues.join(',')
  
  event.target.style.opacity = '1'
}

// 添加新字符串项目
const addEditableStringItem = () => {
  const newItem = {
    value: '',
    editing: true
  }
  editableStringList.value.push(newItem)
  
  // 更新selectedNode中的数据
  const updatedValues = editableStringList.value.map(item => item.value)
  selectedNode.value.data.value = updatedValues.join(',')
  
  // 聚焦到新添加的输入框
  nextTick(() => {
    const inputs = document.querySelectorAll('.string-list-item input')
    if (inputs.length > 0) {
      inputs[inputs.length - 1].focus()
    }
  })
}

// 开始编辑项目
const startEditItem = (index) => {
  editableStringList.value[index].editing = true
  
  nextTick(() => {
    const inputs = document.querySelectorAll('.string-list-item input')
    if (inputs[index]) {
      inputs[index].focus()
      inputs[index].select()
    }
  })
}

// 完成编辑项目
const finishEditItem = (index) => {
  editableStringList.value[index].editing = false
  
  // 更新selectedNode中的数据
  const updatedValues = editableStringList.value.map(item => item.value)
  selectedNode.value.data.value = updatedValues.join(',')
}

// 删除字符串项目
const removeEditableStringItem = (index) => {
  ElMessageBox.confirm('确定要删除这个项目吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    editableStringList.value.splice(index, 1)
    
    // 更新selectedNode中的数据
    const updatedValues = editableStringList.value.map(item => item.value)
    selectedNode.value.data.value = updatedValues.join(',')
    
    ElMessage.success('删除成功')
  })
}

// 聚焦输入框
const focusEditInput = () => {
  // 这个方法会被 @mounted 调用
}

// ==================== 表单可编辑字符串列表功能 ====================

// 获取表单可编辑的字符串列表
const getEditableFormStringList = () => {
  return editableFormStringList.value
}

// 初始化表单可编辑字符串列表
const initEditableFormStringList = () => {
  const stringItems = getStringList(settingForm.value)
  editableFormStringList.value = stringItems.map(item => ({
    value: item,
    editing: false
  }))
}

// 开始表单拖拽
const handleFormDragStart = (event, index) => {
  formDraggedIndex.value = index
  event.dataTransfer.effectAllowed = 'move'
  event.dataTransfer.setData('text/html', event.target.outerHTML)
  event.target.style.opacity = '0.5'
}

// 表单拖拽放下
const handleFormDrop = (event, dropIndex) => {
  event.preventDefault()
  const dragIndex = formDraggedIndex.value
  
  if (dragIndex === dropIndex) return
  
  // 重新排列数组
  const newList = [...editableFormStringList.value]
  const [draggedItem] = newList.splice(dragIndex, 1)
  newList.splice(dropIndex, 0, draggedItem)
  
  editableFormStringList.value = newList
  formDraggedIndex.value = -1
  
  // 更新表单值
  const updatedValues = newList.map(item => item.value)
  settingForm.value = updatedValues.join(',')
  
  event.target.style.opacity = '1'
}

// 添加表单新字符串项目
const addFormEditableStringItem = () => {
  const newItem = {
    value: '',
    editing: true
  }
  editableFormStringList.value.push(newItem)
  
  // 更新表单值
  const updatedValues = editableFormStringList.value.map(item => item.value)
  settingForm.value = updatedValues.join(',')
  
  // 聚焦到新添加的输入框
  nextTick(() => {
    const inputs = document.querySelectorAll('.string-list-item input')
    if (inputs.length > 0) {
      inputs[inputs.length - 1].focus()
    }
  })
}

// 开始编辑表单项目
const startFormEditItem = (index) => {
  editableFormStringList.value[index].editing = true
  
  nextTick(() => {
    const inputs = document.querySelectorAll('.string-list-item input')
    if (inputs[index]) {
      inputs[index].focus()
      inputs[index].select()
    }
  })
}

// 完成编辑表单项目
const finishFormEditItem = (index) => {
  editableFormStringList.value[index].editing = false
  
  // 更新表单值
  const updatedValues = editableFormStringList.value.map(item => item.value)
  settingForm.value = updatedValues.join(',')
}

// 删除表单字符串项目
const removeFormEditableStringItem = (index) => {
  ElMessageBox.confirm('确定要删除这个项目吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    editableFormStringList.value.splice(index, 1)
    
    // 更新表单值
    const updatedValues = editableFormStringList.value.map(item => item.value)
    settingForm.value = updatedValues.join(',')
    
    ElMessage.success('删除成功')
  })
}

// 聚焦表单输入框
const focusFormEditInput = () => {
  // 这个方法会被 @mounted 调用
}

// ==================== 表单可编辑文件列表功能 ====================

// 获取表单可编辑的文件列表
const getEditableFormFileList = () => {
  return editableFormFileList.value
}

// 初始化表单可编辑文件列表
const initEditableFormFileList = () => {
  if (settingForm.type === 'file_list' && fileListInfo.value && fileListInfo.value.length > 0) {
    editableFormFileList.value = fileListInfo.value.map(file => ({
      id: file.id || '',
      url: file.url || '',
      localUrl: file.localUrl || '', // 保留本地URL字段
      realName: file.realName || '文件',
      saveName: file.saveName || 'file',
      size: file.size || 0,
      uploading: false
    }))
  } else {
    editableFormFileList.value = []
  }
}

// 开始表单文件拖拽
const handleFormFileDragStart = (event, index) => {
  formFileDraggedIndex.value = index
  event.dataTransfer.effectAllowed = 'move'
  event.dataTransfer.setData('text/html', event.target.outerHTML)
  event.target.style.opacity = '0.5'
}

// 表单文件拖拽放下
const handleFormFileDrop = (event, dropIndex) => {
  event.preventDefault()
  const dragIndex = formFileDraggedIndex.value
  
  if (dragIndex === dropIndex) return
  
  // 重新排列数组
  const newList = [...editableFormFileList.value]
  const [draggedItem] = newList.splice(dragIndex, 1)
  newList.splice(dropIndex, 0, draggedItem)
  
  editableFormFileList.value = newList
  formFileDraggedIndex.value = -1
  
  // 更新fileListInfo和表单值（使用独立副本，避免引用同一数组）
  fileListInfo.value = newList.map(item => ({ ...item }))
  updateFormFileListValue()
  
  event.target.style.opacity = '1'
}

// 表单文件列表变更
const handleFormFileListChange = async (file) => {
  // 创建本地预览URL
  const localUrl = URL.createObjectURL(file.raw)
  const isImage = file.raw.type.startsWith('image/')
  
  // 立即添加到表单文件列表
  const tempFile = {
    id: '', // 暂时为空，上传成功后会更新
    url: isImage ? localUrl : '',
    realName: file.name,
    saveName: file.name,
    size: file.size,
    isLocal: true,
    uploading: true
  }
  
  editableFormFileList.value.push(tempFile)
  
  try {
    const formData = new FormData()
    formData.append('file_names', file.name)
    formData.append('files', file.raw)
    formData.append('update_type','cover')
    formData.append('open_down','true')
    
    const res = await uploadFile(formData)
    if (res.data.code === 200 && res.data.data && res.data.data.length > 0) {
      const uploadedFile = res.data.data[0]
      
      // 找到对应的本地文件并更新
      const index = editableFormFileList.value.findIndex(f => f.isLocal && f.realName === file.name)
      if (index !== -1) {
        editableFormFileList.value[index] = {
          id: uploadedFile.id || '',
          url: processImageUrl(uploadedFile.url || uploadedFile.realName || ''),
          localUrl: localUrl, // 保留本地URL用于渲染
          realName: uploadedFile.realName || '文件',
          saveName: uploadedFile.saveName || 'file',
          size: uploadedFile.size || 0,
          isLocal: false,
          uploading: false
        }
      }
      
      updateFormFileListValue()
      ElMessage.success('文件上传成功')
    } else {
      // 上传失败，移除临时文件
      const index = editableFormFileList.value.findIndex(f => f.isLocal && f.realName === file.name)
      if (index !== -1) {
        editableFormFileList.value.splice(index, 1)
      }
      ElMessage.error(res.data.message || '文件上传失败')
    }
  } catch (error) {
    console.error('文件上传失败:', error)
    // 上传失败，移除临时文件
    const index = editableFormFileList.value.findIndex(f => f.isLocal && f.realName === file.name)
    if (index !== -1) {
      editableFormFileList.value.splice(index, 1)
    }
    ElMessage.error('文件上传失败')
  }
}

// 表单文件替换
const handleFormFileReplace = async (file, index) => {
  if (!editableFormFileList.value[index]) return
  
  // 创建本地预览URL
  const localUrl = URL.createObjectURL(file.raw)
  const isImage = file.raw.type.startsWith('image/')
  
  // 更新文件信息
  editableFormFileList.value[index] = {
    ...editableFormFileList.value[index],
    url: isImage ? localUrl : '',
    realName: file.name,
    saveName: file.name,
    size: file.size,
    isLocal: true,
    uploading: true
  }
  
  try {
    const formData = new FormData()
    formData.append('file_names', file.name)
    formData.append('files', file.raw)
    formData.append('update_type','cover')
    formData.append('open_down','true')
    
    const res = await uploadFile(formData)
    if (res.data.code === 200 && res.data.data && res.data.data.length > 0) {
      const uploadedFile = res.data.data[0]
      
      // 更新文件信息
      editableFormFileList.value[index] = {
        id: uploadedFile.id || '',
        url: processImageUrl(uploadedFile.url || uploadedFile.realName || ''),
        localUrl: localUrl, // 保留本地URL用于渲染
        realName: uploadedFile.realName || '文件',
        saveName: uploadedFile.saveName || 'file',
        size: uploadedFile.size || 0,
        isLocal: false,
        uploading: false
      }
      
      updateFormFileListValue()
      ElMessage.success('文件替换成功')
    } else {
      // 上传失败，恢复原文件信息
      ElMessage.error(res.data.message || '文件替换失败')
    }
  } catch (error) {
    console.error('文件替换失败:', error)
    ElMessage.error('文件替换失败')
  }
}

// 删除表单文件项目
const removeFormEditableFileItem = (index) => {
  ElMessageBox.confirm('确定要删除这个文件吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 释放本地URL
    if (editableFormFileList.value[index].localUrl) {
      URL.revokeObjectURL(editableFormFileList.value[index].localUrl)
    }
    if (editableFormFileList.value[index].isLocal && editableFormFileList.value[index].url) {
      URL.revokeObjectURL(editableFormFileList.value[index].url)
    }
    
    editableFormFileList.value.splice(index, 1)
    
    // 更新fileListInfo和表单值
    fileListInfo.value = editableFormFileList.value
    updateFormFileListValue()
    
    ElMessage.success('删除成功')
  })
}

// 更新表单文件列表值
const updateFormFileListValue = () => {
  if (!editableFormFileList.value || !Array.isArray(editableFormFileList.value)) {
    return
  }
  
  const fileIds = editableFormFileList.value.map(file => file.id).filter(id => id)
  settingForm.value = fileIds.join(',')
}

// 文件预览
const previewFile = async (fileId) => {
  if (!fileId) return
  try {
    // 先获取文件详情拿到下载URL
    const res = await getFileDetail({ file_id: fileId })
    if (res.data.code === 200 && res.data.data?.url) {
      const url = processImageUrl(res.data.data.url)
      const fileName = res.data.data.data?.realName || ''
      // 判断是否为图片
      const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg']
      const ext = fileName.toLowerCase().substring(fileName.lastIndexOf('.'))
      if (imageExts.includes(ext) || url.match(/\.(jpg|jpeg|png|gif|bmp|webp|svg)/i)) {
        // 图片类型：使用内置图片查看器
        currentViewImage.value = url
        imageViewerVisible.value = true
      } else {
        // 非图片类型：在新窗口打开
        window.open(url, '_blank')
      }
    } else {
      // 降级：尝试用下载接口
      const downRes = await downloadFile({ file_id: fileId })
      if (downRes.data.code === 200 && downRes.data.data?.url) {
        window.open(processImageUrl(downRes.data.data.url), '_blank')
      } else {
        ElMessage.error('获取文件预览失败')
      }
    }
  } catch (error) {
    console.error('文件预览失败:', error)
    ElMessage.error('文件预览失败')
  }
}

const previewUrl = (url) => {
  window.open(url, '_blank')
}

// 检查是否为图片文件
const isImageFile = (url) => {
  if (!url) return false
  const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg']
  // 使用相同的URL处理逻辑
  const processedUrl = processImageUrl(url)
  const extension = processedUrl.toLowerCase().substring(processedUrl.lastIndexOf('.'))
  return imageExtensions.includes(extension)
}

// 处理图片URL，确保正确显示
const processImageUrl = (url) => {
  if (!url) return ''
  // 先处理转义字符：将 \u0026 替换为 &
  let processedUrl = url.replace(/\\u0026/g, '&')
  // 再进行URL解码
  return decodeURIComponent(processedUrl)
}

// 图片预览
const previewImage = (url) => {
  // 使用图片查看器对话框
  currentViewImage.value = processImageUrl(url)
  imageViewerVisible.value = true
}

// 处理图片加载失败
const handleImageError = (event) => {
  // 图片加载失败时，可以隐藏图片或显示占位符
  console.error('图片加载失败:', event.target.src)
  // 这里可以添加更多的错误处理逻辑
}

// ==================== 图像选择器相关 ====================

// 打开图像选择器（单个文件）
const openImageSelector = () => {
  imageSelectorMode.value = 'single'
  currentImageSelectorFileId.value = settingForm.value || ''
  imageSelectorVisible.value = true
}

// 打开图像选择器（文件列表）
const openImageSelectorForList = () => {
  imageSelectorMode.value = 'list'
  currentImageSelectorFileId.value = ''
  imageSelectorVisible.value = true
}

// 打开图像选择器（文件列表中的特定项）
const openImageSelectorForListItem = (index) => {
  imageSelectorMode.value = 'list-item'
  currentImageSelectorFileId.value = index
  imageSelectorVisible.value = true
}

// 处理图像选择器确认
const handleImageSelectorConfirm = (selectedFileOrFiles) => {
  if (imageSelectorMode.value === 'list' && Array.isArray(selectedFileOrFiles)) {
    // 多选文件列表模式 - 接收文件数组
    if (selectedFileOrFiles.length === 0) {
      ElMessage.warning('未选择任何文件')
      return
    }
    
    if (!fileListInfo.value) {
      fileListInfo.value = []
    }
    
    for (const selectedFile of selectedFileOrFiles) {
      if (!selectedFile || !selectedFile.id) continue
      
      const newFile = {
        id: selectedFile.id,
        url: processImageUrl(selectedFile.url || ''),
        realName: selectedFile.realName || '文件',
        saveName: selectedFile.realName || 'file',
        size: selectedFile.size || 0
      }
      fileListInfo.value.push(newFile)
      
      // 同步更新 editableFormFileList（表单UI读取的数据源）
      editableFormFileList.value.push({
        id: selectedFile.id,
        url: processImageUrl(selectedFile.url || ''),
        localUrl: '',
        realName: selectedFile.realName || '文件',
        saveName: selectedFile.realName || 'file',
        size: selectedFile.size || 0,
        uploading: false
      })
    }
    
    updateFormFileListValue()
    ElMessage.success(`已添加 ${selectedFileOrFiles.length} 个文件`)
    imageSelectorVisible.value = false
    return
  }
  
  // 以下为单选模式处理
  const selectedFile = selectedFileOrFiles
  if (!selectedFile || !selectedFile.id) {
    ElMessage.warning('选择的文件无效')
    return
  }
  
  if (imageSelectorMode.value === 'single') {
    // 单个文件模式
    settingForm.value = selectedFile.id
    fileInfo.value = {
      id: selectedFile.id,
      url: processImageUrl(selectedFile.url || ''),
      realName: selectedFile.realName || '文件',
      saveName: selectedFile.realName || 'file',
      size: selectedFile.size || 0
    }
  } else if (imageSelectorMode.value === 'list') {
    // 单选兼容：文件列表模式（单个文件对象）
    if (!fileListInfo.value) {
      fileListInfo.value = []
    }
    
    const newFile = {
      id: selectedFile.id,
      url: processImageUrl(selectedFile.url || ''),
      realName: selectedFile.realName || '文件',
      saveName: selectedFile.realName || 'file',
      size: selectedFile.size || 0
    }
    fileListInfo.value.push(newFile)
    
    // 同步更新 editableFormFileList（表单UI读取的数据源）
    editableFormFileList.value.push({
      id: selectedFile.id,
      url: processImageUrl(selectedFile.url || ''),
      localUrl: '',
      realName: selectedFile.realName || '文件',
      saveName: selectedFile.realName || 'file',
      size: selectedFile.size || 0,
      uploading: false
    })
    
    updateFormFileListValue()
  } else if (imageSelectorMode.value === 'list-item') {
    // 文件列表中的特定项替换模式
    const index = currentImageSelectorFileId.value
    const updatedFile = {
      id: selectedFile.id,
      url: processImageUrl(selectedFile.url || ''),
      realName: selectedFile.realName || '文件',
      saveName: selectedFile.realName || 'file',
      size: selectedFile.size || 0
    }
    
    if (fileListInfo.value && fileListInfo.value[index] !== undefined) {
      fileListInfo.value[index] = updatedFile
    }
    
    // 同步更新 editableFormFileList
    if (editableFormFileList.value && editableFormFileList.value[index] !== undefined) {
      editableFormFileList.value[index] = {
        ...updatedFile,
        localUrl: '',
        uploading: false
      }
    }
    
    updateFormFileListValue()
    ElMessage.success('文件替换成功')
  }
  
  imageSelectorVisible.value = false
}

const getFileList = (value) => {
  if (!value || typeof value !== 'string') return []
  return value.split(',').filter(id => id && id.trim())
}

const getStringList = (value) => {
  if (!value || typeof value !== 'string') return []
  return value.split(',').filter(str => str && str.trim())
}

const truncateText = (text, maxLength = 30) => {
  if (!text) return ''
  if (text.length <= maxLength) return text
  return text.substring(0, maxLength) + '...'
}

const handleFileListChange = async (file) => {
  fileUploading.value = true
  
  // 创建本地预览URL
  const localUrl = URL.createObjectURL(file.raw)
  const isImage = file.raw.type.startsWith('image/')
  
  // 立即添加本地预览到列表
  if (!fileListInfo.value) {
    fileListInfo.value = []
  }
  
  const tempFile = {
    id: '', // 暂时为空，上传成功后会更新
    url: isImage ? localUrl : '',
    realName: file.name,
    saveName: file.name,
    size: file.size,
    isLocal: true // 标记为本地文件
  }
  
  fileListInfo.value.push(tempFile)
  
  try {
    const formData = new FormData()
    formData.append('file_names', file.name)
    formData.append('files', file.raw)
    formData.append('update_type','cover')
    formData.append('open_down','true')
    
    const res = await uploadFile(formData)
    if (res.data.code === 200 && res.data.data && res.data.data.length > 0) {
      const uploadedFile = res.data.data[0]
      const currentFileIds = getFileList(settingForm.value)
      currentFileIds.push(String(uploadedFile.id || ''))
      settingForm.value = currentFileIds.join(',')
      
      // 找到对应的本地文件并更新
      const index = fileListInfo.value.findIndex(f => f.isLocal && f.realName === file.name)
      if (index !== -1) {
        // 释放本地URL（暂时不释放，保留用于渲染）
        // if (fileListInfo.value[index].isLocal) {
        //   URL.revokeObjectURL(fileListInfo.value[index].url)
        // }
        
        // 更新为服务器返回的文件信息，但保留本地URL用于渲染
        fileListInfo.value[index] = {
          id: uploadedFile.id || '',
          url: processImageUrl(uploadedFile.url || uploadedFile.realName || ''),
          localUrl: fileListInfo.value[index]?.url || '', // 保留本地URL用于渲染
          realName: uploadedFile.realName || '文件',
          saveName: uploadedFile.saveName || 'file',
          size: uploadedFile.size || 0,
          isLocal: false // 标记为已上传，但保留本地渲染
        }
      }
      
      updateFileListValue()
      ElMessage.success('文件上传成功')
    } else {
      // 上传失败，不清理本地预览，让用户可以重新上传或删除
      ElMessage.error(res.data.message || '文件上传失败')
    }
  } catch (error) {
    console.error('文件上传失败:', error)
    // 上传失败，不清理本地预览，让用户可以重新上传或删除
    ElMessage.error('文件上传失败')
  } finally {
    fileUploading.value = false
  }
}

const removeFile = (index) => {
  if (!fileListInfo.value || index < 0 || index >= fileListInfo.value.length) {
    return
  }
  
  // 释放本地URL
  if (fileListInfo.value[index].localUrl) {
    URL.revokeObjectURL(fileListInfo.value[index].localUrl)
  }
  if (fileListInfo.value[index].isLocal && fileListInfo.value[index].url) {
    URL.revokeObjectURL(fileListInfo.value[index].url)
  }
  
  const currentFileIds = getFileList(settingForm.value) || []
  currentFileIds.splice(index, 1)
  settingForm.value = currentFileIds.join(',')
  fileListInfo.value.splice(index, 1)
}

// 更新文件列表值
const updateFileListValue = () => {
  if (!fileListInfo.value || !Array.isArray(fileListInfo.value)) {
    return
  }
  
  const fileIds = fileListInfo.value.map(file => file.id).filter(id => id)
  settingForm.value = fileIds.join(',')
}

const addStringItem = () => {
  if (newStringItem.value.trim()) {
    const currentItems = getStringList(settingForm.value)
    currentItems.push(newStringItem.value.trim())
    settingForm.value = currentItems.join(',')
    newStringItem.value = ''
  }
}

const removeStringItem = (index) => {
  const currentItems = getStringList(settingForm.value)
  currentItems.splice(index, 1)
  settingForm.value = currentItems.join(',')
}

// 提交配置表单
const submitSettingForm = async () => {
  if (!settingFormRef.value) return
  
  try {
    await settingFormRef.value.validate()
    
    const submitData = {
      id: settingForm.id,
      name: settingForm.name,
      value: settingForm.value,
      type: settingForm.type,
      setting_group_id: settingForm.settingGroupID,
      open: settingForm.open,
      note: settingForm.note
    }
    
    // 保存原始的开放状态用于比较
    const originalOpen = selectedNode.value?.data?.open
    const newOpen = settingForm.open
    
    const res = settingForm.id 
      ? await updateSetting(submitData)
      : await createSetting(submitData)
      
    if (res.data.code === 200) {
      // 如果是修改配置且开放状态有变化，调用setSettingOpen
      if (settingForm.id && originalOpen !== newOpen) {
        try {
          await setSettingOpen({
            id: settingForm.id,
            open: newOpen
          })
          console.log('配置开放状态已更新:', { id: settingForm.id, open: newOpen })
        } catch (openError) {
          console.error('更新开放状态失败:', openError)
          ElMessage.warning('配置已更新，但开放状态更新失败')
        }
      }
      
      ElMessage.success(settingForm.id ? '修改成功' : '创建成功')
      settingDialogVisible.value = false
      
      // 重新加载数据
      if (settingForm.settingGroupID) {
        // 找到对应的配置组并重新加载其配置项
        const groupNode = treeData.value.find(item => 
          item.type === 'group' && item.data.id === settingForm.settingGroupID
        )
        if (groupNode) {
          groupNode._children = []
          groupNode._expanded = false
          await toggleExpand(groupNode)
        }
      } else {
        // 重新加载所有数据
        loadGroups()
      }
    } else {
      ElMessage.error(res.data.message || '操作失败')
    }
  } catch (error) {
    console.error('提交配置失败:', error)
    ElMessage.error('操作失败')
  }
}

// ==================== 一键导入配置 ====================
const batchImportDialogVisible = ref(false)
const batchImportText = ref('')
const batchImportParsed = ref([])
const batchImportGroupId = ref(undefined)
const batchImportGroupName = ref('')
const batchImportGroupExists = ref(false)
const batchImportOpen = ref(true)
const batchImportLoading = ref(false)
const batchImportProgress = ref(0)
const batchImportTotal = ref(0)
const batchImportStatusText = ref('')

const handleBatchImport = async () => {
  batchImportText.value = ''
  batchImportParsed.value = []
  batchImportGroupId.value = undefined
  batchImportGroupName.value = ''
  batchImportGroupExists.value = false
  batchImportOpen.value = true
  batchImportProgress.value = 0
  batchImportTotal.value = 0
  batchImportStatusText.value = ''
  batchImportDialogVisible.value = true

  try {
    const clipText = await navigator.clipboard.readText()
    if (clipText && clipText.trim()) {
      batchImportText.value = clipText.trim()
    }
  } catch (e) {
    console.warn('读取剪贴板失败（可能需要用户授权）:', e)
  }
}

/**
 * 解析 Markdown 表格文本为配置项数组
 * 支持格式：
 *   | 配置名 | 类型 | 默认值 | 说明 |
 *   |--------|------|--------|------|
 *   | `移动端_主题主色` | `string` | `#2B7EFB` | 按钮、链接、选中态主色 |
 */
const parseBatchImportText = () => {
  const text = batchImportText.value.trim()
  if (!text) {
    ElMessage.warning('请先粘贴导入内容')
    return
  }

  const lines = text.split('\n').map(l => l.trim()).filter(l => l.length > 0)
  const validTypes = ['string', 'int', 'float', 'bool', 'file', 'file_list', 'string_list']
  const results = []

  const stripBackticks = (str) => str.replace(/`/g, '').trim()

  // 识别 [配置组] 行
  let detectedGroupName = ''
  for (const line of lines) {
    const groupMatch = line.match(/^\[配置组\]\s*(.+)$/)
    if (groupMatch) {
      detectedGroupName = groupMatch[1].trim()
      continue
    }

    if (/^[\s|:\-]+$/.test(line)) continue
    if (/配置名|类型.*默认值|名称.*类型/.test(line)) continue

    const parts = line.split('|').map(s => s.trim()).filter(s => s.length > 0)
    if (parts.length < 3) continue

    const name = stripBackticks(parts[0])
    const type = stripBackticks(parts[1]).toLowerCase()
    const value = stripBackticks(parts[2])
    const note = parts.length >= 4 ? stripBackticks(parts[3]) : ''

    if (!name) continue
    if (!validTypes.includes(type)) {
      console.warn(`跳过无效类型 "${type}" (配置名: ${name})`)
      continue
    }

    results.push({ name, type, value, note, _duplicate: false })
  }

  // 更新配置组识别结果
  if (detectedGroupName) {
    batchImportGroupName.value = detectedGroupName
    const existingGroup = allGroupList.value.find(g => g.name === detectedGroupName)
    if (existingGroup) {
      batchImportGroupId.value = existingGroup.id
      batchImportGroupExists.value = true
    } else {
      batchImportGroupId.value = undefined
      batchImportGroupExists.value = false
    }
  }

  // 标记重复项
  const nameSet = new Set()
  results.forEach(item => {
    if (nameSet.has(item.name)) {
      item._duplicate = true
    } else {
      nameSet.add(item.name)
    }
  })

  batchImportParsed.value = results

  if (results.length === 0) {
    ElMessage.warning('未能解析到有效的配置项，请检查格式')
  } else {
    const groupInfo = detectedGroupName ? `，配置组：${detectedGroupName}` : ''
    ElMessage.success(`成功解析 ${results.length} 条配置项${groupInfo}`)
  }
}

// 监听文本变化自动解析
watch(batchImportText, (val) => {
  if (val && val.trim().split('\n').length >= 2) {
    parseBatchImportText()
  }
})

const submitBatchImport = async () => {
  if (!batchImportGroupName.value) {
    ElMessage.warning('未识别到配置组名称，请检查内容格式')
    return
  }
  const items = batchImportParsed.value.filter(i => !i._duplicate)
  if (items.length === 0) {
    ElMessage.warning('没有可导入的配置项')
    return
  }

  batchImportLoading.value = true
  batchImportProgress.value = 0
  batchImportTotal.value = items.length
  let successCount = 0
  let failCount = 0
  const errors = []

  // 步骤 1：确保配置组存在
  let targetGroupId = batchImportGroupId.value
  if (!targetGroupId) {
    batchImportStatusText.value = `正在创建配置组「${batchImportGroupName.value}」...`
    try {
      const res = await createSettingGroup({ name: batchImportGroupName.value, note: '' })
      if (res.data.code === 200) {
        targetGroupId = res.data.data?.id || res.data.data?.ID
        batchImportGroupId.value = targetGroupId
        batchImportGroupExists.value = true
      } else {
        batchImportLoading.value = false
        batchImportStatusText.value = ''
        ElMessage.error(`创建配置组失败：${res.data.message || '未知错误'}`)
        return
      }
    } catch (error) {
      batchImportLoading.value = false
      batchImportStatusText.value = ''
      ElMessage.error(`创建配置组失败：${error.response?.data?.message || error.message}`)
      return
    }
  }

  // 步骤 2：逐条导入配置项
  for (let i = 0; i < items.length; i++) {
    const item = items[i]
    batchImportStatusText.value = `正在导入：${item.name}`
    batchImportProgress.value = i

    try {
      const res = await createSetting({
        name: item.name,
        value: item.value,
        type: item.type,
        setting_group_id: targetGroupId,
        open: batchImportOpen.value,
        note: item.note
      })
      if (res.data.code === 200) {
        if (batchImportOpen.value && res.data.data?.id) {
          try {
            await setSettingOpen({ id: res.data.data.id, open: true })
          } catch (e) {
            console.warn('设置公开状态失败:', item.name, e)
          }
        }
        successCount++
      } else {
        failCount++
        errors.push(`${item.name}: ${res.data.message || '未知错误'}`)
      }
    } catch (error) {
      failCount++
      errors.push(`${item.name}: ${error.response?.data?.message || error.message || '请求失败'}`)
    }
  }

  batchImportProgress.value = items.length
  batchImportStatusText.value = '导入完成'
  batchImportLoading.value = false

  if (failCount === 0) {
    ElMessage.success(`全部导入成功！共 ${successCount} 条，配置组：${batchImportGroupName.value}`)
    batchImportDialogVisible.value = false
  } else {
    ElMessage.warning(`导入完成：成功 ${successCount} 条，失败 ${failCount} 条`)
    if (errors.length > 0) {
      console.error('批量导入失败详情:', errors)
    }
  }

  // 刷新配置组树
  await loadGroups()
  await nextTick()
  const groupNode = treeData.value.find(item =>
    item.type === 'group' && item.data.id === targetGroupId
  )
  if (groupNode) {
    groupNode._children = []
    groupNode._expanded = false
    await toggleExpand(groupNode)
  }
}

// 一键复制：将配置组的所有配置项格式化为 Markdown 批量导入表格并复制到剪贴板
const handleCopyGroupSettings = async (row) => {
  const groupId = row.data.id
  const groupName = row.data.name
  try {
    let settings = []
    if (row._expanded && row._children && row._children.length > 0) {
      settings = row._children.map(child => child.data)
    } else {
      const res = await getSettingList({ group_id: groupId, page: 1, count: 10 })
      if (res.data.code === 200) {
        settings = res.data.data.data || []
      }
    }

    if (settings.length === 0) {
      ElMessage.warning(`配置组「${groupName}」下没有配置项`)
      return
    }

    const lines = [
      `[配置组] ${groupName}`,
      '',
      '| 配置名 | 类型 | 默认值 | 说明 |',
      '|--------|------|--------|------|'
    ]
    settings.forEach(s => {
      const name = s.name || ''
      const type = s.type || 'string'
      const value = (s.value != null ? String(s.value) : '').replace(/\|/g, '\\|')
      const note = (s.note || '-').replace(/\|/g, '\\|')
      lines.push(`| \`${name}\` | \`${type}\` | \`${value}\` | ${note} |`)
    })

    const text = lines.join('\n')
    await navigator.clipboard.writeText(text)
    ElMessage.success(`已复制「${groupName}」的 ${settings.length} 条配置项到剪贴板`)
  } catch (error) {
    console.error('一键复制失败:', error)
    ElMessage.error('复制失败，请重试')
  }
}

// 一键导入：打开批量导入弹窗并预选当前配置组
const handleImportToGroup = (groupData) => {
  batchImportText.value = ''
  batchImportParsed.value = []
  batchImportGroupId.value = groupData.id
  batchImportGroupName.value = groupData.name
  batchImportGroupExists.value = true
  batchImportOpen.value = true
  batchImportProgress.value = 0
  batchImportTotal.value = 0
  batchImportStatusText.value = ''
  batchImportDialogVisible.value = true
}

// 初始化
onMounted(() => {
  // 初始化时加载配置组数据
  loadGroups()
})
</script>

<style scoped>
.setting-manage-container {
  padding: 0;
}

.main-container {
  border: 1px solid #e1e8ed;
  background: #ffffff;
}

/* 树状图样式 */
.tree-section {
  padding: 20px;
  min-height: 400px;
  max-height: 500px;
  overflow-y: auto;
  /* 隐藏滚动条 */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}

.tree-section::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Opera */
}

.setting-tree-table {
  background: white;
}

/* 树状层级样式 */
.tree-item-content {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
}

.expand-icon {
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #606266;
  transition: transform 0.2s ease;
}

.expand-icon:hover {
  color: #409eff;
}

.expand-icon .is-expanded {
  transform: rotate(90deg);
}

.expand-placeholder {
  width: 20px;
  height: 20px;
}

.tree-node {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tree-icon {
  color: #409eff;
  font-size: 16px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.tree-label {
  font-weight: 500;
  color: #303133;
  font-size: 14px;
  flex: 1;
  line-height: 16px; /* 与图标高度保持一致 */
}

/* 表格中文字值样式 */
.text-value {
  display: inline-block;
  max-width: 200px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}

/* 文件预览样式 */
.file-preview {
  margin-top: 8px;
  position: relative;
  flex-shrink: 0;
}

.preview-image {
  width: 80px;
  height: 80px;
  border-radius: 4px;
  cursor: pointer;
  transition: transform 0.2s ease;
  border: 1px solid #e1e8ed;
  object-fit: cover;
}

.preview-image:hover {
  transform: scale(1.1);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.file-preview-link {
  margin-top: 8px;
}

.file-item {
  border: 1px solid #e1e8ed;
  border-radius: 4px;
  padding: 12px;
  margin-bottom: 8px;
  background: #fafbfc;
  display: flex;
  align-items: center;
  gap: 12px;
}

.file-placeholder {
  width: 80px;
  height: 80px;
  border-radius: 4px;
  border: 1px solid #e1e8ed;
  background: #f5f7fa;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #909399;
  font-size: 24px;
}

.file-details {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}

.file-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
  flex-shrink: 0;
}

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

.file-id {
  font-size: 12px;
  color: #909399;
}

.file-size {
  font-size: 12px;
  color: #909399;
}

/* 表格行样式 */
:deep(.setting-tree-table .el-table__row--level-1) {
  background-color: #fafbfc;
}

:deep(.setting-tree-table .el-table__row--level-2) {
  background-color: #f5f7fa;
}

/* 表格样式优化 */
:deep(.setting-tree-table .el-table) {
  border: none;
  color: #2c3e50;
}

:deep(.setting-tree-table .el-table__header) {
  background: #f8f9fa;
}

:deep(.setting-tree-table .el-table th) {
  background: #f8f9fa !important;
  border-bottom: 2px solid #e1e8ed;
  color: #2c3e50;
  font-weight: 600;
  font-size: 13px;
}

:deep(.setting-tree-table .el-table td) {
  border-bottom: 1px solid #f0f2f5;
  color: #34495e;
}

:deep(.setting-tree-table .el-table tr:hover > td) {
  background-color: #f8f9fa !important;
}

/* 详细信息面板样式 */
.detail-section {
  padding: 20px;
  background: #fafbfc;
  border-top: 1px solid #e1e8ed;
}

.detail-content {
  background: white;
  border-radius: 8px;
  padding: 20px;
}

.filter-section {
  padding: 0;
  border-bottom: 1px solid #e1e8ed;
  background: #fafbfc;
  margin: 0 -20px;
}

.filter-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  gap: 20px;
  flex-wrap: wrap;
}

.search-form {
  margin: 0;
  flex: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.search-form :deep(.el-form-item) {
  margin-bottom: 0;
  margin-right: 12px;
}

.action-bar {
  display: flex;
  gap: 12px;
  flex-shrink: 0;
}

.table-section {
  padding: 20px 0;
}

.pagination {
  margin-top: 20px;
  padding: 16px 0;
  border-top: 1px solid #e1e8ed;
  justify-content: flex-end;
}

/* 表格样式优化 */
:deep(.el-table) {
  border: none;
  color: #2c3e50;
}

:deep(.el-table__header) {
  background: #f8f9fa;
}

:deep(.el-table th) {
  background: #f8f9fa !important;
  border-bottom: 2px solid #e1e8ed;
  color: #2c3e50;
  font-weight: 600;
  font-size: 13px;
}

:deep(.el-table td) {
  border-bottom: 1px solid #f0f2f5;
  color: #34495e;
}

:deep(.el-table tr:hover > td) {
  background-color: #f8f9fa !important;
}

:deep(.dialog-scrollable .el-dialog) {
  max-height: 90vh;
  display: flex;
  flex-direction: column;
}

:deep(.dialog-scrollable .el-dialog__body) {
  max-height: calc(90vh - 120px);
  overflow-y: auto;
  padding: 20px;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}

/* 完全隐藏滚动条但保持滚动功能 */
:deep(.dialog-scrollable .el-dialog__body)::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Opera */
}

/* 确保弹窗内容区域正确布局 */
:deep(.dialog-scrollable .el-dialog__header) {
  flex-shrink: 0;
}

:deep(.dialog-scrollable .el-dialog__footer) {
  flex-shrink: 0;
  padding: 20px;
  border-top: 1px solid #e4e7ed;
}

/* 移动端适配 */
@media (max-width: 768px) {
  :deep(.dialog-scrollable .el-dialog) {
    max-height: 95vh;
    width: 95vw !important;
    margin: 0 auto;
  }
  
  :deep(.dialog-scrollable .el-dialog__body) {
    max-height: calc(95vh - 140px);
    padding: 15px;
  }
  
  :deep(.dialog-scrollable .el-dialog__footer) {
    padding: 15px;
  }

  .tree-section {
    max-height: 300px;
    min-height: 300px;
    padding: 10px;
  }

  .tree-item-content {
    padding: 4px 0;
  }

  .tree-label {
    font-size: 13px;
    line-height: 14px; /* 移动端调整行高 */
  }

  .tree-icon {
    font-size: 14px;
  }

  :deep(.setting-tree-table .el-table th) {
    font-size: 12px;
    padding: 8px 4px;
  }

  :deep(.setting-tree-table .el-table td) {
    font-size: 12px;
    padding: 8px 4px;
  }
}

/* 确保表单在弹窗中正确显示 */
:deep(.dialog-scrollable .el-form) {
  margin: 0;
}

:deep(.dialog-scrollable .el-form-item) {
  margin-bottom: 20px;
}

/* 文件上传组件在弹窗中的样式优化 */
:deep(.dialog-scrollable .file-uploader) {
  margin-bottom: 10px;
}

:deep(.dialog-scrollable .file-info-display),
:deep(.dialog-scrollable .file-list-info-display) {
  margin-bottom: 15px;
}

:deep(.el-tabs__header) {
  margin: 0;
  padding: 0 0 0 0;
  border-bottom: 1px solid #e1e8ed;
}

:deep(.el-tabs__nav-wrap::after) {
  display: none;
}

:deep(.el-tabs__item) {
  padding: 0 20px;
  height: 50px;
  line-height: 50px;
  font-size: 14px;
  font-weight: 500;
}

:deep(.el-tabs__item.is-active) {
  color: #2c3e50;
  font-weight: 600;
}

:deep(.el-tabs__active-bar) {
  background-color: #2c3e50;
}

/* JSON 编辑工具栏 */
.json-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

/* 导入进度面板 */
.import-progress-panel {
  padding: 40px 20px;
  text-align: center;
}

.progress-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-bottom: 24px;
}

.progress-info {
  max-width: 500px;
  margin: 0 auto;
}

/* 文件上传相关样式 */
.file-upload-section {
  width: 100%;
}

.file-uploader {
  width: 100%;
}

.file-upload-options {
  width: 100%;
}

.upload-methods {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: center;
}

.divider {
  position: relative;
  text-align: center;
  color: #909399;
  font-size: 14px;
  margin: 8px 0;
}

.divider::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background: #dcdfe6;
}

.divider {
  background: #fff;
  padding: 0 16px;
}

.image-selector-btn {
  width: 200px;
  height: 40px;
}

:deep(.file-uploader .el-upload) {
  width: 100%;
}

:deep(.file-uploader .el-upload-dragger) {
  width: 100%;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: border-color 0.3s;
}

:deep(.file-uploader .el-upload-dragger:hover) {
  border-color: #409eff;
}

.file-info-display {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  background-color: #f5f7fa;
}

.file-details {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.file-name {
  font-weight: 500;
  color: #303133;
  max-width: 200px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: inline-block;
}

.file-id {
  font-size: 12px;
  color: #909399;
}

.file-size {
  font-size: 12px;
  color: #909399;
}

/* 文件列表相关样式 */
.file-list-section {
  width: 100%;
}

.file-list-info-display {
  margin-bottom: 16px;
}

.file-list-details {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  background-color: #f5f7fa;
}

.file-item .file-details {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}

.file-item .file-name {
  font-weight: 500;
  color: #303133;
  max-width: 180px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: inline-block;
  cursor: pointer;
  transition: color 0.3s;
}

.file-item .file-name:hover {
  color: #409eff;
}

/* 上传状态指示器样式 */
.file-item.uploading {
  border-color: #409eff;
  background-color: #f0f9ff;
}

.upload-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.6);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 12px;
  border-radius: 4px;
}

.upload-overlay .el-icon {
  font-size: 20px;
  margin-bottom: 4px;
}

.upload-overlay span {
  font-size: 11px;
}

/* 字符串列表相关样式 */
.string-list-section {
  width: 100%;
}

.string-list-display {
  margin-bottom: 16px;
}

.string-list-items {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.string-item {
  margin: 0;
}

.string-list-input {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* 文件列表摘要样式 */
.file-list-summary {
  display: flex;
  align-items: center;
}

.file-list-summary .el-tag {
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.file-list-summary .el-tag:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* 字符串列表摘要样式 */
.string-list-summary {
  display: flex;
  align-items: center;
}

.string-list-summary .el-tag {
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.string-list-summary .el-tag:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* 表格中的文件列表和字符串列表样式 */
.table-file-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 120px;
  overflow-y: auto;
}

.table-file-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  background-color: #f8f9fa;
  border-radius: 4px;
  border: 1px solid #e9ecef;
  transition: all 0.2s ease;
}

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

.file-preview-mini {
  width: 24px;
  height: 24px;
  border-radius: 3px;
  overflow: hidden;
  flex-shrink: 0;
  border: 1px solid #dee2e6;
}

.preview-mini-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  cursor: pointer;
}

.file-placeholder-mini {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f8f9fa;
  color: #6c757d;
  font-size: 10px;
}

.file-info-mini {
  flex: 1;
  min-width: 0;
}

.file-name-mini {
  font-size: 12px;
  font-weight: 500;
  color: #495057;
  margin-bottom: 2px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.file-id-mini {
  font-size: 10px;
  color: #6c757d;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.table-string-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 120px;
  overflow-y: auto;
}

.table-string-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 6px;
  background-color: #f8f9fa;
  border-radius: 3px;
  border-left: 3px solid #007bff;
  transition: all 0.2s ease;
  cursor: pointer;
}

.table-string-item:hover {
  background-color: #e9ecef;
  border-left-color: #0056b3;
}

.string-index {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  background-color: #007bff;
  color: white;
  font-size: 10px;
  font-weight: bold;
  border-radius: 50%;
  flex-shrink: 0;
}

.string-content {
  font-size: 12px;
  color: #495057;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  flex: 1;
}

.file-list-display {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.file-link {
  font-size: 12px;
  margin-right: 8px;
  max-width: 150px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: inline-block;
  vertical-align: middle;
}

.string-list-display {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.string-tag {
  margin: 0;
  max-width: 120px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: inline-block;
}

/* 可编辑字符串列表样式 */
.editable-string-list {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 16px;
  background-color: #fafafa;
}

.string-list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #ebeef5;
}

.list-title {
  font-weight: 500;
  color: #303133;
  font-size: 14px;
}

.string-list-items {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.string-list-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  background-color: #ffffff;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  transition: all 0.3s ease;
  cursor: move;
}

.string-list-item:hover {
  border-color: #c0c4cc;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.drag-handle {
  color: #909399;
  cursor: grab;
  flex-shrink: 0;
}

.drag-handle:hover {
  color: #606266;
}

.item-content {
  flex: 1;
  min-width: 0;
}

.item-text {
  padding: 4px 8px;
  border-radius: 4px;
  transition: background-color 0.3s ease;
  cursor: pointer;
  word-break: break-word;
  white-space: normal;
  line-height: 1.4;
}

.item-text:hover {
  background-color: #f5f7fa;
}

.item-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

.danger-btn {
  color: #f56c6c;
}

.danger-btn:hover {
  color: #f78989;
}

/* 可编辑文件列表样式 */
.editable-file-list {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 16px;
  background-color: #fafafa;
}

.file-list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #ebeef5;
}

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

.file-list-items {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.file-list-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  background-color: #ffffff;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  transition: all 0.3s ease;
  cursor: move;
}

.file-list-item:hover {
  border-color: #c0c4cc;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.file-list-item .file-preview {
  width: 60px;
  height: 60px;
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid #e4e7ed;
  flex-shrink: 0;
  position: relative;
}

.file-list-item .preview-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  cursor: pointer;
}

.file-list-item .file-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f5f7fa;
  color: #909399;
}

.file-list-item .file-info {
  flex: 1;
  min-width: 0;
}

.file-list-item .file-name {
  font-weight: 500;
  color: #303133;
  margin-bottom: 4px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.file-list-item .file-id {
  font-size: 12px;
  color: #909399;
  margin-bottom: 2px;
}

.file-list-item .file-size {
  font-size: 12px;
  color: #909399;
}

.file-list-item .file-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

/* 弹窗中值内容的省略号样式 */
.value-content {
  max-width: 100%;
}

.value-content .text-value {
  display: block;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  word-break: break-all;
}

/* 响应式样式 */
@media (max-width: 768px) {
  .table-file-list {
    max-height: 80px;
  }
  
  .table-string-list {
    max-height: 80px;
  }
  
  .file-preview-mini {
    width: 20px;
    height: 20px;
  }
  
  .file-name-mini {
    font-size: 11px;
  }
  
  .file-id-mini {
    font-size: 9px;
  }
  
  .string-index {
    width: 16px;
    height: 16px;
    font-size: 9px;
  }
  
  .string-content {
    font-size: 11px;
  }
  
  .file-link {
    max-width: 100px !important;
  }
  
  .string-tag {
    max-width: 80px !important;
  }
}

@media (max-width: 1200px) {
  .table-file-list {
    max-height: 100px;
  }
  
  .table-string-list {
    max-height: 100px;
  }
}

@media (max-width: 768px) {
  .file-name {
    max-width: 120px !important;
  }
  
  .file-item .file-name {
    max-width: 100px !important;
  }
  
  .file-link {
    max-width: 100px !important;
  }
  
  .string-tag {
    max-width: 80px !important;
  }
}
</style>
