<script setup lang="ts">
import type { FilterState } from '~/components/FilterBar.vue'
import { onMounted, ref, watch, computed } from 'vue'
import { onBeforeRouteLeave } from 'vue-router'
import { getUserMajorList, type MajorItem } from '~/service/api/major'
import { saveVolunteer, getVolunteerDetail, type VolunteerItem, type VolunteerInfo } from '~/service/api/volunteer'

// --- 类型定义 ---
type TabKey = 'all' | 'hard' | 'risky' | 'safe' | 'stable' | '本科' | '专科' | '985/211/双一流' | '公办本科' | '民办本科'
type PanelType = 'market' | 'my-volunteers'

interface VolunteerTab {
  key: TabKey
  label: string
  count: number
  max: number
}

interface MajorDetail {
  code: string
  name: string
  prob: number
  batch: string
  score: number // 最低分
  diff: number // 线差
  plan: number // 计划数
  req: string // 选科
  tuition: string
  rulesEnrollProbability: string //录取方式
}

// --- 状态数据 ---
const showSwitchModal = ref(false) // 控制切换方案弹窗显示
const activePlanId = ref('2025121426') // 当前选中的方案ID
// 模拟方案列表数据 (对应截图)
const volunteerPlans = ref([
  {
    id: '2025121426',
    name: '志愿2025121426',
    tag: '手动', // 截图中的橙色标签
    province: '北京',
    artType: '美术与设计类',
    cultureScore: 450,
    cultureSubjects: '物化生',
    artScore: 250,
    updateTime: '2025-12-14 10:33:46',
    status: '有效',
  },
  {
    id: '2025121427',
    name: '志愿2025121427',
    tag: '智能',
    province: '湖北',
    artType: '音乐类',
    cultureScore: 480,
    cultureSubjects: '历史',
    artScore: 240,
    updateTime: '2025-12-13 14:20:00',
    status: '有效',
  },
])

const activePanel = ref<PanelType>('market') // 当前激活的面板
const myVolunteers = ref<VolunteerItem[]>([])
const originalVolunteers = ref<VolunteerItem[]>([]) // 用于对比变动
const currentVolunteerInfo = ref<VolunteerInfo | null>(null)


// 志愿Tab
const volunteerCurrentTab = ref<string>('本科批')
const volunteerTabs = ref([
  { key: '提前批', label: '提前批', count: 0, max: 64 },
  { key: '本科批', label: '本科批', count: 0, max: 64 },
  { key: '专科批', label: '专科批', count: 0, max: 64 },
]) as any


//============= Panel A 数据

// 批次Tab
const currentBatchTab = ref<TabKey>('本科')
const batchTabs = [
  { key: '本科提前', label: '本科提前批', count: 0 },
  { key: '本科', label: '本科批', count: 0 },
  { key: '高职高专', label: '高职批', count: 0 },
] as VolunteerTab[]

// 二级批次Tab
const currentBatch2Tab = ref<TabKey>('公办本科')
const batch2Tabs = [
  { key: '双一流', label: '985/211/双一流', count: 0 },
  { key: '公办本科', label: '公办本科', count: 0 },
  { key: '民办本科', label: '民办本科', count: 0 },
] as VolunteerTab[]




// 概率Tab
const currentProbTab = ref<TabKey>('all')
const probTabs = [
  { key: 'all', label: '全部', count: 0 },
  { key: 'safe', label: '可保底', count: 1 },
  { key: 'stable', label: '较稳妥', count: 11 },
  { key: 'risky', label: '可冲击', count: 11 },
  { key: 'hard', label: '难录取', count: 145 },
] as VolunteerTab[]

const oldYears = ref(['2025','2024','2023'])

const schools = ref<MajorItem[]>([]) 
const page = ref(1)
const size = ref(10)
const total = ref(0)
const isLoading = ref(false)
const isFinished = ref(false)
const scrollContainer = ref<HTMLElement | null>(null)

// 弹窗相关状态
const showModal = ref(false)
const currentSchool = ref<MajorItem | null>(null)
const modalLoading = ref(false)
const modalMajors = ref<MajorDetail[]>([])

// 选课/志愿相关状态
const selectedMajorCodes = ref<string[]>([]) // 存储已选的专业Code，数组顺序即为志愿顺序
const showSaveConfirm = ref(false) // 控制气泡确认框显示
const isSaving = ref(false) // 保存接口Loading状态


//============= Panel A 数据
// --- 辅助函数 ---
function getProbabilityLabel(prob: number): string {
  if (prob >= 93) return '保'
  if (prob >= 73) return '稳'
  if (prob >= 60) return '冲'
  return '难'
}

function getStatusColor(status: string) {
  switch (status) {
    case '保':
      return 'border-green-500 text-green-600 bg-green-50'
    case '稳':
      return 'border-blue-500 text-blue-600 bg-blue-50'
    case '冲':
      return 'border-orange-500 text-orange-500 bg-orange-50'
    default:
      return 'border-gray-400 text-gray-400 bg-gray-50'
  }
}

// --- 数据加载逻辑 ---
async function loadMore(reset = false) {
  if (isLoading.value) return
  if (!reset && isFinished.value) return

  isLoading.value = true
  if (reset) {
    page.value = 1
    schools.value = []
    isFinished.value = false
  }

  try {
    // 映射 Tab 到 API 参数
    let probability: string | undefined
    if (currentProbTab.value === 'hard') probability = '难录取'
    if (currentProbTab.value === 'risky') probability = '可冲击'
    if (currentProbTab.value === 'stable') probability = '较稳妥'
    if (currentProbTab.value === 'safe') probability = '可保底'
    
    const res = await getUserMajorList({
      page: page.value,
      size: size.value,
      probability,
      batch: currentBatchTab.value,
      batch2: currentBatch2Tab.value,
    })
    console.warn(res)
    if (res && res.list && res.list.items) {
      schools.value.push(...res.list.items)
      total.value = res.total
      
      // 更新 Tabs 计数
      if (res.list.probCount) {
        probTabs.forEach(tab => {
          if (tab.key && tab.key == 'all'){
            tab.count = total.value
          }else if (tab.key && res.list.probCount[tab.key] !== undefined) {
            tab.count = res.list.probCount[tab.key]
          }
        })
      }

      if (schools.value.length >= res.total || res.list.items.length < size.value) {
        isFinished.value = true
      } else {
        page.value++
      }
    } else {
      isFinished.value = true
    }
  } catch (error) {
    console.error('Failed to load major list:', error)
    isFinished.value = true
  } finally {
    isLoading.value = false
  }
}

// 监听 Tab 切换，重新加载
watch(currentBatchTab, () => {
  loadMore(true)
})

watch(currentBatch2Tab, () => {
  loadMore(true)
})

watch(currentProbTab, () => {
  loadMore(true)
})

watch(activePanel, (newVal, oldVal) => {
  if (oldVal === 'my-volunteers' && newVal === 'market' && isModified.value) {
    const confirmRevert = window.confirm('您有未保存的志愿变动，切换回模拟填报将恢复初始状态，确认吗？')
    if (confirmRevert) {
      // 恢复数据
      myVolunteers.value = JSON.parse(JSON.stringify(originalVolunteers.value))
    } else {
      // 阻止切换 (由于 watch 是在变化后触发的，这里需要 nextTick 或者特殊处理)
      // 注意：直接修改 activePanel.value 会再次触发 watch，但因为满足 newVal === 'my-volunteers' 不会再次弹窗
      activePanel.value = 'my-volunteers'
    }
  }
})



function handleScroll() {
  if (!scrollContainer.value)
    return
  const { scrollTop, clientHeight, scrollHeight } = scrollContainer.value
  // 距离底部 50px 时触发加载
  if (scrollTop + clientHeight >= scrollHeight - 50) {
    loadMore()
  }
}

// --- 弹窗逻辑 ---
async function openMajorModal(school: MajorItem) {
  currentSchool.value = school
  showModal.value = true
  modalLoading.value = true
  modalMajors.value = []
  // 重置弹窗内的状态
  selectedMajorCodes.value = []
  showSaveConfirm.value = false

  try {
    const res = await getUserMajorList({
      schoolCode: school.schoolCode,
      batch: currentBatchTab.value,
      page: 1,
      size: 100 // 获取该校所有推荐专业
    })
    
    if (res && res.list && res.list.items) {
      modalMajors.value = res.list.items.map(m => ({
        code: m.majorCode,
        name: m.majorName,
        prob: m.enrollProbability,
        score: m.studentScore,
        batch: m.batch != "高职高专" ? "本科": "高职高专",
        rulesEnrollProbability: m.rulesEnrollProbability,
        diff: 0,
        plan: m.planNum,
        req: m.mainSubjects,
        tuition: m.tuition,
        enrollmentCode: m.enrollmentCode // 保持后端原始字段以便拼接
      }))
    }
  } catch (error) {
    console.error('获取学校专业列表失败:', error)
  } finally {
    modalLoading.value = false
  }
}

// 2. 选择/取消专业 (点击行内按钮)
function toggleMajor(major: any) {
  if (!currentSchool.value) return
  
  // 拼接格式: schoolCode_majorCode_enrollmentCode
  const fullCode = `${currentSchool.value.schoolCode}_${major.code}_${major.enrollmentCode || currentSchool.value.enrollmentCode}`
  const index = selectedMajorCodes.value.indexOf(fullCode)
  
  if (index > -1) {
    // 已存在，移除
    selectedMajorCodes.value.splice(index, 1)
  }
  else {
    // 不存在，加入
    selectedMajorCodes.value.push(fullCode)
  }
}

// 获取按钮状态显示文本
function getVolunteerBtnText(major: any) {
  if (!currentSchool.value) return '加入志愿单'
  const fullCode = `${currentSchool.value.schoolCode}_${major.code}_${major.enrollmentCode || currentSchool.value.enrollmentCode}`
  const index = selectedMajorCodes.value.indexOf(fullCode)
  if (index > -1) {
    return `志愿 ${index + 1}`
  }
  return '加入志愿单'
}

/**
 * 获取志愿详情
 */
async function fetchVolunteerDetail() {
  try {
    const res = await getVolunteerDetail()
    if (res && res.volunteer) {
      currentVolunteerInfo.value = res.volunteer
      // 合并所有批次数据用于 Panel B 显示（根据当前 Tab 过滤）
      const allItems: VolunteerItem[] = []
      Object.keys(res.items).forEach(batch => {
        const items = res.items[batch].map(item => ({...item, batchName: batch}))
        allItems.push(...items)
        
        // 更新 Tab 计数
        const tab = volunteerTabs.value.find((t: any) => t.key === batch)
        if (tab) {
          tab.count = res.items[batch].length
        }
      })
      
      myVolunteers.value = allItems
      // 备份原始数据用于变动对比
      originalVolunteers.value = JSON.parse(JSON.stringify(allItems))
    }
  } catch (error) {
    console.error('获取志愿详情失败:', error)
  }
}

/**
 * 过滤后的当前显示志愿（Panel B）
 */
const filteredVolunteers = computed(() => {
  // 根据 volunteerCurrentTab 过滤
  // 直接从 myVolunteers 中过滤出属于该批次的
  // 注意：fetchVolunteerDetail 时我们需要给 item 加上 batch 标识，或者重新设计存储
  return myVolunteers.value.filter(v => (v as any).batchName === volunteerCurrentTab.value)
})

/**
 * 是否修改了志愿列表（拖拽排序或删除）
 */
const isModified = computed(() => {
  if (myVolunteers.value.length !== originalVolunteers.value.length) return true
  // 检查 ID 顺序是否一致
  return myVolunteers.value.some((v, i) => v.id !== originalVolunteers.value[i]?.id)
})

// 3. 保存逻辑
async function saveVolunteers() {
  if (isSaving.value)
    return
  
  const codesToSave = activePanel.value === 'market' 
    ? selectedMajorCodes.value 
    : myVolunteers.value.map(v => `${v.schoolCode}_${v.majorCode}_${v.enrollmentCode}`)

  if (codesToSave.length === 0 && activePanel.value === 'market') {
    // 弹窗中没选专业
    showSaveConfirm.value = false
    return
  }

  isSaving.value = true

  try {
    await saveVolunteer(codesToSave)
    console.warn('保存成功')

    // 成功后刷新详情
    await fetchVolunteerDetail()
    
    // 成功后逻辑
    isSaving.value = false
    showSaveConfirm.value = false
    if (showModal.value) closeModal()
    
    // Toast 提示
    // @ts-ignore
    window.$message?.success?.('保存志愿成功！')
  } catch (error) {
    console.error('保存失败:', error)
    isSaving.value = false
  }
}

// 页面离开保护
onBeforeRouteLeave((to, from, next) => {
  if (isModified.value) {
    const confirmLeave = window.confirm('您有未保存的志愿变动，确定要离开吗？')
    if (confirmLeave) {
      next()
    } else {
      next(false)
    }
  } else {
    next()
  }
})

function closeModal() {
  showModal.value = false
  showSaveConfirm.value = false
}

// 为了节省流量，我们可以加一个简单的判断：只有是 PC 端时才初始加载数据
onMounted(() => {
  // 检查窗口宽度是否大于 1024px
  if (window.innerWidth >= 1024) {
    loadMore()
    fetchVolunteerDetail()
  }

  // 生成一些模拟的“我的志愿”数据
  // const initialVols = generateMockData(5, 1000)
  // // 为了模拟真实志愿，给它们加上自定义的序号或者直接利用数组索引
  // myVolunteers.value = initialVols
  // 监听窗口大小变化（可选：如果用户旋转屏幕或拖拽窗口，动态决定是否加载）
  window.addEventListener('resize', handleResize)
})

function handleResize() {
  // 如果之前没加载过，且现在变宽了，则加载数据
  if (
    window.innerWidth >= 1024
    && schools.value.length === 0
    && !isLoading.value
  ) {
    loadMore()
  }
}

const currentFilters = ref<FilterState | null>(null)
const currentKeyword = ref('')

function handleDataChange(data: { keyword: string, filters: FilterState }) {
  console.warn('发起请求:', data.keyword, data.filters)
  currentKeyword.value = data.keyword
  currentFilters.value = data.filters
}

// 用于记录当前鼠标是否悬停在手柄上，悬停时该行的索引存入这里
const dragEnabledIndex = ref<number | null>(null)
// --- 拖拽排序逻辑 (Panel B) ---
const dragStartIndex = ref<number | null>(null)

function switchVolunteerTab(tabKey: TabKey) {
  volunteerCurrentTab.value = tabKey
}

function handleDragStart(e: DragEvent, index: number) {
  dragStartIndex.value = index
  if (e.dataTransfer) {
    e.dataTransfer.effectAllowed = 'move'
    // 某些浏览器需要设置数据才能拖拽
    e.dataTransfer.setData('text/plain', index.toString())
    // 可选：设置拖拽时的重影图像（使其看起来更好看，不包含多余背景）
    // e.dataTransfer.setDragImage(target.closest('tr') as Element, 0, 0)
  }
}

function handleDragOver(e: DragEvent) {
  // 必须阻止默认行为才能触发 drop
  e.preventDefault()
  if (e.dataTransfer) {
    e.dataTransfer.dropEffect = 'move'
  }
}

function handleDrop(index: number) {
  if (dragStartIndex.value === null || dragStartIndex.value === index)
    return

  const draggedItem = filteredVolunteers.value[dragStartIndex.value]
  const targetItem = filteredVolunteers.value[index]
  
  const realStartIdx = myVolunteers.value.findIndex(v => v.id === draggedItem.id)
  const realTargetIdx = myVolunteers.value.findIndex(v => v.id === targetItem.id)
  
  if (realStartIdx === -1 || realTargetIdx === -1) return

  // 移动数组元素
  const [removed] = myVolunteers.value.splice(realStartIdx, 1)
  myVolunteers.value.splice(realTargetIdx, 0, removed)

  // 触发结束事件
  handleDragEnd()

  dragStartIndex.value = null
}

function handleDragEnd() {
  console.warn('拖拽排序结束，当前志愿顺序ID:', myVolunteers.value.map(v => v.id))
  // 这里可以调用保存接口 API
}

function removeVolunteer(index: number) {
  // index 是在 myVolunteers 中的索引
  myVolunteers.value.splice(index, 1)
}

function handleCreatePlan() {
  console.warn('点击新建方案')
  // 逻辑：弹出新建表单...
}

function handleEditPlan() {
  console.warn('点击修改方案信息')
  // 逻辑：修改当前方案的分数/选科等...
}

function handleSwitchPlan() {
  showSwitchModal.value = true
}

function handleExportPlan() {
  console.warn('点击导出当前方案')
}

// 切换到指定方案
function switchActivePlan(planId: string) {
  activePlanId.value = planId
  showSwitchModal.value = false
  console.warn('切换到了方案:', planId)
  // 逻辑：重新加载 myVolunteers 数据...
  // isLoading.value = true ...
}

function deletePlan(planId: string) {
  console.warn('删除方案:', planId)
  // 逻辑：删除API调用...
}
</script>

<template>
  <div>
    <!-- =========================================================
      1. 移动端提示层 (Phone View)
      逻辑：默认显示 (flex)，在 lg (1024px) 及以上屏幕隐藏
  ========================================================== -->
    <div class="w-full flex flex-col items-center justify-center bg-gray-50 p-8 text-center lg:hidden">
      <div class="max-w-sm w-full rounded-2xl bg-white p-8 shadow-lg">
        <!-- 图标 (手机) -->
        <div class="mx-auto mb-4 h-16 w-16 flex items-center justify-center rounded-full bg-blue-50 text-blue-500">
          <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path
              stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
              d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"
            />
          </svg>
        </div>

        <h3 class="mb-2 text-xl text-slate-800 font-bold">
          请访问小程序
        </h3>
        <p class="mb-6 text-sm text-slate-500 leading-relaxed">
          当前页面包含大量数据表格，<br>为保证最佳体验，请在 PC 端浏览<br>或前往微信小程序查看。
        </p>

        <!-- 模拟一个小程序跳转按钮 -->
        <button
          class="w-full rounded-full bg-blue-600 py-2.5 text-sm text-white font-medium shadow-blue-200 shadow-md transition-colors hover:bg-blue-700"
        >
          打开微信小程序
        </button>
      </div>
    </div>

    <!-- =========================================================
         新增：左侧固定侧边栏
    ========================================================== -->
    <div
      class="fixed left-0 top-24 z-50 hidden w-15 flex-col select-none items-center border-r border-slate-200 rounded-lg bg-white py-8 shadow-lg lg:flex"
    >
      <!-- Logo 占位 -->
      <!-- <div class="mb-8">
        <div class="h-10 w-10 rounded-lg bg-blue-600"></div>
      </div> -->

      <div class="w-full flex flex-col gap-6 px-2">
        <button
          class="group flex flex-col items-center gap-1 rounded-lg p-2 transition-colors"
          :class="activePanel === 'market' ? 'bg-blue-50 text-blue-600' : 'text-slate-500 hover:bg-slate-50'"
          @click="activePanel = 'market'"
        >
          <div
            class="rounded-full p-2"
            :class="activePanel === 'market' ? 'bg-blue-100' : 'bg-slate-100 group-hover:bg-slate-200'"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
              />
            </svg>
          </div>
          <span class="text-xs font-medium">模拟填报</span>
        </button>

        <button
          class="group flex flex-col items-center gap-1 rounded-lg p-2 transition-colors"
          :class="activePanel === 'my-volunteers' ? 'bg-blue-50 text-blue-600' : 'text-slate-500 hover:bg-slate-50'"
          @click="activePanel = 'my-volunteers'"
        >
          <div
            class="relative rounded-full p-2"
            :class="activePanel === 'my-volunteers' ? 'bg-blue-100' : 'bg-slate-100 group-hover:bg-slate-200'"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"
              />
            </svg>
            <!-- 数量角标 -->
            <span
              v-if="myVolunteers.length > 0"
              class="absolute h-5 w-5 flex items-center justify-center rounded-full bg-red-500 text-[10px] text-white -right-1 -top-1"
            >
              {{ myVolunteers.length }}
            </span>
          </div>
          <span class="text-xs font-medium">我的志愿</span>
        </button>
      </div>
    </div>

    <div
      id="bPanel"
      class="mx-auto hidden h-screen max-w-7xl flex-col select-none px-4 text-slate-700 font-sans lg:flex lg:px-8 sm:px-6"
    >
      <!-- =========================================================
           Panel A: 模拟填志愿 (原有的市场列表)
           使用 v-show 控制显示
      ========================================================== -->
      <div v-show="activePanel === 'market'" class="h-full flex flex-col">
        <!-- 顶部筛选栏 (保持不变) -->
        <div class="mt-8 rounded-t-lg bg-white p-6 border-b border-slate-200">
          <div class="grid grid-cols-1 select-none gap-6 lg:grid-cols-6">
            <!-- Top Toolbar -->
            <div class="lg:col-span-4">
              <FilterBar :sort-enabled="false" @change="handleDataChange" />
            </div>
          </div>
        </div>
        <div class="flex flex-shrink-0 space-x-2 justify-between mb-8">
          <div class="flex flex-shrink-0 space-x-2">
            <button
              v-for="tab in batchTabs" :key="tab.key"
              class="border-x border-t border-transparent rounded-b-md px-6 py-2 text-sm font-medium transition-colors duration-200"
              :class="[
                currentBatchTab === tab.key
                  ? 'bg-blue-500 text-white border-blue-500'
                  : 'bg-white text-slate-600 hover:text-blue-500 border-slate-200',
              ]" @click="currentBatchTab = tab.key"
            >
              {{ tab.label }}
            </button>
          </div>

          <div class="flex flex-shrink-0 space-x-2" v-show="currentBatchTab == '本科'">
            <button
              v-for="tab in batch2Tabs" :key="tab.key"
              class="border-x border-t border-transparent rounded-b-md px-6 py-2 text-sm font-medium transition-colors duration-200"
              :class="[
                currentBatch2Tab === tab.key
                  ? 'bg-blue-500 text-white border-blue-500'
                  : 'bg-white text-slate-600 hover:text-blue-500 border-slate-200',
              ]" @click="currentBatch2Tab = tab.key"
            >
              {{ tab.label }}
            </button>
          </div>
        </div>
        

        <div class="flex flex-shrink-0 space-x-2">
          <button
            v-for="tab in probTabs" :key="tab.key"
            class="border-x border-t border-transparent rounded-t-md px-6 py-2 text-sm font-medium transition-colors duration-200"
            :class="[
              currentProbTab === tab.key
                ? 'bg-blue-500 text-white border-blue-500'
                : 'bg-white text-slate-600 hover:text-blue-500 border-slate-200',
            ]" @click="currentProbTab = tab.key"
          >
            {{ tab.label }} <span class="ml-1 opacity-90">{{ tab.count }}</span>
          </button>
        </div>
        

        <!-- 表格容器：限制高度 + 滚动监听 -->
        <!-- 关键点：h-[calc(100vh-150px)] 用于限制高度，overflow-auto 用于滚动 -->
        <div
          ref="scrollContainer"
          class="relative flex-1 h-[calc(100vh-320px)] overflow-auto scroll-smooth border border-slate-200 rounded-b-md bg-white shadow-sm"
          @scroll="handleScroll"
        >
          <table class="relative min-w-[1500px] w-full border-collapse text-sm">
            <!-- 表头 -->
            <thead class="sticky top-0 z-30 bg-slate-50 text-center text-slate-500 font-medium shadow-sm">
              <tr>
                <!-- 左侧冻结列：院校 -->
                <th
                  class="sticky left-0 z-40 w-52 border-r border-slate-200 bg-slate-50 p-4 text-left shadow-[4px_0_8px_-4px_rgba(0,0,0,0.1)]"
                >
                  招生院校
                </th>
                <th class="w-auto border-r border-slate-200 p-4">
                  招生专业
                </th>
                <th class="w-40 border-r border-slate-200 p-2">
                  录取概率
                </th>
                <th class="w-32 border-r border-slate-200 p-2">
                  26省内招生
                </th>
                <!-- 假设中间有很多历年数据列，撑开宽度 -->
                <th class="w-20 border-r border-slate-200 p-2">
                  历年
                </th>
                <th class="w-32 border-r border-slate-200 p-2" v-for="(item) in oldYears" :key="item">
                  {{item}}
                </th>
                <!-- 右侧冻结列：操作 -->
                <th
                  class="sticky right-0 z-40 w-40 border-l border-slate-200 bg-slate-50 p-4 shadow-[-4px_0_8px_-4px_rgba(0,0,0,0.1)]"
                >
                  操作
                </th>
              </tr>
            </thead>

            <!-- 表格内容 -->
            <tbody class="divide-y divide-slate-200">
              <template v-for="school in schools" :key="school.schoolCode + school.majorCode">
                <!-- Row 1 -->
                <tr class="group transition-colors hover:bg-slate-50">
                  <!-- Sticky Left: 院校信息 -->
                  <!-- 注意：bg-white 是为了遮挡滚动的文字，group-hover:bg-slate-50 是为了保持 hover 效果 -->
                  <td
                    rowspan="4"
                    class="sticky left-0 z-20 border-r border-slate-200 bg-white p-4 align-top shadow-[4px_0_8px_-4px_rgba(0,0,0,0.1)] group-hover:bg-slate-50"
                  >
                    <div class="mb-1 w-52 truncate text-left text-base text-slate-900 font-bold" :title="school.schoolName">
                      {{ school.schoolName }}
                    </div>
                    <div class="mb-2 flex flex-wrap gap-1 text-xs text-slate-500">
                      <span v-for="tag in [school.province, school.schoolNature, school.institutionType].filter(Boolean)" :key="tag" class="rounded bg-slate-100 px-1 py-0.5">{{ tag
                      }}</span>
                    </div>
                    <div class="text-left text-xs text-slate-400">
                      代码 {{ school.schoolCode }}
                    </div>
                  </td>

                  <!-- 中间普通滚动列 -->

                  <td rowspan="4" class="border-r border-slate-100 bg-white p-4 align-top group-hover:bg-slate-50">
                    <div class="mb-1 text-slate-900 font-bold">
                      {{ school.majorName }}
                    </div>
                    <div class="mb-1 text-xs text-slate-500">
                      {{ school.limitation }}
                    </div>
                    <div class="mt-2 text-xs text-slate-400">
                      {{ `[${school.enrollmentCode}]` }} {{ school.tuition }}
                    </div>
                  </td>

                  <td
                    rowspan="4"
                    class="border-r border-slate-100 bg-white p-2 text-center align-top group-hover:bg-slate-50"
                  >
                    <div class="mb-2 text-lg font-bold">
                      {{ school.enrollProbability }}%
                    </div>
                    <div class="mb-2 flex justify-center">
                      <div
                        class="h-8 w-8 flex items-center justify-center border-2 rounded-full text-xs font-bold"
                        :class="getStatusColor(getProbabilityLabel(school.enrollProbability))"
                      >
                        {{ getProbabilityLabel(school.enrollProbability) }}
                      </div>
                    </div>
                    <div class="mb-2 flex justify-center">
                      折合分：{{school.studentScore}}
                    </div>
                  </td>

                  <td
                    rowspan="4"
                    class="border-r border-slate-100 bg-white p-2 text-center align-top group-hover:bg-slate-50"
                  >
                    <div class="text-lg font-medium">
                      {{ school.planNum }}人
                    </div>
                  </td>

                  <!-- 历年数据区域 (横向较宽) -->
                  <td
                    class="h-10 border-r border-slate-100 bg-slate-50/50 px-2 py-2 text-center text-xs text-slate-500"
                  >
                    招生人数
                  </td>
                  <td class="border-r border-slate-100 px-2 py-2 text-center text-sm" v-for="year in oldYears" :key="year">
                    {{ school.historyMajorEnrollMap?.[year]?.enrollmentCount || "-" }}
                  </td>
                  <!-- Sticky Right: 操作 -->
                  <td
                    rowspan="4"
                    class="sticky right-0 z-20 border-l border-slate-200 bg-white p-4 text-center align-middle shadow-[-4px_0_8px_-4px_rgba(0,0,0,0.1)] group-hover:bg-slate-50"
                  >
                    <button
                      class="whitespace-nowrap border border-blue-500 rounded-full bg-white px-3 py-1.5 text-xs text-blue-500 transition-colors hover:bg-blue-50"
                      @click="openMajorModal(school)"
                    >
                      查看可选专业
                    </button>
                  </td>
                </tr>

                <!-- Row 2: 最低分数 -->
                <tr class="group hover:bg-slate-50">
                  <td
                    class="h-10 border-r border-slate-100 bg-slate-50/50 px-2 py-2 text-center text-xs text-slate-500"
                  >
                    最低分数
                  </td>
                  <td class="border-r border-slate-100 px-2 py-2 text-center text-sm font-medium" v-for="year in oldYears" :key="year">
                    {{ school.historyMajorEnrollMap?.[year]?.admissionLine || "-" }}
                  </td>
                </tr>

                <!-- Row 3: 历年线差 -->
                <tr class="group hover:bg-slate-50">
                  <td
                    class="h-10 border-r border-slate-100 bg-slate-50/50 px-2 py-2 text-center text-xs text-slate-500"
                  >
                    历年线差
                  </td>
                  <td class="border-r border-slate-100 px-2 py-2 text-center text-sm" v-for="year in oldYears" :key="year">
                    {{ (school.historyMajorEnrollMap?.[year]?.admissionLine && school.historyMajorEnrollMap?.[year]?.controlLine) 
                       ? (school.historyMajorEnrollMap[year].admissionLine - school.historyMajorEnrollMap[year].controlLine).toFixed(1) 
                       : "-" }}
                  </td>
                </tr>

                <!-- Row 4: 录取方式 -->
                <tr class="group border-b border-slate-200 hover:bg-slate-50">
                  <td
                    class="h-10 border-r border-slate-100 bg-slate-50/50 px-2 py-2 text-center text-xs text-slate-500"
                  >
                    录取方式
                  </td>
                  <td class="border-r border-slate-100 px-2 py-2 text-center text-xs text-slate-600" v-for="year in oldYears" :key="year">
                    {{ school.historyMajorEnrollMap?.[year]?.rulesEnrollProbability || "-" }}
                  </td>
                </tr>
              </template>

              <!-- 加载状态条 -->
              <tr v-if="isLoading || isFinished">
                <td colspan="100%" class="sticky left-0 bg-slate-50 p-4 text-center text-sm text-slate-500">
                  <span v-if="isLoading" class="flex items-center justify-center gap-2">
                    <svg
                      class="h-5 w-5 animate-spin text-blue-500" xmlns="http://www.w3.org/2000/svg" fill="none"
                      viewBox="0 0 24 24"
                    >
                      <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
                      <path
                        class="opacity-75" fill="currentColor"
                        d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
                      />
                    </svg>
                    正在加载更多数据...
                  </span>
                  <span v-else-if="isFinished">没有更多数据了</span>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>

      <!-- =========================================================
           Panel B: 我的志愿表 (新增)
           v-show="activePanel === 'my-volunteers'"
      ========================================================== -->
      <div v-show="activePanel === 'my-volunteers'" class="h-full flex flex-col animate-fade-in-up">
        <div
          class="mb-6 mt-8 flex flex-col gap-4 rounded-lg bg-white p-6 shadow lg:flex-row lg:items-center lg:justify-between"
        >
          <!-- 左侧：标题与统计 -->
          <div>
            <div class="flex items-center gap-3">
              <h2 class="text-2xl text-slate-800 font-bold">
                {{ volunteerPlans.find(p => p.id === activePlanId)?.name || '未命名方案' }}
              </h2>
              <span class="border border-orange-100 rounded bg-orange-50 px-2 py-0.5 text-xs text-orange-500">
                {{ volunteerPlans.find(p => p.id === activePlanId)?.tag || '手动' }}
              </span>
            </div>
            <p class="mt-2 text-sm text-slate-500">
              拖拽左侧手柄可调整顺序，共 <span class="text-blue-600 font-bold">{{ myVolunteers.length }}</span> 个志愿
            </p>
          </div>

          <!-- 右侧：功能按钮组 -->
          <div class="flex flex-wrap items-center gap-3">
            <!-- 新建 -->
            <button
              class="flex items-center gap-1.5 border border-transparent rounded-md px-3 py-2 text-sm text-slate-600 transition-colors hover:border-slate-200 hover:bg-slate-50 hover:text-blue-600"
              @click="handleCreatePlan"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
              </svg>
              新建
            </button>

            <!-- 修改 -->
            <button
              class="flex items-center gap-1.5 border border-transparent rounded-md px-3 py-2 text-sm text-slate-600 transition-colors hover:border-slate-200 hover:bg-slate-50 hover:text-blue-600"
              @click="handleEditPlan"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                  d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
                />
              </svg>
              修改
            </button>

            <!-- 切换 (点击触发弹窗) -->
            <button
              class="flex items-center gap-1.5 border border-transparent rounded-md px-3 py-2 text-sm text-slate-600 transition-colors hover:border-slate-200 hover:bg-slate-50 hover:text-blue-600"
              @click="handleSwitchPlan"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                  d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"
                />
              </svg>
              切换
            </button>

            <!-- 导出 -->
            <button
              class="flex items-center gap-1.5 border border-transparent rounded-md px-3 py-2 text-sm text-slate-600 transition-colors hover:border-slate-200 hover:bg-slate-50 hover:text-blue-600"
              @click="handleExportPlan"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                  d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
                />
              </svg>
              导出
            </button>

            <!-- 提交按钮 (突出显示) -->
            <div class="mx-1 h-6 w-px bg-slate-200" />
            <button
              :disabled="!isModified || isSaving"
              class="ml-1 rounded bg-blue-600 px-5 py-2 text-sm text-white font-medium shadow-md transition-all active:scale-95 hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
              @click="saveVolunteers"
            >
              <span v-if="isSaving" class="mr-1 inline-block h-3 w-3 animate-spin border-2 border-white/30 border-t-white rounded-full"></span>
              提交志愿表
            </button>
          </div>
        </div>

        <div class="flex flex-shrink-0 space-x-2">
          <button
            v-for="tab in volunteerTabs" :key="tab.key"
            class="border-x border-t border-transparent rounded-t-md px-6 py-2 text-sm font-medium transition-colors duration-200"
            :class="[
              volunteerCurrentTab === tab.key
                ? 'bg-blue-500 text-white border-blue-500'
                : 'bg-white text-slate-600 hover:text-blue-500 border-slate-200',
            ]" @click="switchVolunteerTab(tab.key)"
          >
            {{ tab.label }} <span class="ml-1 opacity-90">({{ `${tab.count}/${tab.max}` }})</span>
          </button>
        </div>
        <div
          class="relative flex-1 overflow-auto scroll-smooth border border-slate-200 rounded-b-md bg-white shadow-sm"
        >
          <table class="w-full border-collapse text-sm">
            <thead class="sticky top-0 z-30 bg-slate-50 text-slate-500 font-medium shadow-sm">
              <tr>
                <th class="w-16 border-r border-slate-200 p-4 text-center">
                  排序
                </th>
                <th class="w-20 border-r border-slate-200 p-4 text-center">
                  序号
                </th>
                <th class="border-r border-slate-200 p-4 text-left">
                  院校信息
                </th>
                <th class="border-r border-slate-200 p-4 text-left">
                  专业信息
                </th>
                <th class="border-r border-slate-200 p-4 text-center">
                  概率/分数
                </th>
                <th class="border-r border-slate-200 p-4 text-center">
                  25省内招生
                </th>
                <th class="w-32 p-4 text-center">
                  操作
                </th>
              </tr>
            </thead>
            <tbody class="divide-y divide-slate-200">
              <tr
                v-for="(vol, index) in filteredVolunteers" :key="vol.id"
                class="group bg-white transition-colors hover:bg-slate-50" :draggable="dragEnabledIndex === index"
                @dragstart="handleDragStart($event, index)" @dragover="handleDragOver($event)"
                @drop="handleDrop(index)"
              >
                <!-- 拖拽手柄列 -->
                <td
                  class="cursor-move cursor-move border-r border-slate-200 p-4 text-center text-slate-400 active:text-blue-700 hover:text-blue-500" @mouseenter="dragEnabledIndex = index"
                  @mouseleave="dragEnabledIndex = null"
                >
                  <svg
                    xmlns="http://www.w3.org/2000/svg" class="pointer-events-none mx-auto h-6 w-6" fill="none"
                    viewBox="0 0 24 24" stroke="currentColor"
                  >
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8h16M4 16h16" />
                  </svg>
                </td>

                <!-- 志愿序号 -->
                <td class="border-r border-slate-200 p-4 text-center text-lg text-slate-500 font-bold">
                  {{ index + 1 }}
                </td>

                <!-- 院校信息 -->
                <td class="border-r border-slate-200 p-4 text-left">
                  <div class="text-base text-slate-900 font-bold">
                    {{ vol.schoolName }}
                  </div>
                  <div class="mt-1 flex gap-2">
                    <span
                      v-for="tag in (vol.tags || [vol.province, vol.schoolNature].filter(Boolean))" :key="tag"
                      class="rounded bg-slate-100 px-1.5 py-0.5 text-xs text-slate-500"
                    >{{ tag }}</span>
                  </div>
                  <div class="mt-1 text-xs text-slate-400">
                    代码: {{ vol.schoolCode }}
                  </div>
                </td>

                <!-- 专业信息 -->
                <td class="border-r border-slate-200 p-4">
                  <div class="text-slate-800 font-bold">
                    {{ vol.majorName }}
                  </div>
                  <div class="mt-1 text-xs text-slate-500">
                    {{ vol.tuition || '-' }}
                  </div>
                  <div class="text-xs text-slate-400">
                    代码: {{ vol.majorCode }}
                  </div>
                </td>

                <!-- 分数/概率 -->
                <td class="border-r border-slate-200 p-4 text-center">
                  <div class="text-lg text-blue-600 font-bold">
                    {{ vol.enrollProbability }}%
                  </div>
                  <div class="mt-1 text-xs text-slate-500">
                    排名 {{ vol.indexs }}
                  </div>
                  <div
                    class="mt-1 inline-block border rounded px-2 py-0.5 text-xs"
                    :class="getStatusColor(getProbabilityLabel(vol.enrollProbability))"
                  >
                    {{ getProbabilityLabel(vol.enrollProbability) }}
                  </div>
                </td>

                <!-- 25省内招生 -->
                <td class="border-r border-slate-200 p-4 text-center">
                  <div class="text-lg font-bold">
                    {{ vol.planNum }}人
                  </div>
                </td>

                <!-- 操作：移除 -->
                <td class="p-4 text-center">
                  <button
                    class="rounded-full p-2 text-red-500 transition-colors hover:bg-red-50 hover:text-red-700"
                    title="移除此志愿"
                    @click="removeVolunteer(index)"
                  >
                    <svg
                      xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
                      stroke="currentColor"
                    >
                      <path
                        stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                        d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
                      />
                    </svg>
                  </button>
                </td>
              </tr>

              <!-- 空状态 -->
              <tr v-if="myVolunteers.length === 0">
                <td colspan="7" class="items-center justify-center py-20 text-center text-slate-400">
                  <div class="flex flex-col items-center justify-center">
                    <div class="mb-3 rounded-full bg-slate-100 p-4">
                    <svg
                      xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-slate-300" fill="none"
                      viewBox="0 0 24 24" stroke="currentColor"
                    >
                      <path
                        stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                        d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
                      />
                    </svg>
                  </div>
                  <p>暂无志愿，请前往“模拟填报”添加</p>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <!-- Panel B End -->
    </div>
    <!-- =========================================================
        弹窗层 (Modal) - 重点更新区域
  ========================================================== -->
    <Teleport to="body">
      <div
        v-if="showModal" class="fixed inset-0 z-[100] flex items-center justify-center bg-black/50 backdrop-blur-sm"
        @click.self="closeModal"
      >
        <!-- 宽度加宽至 1100px 以容纳更多列 -->
        <div
          class="h-[85vh] w-[1100px] flex flex-col animate-fade-in-up overflow-hidden rounded-lg bg-white shadow-2xl"
        >
          <!-- Header -->
          <div class="flex items-center justify-between border-b border-slate-200 bg-slate-50 px-6 py-4">
            <div>
              <div class="flex items-end gap-3">
                <h3 class="text-xl text-slate-800 font-bold">
                  {{ currentSchool?.schoolName }}
                </h3>
                <span class="text-sm text-slate-500">院校代码: {{ currentSchool?.schoolCode }}</span>
              </div>
              <p class="mt-1 text-xs text-slate-500">
                该院校下符合您选科要求的其他专业列表
              </p>
            </div>
            <button class="rounded-full p-1 text-slate-400 hover:bg-slate-200 hover:text-slate-600" @click="closeModal">
              <svg
                xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          </div>

          <!-- Content: Table -->
          <div class="flex-1 overflow-auto bg-slate-50 p-0">
            <table class="w-full border-collapse text-left text-sm">
              <thead
                class="sticky top-0 z-10 bg-slate-100 text-xs text-slate-500 font-semibold tracking-wider uppercase shadow-sm"
              >
                <tr>
                  <th class="w-16 px-6 py-3">
                    代码
                  </th>
                  <th class="px-6 py-3">
                    专业名称 / 选科 / 学费
                  </th>
                  <th class="px-6 py-3 text-center">
                    录取概率
                  </th>
                  <th class="px-6 py-3 text-center">
                    上次最低分
                  </th>
                  <th class="px-6 py-3 text-center">
                    录取方式
                  </th>
                  <th class="px-6 py-3 text-center">
                    招生计划
                  </th>
                  <th
                    class="sticky right-0 bg-slate-100 px-6 py-3 text-center shadow-[-4px_0_8px_-4px_rgba(0,0,0,0.1)]"
                  >
                    加入志愿
                  </th>
                </tr>
              </thead>
              <tbody class="bg-white divide-y divide-slate-100">
                <tr v-if="modalLoading">
                  <td colspan="7" class="p-12 text-center text-slate-400">
                    <svg class="mx-auto mb-2 h-8 w-8 animate-spin text-blue-400" viewBox="0 0 24 24">
                      <path fill="currentColor" d="M12 2A10 10 0 1 0 22 12A10 10 0 0 0 12 2Z" opacity="0.2" />
                      <path fill="currentColor" d="M12 2A10 10 0 0 1 22 12h-2a8 8 0 0 0-8-8V2Z" />
                    </svg>
                    正在获取专业数据...
                  </td>
                </tr>
                <tr
                  v-for="major in modalMajors" v-else :key="major.code"
                  class="group transition-colors hover:bg-blue-50/30"
                >
                  <td class="px-6 py-4 text-xs text-slate-400 font-mono">
                    {{ major.code }}
                  </td>
                  <td class="px-6 py-4">
                    <div class="text-base text-slate-800 font-bold">
                      {{ major.name }}
                    </div>
                    <div class="mt-1 flex gap-2 text-xs text-slate-500">
                      <span class="rounded bg-slate-100 px-1.5 py-0.5">{{
                        major.batch
                      }}</span>
                      <span class="rounded bg-slate-100 px-1.5 py-0.5">{{
                        major.tuition
                      }}</span>
                    </div>
                  </td>
                  <td class="px-6 py-4 text-center">
                    <span
                      class="font-bold" :class="major.prob >= 80 ? 'text-green-600' : 'text-orange-500'
                      "
                    >{{ major.prob }}%</span>
                  </td>
                  <td class="px-6 py-4 text-center font-medium">
                    {{ major.score }}
                  </td>
                  <td class="px-6 py-4 text-center text-slate-500">
                    {{ major.rulesEnrollProbability }}
                  </td>
                  <td class="px-6 py-4 text-center text-slate-500">
                    {{ major.plan }}人
                  </td>

                  <!-- 操作列：加入/移除 -->
                  <td
                    class="sticky right-0 bg-white px-6 py-4 text-center shadow-[-4px_0_8px_-4px_rgba(0,0,0,0.1)] group-hover:bg-blue-50/30"
                  >
                    <button
                      class="min-w-[90px] rounded-full px-3 py-1.5 text-xs font-medium transition-all duration-200"
                      :class="[
                        selectedMajorCodes.includes(`${currentSchool?.schoolCode}_${major.code}_${major.enrollmentCode || currentSchool?.enrollmentCode}`)
                          ? 'bg-red-50 text-red-500 border border-red-200 hover:bg-red-100' // 选中状态：红色，显示志愿序号
                          : 'bg-white text-blue-600 border border-blue-500 hover:bg-blue-50', // 未选状态：蓝色
                      ]" @click="toggleMajor(major)"
                    >
                      {{ getVolunteerBtnText(major) }}
                    </button>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>

          <!-- Footer: Confirm with Popover -->
          <div class="relative flex items-center justify-between border-t border-slate-200 bg-white p-4">
            <div class="text-sm text-slate-500">
              已选
              <span class="text-lg text-blue-600 font-bold">{{
                selectedMajorCodes.length
              }}</span>
              个志愿
            </div>

            <div class="relative flex gap-3">
              <button class="px-5 py-2 text-sm text-slate-600 hover:text-slate-900" @click="closeModal">
                取消
              </button>

              <!--
              气泡确认框 (Popconfirm) 实现逻辑
              如果不想封装组件，这种 inline 方式最简单
            -->
              <div class="relative">
                <!-- 主按钮 -->
                <w-popconfirm
                  title="底部右对齐" placement="top-right" :ok-button-props="{ loading: isSaving }"
                  @confirm="saveVolunteers"
                >
                  <button
                    :disabled="isSaving"
                    class="rounded bg-blue-600 px-6 py-2 text-sm text-white font-medium shadow-md transition-colors disabled:cursor-not-allowed hover:bg-blue-700 disabled:opacity-50"
                  >
                    确认保存
                  </button>
                  <!-- Slots -->
                  <template #icon>
                    <span class="text-xl">🎉</span>
                  </template>
                  <template #title>
                    <span class="text-purple-600">确认要保存吗？</span>
                  </template>
                  <template #description>
                    这里可以放很长很长的<br>HTML内容哦。
                  </template>
                </w-popconfirm>

                <!-- 气泡层 -->
                <div
                  v-if="showSaveConfirm"
                  class="absolute bottom-full right-0 z-50 mb-3 w-64 animate-fade-in-up border border-slate-200 rounded-lg bg-white p-4 shadow-xl"
                >
                  <!-- 小三角 -->
                  <div
                    class="absolute right-6 h-3 w-3 rotate-45 border-b border-r border-slate-200 bg-white -bottom-1.5"
                  />

                  <div class="mb-3 flex items-start gap-3">
                    <div class="mt-0.5 text-orange-500">
                      <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                        <path
                          fill-rule="evenodd"
                          d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
                          clip-rule="evenodd"
                        />
                      </svg>
                    </div>
                    <div>
                      <p class="text-sm text-slate-800 font-bold">
                        确认提交志愿？
                      </p>
                      <p class="mt-1 text-xs text-slate-500">
                        提交后将更新您的志愿表，已选
                        {{ selectedMajorCodes.length }} 个专业。
                      </p>
                    </div>
                  </div>

                  <div class="flex justify-end gap-2">
                    <button
                      class="rounded px-2 py-1 text-xs text-slate-500 hover:bg-slate-100"
                      @click="showSaveConfirm = false"
                    >
                      再想想
                    </button>
                    <button
                      class="flex items-center gap-1 rounded bg-blue-600 px-3 py-1 text-xs text-white hover:bg-blue-700"
                      :disabled="isSaving" @click="saveVolunteers"
                    >
                      <span
                        v-if="isSaving"
                        class="h-3 w-3 animate-spin border-2 border-white/30 border-t-white rounded-full"
                      />
                      {{ isSaving ? "保存中" : "确定" }}
                    </button>
                  </div>
                </div>
              </div>
              <!-- End of Popconfirm -->
            </div>
          </div>
        </div>
      </div>

      <!-- =========================================================
     方案切换模态框 (新增)
========================================================== -->
      <div
        v-if="showSwitchModal"
        class="fixed inset-0 z-[110] flex items-center justify-center bg-black/50 backdrop-blur-sm"
        @click.self="showSwitchModal = false"
      >
        <div
          class="max-h-[80vh] w-[1000px] flex flex-col animate-fade-in-up overflow-hidden rounded-lg bg-white shadow-2xl"
        >
          <!-- Header -->
          <div class="flex items-center justify-between border-b border-slate-200 px-6 py-4">
            <h3 class="text-lg text-slate-800 font-bold">
              我的志愿方案
            </h3>

            <!-- 简单的关闭按钮 -->
            <button class="text-slate-400 hover:text-slate-600" @click="showSwitchModal = false">
              <svg
                xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          </div>

          <!-- Toolbar / Filter -->
          <div class="flex justify-end border-b border-slate-100 bg-slate-50 px-6 py-3">
            <div class="relative">
              <select
                class="appearance-none border border-slate-300 rounded bg-white py-1.5 pl-3 pr-8 text-sm text-slate-700 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
              >
                <option>请选择省份</option>
                <option>北京</option>
                <option>湖北</option>
              </select>
              <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-slate-500">
                <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
                </svg>
              </div>
            </div>
          </div>

          <!-- Table -->
          <div class="flex-1 overflow-auto p-6">
            <table class="w-full border border-slate-200 text-left text-sm">
              <thead class="bg-slate-50 text-slate-500">
                <tr>
                  <th class="border-b border-r border-slate-200 px-4 py-3 font-medium">
                    名称
                  </th>
                  <th class="border-b border-r border-slate-200 px-4 py-3 text-center font-medium">
                    省份
                  </th>
                  <th class="border-b border-r border-slate-200 px-4 py-3 text-center font-medium">
                    艺术类别
                  </th>
                  <th class="border-b border-r border-slate-200 px-4 py-3 text-center font-medium">
                    文化分
                  </th>
                  <th class="border-b border-r border-slate-200 px-4 py-3 text-center font-medium">
                    统考分
                  </th>
                  <th class="border-b border-r border-slate-200 px-4 py-3 text-center font-medium">
                    最后更新时间
                  </th>
                  <th class="border-b border-r border-slate-200 px-4 py-3 text-center font-medium">
                    状态
                  </th>
                  <th class="border-b border-slate-200 px-4 py-3 text-center font-medium">
                    操作
                  </th>
                </tr>
              </thead>
              <tbody class="divide-y divide-slate-100">
                <tr v-for="plan in volunteerPlans" :key="plan.id" class="transition-colors hover:bg-slate-50">
                  <td class="border-r border-slate-100 px-4 py-3">
                    <div class="flex items-center gap-2">
                      <span class="text-slate-700 font-medium">{{ plan.name }}</span>
                      <span
                        class="rounded px-1.5 py-0.5 text-[10px]"
                        :class="plan.tag === '手动' ? 'bg-orange-50 text-orange-500' : 'bg-blue-50 text-blue-500'"
                      >
                        {{ plan.tag }}
                      </span>
                    </div>
                  </td>
                  <td class="border-r border-slate-100 px-4 py-3 text-center text-slate-600">
                    {{ plan.province }}
                  </td>
                  <td class="border-r border-slate-100 px-4 py-3 text-center text-slate-600">
                    {{ plan.artType }}
                  </td>
                  <td class="border-r border-slate-100 px-4 py-3 text-center">
                    <span class="text-slate-800 font-medium">{{ plan.cultureScore }}</span>
                    <span class="ml-1 text-xs text-slate-400">{{ plan.cultureSubjects }}</span>
                  </td>
                  <td class="border-r border-slate-100 px-4 py-3 text-center text-slate-800 font-medium">
                    {{
                      plan.artScore }}
                  </td>
                  <td class="border-r border-slate-100 px-4 py-3 text-center text-xs text-slate-500 font-mono">
                    {{
                      plan.updateTime }}
                  </td>
                  <td class="border-r border-slate-100 px-4 py-3 text-center text-slate-600">
                    {{ plan.status }}
                  </td>
                  <td class="px-4 py-3 text-center">
                    <div class="flex items-center justify-center gap-2">
                      <!-- 当前选中状态 -->
                      <span v-if="activePlanId === plan.id" class="text-xs text-orange-500 font-bold">当前</span>
                      <!-- 切换按钮 -->
                      <button
                        v-else class="text-xs text-blue-600 hover:text-blue-800 hover:underline"
                        @click="switchActivePlan(plan.id)"
                      >
                        切换
                      </button>
                      <span class="text-slate-300">|</span>
                      <button class="text-xs text-slate-600 hover:text-slate-900 hover:underline">
                        导出
                      </button>
                      <span class="text-slate-300">|</span>
                      <button
                        class="text-xs text-slate-600 hover:text-red-600 hover:underline"
                        @click="deletePlan(plan.id)"
                      >
                        删除
                      </button>
                    </div>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </Teleport>
  </div>
</template>

<style scoped>
/* 定义淡入动画 */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.animate-fade-in-up {
  animation: fadeInUp 0.3s ease-out;
}

/* 滚动条美化 */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb {
  background: #cbd5e1; /* slate-300 */
  border-radius: 4px;
  transition: background 0.2s;
}

::-webkit-scrollbar-thumb:hover {
  background: #94a3b8; /* slate-400 */
}

/* 兼容 Firefox */
* {
  scrollbar-width: thin;
  scrollbar-color: #cbd5e1 transparent;
}
</style>
