<template>
  <dialog ref="dialogRef" class="app-dialog user-manage-dialog" @close="handleClose">
    <form class="dialog-form" method="dialog">
      <header>
        <h2>用户管理</h2>
        <button type="button" aria-label="关闭" @click="closeDialog">×</button>
      </header>

      <div class="user-manage-body">
        <!-- 操作栏：搜索和新增按钮 -->
        <div class="user-manage-toolbar">
          <div class="search-filters">
            <!-- 用户名搜索 -->
            <input
              v-model="searchForm.username"
              type="text"
              placeholder="搜索用户名"
              class="filter-input"
              @keydown.enter="handleSearch"
            />
            <!-- 状态筛选 -->
            <select v-model.number="searchForm.status" class="filter-select">
              <option value="">全部状态</option>
              <option :value="0">禁用</option>
              <option :value="1">正常</option>
              <option :value="2">锁定</option>
            </select>
            <!-- 角色筛选 -->
            <select v-model.number="searchForm.userType" class="filter-select">
              <option value="">全部角色</option>
              <option :value="0">普通用户</option>
              <option :value="1">VIP用户</option>
              <option :value="2">管理员</option>
            </select>
            <!-- 搜索按钮 -->
            <button type="button" class="btn-search" @click="handleSearch">搜索</button>
            <!-- 重置按钮 -->
            <button type="button" class="btn-reset" @click="handleResetSearch">重置</button>
          </div>
          <!-- 新增用户按钮 -->
          <button type="button" class="btn-primary" @click="handleAddUser">+ 新增用户</button>
        </div>

        <!-- 加载状态提示 -->
        <div v-if="loading" class="loading-hint">正在加载用户数据...</div>

        <!-- 空数据提示 -->
        <div v-else-if="!loading && userList.length === 0" class="empty-hint">
          {{ pagination.pageNo === 1 ? '暂无用户数据' : '没有符合筛选条件的用户' }}
        </div>

        <!-- 用户列表表格 -->
        <table v-else class="user-table">
          <thead>
            <tr>
              <th>ID</th>
              <th>用户名</th>
              <th>真实姓名</th>
              <th>邮箱</th>
              <th>手机号</th>
              <th>角色</th>
              <th>状态</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="user in userList" :key="user.id">
              <td>{{ user.id }}</td>
              <td>{{ user.username }}</td>
              <td>{{ user.realName || '-' }}</td>
              <td>{{ user.email || '-' }}</td>
              <td>{{ user.phone || '-' }}</td>
              <td>
                <span class="role-badge" :class="`role-${user.userType}`">
                  {{ getUserTypeLabel(user.userType) }}
                </span>
              </td>
              <td>
                <span class="status-badge" :class="`status-${user.status}`">
                  {{ getStatusLabel(user.status) }}
                </span>
              </td>
              <td class="action-cell">
                <button type="button" class="btn-edit" @click="handleEditUser(user)">编辑</button>
                <button type="button" class="btn-delete" @click="handleDeleteUser(user)">删除</button>
              </td>
            </tr>
          </tbody>
        </table>

        <!-- 分页控制 -->
        <div v-if="pagination.total > 0" class="pagination-bar">
          <div class="pagination-info">
            共 {{ pagination.total }} 条记录，当前第 {{ pagination.pageNo }} / {{ totalPages }} 页
          </div>
          <div class="pagination-controls">
            <button
              type="button"
              :disabled="pagination.pageNo <= 1"
              @click="handlePageChange(pagination.pageNo - 1)"
            >
              上一页
            </button>
            <button
              type="button"
              :disabled="pagination.pageNo >= totalPages"
              @click="handlePageChange(pagination.pageNo + 1)"
            >
              下一页
            </button>
          </div>
        </div>

        <!-- 全局加载遮罩层：在任何异步操作期间显示 -->
        <!-- 覆盖整个对话框内容区域，防止用户重复操作 -->
        <Transition name="loading-fade">
          <div v-if="isAnyLoading" class="global-loading-overlay">
            <div class="loading-spinner-container">
              <!-- CSS旋转动画加载指示器 -->
              <div class="spinner"></div>
              <!-- 动态显示当前操作类型 -->
              <p class="loading-text">{{ loadingText }}</p>
            </div>
          </div>
        </Transition>
      </div>

      <footer>
        <button type="button" class="secondary" @click="closeDialog">关闭</button>
      </footer>
    </form>
  </dialog>

  <!-- 用户编辑对话框（新增/编辑共用） -->
  <dialog ref="editDialogRef" class="app-dialog user-edit-dialog" @close="handleEditClose">
    <form class="dialog-form" method="dialog">
      <header>
        <h2>{{ isEditing ? '编辑用户' : '新增用户' }}</h2>
        <button type="button" aria-label="关闭" @click="closeEditDialog">×</button>
      </header>

      <div class="edit-form-body">
        <!-- 用户名（必填） -->
        <div class="form-group">
          <label for="username">
            用户名 <span class="required">*</span>
          </label>
          <input
            id="username"
            v-model="editForm.username"
            type="text"
            placeholder="请输入用户名"
            :disabled="isEditing"
            autocomplete="off"
          />
        </div>

        <!-- 密码（新增时必填，编辑时可选） -->
        <div class="form-group">
          <label for="password">
            密码 <span class="required">{{ isEditing ? '' : '*' }}</span>
          </label>
          <input
            id="password"
            v-model="editForm.password"
            type="password"
            :placeholder="isEditing ? '留空则不修改密码' : '请输入密码'"
            autocomplete="new-password"
          />
        </div>

        <!-- 真实姓名（可选） -->
        <div class="form-group">
          <label for="realName">真实姓名</label>
          <input
            id="realName"
            v-model="editForm.realName"
            type="text"
            placeholder="请输入真实姓名（可选）"
            autocomplete="off"
          />
        </div>

        <!-- 邮箱（可选） -->
        <div class="form-group">
          <label for="email">邮箱</label>
          <input
            id="email"
            v-model="editForm.email"
            type="email"
            placeholder="请输入邮箱（可选）"
            autocomplete="off"
          />
        </div>

        <!-- 手机号（可选） -->
        <div class="form-group">
          <label for="phone">手机号</label>
          <input
            id="phone"
            v-model="editForm.phone"
            type="tel"
            placeholder="请输入手机号（可选）"
            autocomplete="off"
          />
        </div>

        <!-- 角色选择 -->
        <div class="form-group">
          <label for="userType">角色</label>
          <select id="userType" v-model.number="editForm.userType">
            <option :value="0">普通用户</option>
            <option :value="1">VIP用户</option>
            <option :value="2">管理员</option>
          </select>
        </div>

        <!-- 状态选择（仅编辑时显示） -->
        <div v-if="isEditing" class="form-group">
          <label for="status">状态</label>
          <select id="status" v-model.number="editForm.status">
            <option :value="0">禁用</option>
            <option :value="1">正常</option>
            <option :value="2">锁定</option>
          </select>
        </div>
      </div>

      <footer>
        <button type="button" class="secondary" @click="closeEditDialog">取消</button>
        <button type="button" class="btn-primary" @click="handleSubmitUser" :disabled="submitting">
          {{ submitting ? '提交中...' : (isEditing ? '保存' : '创建') }}
        </button>
      </footer>
    </form>
  </dialog>

  <!-- 删除确认弹窗（绝对定位浮层，确保在对话框最上层） -->
  <Transition name="confirm-fade">
    <div
      v-if="showConfirm"
      class="confirm-overlay"
      @click.self="closeConfirmDialog"
    >
      <div class="confirm-box">
        <header class="confirm-header">
          <h3>⚠️ 确认删除</h3>
          <button type="button" class="confirm-close" @click="closeConfirmDialog">×</button>
        </header>

        <div class="confirm-body">
          <p class="confirm-message">
            确定要删除用户 <strong>"{{ confirmTarget?.username }}"</strong> 吗？
          </p>
          <p class="confirm-hint">
            注意：此操作为软删除，数据将被标记为已删除但不会物理移除。
          </p>
        </div>

        <footer class="confirm-footer">
          <button type="button" class="secondary" @click="closeConfirmDialog">取消</button>
          <button type="button" class="btn-danger" @click="confirmDelete">确认删除</button>
        </footer>
      </div>
    </div>
  </Transition>
</template>

<script setup>
import { reactive, ref, computed, watch } from 'vue'
import {
  fetchUserList,
  createUser,
  updateUser,
  deleteUser,
} from '../api'
import { lockScroll, unlockScroll } from '../utils/scrollLock'

// ==================== 组件属性和事件 ====================
const props = defineProps({
  open: Boolean, // 对话框是否打开
})

const emit = defineEmits(['close', 'success', 'error']) // 关闭、成功、错误事件

// ==================== 对话框引用 ====================
const dialogRef = ref(null) // 主对话框引用
const editDialogRef = ref(null) // 编辑对话框引用

// ==================== 数据状态 ====================
const loading = ref(false) // 列表加载状态
const submitting = ref(false) // 提交状态（新增/编辑）
const deleting = ref(false) // 删除操作加载状态
const userList = ref([]) // 用户列表数据
const isEditing = ref(false) // 是否处于编辑模式
const editingUserId = ref(null) // 正在编辑的用户ID

// 计算属性：是否有任何操作正在执行（用于显示全局加载遮罩）
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 showConfirm = ref(false) // 确认弹窗显示状态
const confirmTarget = ref(null) // 待删除的目标用户对象
const isModeSwitching = ref(false) // 标记是否正在切换dialog模式（防止误触发关闭事件）

// 搜索表单
const searchForm = reactive({
  username: '', // 用户名关键词
  status: '', // 状态筛选
  userType: '', // 角色筛选
})

// 分页参数
const pagination = reactive({
  pageNo: 1, // 当前页码
  pageSize: 10, // 每页条数
  total: 0, // 总记录数
})

// 编辑表单（新增/编辑共用）
const editForm = reactive({
  username: '', // 用户名
  password: '', // 密码
  realName: '', // 真实姓名
  email: '', // 邮箱
  phone: '', // 手机号
  userType: 0, // 角色：0=普通, 1=VIP, 2=管理员
  status: 1, // 状态：0=禁用, 1=正常, 2=锁定
})

// ==================== 计算属性 ====================
/**
 * 计算总页数
 */
const totalPages = computed(() => {
  return Math.ceil(pagination.total / pagination.pageSize) || 1
})

// ==================== 对话框控制方法 ====================
/**
 * 关闭主对话框
 */
function closeDialog() {
  dialogRef.value?.close()
}

/**
 * 关闭编辑对话框
 */
function closeEditDialog() {
  editDialogRef.value?.close()
}

/**
 * 处理主对话框关闭事件
 * 注意：当 isModeSwitching 为 true 时，说明是模式切换（showModal↔show）触发的 close，
 * 不是用户主动关闭，此时不应该 emit close 事件
 */
function handleClose() {
  // 如果正在切换模式，不触发真正的关闭事件
  if (isModeSwitching.value) return
  unlockScroll()
  emit('close')
}

/**
 * 处理编辑对话框关闭事件
 */
function handleEditClose() {
  resetEditForm()
}

// ==================== 确认弹窗控制方法 ====================

/**
 * 关闭确认弹窗并恢复主dialog为modal模式
 */
function closeConfirmDialog() {
  showConfirm.value = false
  confirmTarget.value = null
  // 恢复主dialog为showModal模式
  restoreMainDialog()
}

/**
 * 打开删除确认弹窗
 * 核心技巧：先将主dialog从modal切换为普通mode，
 * 这样confirm弹窗的z-index才能生效覆盖主dialog
 * @param {Object} user - 要删除的用户对象
 */
function openConfirmDialog(user) {
  confirmTarget.value = user
  showConfirm.value = true

  // 关键步骤：将主dialog从showModal()改为show()
  // showModal()会创建浏览器Top Layer，导致任何z-index都无法覆盖
  // 改用show()后，dialog变为普通元素，z-index可以正常工作
  if (dialogRef.value?.open) {
    // 设置模式切换标志，防止close事件误触发父组件关闭
    isModeSwitching.value = true
    // 先关闭当前状态（无论是modal还是非modal）
    dialogRef.value.close()
    // 立即以非modal方式重新打开（不创建Top Layer）
    dialogRef.value.show()
    // 延迟重置标志位（确保 close 事件处理完毕）
    setTimeout(() => {
      isModeSwitching.value = false
    }, 50)
  }
}

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

  const targetUser = confirmTarget.value

  // 先隐藏确认弹窗
  showConfirm.value = false
  confirmTarget.value = null

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

  try {
    await deleteUser(targetUser.id)
    emit('success', `用户 "${targetUser.username}" 已删除`)

    // 如果当前页没有数据了且不是第一页，则回到上一页
    if (userList.value.length === 1 && pagination.pageNo > 1) {
      loadUserList(pagination.pageNo - 1)
    } else {
      loadUserList(pagination.pageNo)
    }
  } 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 = ''

    // 策略1：根据后端返回的消息内容智能匹配
    if (serverMessage) {
      if (serverMessage.includes('不存在') || serverMessage.includes('已被删除') || serverMessage.includes('未找到')) {
        errorMessage = serverMessage
      } else if (serverMessage.includes('权限') || serverMessage.includes('无权')) {
        errorMessage = serverMessage
      } else {
        errorMessage = serverMessage  // 其他情况直接使用后端消息
      }
    }

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

    emit('error', `删除用户失败：${errorMessage}`)
  } finally {
    // 无论成功失败，都关闭加载状态并恢复主dialog
    deleting.value = false
    restoreMainDialog()
  }
}

/**
 * 恢复主dialog为showModal模式
 * 确保用户管理对话框始终可见且具有模态效果
 */
function restoreMainDialog() {
  if (dialogRef.value && dialogRef.value.open) {
    // 设置模式切换标志，防止close事件误触发父组件关闭
    isModeSwitching.value = true
    // 先关闭当前的非modal状态
    dialogRef.value.close()
    // 使用 requestAnimationFrame 确保 DOM 更新完成后再打开
    requestAnimationFrame(() => {
      if (dialogRef.value && !dialogRef.value.open) {
        dialogRef.value.showModal()
      }
      // 延迟重置标志位
      setTimeout(() => {
        isModeSwitching.value = false
      }, 50)
    })
  }
}

// ==================== 数据加载方法 ====================
/**
 * 加载用户列表数据
 * @param {number} [page=1] - 要加载的页码
 */
async function loadUserList(page = 1) {
  loading.value = true
  try {
    // 构建查询参数
    const params = {
      pageNo: page,
      pageSize: pagination.pageSize,
    }
    
    // 只有非空值才加入查询参数
    if (searchForm.username.trim()) {
      params.username = searchForm.username.trim()
    }
    if (searchForm.status !== '') {
      params.status = searchForm.status
    }
    if (searchForm.userType !== '') {
      params.userType = searchForm.userType
    }

    // 调用API获取用户列表
    const res = await fetchUserList(params)
    
    if (res.code === 200 && res.data) {
      userList.value = res.data.list || []
      pagination.total = res.data.total || 0
      pagination.pageNo = res.data.pageNo || page
    } else {
      console.error('获取用户列表失败', res)
      userList.value = []
      pagination.total = 0
      // 显示后端返回的错误信息（优先使用后端原始消息）
      const errorMsg = res?.message || res?.msg || `获取用户列表失败 [Code: ${res?.code || '未知'}]`
      emit('error', errorMsg)
    }
  } catch (err) {
    console.error('加载用户列表出错', err)
    userList.value = []
    pagination.total = 0

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

    let errorMessage = ''

    // 策略1：根据后端返回的消息内容智能匹配
    if (serverMessage) {
      if (serverMessage.includes('权限') || serverMessage.includes('无权')) {
        errorMessage = serverMessage
      } else if (serverMessage.includes('登录') || serverMessage.includes('Token') || serverMessage.includes('认证')) {
        errorMessage = serverMessage
      } else {
        errorMessage = serverMessage  // 其他情况直接使用后端消息
      }
    }

    // 策略2：兜底使用错误码映射
    if (!errorMessage) {
      const errorMessages = {
        401: '登录已过期或 Token 无效，请重新登录',
        403: '权限不足：非管理员无法查看用户列表',
        500: '服务器繁忙，请稍后重试',
      }
      errorMessage = errorMessages[errorCode] || `加载用户列表失败 [错误码:${errorCode}]`
    }

    emit('error', errorMessage)
  } finally {
    loading.value = false
  }
}

// ==================== 搜索和分页方法 ====================
/**
 * 执行搜索操作（从第一页开始）
 */
function handleSearch() {
  pagination.pageNo = 1
  loadUserList(1)
}

/**
 * 重置搜索条件并重新加载
 */
function handleResetSearch() {
  searchForm.username = ''
  searchForm.status = ''
  searchForm.userType = ''
  pagination.pageNo = 1
  loadUserList(1)
}

/**
 * 切换页码
 * @param {number} page - 目标页码
 */
function handlePageChange(page) {
  if (page < 1 || page > totalPages.value) return
  loadUserList(page)
}

// ==================== 用户新增/编辑方法 ====================
/**
 * 打开新增用户对话框
 */
function handleAddUser() {
  isEditing.value = false
  editingUserId.value = null
  resetEditForm()
  editDialogRef.value?.showModal()
}

/**
 * 打开编辑用户对话框
 * @param {Object} user - 要编辑的用户对象
 */
function handleEditUser(user) {
  isEditing.value = true
  editingUserId.value = user.id
  
  // 将用户数据填充到表单
  editForm.username = user.username || ''
  editForm.password = '' // 编辑时密码留空
  editForm.realName = user.realName || ''
  editForm.email = user.email || ''
  editForm.phone = user.phone || ''
  editForm.userType = user.userType ?? 0
  editForm.status = user.status ?? 1
  
  editDialogRef.value?.showModal()
}

/**
 * 重置编辑表单为初始状态
 */
function resetEditForm() {
  editForm.username = ''
  editForm.password = ''
  editForm.realName = ''
  editForm.email = ''
  editForm.phone = ''
  editForm.userType = 0
  editForm.status = 1
}

/**
 * 提交用户表单（新增或编辑）
 */
async function handleSubmitUser() {
  // 表单验证：用户名必填
  if (!editForm.username.trim()) {
    emit('error', '请输入用户名')
    return
  }

  // 新增模式：密码必填
  if (!isEditing.value && !editForm.password.trim()) {
    emit('error', '请输入密码')
    return
  }

  submitting.value = true
  try {
    if (isEditing.value) {
      // ========== 编辑模式 ==========
      const updateData = {
        realName: editForm.realName.trim(),
        email: editForm.email.trim(),
        phone: editForm.phone.trim(),
        userType: editForm.userType,
        status: editForm.status,
      }
      
      await updateUser(editingUserId.value, updateData)
      emit('success', `用户 "${editForm.username}" 已更新`)
    } else {
      // ========== 新增模式 ==========
      await createUser({
        username: editForm.username.trim(),
        password: editForm.password,
        realName: editForm.realName.trim(),
        email: editForm.email.trim(),
        phone: editForm.phone.trim(),
        userType: editForm.userType,
        status: editForm.status,
      })
      emit('success', `用户 "${editForm.username}" 已创建`)
    }

    // 关闭编辑对话框并刷新列表
    closeEditDialog()
    loadUserList(pagination.pageNo)
  } catch (err) {
    console.error('保存用户失败', err)

    // ========== 智能错误信息展示 ==========
    // 优先级：后端message > 基于消息内容匹配 > 错误码映射 > 默认提示
    const errorCode = err.code || err.status || 0
    const httpStatus = err.status || '-'
    const serverMessage = (err.payload?.message || err.payload?.msg || err.message || '').trim()

    let errorMessage = ''

    // 策略1：根据后端返回的具体消息内容进行智能匹配（最准确）
    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
      }
      // 登录/Token相关
      else if (serverMessage.includes('登录') || serverMessage.includes('Token') || serverMessage.includes('认证') || serverMessage.includes('未授权')) {
        errorMessage = serverMessage
      }
      // 其他情况：直接使用后端消息
      else {
        errorMessage = serverMessage
      }
    }

    // 策略2：如果没有后端消息或消息为空，使用错误码映射作为兜底
    if (!errorMessage) {
      const errorMessages = {
        400: '请求参数有误：请检查必填字段',
        401: '登录已过期或 Token 无效，请重新登录',
        403: '权限不足：非管理员无法执行此操作',
        404: '目标用户不存在或已被删除',
        409: '创建失败：该用户名已被占用',
        500: '服务器繁忙，请稍后重试',
      }
      errorMessage = errorMessages[errorCode] || `操作失败 [错误码:${errorCode}]`
    }

    // 弹窗展示完整错误信息（包含HTTP状态码和业务码便于调试）
    emit('error', `${isEditing.value ? '更新' : '创建'}用户失败：${errorMessage}`)
  } finally {
    submitting.value = false
  }
}

// ==================== 用户删除方法 ====================
/**
 * 删除用户（打开确认对话框）
 * @param {Object} user - 要删除的用户对象
 */
function handleDeleteUser(user) {
  // 使用自定义确认对话框替代 window.confirm（避免被dialog遮挡）
  openConfirmDialog(user)
}

// ==================== 辅助方法 ====================
/**
 * 获取角色类型标签文本
 * @param {number} userType - 角色类型代码
 * @returns {string} 角色名称
 */
function getUserTypeLabel(userType) {
  const labels = {
    0: '普通用户',
    1: 'VIP用户',
    2: '管理员',
  }
  return labels[userType] || '未知'
}

/**
 * 获取状态标签文本
 * @param {number} status - 状态代码
 * @returns {string} 状态名称
 */
function getStatusLabel(status) {
  const labels = {
    0: '禁用',
    1: '正常',
    2: '锁定',
  }
  return labels[status] || '未知'
}

// ==================== 监听器 ====================
/**
 * 监听对话框打开状态，自动加载数据
 */
watch(
  () => props.open,
  (value) => {
    if (!dialogRef.value) return
    
    if (value && !dialogRef.value.open) {
      // 打开对话框时，重置搜索条件并加载第一页数据
      dialogRef.value.showModal()
      lockScroll()
      handleResetSearch()
    }
    if (!value && dialogRef.value.open) {
      dialogRef.value.close()
      unlockScroll()
    }
  },
)
</script>

<!-- ==================== 样式部分 ==================== -->
<style scoped>
/* ====== 主容器样式 ====== */
.user-manage-dialog {
  width: 95vw;
  max-width: 1200px;
  height: 85vh;
}

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

/* ====== 工具栏样式 ====== */
.user-manage-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.search-filters {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.filter-input,
.filter-select {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
  min-width: 120px;
}

.filter-input:focus,
.filter-select:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.btn-search {
  padding: 8px 16px;
  border: 1px solid #409eff; /* 蓝色边框 */
  border-radius: 4px;
  background: #fff;
  color: #409eff; /* 蓝色文字，确保可见 */
  cursor: pointer;
  font-size: 14px;
  font-weight: 500; /* 加粗让文字更清晰 */
  transition: all 0.2s;
}

.btn-reset {
  padding: 8px 16px;
  border: 1px solid #a52a2a; /* 暗红色边框 */
  border-radius: 4px;
  background: #fff;
  color: #a52a2a; /* 暗红色文字 */
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s;
}

.btn-search:hover {
  background: #409eff; /* 悬停时蓝色背景 */
  color: #fff; /* 白色文字 */
}

.btn-reset:hover {
  background: #a52a2a; /* 暗红色背景 */
  color: #fff; /* 白色文字 */
}

.btn-primary {
  padding: 8px 20px;
  background: #409eff;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: background 0.2s;
}

.btn-primary:hover {
  background: #66b1ff;
}

.btn-primary:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* ====== 表格样式 ====== */
.user-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  overflow-x: auto;
  display: block;
}

.user-table thead,
.user-table tbody,
.user-table tr {
  display: table;
  width: 100%;
  table-layout: fixed;
}

.user-table th,
.user-table td {
  padding: 12px 8px;
  text-align: left;
  border-bottom: 1px solid #ebeef5;
  word-wrap: break-word;
}

.user-table th {
  background: #f5f7fa;
  font-weight: 600;
  color: #606266;
}

.user-table tbody tr:hover {
  background: #f5f7fa;
}

/* 角色徽章样式 */
.role-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
}

.role-0 {
  background: #e6f0ff;
  color: #409eff; /* 普通用户 - 蓝色 */
}

.role-1 {
  background: #fff6e6;
  color: #e6a23c; /* VIP用户 - 橙色 */
}

.role-2 {
  background: #f0e6ff;
  color: #909399; /* 管理员 - 紫色 */
}

/* 状态徽章样式 */
.status-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
}

.status-0 {
  background: #fef0f0;
  color: #f56c6c; /* 禁用 - 红色 */
}

.status-1 {
  background: #f0f9eb;
  color: #67c23a; /* 正常 - 绿色 */
}

.status-2 {
  background: #f4f4f5;
  color: #909399; /* 锁定 - 灰色 */
}

/* 操作列样式 */
.action-cell {
  white-space: nowrap;
}

.btn-edit,
.btn-delete {
  padding: 4px 12px;
  margin-right: 6px;
  border: 1px solid;
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
  font-size: 13px;
  transition: all 0.2s;
}

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

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

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

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

/* ====== 分页样式 ====== */
.pagination-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 0;
  border-top: 1px solid #ebeef5;
  margin-top: auto;
}

.pagination-info {
  color: #909399;
  font-size: 13px;
}

.pagination-controls {
  display: flex;
  gap: 8px;
}

.pagination-controls button {
  padding: 6px 16px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
  font-size: 13px;
  transition: all 0.2s;
}

.pagination-controls button:hover:not(:disabled) {
  color: #409eff;
  border-color: #409eff;
}

.pagination-controls button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

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

/* ====== 全局加载遮罩层 ====== */
/* 覆盖整个对话框内容区域，显示旋转动画和提示文字 */
.global-loading-overlay {
  position: absolute; /* 相对于 user-manage-body 定位 */
  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; /* 与对话框圆角一致 */
}

/* 加载动画容器：垂直居中显示spinner和文字 */
.loading-spinner-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

/* CSS旋转动画 - 使用border技巧创建圆形loading指示器 */
.spinner {
  width: 48px;
  height: 48px;
  border: 4px solid #e4e7ed; /* 浅灰色底圈 */
  border-top-color: #409eff;   /* 蓝色顶部（旋转时可见） */
  border-radius: 50%;          /* 圆形 */
  animation: spin 0.8s linear infinite; /* 线性匀速旋转动画 */
}

/* 旋转关键帧定义：从0度转到360度 */
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* 加载提示文字样式 */
.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;
}

/* ====== 编辑对话框样式 ====== */
.user-edit-dialog {
  width: 480px;
  max-width: 90vw;
}

.edit-form-body {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

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

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

.form-group input,
.form-group select {
  padding: 10px 12px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  font-size: 14px;
  transition: border-color 0.2s;
}

.form-group input:focus,
.form-group select:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

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

/* ====== 确认弹窗样式（使用:global确保fixed定位元素样式正确） ====== */
:global(.confirm-overlay) {
  position: fixed; /* 使用fixed定位脱离文档流 */
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2147483647; /* 使用最大z-index值，确保在所有元素之上 */
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.6); /* 半透明黑色遮罩（稍深一点） */
}

:global(.confirm-box) {
  width: 420px;
  max-width: 90vw;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
  overflow: hidden;
  animation: confirm-scale-in 0.2s ease-out;
}

@keyframes confirm-scale-in {
  from {
    opacity: 0;
    transform: scale(0.9) translateY(-10px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

:global(.confirm-header) {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #ebeef5;
  background: #fafafa;
}

:global(.confirm-header h3) {
  margin: 0;
  font-size: 16px;
  color: #303133;
}

:global(.confirm-close) {
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
  font-size: 20px;
  color: #909399;
  cursor: pointer;
  border-radius: 4px;
  line-height: 1;
  transition: all 0.2s;
}

:global(.confirm-close:hover) {
  background: #f5f7fa;
  color: #303133;
}

:global(.confirm-body) {
  padding: 24px 20px;
  text-align: center;
}

:global(.confirm-message) {
  font-size: 16px;
  color: #303133;
  margin-bottom: 12px;
  line-height: 1.6;
}

:global(.confirm-message strong) {
  color: #f56c6c; /* 用户名用红色高亮 */
}

:global(.confirm-hint) {
  font-size: 13px;
  color: #909399;
  line-height: 1.5;
}

:global(.confirm-footer) {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 16px 20px;
  border-top: 1px solid #ebeef5;
  background: #fafafa;
}

:global(.btn-danger) {
  padding: 8px 20px;
  background: #f56c6c; /* 危险操作红色按钮 */
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s;
}

:global(.btn-danger:hover) {
  background: #f78989; /* 悬停时稍浅的红色 */
}

/* 确认弹窗淡入淡出过渡动画 */
.confirm-fade-enter-active,
.confirm-fade-leave-active {
  transition: opacity 0.25s ease;
}

.confirm-fade-enter-from,
.confirm-fade-leave-to {
  opacity: 0;
}
</style>
