<template>
  <!-- 网盘管理对话框：统一的增删改查入口 -->
  <dialog ref="dialogRef" class="app-dialog drive-manage-dialog" @close="handleClose">
    <form class="dialog-form" method="dialog">
      <header>
        <h2>网盘管理</h2>
        <button type="button" aria-label="关闭" @click="closeDialog">×</button>
      </header>

      <div class="drive-manage-body">
        <!-- ==================== 网盘列表视图（默认） ==================== -->
        <template v-if="!showForm">
          <!-- 操作栏 -->
          <div class="drive-toolbar">
            <h3>网盘列表</h3>
            <button type="button" class="btn-primary" @click="handleAddDrive">+ 新建网盘</button>
          </div>

          <!-- 加载状态提示 -->
          <div v-if="loading" class="loading-hint">
            <div class="spinner-small"></div>
            正在加载网盘列表...
          </div>

          <!-- 空数据提示 -->
          <div v-else-if="driveList.length === 0" class="empty-hint">
            暂无网盘，点击上方按钮创建
          </div>

          <!-- 网盘列表卡片 -->
          <div v-else class="drive-list">
            <div v-for="drive in driveList" :key="drive.id" class="drive-card">
              <!-- 网盘信息区域：Logo + 名称 + 描述提示 -->
              <div class="drive-info-main">
                <!-- 网盘Logo：显示在名称旁边 -->
                <div class="drive-logo-small">
                  <img
                    v-if="drive.logoData || drive.icon || drive.logoUrl"
                    :src="drive.logoData || drive.icon || drive.logoUrl"
                    :alt="drive.name"
                    class="drive-logo-img"
                  />
                  <div v-else class="drive-icon-small">📁</div>
                </div>

                <!-- 网盘名称 + 悬浮描述 -->
                <div class="drive-name-wrapper" @mouseenter="showTooltip(drive.id)" @mouseleave="hideTooltip">
                  <h4 class="drive-name">{{ drive.name }}</h4>
                  <!-- 悬浮提示图标 -->
                  <span v-if="drive.description" class="tooltip-trigger" title="">ℹ️</span>

                  <!-- 悬浮描述提示框 -->
                  <Transition name="tooltip-fade">
                    <div
                      v-if="activeTooltipId === drive.id && drive.description"
                      class="drive-tooltip"
                    >
                      <div class="tooltip-header">{{ drive.name }}</div>
                      <div class="tooltip-content">{{ drive.description }}</div>
                      <div class="tooltip-arrow"></div>
                    </div>
                  </Transition>
                </div>
              </div>

              <!-- 元数据信息 -->
              <div class="drive-meta">
                <span class="drive-id">ID: {{ drive.id }}</span>
                <span class="drive-time">{{ formatTime(drive.createTime || drive.createdAt) }}</span>
              </div>

              <!-- 操作按钮组 -->
              <div class="drive-actions">
                <button type="button" class="btn-edit" @click="handleEditDrive(drive)">编辑</button>
                <button type="button" class="btn-delete" @click="handleDeleteDrive(drive)">删除</button>
              </div>
            </div>
          </div>
        </template>

        <!-- ==================== 新增/编辑表单视图 ==================== -->
        <template v-else>
          <!-- 表单标题栏 -->
          <div class="form-header">
            <button type="button" class="btn-back" @click="cancelForm">← 返回列表</button>
            <h3>{{ isEditing ? '编辑网盘' : '新建网盘' }}</h3>
          </div>

          <!-- 表单内容 -->
          <div class="form-content">
            <!-- Logo上传区域 -->
            <div class="form-group form-group--logo">
              <label>网盘Logo</label>
              <div class="logo-upload-area" :class="{ 'has-image': form.logoPreview }">
                <!-- 已有图片时显示预览 -->
                <img 
                  v-if="form.logoPreview" 
                  :src="form.logoPreview" 
                  alt="Logo预览"
                  class="logo-preview"
                />
                <!-- 未上传或点击更换 -->
                <div v-else class="upload-placeholder">
                  <span class="upload-icon">📷</span>
                  <span>点击上传Logo</span>
                  <span class="upload-hint">支持 JPG、PNG、GIF</span>
                </div>
                <!-- 隐藏的文件输入框 -->
                <input
                  ref="logoInputRef"
                  type="file"
                  accept="image/jpeg,image/png,image/gif,image/webp"
                  class="hidden-input"
                  @change="handleLogoChange"
                />
                <!-- 操作按钮 -->
                <div v-if="form.logoPreview" class="logo-actions">
                  <button type="button" class="btn-change" @click="$refs.logoInputRef.click()">更换</button>
                  <button type="button" class="btn-remove" @click="removeLogo">移除</button>
                </div>
              </div>
              <div class="logo-upload-tips">
                <span class="tips-icon">💡</span>
                <span>建议尺寸 <strong>256×256px</strong> 或 <strong>512×512px</strong>，正方形最佳，最大 5MB</span>
              </div>
            </div>

            <!-- 网盘名称输入 -->
            <div class="form-group">
              <label for="driveName">网盘名称 <span class="required">*</span></label>
              <input
                id="driveName"
                v-model.trim="form.name"
                type="text"
                placeholder="请输入网盘名称"
                class="form-input"
                maxlength="50"
                :disabled="submitting"
              />
            </div>

            <!-- 网盘描述输入 -->
            <div class="form-group">
              <label for="driveDesc">网盘描述</label>
              <textarea
                id="driveDesc"
                v-model.trim="form.description"
                placeholder="请输入网盘描述（可选）"
                class="form-textarea"
                rows="4"
                maxlength="200"
                :disabled="submitting"
              ></textarea>
              <div class="char-count">{{ (form.description || '').length }}/200</div>
            </div>
          </div>

          <!-- 表单操作按钮 -->
          <div class="form-footer">
            <button type="button" class="btn-cancel" @click="cancelForm" :disabled="submitting">取消</button>
            <button 
              type="button" 
              class="btn-primary btn-submit" 
              @click="handleSubmitDrive" 
              :disabled="submitting || !isFormValid"
            >
              {{ submitting ? '保存中...' : (isEditing ? '保存修改' : '创建网盘') }}
            </button>
          </div>
        </template>

        <!-- ==================== 全局加载遮罩层 ==================== -->
        <Transition name="loading-fade">
          <div v-if="isAnyLoading && !showForm" class="global-loading-overlay">
            <div class="loading-spinner-container">
              <div class="spinner"></div>
              <p class="loading-text">{{ loadingText }}</p>
            </div>
          </div>
        </Transition>
      </div>
    </form>

    <!-- 使用 Teleport 将确认弹窗渲染为一个真正的 modal <dialog>，并在打开时调用 showModal()，以确保它位于主对话框之上 -->
      <Teleport to="body">
        <dialog ref="confirmRef" class="confirm-overlay" @click.self="closeConfirmDialog" @close="closeConfirmDialog">
          <Transition name="confirm-scale-in">
            <div v-if="showConfirm" class="confirm-dialog">
              <header>⚠️ 确认删除</header>
              <div class="confirm-body">
                <p>确定要删除网盘 <strong>"{{ confirmTarget?.name }}"</strong> 吗？</p>
                <p class="confirm-hint">注意：该网盘下的所有文件和文件夹都将被永久删除！此操作不可恢复。</p>
              </div>
              <footer>
                <button type="button" @click="closeConfirmDialog">取消</button>
                <button type="button" class="btn-danger" @click="confirmDelete">确认删除</button>
              </footer>
            </div>
          </Transition>
        </dialog>
      </Teleport>
  </dialog>
</template>

<script setup>
import { ref, computed, watch, nextTick } from 'vue'
import { fetchDriveList, createDrive, updateDrive, deleteDrive } from '../api'
import { lockScroll, unlockScroll } from '../utils/scrollLock'

// ==================== Props & Emits ====================
const props = defineProps({
  open: {
    type: Boolean,
    default: false,
  },
})

const emit = defineEmits(['close', 'success', 'refresh', 'error'])

// ==================== Refs ====================
const dialogRef = ref(null) // 主对话框引用
const logoInputRef = ref(null) // Logo文件选择器引用

// ==================== 数据状态 ====================
const loading = ref(false) // 列表加载状态
const submitting = ref(false) // 提交状态（新增/编辑）
const deleting = ref(false) // 删除操作加载状态
const showForm = ref(false) // 是否显示表单（true=表单视图, false=列表视图）
const isEditing = ref(false) // 是否处于编辑模式
const editingId = ref(null) // 正在编辑的网盘ID

// 网盘列表数据
const driveList = ref([])

// 删除确认弹窗相关状态
const showConfirm = ref(false)
const confirmTarget = ref(null)
const confirmRef = ref(null)
// 用于锁定/解锁 body 滚动，避免 modal 打开时出现滚动条或页面抖动
// 使用 position:fixed 锁定 body，记录并恢复滚动位置，避免因消失的滚动条导致页面抖动
let _prevBodyStyle = {}
let _prevScrollY = 0
function lockBodyScroll() {
  try {
    const body = document && document.body
    if (!body) return

    // 记录当前滚动位置与样式
    _prevScrollY = window.scrollY || window.pageYOffset || 0
    _prevBodyStyle = {
      position: body.style.position || '',
      top: body.style.top || '',
      left: body.style.left || '',
      right: body.style.right || '',
      width: body.style.width || '',
      overflow: body.style.overflow || '',
      paddingRight: body.style.paddingRight || '',
    }

    // 锁定 body：固定定位并向上偏移以保持视觉位置不变
    body.style.position = 'fixed'
    body.style.top = `-${_prevScrollY}px`
    body.style.left = '0'
    body.style.right = '0'
    body.style.width = '100%'
    body.style.overflow = 'hidden'
  } catch (e) {
    // ignore
  }
}

function unlockBodyScroll() {
  try {
    const body = document && document.body
    if (!body) return

    // 恢复之前记录的样式
    body.style.position = _prevBodyStyle.position
    body.style.top = _prevBodyStyle.top
    body.style.left = _prevBodyStyle.left
    body.style.right = _prevBodyStyle.right
    body.style.width = _prevBodyStyle.width
    body.style.overflow = _prevBodyStyle.overflow
    body.style.paddingRight = _prevBodyStyle.paddingRight

    // 恢复滚动位置
    window.scrollTo(0, _prevScrollY)

    _prevBodyStyle = {}
    _prevScrollY = 0
  } catch (e) {
    // ignore
  }
}

// 悬浮提示状态：当前显示提示的网盘ID
const activeTooltipId = ref(null)
let tooltipTimer = null // 悬浮提示延迟定时器

// （已移除）模式切换标志位，旧的 showModal/show 切换逻辑不再使用

// 计算属性：是否有任何操作正在执行
const isAnyLoading = computed(() => loading.value || submitting.value || deleting.value)

// 计算属性：动态加载提示文字
const loadingText = computed(() => {
  if (loading.value) return '正在加载数据...'
  if (submitting.value) return isEditing.value ? '正在保存修改...' : '正在创建网盘...'
  if (deleting.value) return '正在删除网盘...'
  return '处理中...'
})

// ==================== 表单数据 ====================
const defaultForm = () => ({
  name: '',
  description: '',
  logoFile: null, // 原始文件对象（用于上传）
  logoPreview: '', // 预览URL（用于显示）
})

const form = ref(defaultForm())

// 计算属性：表单是否有效（必填项校验）
const isFormValid = computed(() => {
  return form.value.name && form.value.name.trim().length > 0
})

// ==================== 生命周期与监听 ====================
/**
 * 监听 open 属性变化，自动打开/关闭对话框
 */
watch(
  () => props.open,
  async (newVal) => {
    await nextTick()
    if (newVal) {
      dialogRef.value?.showModal()//弹框打开操作
      lockScroll()
      // 打开时自动加载网盘列表
      loadDriveList()
    } else {
      if (dialogRef.value?.open) {
        dialogRef.value.close()
        unlockScroll()
      }
    }
  }
)

/**
 * 监听 showForm 变化，重置表单状态
 */
watch(showForm, (newVal) => {
  if (!newVal) {
    // 返回列表视图时重置表单
    resetForm()
  }
})

// ==================== 对话框控制方法 ====================

/**
 * 关闭对话框
 */
function closeDialog() {
  if (dialogRef.value?.open) {
    dialogRef.value.close()
  }
}

/**
 * 处理对话框关闭事件
 * 防止模式切换时误触发关闭
 */
function handleClose() {
  // 重置状态并通知父组件
  showForm.value = false
  unlockScroll()
  emit('close')
}

// ==================== 数据加载方法 ====================

/**
 * 从后端加载网盘列表
 */
async function loadDriveList() {
  loading.value = true
  try {
    const res = await fetchDriveList()
    
    if (res.code === 200 && res.data) {
      // 处理返回的数据格式
      const data = res.data
      
      if (Array.isArray(data)) {
        driveList.value = data
      } else if (data.list && Array.isArray(data.list)) {
        driveList.value = data.list
      } else if (data.records && Array.isArray(data.records)) {
        driveList.value = data.records
      } else {
        driveList.value = []
      }
    } else {
      console.error('获取网盘列表失败', res)
      driveList.value = []
      emit('error', res.message || '获取网盘列表失败')
    }
  } catch (err) {
    console.error('加载网盘列表出错', err)
    driveList.value = []
    const serverMessage = err?.payload?.message || err?.message || ''
    let errorMsg = serverMessage || '加载网盘列表失败'
    if (serverMessage.includes('权限') || serverMessage.includes('无权')) {
      errorMsg = serverMessage
    } else if (serverMessage.includes('登录') || serverMessage.includes('Token')) {
      errorMsg = serverMessage
    }
    emit('error', errorMsg)
  } finally {
    loading.value = false
  }
}

// ==================== CRUD 操作方法 ====================

/**
 * 打开新建网盘表单
 */
function handleAddDrive() {
  isEditing.value = false
  editingId.value = null
  form.value = defaultForm()
  showForm.value = true
}

/**
 * 打开编辑网盘表单
 * @param {Object} drive - 要编辑的网盘对象
 */
function handleEditDrive(drive) {
  isEditing.value = true
  editingId.value = drive.id
  
  // 填充表单数据
  form.value = {
    name: drive.name || '',
    description: drive.description || '',
    logoFile: null,
    logoPreview: drive.logoData || drive.icon || drive.logoUrl || '', // 使用已有的logo作为预览
  }
  
  showForm.value = true
}

/**
 * 取消表单编辑，返回列表视图
 */
function cancelForm() {
  showForm.value = false
  resetForm()
}

/**
 * 重置表单到初始状态
 */
function resetForm() {
  form.value = defaultForm()
  isEditing.value = false
  editingId.value = null
}

/**
 * 提交表单（新增或编辑网盘）
 */
async function handleSubmitDrive() {
  // 前端表单验证
  if (!form.value.name || !form.value.name.trim()) {
    emit('error', '请输入网盘名称')
    return
  }

  submitting.value = true

  try {
    // 构建提交数据对象
    const submitData = {
      name: form.value.name.trim(),
      description: form.value.description?.trim() || '',
      logoData: form.value.logoPreview || '', // 将 Logo 图片（base64或URL）提交到后端
    }

    let result

    if (isEditing.value) {
      // 编辑模式：调用更新接口
      result = await updateDrive(editingId.value, submitData)
    } else {
      // 新建模式：调用创建接口
      result = await createDrive(submitData)
    }

    // 处理成功响应
    if (result?.code === 200 && result?.data) {
      const actionText = isEditing.value ? '更新' : '创建'
      const successMsg = `网盘"${form.value.name}"${actionText}成功`
      
      // 显示成功提示
      emit('success', successMsg)
      
      // 返回列表视图并刷新数据
      showForm.value = false
      await loadDriveList()
      // 在数据加载完成后再通知父组件刷新
      emit('refresh')
    } else {
      emit('error', result?.message || (isEditing.value ? '更新失败' : '创建失败'))
    }
  } catch (err) {
    console.error(`${isEditing.value ? '更新' : '创建'}网盘失败`, err)
    
    // 智能错误信息展示
    const errorCode = err.code || err.status || 0
    const httpStatus = err.status || '-'
    const serverMessage = (err.payload?.message || err.payload?.msg || err.message || '').trim()

    let errorMessage = ''

    if (serverMessage) {
      if (serverMessage.includes('已存在') || serverMessage.includes('已被') || serverMessage.includes('已占用') || serverMessage.includes('已注册')) {
        errorMessage = serverMessage
      } else if (serverMessage.includes('不能为空') || serverMessage.includes('必填') || serverMessage.includes('required')) {
        errorMessage = `参数有误：${serverMessage}`
      } else if (serverMessage.includes('权限') || serverMessage.includes('无权') || serverMessage.includes('禁止')) {
        errorMessage = serverMessage
      } else if (serverMessage.includes('不存在') || serverMessage.includes('未找到')) {
        errorMessage = serverMessage
      } else {
        errorMessage = serverMessage
      }
    }

    if (!errorMessage) {
      const errorMessages = {
        400: '请求参数有误：请检查必填字段',
        401: '登录已过期或 Token 无效，请重新登录',
        403: '权限不足：非管理员无法执行此操作',
        404: '目标网盘不存在或已被删除',
        500: '服务器繁忙，请稍后重试',
      }
      errorMessage = errorMessages[errorCode] || `操作失败 [错误码:${errorCode}]`
    }

    emit('error', `${isEditing.value ? '更新' : '创建'}网盘失败：${errorMessage}`)
  } finally {
    submitting.value = false
  }
}

/**
 * 打开删除确认弹窗
 * @param {Object} drive - 要删除的网盘对象
 */
function handleDeleteDrive(drive) {
  
  confirmTarget.value = drive
  // 立即锁定 body（避免在显示弹窗时产生滚动条消失导致的抖动）
  lockBodyScroll()

  // 显示确认弹窗
  showConfirm.value = true

  // 等待 confirmRef 挂载后以 modal 方式打开，确保覆盖在主 dialog 之上
  nextTick(() => {
    try {
      if (confirmRef.value && typeof confirmRef.value.showModal === 'function') {
        if (confirmRef.value.open) confirmRef.value.close()
        confirmRef.value.showModal()
      }
    } catch (e) {
      console.warn('打开确认弹窗失败', e)
    }
  })
  // 删除弹窗已请求显示
}

/**
 * 关闭删除确认弹窗
 */
function closeConfirmDialog() {
  // 关闭 confirm dialog 元素（如果是以 modal 打开的）
  try {
    if (confirmRef.value && confirmRef.value.open) confirmRef.value.close()
  } catch (e) {
    console.warn('关闭确认弹窗失败', e)
  }

  // 解锁 body 滚动
  unlockBodyScroll()

  showConfirm.value = false
  confirmTarget.value = null
}

/**
 * 执行确认删除操作
 */
async function confirmDelete() {
  if (!confirmTarget.value) return

  const targetDrive = confirmTarget.value

  // 先隐藏确认弹窗
  try {
    if (confirmRef.value && confirmRef.value.open) confirmRef.value.close()
  } catch (e) {
    console.warn('关闭确认弹窗失败', e)
  }
  showConfirm.value = false
  confirmTarget.value = null

  // 设置删除加载状态
  deleting.value = true

  try {
    await deleteDrive(targetDrive.id)

    // 重新加载列表
    await loadDriveList()
    
    // 在数据加载完成后再通知父组件刷新
    emit('success', `网盘 "${targetDrive.name}" 已删除`)
    emit('refresh')
  } catch (err) {
    console.error('删除网盘失败', err)

    // 智能错误信息展示
    const errorCode = err.code || err.status || 0
    const httpStatus = err.status || '-'
    const serverMessage = (err.payload?.message || err.payload?.msg || err.message || '').trim()

    let errorMessage = ''

    if (serverMessage) {
      if (serverMessage.includes('不存在') || serverMessage.includes('已被删除') || serverMessage.includes('未找到')) {
        errorMessage = serverMessage
      } else if (serverMessage.includes('权限') || serverMessage.includes('无权')) {
        errorMessage = serverMessage
      } else {
        errorMessage = serverMessage
      }
    }

    if (!errorMessage) {
      const errorMessages = {
        400: '删除失败：请求参数有误',
        403: '权限不足：非管理员无法执行此操作',
        404: '目标网盘不存在或已被删除',
        500: '服务器繁忙，请稍后重试',
      }
      errorMessage = errorMessages[errorCode] || `删除失败 [错误码:${errorCode}]`
    }

    emit('error', `删除网盘失败：${errorMessage}`)
  } finally {
    deleting.value = false
    // 确保在删除流程结束后解锁 body（防止未正确关闭时仍然被锁定）
    unlockBodyScroll()
  }
}

/**
 * 恢复主 dialog 为 modal 模式
 * 同时恢复背景样式，确保视觉一致性
 */
// (已移除) 原先用于恢复主 dialog 的模式切换逻辑，不再需要

// ==================== 悬浮提示相关方法 ====================

/**
 * 显示网盘描述悬浮提示（带延迟，避免快速划过时闪烁）
 * @param {number} driveId - 网盘ID
 */
function showTooltip(driveId) {
  // 清除之前的定时器
  if (tooltipTimer) {
    clearTimeout(tooltipTimer)
  }

  // 延迟 300ms 后显示，提升用户体验
  tooltipTimer = setTimeout(() => {
    activeTooltipId.value = driveId
  }, 300)
}

/**
 * 隐藏网盘描述悬浮提示
 */
function hideTooltip() {
  // 清除定时器（防止延迟期间鼠标已离开）
  if (tooltipTimer) {
    clearTimeout(tooltipTimer)
    tooltipTimer = null
  }

  // 立即隐藏
  activeTooltipId.value = null
}

// ==================== Logo上传相关方法 ====================

/**
 * 处理Logo文件选择变化
 * @param {Event} event - 文件选择事件
 */
function handleLogoChange(event) {
  const file = event.target.files[0]
  
  if (!file) return

  // 文件类型验证
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
  if (!allowedTypes.includes(file.type)) {
    emit('error', '仅支持 JPG、PNG、GIF、WebP 格式的图片')
    return
  }

  // 文件大小限制（最大5MB）
  const maxSize = 5 * 1024 * 1024
  if (file.size > maxSize) {
    emit('error', '图片大小不能超过 5MB')
    return
  }

  // 保存文件对象
  form.value.logoFile = file

  // 创建预览URL（使用 FileReader 或 URL.createObjectURL）
  const reader = new FileReader()
  reader.onload = (e) => {
    form.value.logoPreview = e.target.result
  }
  reader.readAsDataURL(file)
}

/**
 * 移除已上传的Logo
 */
function removeLogo() {
  form.value.logoFile = null
  form.value.logoPreview = ''
  // 清空文件输入框
  if (logoInputRef.value) {
    logoInputRef.value.value = ''
  }
}

// ==================== 工具函数 ====================

/**
 * 格式化时间戳为可读字符串
 * @param {string|number|Date} time - 时间值
 * @returns {string} 格式化的时间字符串
 */
function formatTime(time) {
  if (!time) return '-'
  
  try {
    const date = new Date(time)
    if (isNaN(date.getTime())) return String(time)
    
    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')
    
    return `${year}-${month}-${day} ${hours}:${minutes}`
  } catch {
    return String(time)
  }
}
</script>

<style scoped>
/* ====== 网盘管理对话框整体样式 ====== */
.drive-manage-dialog {
  width: 900px;
  max-width: 95vw;
  height: 80vh;
  max-height: 90vh;
}

.drive-manage-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: relative; /* 为全局加载遮罩层提供定位参考 */
}

/* ====== 工具栏样式 ====== */
.drive-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 12px;
  border-bottom: 2px solid #e8ecf1;
}

.drive-toolbar h3 {
  margin: 0;
  font-size: 18px;
  color: #303133;
  font-weight: 600;
}

/* ====== 网盘列表样式 ====== */
.drive-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* 单个网盘卡片 */
.drive-card {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  background: #f8fafc;
  border-radius: 10px;
  border: 1px solid #e2e8f0;
  transition: all 0.25s ease;
}

.drive-card:hover {
  background: #fff;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  transform: translateY(-1px);
  border-color: #cbd5e1;
}

/* ====== 网盘信息主区域：Logo + 名称 + 描述提示 ====== */
.drive-info-main {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
}

/* 小型Logo（显示在名称旁边） */
.drive-logo-small {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 8px;
  overflow: hidden;
  background: linear-gradient(135deg, #f0f4f8 0%, #e2e8f0 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #e2e8f0;
}

.drive-logo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.drive-icon-small {
  font-size: 20px;
  line-height: 1;
}

/* 网盘名称包装器（包含名称和悬浮提示） */
.drive-name-wrapper {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
}

.drive-name {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #1e293b;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 悬浮提示触发图标 */
.tooltip-trigger {
  flex-shrink: 0;
  font-size: 14px;
  cursor: help;
  opacity: 0.6;
  transition: opacity 0.2s ease;
}

.tooltip-trigger:hover {
  opacity: 1;
}

/* ====== 悬浮描述提示框 ====== */
.drive-tooltip {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 9999;
  background: #fff;
  border-radius: 10px;
  padding: 16px 18px;
  min-width: 280px;
  max-width: 380px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid #e8ecf1;
  animation: tooltip-appear 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes tooltip-appear {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(-5px) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateX(-50%) translateY(0) scale(1);
  }
}

.tooltip-header {
  font-size: 14px;
  font-weight: 700;
  color: #1e293b;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 2px solid #f0f2f5;
}

.tooltip-content {
  font-size: 13px;
  color: #475569;
  line-height: 1.65;
  word-break: break-word;
}

/* 提示框小箭头 */
.tooltip-arrow {
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%) rotate(45deg);
  width: 12px;
  height: 12px;
  background: #fff;
  border-left: 1px solid #e8ecf1;
  border-top: 1px solid #e8ecf1;
}

/* 悬浮提示过渡动画 */
.tooltip-fade-enter-active {
  transition: opacity 0.2s ease;
}
.tooltip-fade-leave-active {
  transition: opacity 0.15s ease;
}
.tooltip-fade-enter-from,
.tooltip-fade-leave-to {
  opacity: 0;
}

/* 元数据信息 */
.drive-meta {
  display: flex;
  gap: 16px;
  font-size: 12px;
  color: #94a3b8;
}

/* 操作按钮组 */
.drive-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

/* ====== 表单视图样式 ====== */
.form-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 12px;
  border-bottom: 2px solid #e8ecf1;
}

.form-header h3 {
  margin: 0;
  font-size: 18px;
  color: #303133;
  font-weight: 600;
}

.btn-back {
  padding: 6px 14px;
  background: #f0f2f5;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  color: #606266;
  transition: all 0.2s ease;
}

.btn-back:hover {
  background: #e4e7ed;
  border-color: #c0c4cc;
}

.form-content {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 20px 0;
}

/* Logo上传区域 */
.form-group--logo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.form-group--logo label {
  align-self: flex-start;
  font-weight: 600;
  color: #303133;
  font-size: 15px;
}

.logo-upload-area {
  position: relative;
  width: 180px;
  height: 180px;
  border: 2px dashed #dcdfe6;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
  overflow: hidden;
  background: #fafafa;
}

.logo-upload-area:hover {
  border-color: #409eff;
  background: #ecf5ff;
}

.logo-upload-area.has-image {
  border-style: solid;
  border-color: #e4e7ed;
}

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: #909399;
  text-align: center;
}

.upload-icon {
  font-size: 36px;
}

.upload-placeholder span:nth-child(2) {
  font-size: 14px;
  font-weight: 500;
}

.upload-hint {
  font-size: 12px !important;
  color: #c0c4cc !important;
}

.hidden-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.logo-preview {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 8px;
}

.logo-actions {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  z-index: 1;
}

.btn-change,
.btn-remove {
  padding: 4px 12px;
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: none;
}

.btn-change {
  background: rgba(64, 158, 255, 0.9);
  color: #fff;
}

.btn-change:hover {
  background: #409eff;
}

.btn-remove {
  background: rgba(245, 108, 108, 0.9);
  color: #fff;
}

.btn-remove:hover {
  background: #f56c6c;
}

/* 表单项通用样式 */
.form-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.form-group label {
  font-weight: 600;
  color: #303133;
  font-size: 14px;
}

.required {
  color: #f56c6c;
  margin-left: 2px;
}

.form-input,
.form-textarea {
  padding: 10px 14px;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  font-size: 14px;
  color: #303133;
  background: #fff;
  transition: all 0.25s ease;
  outline: none;
  font-family: inherit;
}

.form-input:focus,
.form-textarea:focus {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.15);
}

.form-input:disabled,
.form-textarea:disabled {
  background: #f5f7fa;
  cursor: not-allowed;
  color: #c0c4cc;
}

.form-textarea {
  resize: vertical;
  min-height: 80px;
  line-height: 1.5;
}

.char-count {
  text-align: right;
  font-size: 12px;
  color: #c0c4cc;
  margin-top: -4px;
}

/* Logo上传提示样式 */
.logo-upload-tips {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: #f0f9ff;
  border: 1px solid #bae6fd;
  border-radius: 6px;
  font-size: 12px;
  color: #0369a1;
  line-height: 1.5;
}
.logo-upload-tips .tips-icon {
  font-size: 14px;
  flex-shrink: 0;
}
.logo-upload-tips strong {
  color: #0c4a6e;
  font-weight: 600;
}

/* 表单底部操作区 */
.form-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding-top: 20px;
  border-top: 1px solid #ebeef5;
  margin-top: auto;
}

/* ====== 按钮样式 ====== */
.btn-primary {
  padding: 9px 22px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.28s ease;
  letter-spacing: 0.3px;
}

.btn-primary:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 6px 20px rgba(102, 126, 234, 0.35);
}

.btn-primary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none !important;
}

.btn-submit {
  min-width: 110px;
}

.btn-cancel {
  padding: 9px 22px;
  background: #fff;
  color: #606266;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.25s ease;
}

.btn-cancel:hover:not(:disabled) {
  color: #409eff;
  border-color: #c6e2ff;
  background-color: #ecf5ff;
}

.btn-cancel:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn-edit {
  padding: 7px 16px;
  background: #ecf5ff;
  color: #409eff;
  border: 1px solid #b3d8ff;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.25s ease;
}

.btn-edit:hover {
  background: #409eff;
  color: #fff;
  border-color: #409eff;
}

.btn-delete {
  padding: 7px 16px;
  background: #fef0f0;
  color: #f56c6c;
  border: 1px solid #fbc4c4;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.25s ease;
}

.btn-delete:hover {
  background: #f56c6c;
  color: #fff;
  border-color: #f56c6c;
}

/* ====== 加载和空状态 ====== */
.loading-hint,
.empty-hint {
  text-align: center;
  padding: 40px 20px;
  color: #909399;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

/* 小型旋转动画 */
.spinner-small {
  width: 24px;
  height: 24px;
  border: 3px solid #e4e7ed;
  border-top-color: #409eff;
  border-radius: 50%;
  animation: spin 0.75s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ====== 全局加载遮罩层 ====== */
.global-loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  border-radius: 8px;
}

.loading-spinner-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.spinner {
  width: 48px;
  height: 48px;
  border: 4px solid #e4e7ed;
  border-top-color: #409eff;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

.loading-text {
  color: #606266;
  font-size: 14px;
  font-weight: 500;
  margin: 0;
  letter-spacing: 0.5px;
}

/* 加载遮罩过渡动画 */
.loading-fade-enter-active {
  transition: opacity 0.3s ease;
}
.loading-fade-leave-active {
  transition: opacity 0.2s ease;
}
.loading-fade-enter-from,
.loading-fade-leave-to {
  opacity: 0;
}

/* ====== 删除确认弹窗样式 ====== */
.confirm-overlay {
  /* 作为 <dialog> 使用时，我们把它固定定位并让内容居中；实际遮罩使用 ::backdrop 以兼容 showModal() */
  position: fixed;
  inset: 0;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2147483647;
  border: none;
  padding: 0;
  overflow: hidden; /* 防止 dialog 本身显示滚动条 */
  border-radius: 14px; /* 在 dialog 元素上直接加圆角，确保一开始就是圆角外观 */
  -webkit-border-radius: 14px;
}

.confirm-overlay::backdrop {
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(3px);
}

.confirm-dialog {
  background: #fff;
  border-radius: 14px;
  padding: 24px 28px;
  min-width: 420px;
  max-width: 90vw;
  box-shadow: 0 20px 70px rgba(0, 0, 0, 0.25);
  border: none;
  overflow: visible;
  max-height: calc(100vh - 80px);
}

.confirm-dialog header {
  font-size: 17px;
  font-weight: 700;
  color: #303133;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid #ebeef5;
}

.confirm-body {
  font-size: 15px;
  color: #606266;
  line-height: 1.65;
  margin-bottom: 8px;
}

.confirm-body strong {
  color: #f56c6c;
  font-weight: 700;
}

.confirm-hint {
  font-size: 13px !important;
  color: #f56c6c !important;
  background: #fef0f0;
  padding: 10px 14px;
  border-radius: 8px;
  border-left: 3px solid #f56c6c;
}

.confirm-dialog footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid #ebeef5;
}

.confirm-dialog footer button {
  padding: 9px 22px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.25s ease;
  border: none;
}

.confirm-dialog footer button:first-child {
  background: #fff;
  color: #606266;
  border: 1px solid #dcdfe6;
}

.confirm-dialog footer button:first-child:hover {
  background: #f5f7fa;
  border-color: #c0c4cc;
}

.btn-danger {
  background: linear-gradient(135deg, #f56c6c 0%, #e74c3c 100%) !important;
  color: #fff !important;
  border: none !important;
}

.btn-danger:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(245, 108, 108, 0.35);
}

/* 确认弹窗动画 */
.confirm-fade-enter-active {
  transition: opacity 0.25s ease;
}
.confirm-fade-leave-active {
  transition: opacity 0.2s ease;
}
.confirm-fade-enter-from,
.confirm-fade-leave-to {
  opacity: 0;
}

.confirm-scale-in-enter-active {
  transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.confirm-scale-in-leave-active {
  transition: all 0.2s ease;
}
.confirm-scale-in-enter-from {
  opacity: 0;
  transform: scale(0.85) translateY(15px);
}
.confirm-scale-in-leave-to {
  opacity: 0;
  transform: scale(0.95) translateY(-8px);
}
</style>
