<script setup lang="ts">
import { ref, reactive, watch, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { useI18n } from '../composables/useI18n'
import { useMessage } from '../composables/useMessage'
import DatePicker from './DatePicker.vue'
import GanttConfirmDialog from './GanttConfirmDialog.vue'
import MultiSelectPredecessor from './MultiSelectPredecessor.vue'
import ConfirmTimerDialog from './ConfirmTimerDialog.vue'
import type { Task } from '../models/classes/Task'
import { createResource } from '../utils/resourceUtils'
import '../styles/app.css'

interface AssigneeOption {
  key?: string | number
  value: string | number
  label: string
  avatar?: string // v1.9.0 资源头像
}

interface Props {
  visible: boolean
  task?: Task | null
  isEdit?: boolean
  onDelete?: (task: Task) => void
  assigneeOptions?: AssigneeOption[]
  pendingTaskBackgroundColor?: string
  delayTaskBackgroundColor?: string
  completeTaskBackgroundColor?: string
  ongoingTaskBackgroundColor?: string
}

const props = withDefaults(defineProps<Props>(), {
  visible: false,
  task: null,
  isEdit: false,
  onDelete: undefined,
  assigneeOptions: () => [
    { value: 'zhangsan', label: '张三' },
    { value: 'lisi', label: '李四' },
    { value: 'wangwu', label: '王五' },
    { value: 'zhaoliu', label: '赵六' },
    { value: 'qianqi', label: '钱七' },
  ],
  pendingTaskBackgroundColor: '#c0c4cc',
  delayTaskBackgroundColor: '#f56c6c',
  completeTaskBackgroundColor: '#67c23a',
  ongoingTaskBackgroundColor: '#409eff',
})

const emit = defineEmits<{
  'update:visible': [value: boolean]
  submit: [task: Task]
  close: []
  delete: [task: Task, deleteChildren?: boolean]
  'start-timer': [task: Task]
  'stop-timer': [task: Task]
}>()

const { t } = useI18n()
const { showMessage } = useMessage()

const submitting = ref(false)
const isVisible = ref(props.visible)
const showDeleteConfirm = ref(false)

// 计时器相关
const timerElapsed = ref(0)
const timerInterval = ref<number | null>(null)

const isTimerRunning = computed(() => props.task?.isTimerRunning)
const timerStartTime = computed(() => props.task?.timerStartTime)
const timerElapsedTime = computed(() => props.task?.timerElapsedTime || 0)

const formattedTimer = computed(() => {
  const totalSeconds = Math.floor(timerElapsed.value / 1000)
  const hours = Math.floor(totalSeconds / 3600)
  const minutes = Math.floor((totalSeconds % 3600) / 60)
  const seconds = totalSeconds % 60
  return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
})

const updateTimer = () => {
  if (isTimerRunning.value && timerStartTime.value) {
    timerElapsed.value = Date.now() - timerStartTime.value + timerElapsedTime.value
  } else {
    timerElapsed.value = timerElapsedTime.value
  }
}

// 新增：监听 props.task 的 isTimerRunning、timerStartTime、timerElapsedTime 变化，确保 header 区域按钮和计时器展示实时同步
watch(
  () => [props.task?.isTimerRunning, props.task?.timerStartTime, props.task?.timerElapsedTime],
  () => {
    updateTimer()
  },
)

// 计时器本地状态，保证点击后UI立即切换
const localTimerRunning = ref(false)

// 只要 props.task 变化或全局事件变化，立即同步本地状态
watch(
  () => props.task?.isTimerRunning,
  val => {
    localTimerRunning.value = !!val
    if (!val && timerInterval.value) {
      clearInterval(timerInterval.value)
      timerInterval.value = null
    }
  },
  { immediate: true },
)

// 修正计时器每秒递增逻辑，保证计时器正常跳动
watch(
  [localTimerRunning, timerStartTime, timerElapsedTime],
  () => {
    if (timerInterval.value) {
      clearInterval(timerInterval.value)
      timerInterval.value = null
    }
    if (localTimerRunning.value && timerStartTime.value) {
      updateTimer()
      timerInterval.value = window.setInterval(updateTimer, 1000)
    } else {
      updateTimer()
    }
  },
  { immediate: true },
)

onUnmounted(() => {
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
  }
})

// 根据任务类型确定dialog类型
const dialogType = computed(() => {
  return props.task?.type === 'story' ? 'yes-no-cancel' : 'confirm-cancel'
})

// 根据任务类型确定dialog消息
const dialogMessage = computed(() => {
  if (props.task?.type === 'story') {
    return t.value.confirmDeleteStory.replace('{name}', props.task?.name || '')
  }
  return t.value.confirmDeleteTask.replace('{name}', props.task?.name || '')
})

// 表单数据
const formData = reactive<Task>({
  id: 0, // 默认值，创建时会被重新分配
  name: '',
  type: 'task',
  assignee: '',
  startDate: '',
  endDate: '',
  actualStartDate: '',
  actualEndDate: '',
  predecessor: [],
  estimatedHours: 0,
  actualHours: 0,
  progress: 0,
  description: '',
  parentId: undefined, // 上级任务ID
  isTimerRunning: false, // 是否正在计时
  timerStartTime: undefined, // 计时器开始时间
  timerEndTime: undefined, // 计时器结束时间
  timerElapsedTime: 0, // 计时器已用时间
  children: undefined, // 子任务列表
  resources: [], // v1.9.0 资源分配列表（包含占比）
})

// 任务列表数据
const allTasks = ref<Task[]>([])

// 获取可作为上级任务的任务列表（只显示story和task类型，排除当前任务自己）
const availableParentTasks = computed(() => {
  return allTasks.value
    .filter(
      task =>
        task.id !== props.task?.id && // 排除当前任务自己
        (task.type === 'story' || task.type === 'task'), // 只显示story和task类型
    )
    .map(task => ({
      ...task,
      displayName: `${task.name} (${getTaskTypeDisplay(task.type || 'task')})`,
    }))
})

// 获取任务类型的显示文本
const getTaskTypeDisplay = (type: string): string => {
  return (t.value.taskTypeMap as Record<string, string>)?.[type] || type
}

// 计算进度条样式
const progressSliderStyle = computed(() => {
  const progressPercent = formData.progress || 0
  return {
    '--progress-capacity': `${progressPercent}%`,
  }
})

// 进度输入框的显示值
const progressDisplayValue = ref('0')

// 处理进度输入
const handleProgressInput = (event: Event) => {
  const target = event.target as HTMLInputElement
  let value = target.value

  // 只保留数字
  value = value.replace(/[^\d]/g, '')

  // 更新输入框显示
  target.value = value
  progressDisplayValue.value = value
}

// 处理进度输入失焦或回车
const handleProgressInputBlur = () => {
  const value = progressDisplayValue.value

  // 转换为数字
  let progress = parseInt(value) || 0

  // 数据验证：小于0或非数字显示0，大于100显示100
  if (progress < 0 || isNaN(progress)) {
    progress = 0
  } else if (progress > 100) {
    progress = 100
  }

  // 更新数据和显示
  formData.progress = progress
  progressDisplayValue.value = progress.toString()
}

// 处理预计工时输入
const handleEstimatedHoursInput = (event: Event) => {
  const target = event.target as HTMLInputElement
  let value = parseFloat(target.value)

  // 数据验证
  if (isNaN(value) || value < 0) {
    value = 0
  } else if (value > 99999) {
    value = 99999
  }

  // 保留两位小数
  formData.estimatedHours = Math.round(value * 100) / 100
}

// 处理实际工时输入
const handleActualHoursInput = (event: Event) => {
  const target = event.target as HTMLInputElement
  let value = parseFloat(target.value)

  // 数据验证
  if (isNaN(value) || value < 0) {
    value = 0
  } else if (value > 99999) {
    value = 99999
  }

  // 保留两位小数
  formData.actualHours = Math.round(value * 100) / 100
}

// 处理进度输入框聚焦（选中全部文本）
const handleProgressInputFocus = (event: Event) => {
  const target = event.target as HTMLInputElement
  // 延迟选中，确保聚焦完成
  setTimeout(() => {
    target.select()
  }, 0)
}

// 处理键盘事件
const handleProgressKeydown = (event: KeyboardEvent) => {
  const key = event.key

  // 允许的按键：数字、退格、删除、方向键、Tab等
  const allowedKeys = [
    'Backspace',
    'Delete',
    'Tab',
    'Escape',
    'Enter',
    'ArrowLeft',
    'ArrowRight',
    'ArrowUp',
    'ArrowDown',
    'Home',
    'End',
    'Control',
    'Meta',
    'Alt',
    'Shift',
  ]

  // 允许数字
  const isNumber = /^\d$/.test(key)
  const isAllowedKey = allowedKeys.includes(key)

  // 如果是Ctrl+A、Ctrl+C、Ctrl+V、Ctrl+X等组合键，允许通过
  if (event.ctrlKey || event.metaKey) {
    return
  }

  // 如果不是允许的按键或数字，阻止输入
  if (!isNumber && !isAllowedKey) {
    event.preventDefault()
  }
}

// 处理小时视图中的日期格式
const processDateForHourView = (dateStr: string | undefined, type: 'start' | 'end'): string => {
  if (!dateStr) return ''

  // 检查是否只有日期部分（YYYY-MM-DD格式）
  if (typeof dateStr === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(dateStr.trim())) {
    // 如果是开始日期，设置为当日00:00
    if (type === 'start') {
      return `${dateStr} 00:00`
    }
    // 如果是结束日期，设置为次日00:00
    if (type === 'end') {
      const date = new Date(dateStr)
      date.setDate(date.getDate() + 1)
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      return `${year}-${month}-${day} 00:00`
    }
  }

  // 已经包含时间部分或其他格式，直接返回
  return dateStr
}

// 错误信息
const errors = reactive({
  name: '',
  type: '',
  startDate: '',
  endDate: '',
  actualStartDate: '',
  actualEndDate: '',
})

// 监听 visible 属性变化
watch(
  () => props.visible,
  newVal => {
    isVisible.value = newVal
    if (newVal) {
      if (props.task && props.isEdit) {
        // 编辑模式，先重置表单再填充表单数据
        resetForm()
        const taskData = { ...props.task }

        // 处理日期格式：如果是只有日期部分的数据，在小时视图编辑时需要特殊处理
        taskData.startDate = processDateForHourView(taskData.startDate, 'start')
        taskData.endDate = processDateForHourView(taskData.endDate, 'end')

        // 使用 nextTick 确保 resetForm 的响应式更新完成后再赋值
        nextTick(() => {
          Object.assign(formData, taskData)

          // v1.9.0 从 assignee/avatar 映射到 resources
          mapAssigneeToResources()
        })
      } else if (props.task && !props.isEdit) {
        // 新建模式，重置表单
        resetForm()
        // 新建模式，自动绑定上级任务
        formData.parentId = props.task.parentId ?? undefined
        // 新建模式，自动绑定前置任务
        formData.predecessor = props.task.predecessor ?? []
      } else {
        // 没有 task，也重置表单
        resetForm()
      }
      // 抽屉显示时重新请求任务数据，确保前置任务列表是最新的
      window.dispatchEvent(new CustomEvent('request-task-list'))
    }
  },
)

// 监听 isVisible 变化，同步到父组件
watch(isVisible, newVal => {
  emit('update:visible', newVal)
})

// 监听 task 变化，同步更新 parentId
watch(
  () => props.task,
  newTask => {
    if (newTask && !props.isEdit) {
      // 新建时，确保 parentId 与传入的 parentId 同步
      formData.parentId = newTask.parentId ?? undefined
    }
  },
  { immediate: true },
)

// 重置表单
const resetForm = () => {
  Object.assign(formData, {
    name: '',
    type: 'task',
    assignee: '',
    startDate: '',
    endDate: '',
    actualStartDate: '',
    actualEndDate: '',
    predecessor: [],
    estimatedHours: 0,
    actualHours: 0,
    progress: 0,
    description: '',
    parentId: undefined,
    isTimerRunning: false,
    timerStartTime: undefined,
    timerEndTime: undefined,
    timerElapsedTime: 0,
    children: undefined,
    bgColor: undefined,
    avatar: undefined,
    barColor: undefined,
    resources: [], // v1.9.0 资源分配
  })

  // 清除错误信息
  Object.keys(errors).forEach(key => {
    errors[key as keyof typeof errors] = ''
  })
}

// 表单验证
const validateForm = (): boolean => {
  let isValid = true
  Object.keys(errors).forEach(key => {
    errors[key as keyof typeof errors] = ''
  })
  if (!formData.name?.trim()) {
    errors.name = t.value.taskNameRequired
    isValid = false
  } else if (formData.name.length > 50) {
    errors.name = t.value.taskNameTooLong
    isValid = false
  }
  if (!formData.type) {
    errors.type = t.value.taskTypeRequired
    isValid = false
  }
  if (!formData.startDate) {
    errors.startDate = t.value.plannedStartDateRequired
    isValid = false
  }
  if (!formData.endDate) {
    errors.endDate = t.value.plannedEndDateRequired
    isValid = false
  } else if (formData.startDate && new Date(formData.endDate) < new Date(formData.startDate)) {
    errors.endDate = t.value.plannedEndDateInvalid
    isValid = false
  }
  // 验证实际日期（可选字段）
  if (formData.actualStartDate && formData.actualEndDate && new Date(formData.actualEndDate) < new Date(formData.actualStartDate)) {
    errors.actualEndDate = t.value.actualEndDateInvalid
    isValid = false
  }
  return isValid
}

// 关闭抽屉
const handleClose = () => {
  isVisible.value = false
  emit('close')
}

// 点击遮罩层关闭
const handleOverlayClick = () => {
  handleClose()
}

// 提交表单
const handleSubmit = async () => {
  if (!validateForm()) {
    return
  }
  try {
    submitting.value = true

    // v1.9.0 提交前从 resources 映射到 assignee/avatar
    mapResourcesToAssignee()

    const taskData: Task = {
      ...formData,
      id: props.isEdit && props.task ? props.task.id : Date.now(),
      resources: formData.resources, // 确保提交 resources 字段
    }
    emit('submit', taskData)
    handleClose()
  } catch (error) {
    // 处理错误但不在控制台输出
  } finally {
    submitting.value = false
  }
}

// 删除任务
const handleDelete = () => {
  showDeleteConfirm.value = true
}

const handleError = (error: unknown) => {
  let msg = ''
  if (
    error &&
    typeof error === 'object' &&
    'message' in error &&
    typeof (error as { message?: unknown }).message === 'string'
  ) {
    msg = (error as { message: string }).message
  } else {
    msg = String(error)
  }
  showMessage(msg, 'error', { closable: true })
}

const confirmDelete = () => {
  showDeleteConfirm.value = false
  if (props.task && props.isEdit) {
    try {
      submitting.value = true
      emit('delete', props.task)
      handleClose()
    } catch (error) {
      handleError(error)
    } finally {
      submitting.value = false
    }
  }
}

const cancelDelete = () => {
  showDeleteConfirm.value = false
}

// Story删除：选择"是" - 删除story及其所有子任务
const handleDeleteYes = () => {
  showDeleteConfirm.value = false
  if (props.task && props.isEdit) {
    try {
      submitting.value = true
      emit('delete', props.task, true) // 传递true表示删除所有子任务
      handleClose()
    } catch (error) {
      handleError(error)
    } finally {
      submitting.value = false
    }
  }
}

// Story删除：选择"否" - 仅删除story，保留子任务
const handleDeleteNo = () => {
  showDeleteConfirm.value = false
  if (props.task && props.isEdit) {
    try {
      submitting.value = true
      emit('delete', props.task, false) // 传递false表示仅删除story
      handleClose()
    } catch (error) {
      handleError(error)
    } finally {
      submitting.value = false
    }
  }
}

// 获取任务数据的事件处理器
const handleTasksChanged = (event: CustomEvent) => {
  allTasks.value = event.detail || []
}

// 组件挂载时添加事件监听器
onMounted(() => {
  window.addEventListener('task-list-updated', handleTasksChanged as EventListener)
  // 请求初始任务数据
  window.dispatchEvent(new CustomEvent('request-task-list'))
})

// 组件卸载时移除事件监听器
onUnmounted(() => {
  window.removeEventListener('task-list-updated', handleTasksChanged as EventListener)
})

// 监听 formData.progress 变化，同步更新显示值
watch(
  () => formData.progress,
  newValue => {
    progressDisplayValue.value = (newValue || 0).toString()
  },
  { immediate: true },
)

// 修正计时器首次启动不跳动问题：每次打开抽屉时重置 timerElapsed，且 timerStartTime 为空时立即赋值
watch(
  () => props.visible,
  visible => {
    if (visible && props.task && props.task.type !== 'story') {
      timerElapsed.value = props.task.timerElapsedTime || 0
      // 若计时器未启动，重置本地interval
      if (!props.task.isTimerRunning) {
        if (timerInterval.value) {
          clearInterval(timerInterval.value)
          timerInterval.value = null
        }
      }
    }
  },
  { immediate: true },
)

const handleStartTimer = (desc?: string) => {
  const now = Date.now()
  if (props.task && typeof props.task === 'object') {
    Object.assign(props.task, {
      timerStartTime: now,
      isTimerRunning: true,
      timerElapsedTime: 0, // 每次从0秒开始
      timerStartDesc: desc || '',
    })
    emit('start-timer', props.task)
  }
  timerElapsed.value = 0 // 启动时重置本地计时器
  localTimerRunning.value = true
  updateTimer()
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
    timerInterval.value = null
  }
  window.dispatchEvent(new CustomEvent('start-timer', { detail: props.task }))
}
const handleStopTimer = () => {
  if (props.task && typeof props.task === 'object') {
    emit('stop-timer', props.task)
  }
  localTimerRunning.value = false
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
    timerInterval.value = null
  }
  updateTimer()
  window.dispatchEvent(new CustomEvent('stop-timer', { detail: props.task }))
}

// 计时器确认弹窗
const showTimerConfirm = ref(false)
const timerDesc = ref('')

function openTimerConfirm() {
  timerDesc.value = props.task?.name || ''
  showTimerConfirm.value = true
}
function cancelTimerConfirm() {
  showTimerConfirm.value = false
}
function confirmTimer(desc: string) {
  showTimerConfirm.value = false
  // desc 可用于后续业务
  handleStartTimer(desc)
}

// v1.9.0 资源占比管理
const addResource = () => {
  if (!formData.resources) {
    formData.resources = []
  }
  formData.resources.push(createResource({
    id: '',
    name: '',
    capacity: 100,
    tasks: [],
  }))
}

const removeResource = (index: number) => {
  if (formData.resources && formData.resources.length > index) {
    formData.resources.splice(index, 1)
  }
}

const handleResourceChange = (index: number, field: 'id' | 'capacity', value: string | number) => {
  if (!formData.resources || !formData.resources[index]) return

  if (field === 'id') {
    const selected = props.assigneeOptions?.find(option => option.value === value)
    if (selected) {
      formData.resources[index].id = selected.value
      formData.resources[index].name = selected.label
    }
  } else if (field === 'capacity') {
    let capacity = typeof value === 'string' ? parseInt(value) : value
    // 校验范围 20-100
    if (capacity < 20) capacity = 20
    if (capacity > 100) capacity = 100
    formData.resources[index].capacity = capacity
  }
}

// v1.9.0 从 task.assignee/avatar 映射到 resources
const mapAssigneeToResources = () => {
  if (!formData.resources) {
    formData.resources = []
  }

  // 如果已有resources数据，保持不变（优先使用resources）
  if (formData.resources && formData.resources.length > 0) {
    return
  }

  // 从 assignee/avatar 映射到 resources
  const assignees = Array.isArray(formData.assignee) ? formData.assignee : (formData.assignee ? [formData.assignee] : [])

  formData.resources = assignees.map((assigneeId) => {
    // 查找对应的assigneeOption获取名称
    const option = props.assigneeOptions?.find(opt => opt.value === assigneeId)
    return createResource({
      id: assigneeId,
      name: option?.label || String(assigneeId),
      capacity: 100, // 默认100%
      tasks: [],
    })
  })
}

// v1.9.0 从 resources 映射回 task.assignee/avatar 数组
const mapResourcesToAssignee = () => {
  if (!formData.resources || formData.resources.length === 0) {
    formData.assignee = ''
    formData.avatar = ''
    return
  }

  // 映射 assignee 数组
  const assignees = formData.resources.map(r => String(r.id)).filter(id => id)
  formData.assignee = assignees.length > 1 ? assignees : (assignees[0] || '')

  // 映射 avatar 数组（从assigneeOptions中查找对应的avatar）
  const avatars = formData.resources
    .map(r => {
      const option = props.assigneeOptions?.find(opt => opt.value === r.id)
      return option?.avatar || ''
    })
    .filter(avatar => avatar)

  formData.avatar = avatars.length > 1 ? avatars : (avatars[0] || '')
}

// 计算任务状态
const taskStatus = computed(() => {
  if (!props.task) return { text: '', color: '', bgColor: '', borderColor: '' }

  const task = props.task
  const progress = task.progress || 0
  const now = new Date()
  const endDate = task.endDate ? new Date(task.endDate) : null
  const startDate = task.startDate ? new Date(task.startDate) : null
  const actualStartDate = task.actualStartDate

  // 待处理：没有实际开始日期并且进度为0
  if (!actualStartDate && progress === 0) {
    const color = props.pendingTaskBackgroundColor
    return {
      text: t.value.statusPending,
      color,
      bgColor: `${color}20`, // 添加20%透明度
      borderColor: color,
    }
  }

  // 已完成
  if (progress >= 100) {
    const color = props.completeTaskBackgroundColor
    return {
      text: t.value.statusCompleted,
      color,
      bgColor: `${color}20`,
      borderColor: color,
    }
  }

  // 已逾期：当前时间已超过结束日期，但未完成
  if (endDate && now > endDate && progress < 100) {
    const color = props.delayTaskBackgroundColor
    return {
      text: t.value.statusDelayed,
      color,
      bgColor: `${color}20`,
      borderColor: color,
    }
  }

  // 进行中：当前时间在开始日期之后，且未完成，且未逾期
  if (startDate && now >= startDate && progress < 100) {
    const color = props.ongoingTaskBackgroundColor
    return {
      text: t.value.statusOngoing,
      color,
      bgColor: `${color}20`,
      borderColor: color,
    }
  }

  // 默认待处理
  const color = props.pendingTaskBackgroundColor
  return {
    text: t.value.statusPending,
    color,
    bgColor: `${color}20`,
    borderColor: color,
  }
})
</script>

<template>
  <div v-if="isVisible" class="drawer-overlay" @click="handleOverlayClick">
    <div class="drawer-container" @click.stop>
      <!-- Drawer Header -->
      <div
        class="drawer-header"
        style="display: flex; align-items: center; justify-content: flex-start; gap: 8px"
      >
        <h3 class="drawer-title" style="margin: 0">{{ isEdit ? t.editTask : t.newTask }}</h3>
        <div
          v-if="props.task?.type !== 'story' && isEdit"
          class="drawer-timer"
          style="display: flex; align-items: center; gap: 6px; margin-left: 8px"
        >
          <button
            v-if="!localTimerRunning"
            class="timer-btn start minimal"
            title="开始计时"
            style="
              width: 24px;
              height: 24px;
              background: #4caf50;
              border: none;
              padding: 0;
              margin: 0;
              box-shadow: none;
              cursor: pointer;
              border-radius: 50%;
              display: flex;
              align-items: center;
              justify-content: center;
              transition: background 0.2s;
            "
            @click.stop="openTimerConfirm"
          >
            <svg
              width="24"
              height="24"
              viewBox="0 0 24 24"
              fill="none"
              style="display: block; margin: 0 auto"
            >
              <circle cx="12" cy="12" r="11" stroke="#4caf50" stroke-width="2" fill="#4caf50" />
              <polygon points="9,7 18,12 9,17" fill="#fff" />
            </svg>
          </button>
          <button
            v-else
            class="timer-btn stop minimal"
            title="停止计时"
            style="
              width: 24px;
              height: 24px;
              background: #f44336;
              border: none;
              padding: 0;
              margin: 0;
              box-shadow: none;
              cursor: pointer;
              border-radius: 50%;
              display: flex;
              align-items: center;
              justify-content: center;
              transition: background 0.2s;
            "
            @click.stop="handleStopTimer"
          >
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
              <circle cx="12" cy="12" r="11" stroke="#f44336" stroke-width="2" fill="#f44336" />
              <rect x="7" y="7" width="10" height="10" fill="#fff" rx="1.5" />
            </svg>
          </button>
          <span
            v-if="localTimerRunning"
            class="timer-badge"
            :class="{ 'timer-active': localTimerRunning }"
            style="
              margin-left: 8px;
              font-size: 13px;
              font-weight: 700;
              padding: 2px 10px;
              border-radius: 10px;
              background: #fffbe6;
              color: #e6a23c;
              box-shadow: 0 0 0 1px #ffe58f;
              display: inline-flex;
              align-items: center;
              min-width: 80px;
              justify-content: center;
            "
          >
            <span
              v-if="localTimerRunning"
              class="timer-dot"
              style="
                background: #67c23a;
                width: 7px;
                height: 7px;
                border-radius: 50%;
                margin-right: 5px;
                animation: pulse 1s infinite;
              "
            ></span>
            {{ formattedTimer }}
          </span>
        </div>
        <div style="flex: 1"></div>
        <!-- Status Badge -->
        <div
          v-if="isEdit && props.task"
          class="status-badge"
          :style="{
            backgroundColor: taskStatus.bgColor,
            color: taskStatus.color,
            border: `1px solid ${taskStatus.borderColor}`,
          }"
        >
          {{ taskStatus.text }}
        </div>
        <button class="drawer-close-btn" type="button" @click="handleClose">
          <svg
            class="close-icon"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            style="vertical-align: middle"
          >
            <line x1="18" y1="6" x2="6" y2="18"></line>
            <line x1="6" y1="6" x2="18" y2="18"></line>
          </svg>
        </button>
      </div>

      <!-- Drawer Body -->
      <div class="drawer-body">
        <form class="task-form" @submit.prevent="handleSubmit">
          <div class="form-group">
            <label class="form-label" for="task-name">
              {{ t.taskName }} <span class="required">*</span></label
            >
            <input
              id="task-name"
              v-model="formData.name"
              type="text"
              class="form-input"
              :class="{ error: errors.name }"
              :placeholder="t.taskNamePlaceholder"
            />
            <span v-if="errors.name" class="error-text">{{ errors.name }}</span>
          </div>

          <div class="form-group">
            <label class="form-label" for="task-type">
              {{ t.taskType }} <span class="required">*</span></label
            >
            <select
              id="task-type"
              v-model="formData.type"
              class="form-select"
              :class="{ error: errors.type }"
            >
              <option value="story">{{ t.taskTypeMap.story }}</option>
              <option value="task">{{ t.taskTypeMap.task }}</option>
              <option value="bug">{{ t.taskTypeMap.bug }}</option>
            </select>
            <span v-if="errors.type" class="error-text">{{ errors.type }}</span>
          </div>

          <!-- v1.9.0 资源分配（含占比配置） -->
          <div class="form-group">
            <label class="form-label">{{ t.resourceAllocation || '资源分配' }}</label>
            <div class="resource-list">
              <!-- 资源分配标题行 -->
              <div class="resource-header">
                <span class="resource-header-label">资源名称</span>
                <span class="resource-header-label">占用比例</span>
                <span class="resource-header-action"></span>
              </div>

              <div
                v-for="(resource, index) in formData.resources"
                :key="index"
                class="resource-item"
              >
                <select
                  v-model="resource.id"
                  class="form-select resource-select"
                  @change="handleResourceChange(index, 'id', ($event.target as HTMLSelectElement).value)"
                >
                  <option value="">{{ t.selectResource || '选择资源' }}</option>
                  <option
                    v-for="assignee in props.assigneeOptions"
                    :key="assignee.key ?? assignee.value"
                    :value="assignee.value"
                    :data-avatar="assignee.avatar"
                  >
                    {{ assignee.label }}
                  </option>
                </select>

                <select
                  v-model.number="resource.capacity"
                  class="form-select capacity-select"
                  @change="handleResourceChange(index, 'capacity', ($event.target as HTMLSelectElement).value)"
                >
                  <option :value="25">25%</option>
                  <option :value="50">50%</option>
                  <option :value="75">75%</option>
                  <option :value="100">100%</option>
                </select>

                <button
                  type="button"
                  class="btn-remove-resource"
                  title="删除资源"
                  @click="removeResource(index)"
                >
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                    <polyline points="3 6 5 6 21 6"></polyline>
                    <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
                    <line x1="10" y1="11" x2="10" y2="17"></line>
                    <line x1="14" y1="11" x2="14" y2="17"></line>
                  </svg>
                </button>
              </div>
              <button
                type="button"
                class="btn-add-resource"
                @click="addResource"
              >
                + {{ t.addResource || '添加资源' }}
              </button>
            </div>
          </div>

          <!-- 上级任务选择 -->
          <div class="form-group">
            <label class="form-label" for="task-parent">{{ t.parentTask }}</label>
            <select id="task-parent" v-model="formData.parentId" class="form-select">
              <option :value="undefined">{{ t.noParentTask }}</option>
              <option
                v-for="parentTask in availableParentTasks"
                :key="parentTask.id"
                :value="parentTask.id"
              >
                {{ parentTask.displayName }}
              </option>
            </select>
          </div>

          <div class="form-row">
            <div class="form-group">
              <label class="form-label" for="task-start-date">
                {{ t.plannedStartDate }} <span class="required">*</span></label
              >
              <DatePicker
                id="task-start-date"
                v-model="formData.startDate"
                :type="'datetime' as any"
                value-format="YYYY-MM-DD HH:mm"
                :placeholder="t.plannedStartDateRequired"
                :class="{ error: errors.startDate }"
              />
              <span v-if="errors.startDate" class="error-text">{{ errors.startDate }}</span>
            </div>

            <div class="form-group">
              <label class="form-label" for="task-end-date">
                {{ t.plannedEndDate }} <span class="required">*</span></label
              >
              <DatePicker
                id="task-end-date"
                v-model="formData.endDate"
                :type="'datetime' as any"
                value-format="YYYY-MM-DD HH:mm"
                :placeholder="t.plannedEndDateRequired"
                :class="{ error: errors.endDate }"
              />
              <span v-if="errors.endDate" class="error-text">{{ errors.endDate }}</span>
            </div>
          </div>

          <div class="form-row">
            <div class="form-group">
              <label class="form-label" for="task-actual-start-date">
                {{ t.actualStartDate }}</label
              >
              <DatePicker
                id="task-actual-start-date"
                v-model="formData.actualStartDate"
                :type="'datetime' as any"
                value-format="YYYY-MM-DD HH:mm"
                :placeholder="t.actualStartDate"
                :class="{ error: errors.actualStartDate }"
              />
              <span v-if="errors.actualStartDate" class="error-text">{{ errors.actualStartDate }}</span>
            </div>

            <div class="form-group">
              <label class="form-label" for="task-actual-end-date">
                {{ t.actualEndDate }}</label
              >
              <DatePicker
                id="task-actual-end-date"
                v-model="formData.actualEndDate"
                :type="'datetime' as any"
                value-format="YYYY-MM-DD HH:mm"
                :placeholder="t.actualEndDate"
                :class="{ error: errors.actualEndDate }"
              />
              <span v-if="errors.actualEndDate" class="error-text">{{ errors.actualEndDate }}</span>
            </div>
          </div>

          <MultiSelectPredecessor
            v-model="formData.predecessor"
            :tasks="allTasks"
            :current-task-id="props.task?.id"
            :label="t.predecessor"
            :placeholder="t.predecessorPlaceholder"
          />

          <div class="form-row">
            <div class="form-group">
              <label class="form-label" for="task-estimated-hours">{{ t.estimatedHours }}</label>
              <input
                id="task-estimated-hours"
                v-model="formData.estimatedHours"
                type="number"
                class="form-input"
                placeholder="0.00"
                min="0"
                max="99999"
                step="0.01"
                @input="handleEstimatedHoursInput"
              />
            </div>

            <div class="form-group">
              <label class="form-label" for="task-actual-hours">{{ t.actualHours }}</label>
              <input
                id="task-actual-hours"
                v-model="formData.actualHours"
                type="number"
                class="form-input"
                placeholder="0.00"
                min="0"
                max="99999"
                step="0.01"
                @input="handleActualHoursInput"
              />
            </div>
          </div>

          <div class="form-group">
            <label class="form-label" for="task-progress">{{ t.progress }}</label>
            <div class="progress-container">
              <input
                id="task-progress"
                v-model.number="formData.progress"
                type="range"
                class="progress-slider"
                :style="progressSliderStyle"
                min="0"
                max="100"
                step="5"
              />
              <div class="progress-input-group">
                <input
                  v-model="progressDisplayValue"
                  type="text"
                  class="progress-input"
                  placeholder="0"
                  maxlength="3"
                  @blur="handleProgressInputBlur"
                  @keyup.enter="handleProgressInputBlur"
                  @input="handleProgressInput"
                  @focus="handleProgressInputFocus"
                  @keydown="handleProgressKeydown"
                />
                <span class="progress-unit">%</span>
              </div>
            </div>
          </div>

          <div class="form-group">
            <label class="form-label" for="task-description">{{ t.description }}</label>
            <textarea
              id="task-description"
              v-model="formData.description"
              class="form-textarea"
              :placeholder="t.descriptionPlaceholder"
              rows="3"
            ></textarea>
          </div>
        </form>
      </div>
      <!-- Drawer Footer -->
      <div class="drawer-footer">
        <div class="footer-left">
          <!-- 删除按钮，仅在编辑模式下显示 -->
          <button
            v-if="isEdit && task"
            type="button"
            class="gantt-btn gantt-btn-danger"
            :disabled="submitting"
            @click="handleDelete"
          >
            <span v-if="submitting" class="loading-spinner"></span>
            {{ t.delete }}
          </button>
          <GanttConfirmDialog
            :visible="showDeleteConfirm"
            :title="t.delete"
            :type="dialogType"
            :message="dialogMessage"
            :confirm-text="t.confirm"
            :cancel-text="t.cancel"
            :yes-text="t.storyDeleteYes"
            :no-text="t.storyDeleteNo"
            @confirm="confirmDelete"
            @yes="handleDeleteYes"
            @no="handleDeleteNo"
            @cancel="cancelDelete"
          />
        </div>
        <div class="footer-right">
          <button type="button" class="gantt-btn gantt-btn-default" @click="handleClose">{{ t.cancel }}</button>
          <button
            type="button"
            class="gantt-btn gantt-btn-primary"
            :disabled="submitting"
            @click="handleSubmit"
          >
            <span v-if="submitting" class="loading-spinner"></span>
            {{ isEdit ? t.update : t.create }}
          </button>
        </div>
      </div>
    </div>
  </div>

  <!-- 计时器确认弹窗 -->
  <ConfirmTimerDialog
    v-if="showTimerConfirm"
    :visible="showTimerConfirm"
    :title="'确认开始计时'"
    :message="`即将为任务${props.task?.name}计时，若有特殊说明请完善下面的描述`"
    :default-desc="props.task?.name || ''"
    @confirm="confirmTimer"
    @cancel="cancelTimerConfirm"
  />
</template>

<style scoped>
@import '../styles/theme-variables.css';

/* 抽屉遮罩层 */
.drawer-overlay {
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 10000; /* 确保在全屏模式下也能正常显示 */
  display: flex;
  justify-content: flex-end;
  align-items: stretch;
}

/* 抽屉容器 */
.drawer-container {
  width: 500px;
  background: var(--gantt-bg-primary, white);
  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  animation: slideIn 0.3s ease-out;
  color: var(--gantt-text-primary, #303133);
}

@keyframes slideIn {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}

/* 抽屉头部 */
.drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--gantt-border-light, #ebeef5);
  background: var(--gantt-bg-secondary, #f5f7fa);
}

.drawer-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--gantt-text-primary, #303133);
}

.status-badge {
  padding: 4px 12px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  margin-left: 12px;
}

.drawer-close-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
  color: var(--gantt-text-muted, #909399);
  transition: color 0.2s;
  margin-left: 12px;
}

.drawer-close-btn:hover {
  color: var(--gantt-text-secondary, #606266);
}

.close-icon {
  width: 16px;
  height: 16px;
  stroke-width: 2;
}

/* 抽屉主体 */
.drawer-body {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
}

/* 表单样式 */
.task-form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

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

.form-row {
  display: flex;
  gap: 16px;
}

.form-row .form-group {
  flex: 1;
}

.form-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--gantt-text-secondary, #606266);
  line-height: 1.4;
}

.required {
  color: var(--gantt-danger, #f56c6c);
  margin-left: 2px;
}

.form-input,
.form-select,
.form-textarea {
  padding: 8px;
  border: 1px solid var(--gantt-border-medium, #dcdfe6);
  border-radius: 4px;
  font-size: 14px;
  color: var(--gantt-text-primary, #303133); /* 录入后为黑色，与 MilestoneDialog 保持一致 */
  background: var(--gantt-bg-primary, white);
  transition: border-color 0.2s;
  outline: none;
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus {
  border-color: var(--gantt-primary, #409eff);
}

.form-input.error,
.form-select.error {
  border-color: var(--gantt-danger, #f56c6c);
}

.form-input::placeholder,
.form-select::placeholder,
.form-textarea::placeholder {
  color: var(--gantt-text-placeholder, #c0c4cc);
}

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

.error-text {
  color: var(--gantt-danger, #f56c6c);
  font-size: 12px;
  line-height: 1.4;
}

/* 进度条容器 */
.progress-container {
  display: flex;
  align-items: center;
  gap: 12px;
}

.progress-slider {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: var(--gantt-border-light, #e4e7ed);
  outline: none;
  appearance: none;
  cursor: pointer;
  position: relative;
  /* 确保input元素本身垂直居中 */
  vertical-align: middle;
}

/* 移除悬停时的高度变化动画，避免抖动 */

/* WebKit 浏览器的已完成部分样式 */
.progress-slider::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(
    to right,
    var(--gantt-primary, #409eff) 0%,
    var(--gantt-primary, #409eff) var(--progress-capacity, 0%),
    var(--gantt-border-light, #e4e7ed) var(--progress-capacity, 0%),
    var(--gantt-border-light, #e4e7ed) 100%
  );
}

/* Firefox 浏览器的已完成部分样式 */
.progress-slider::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(
    to right,
    var(--gantt-primary, #409eff) 0%,
    var(--gantt-primary, #409eff) var(--progress-capacity, 0%),
    var(--gantt-border-light, #e4e7ed) var(--progress-capacity, 0%),
    var(--gantt-border-light, #e4e7ed) 100%
  );
  border: none;
}

/* Firefox 需要额外重置，确保轨道居中 */
.progress-slider::-moz-range-progress {
  height: 6px;
  border-radius: 3px;
  background: var(--gantt-primary, #409eff);
}

/* 为更好的兼容性，添加一个伪元素来显示已完成部分 */
.progress-slider::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  height: 6px;
  width: var(--progress-capacity, 0%);
  background: var(--gantt-primary, #409eff);
  border-radius: 3px;
  pointer-events: none;
  transition: width 0.2s ease; /* 只保留宽度变化的过渡效果 */
}

/* 移除悬停时的高度变化，避免抖动 */

.progress-slider::-webkit-slider-thumb {
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--gantt-primary, #409eff);
  cursor: pointer;
  position: relative;
  z-index: 2;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.2s ease; /* 只保留阴影过渡效果 */
  margin-top: -5px; /* 将滑块向上偏移，使其垂直居中 */
}

.progress-slider::-webkit-slider-thumb:hover {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.progress-slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--gantt-primary, #409eff);
  cursor: pointer;
  border: none;
  position: relative;
  z-index: 2;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.2s ease; /* 只保留阴影过渡效果 */
  margin-top: -5px; /* 将滑块向上偏移，使其垂直居中 */
}

.progress-slider::-moz-range-thumb:hover {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

/* 移除悬停和聚焦状态下的滑块位置调整，保持一致 */

/* 进度输入组样式 */
.progress-input-group {
  display: flex;
  align-items: center;
  border: 1px solid var(--gantt-border-medium, #dcdfe6);
  border-radius: 4px;
  background: var(--gantt-bg-primary, white);
  overflow: hidden;
  transition: border-color 0.2s ease;
  width: 70px; /* 固定宽度，保持紧凑 */
}

.progress-input-group:hover {
  border-color: var(--gantt-primary, #409eff);
}

.progress-input-group:focus-within {
  border-color: var(--gantt-primary, #409eff);
}

/* 进度输入框样式 - 与其他input保持一致 */
.progress-input {
  flex: 1;
  font-size: 14px;
  color: var(--gantt-text-primary, #303133);
  text-align: center;
  border: none;
  outline: none;
  background: transparent;
  padding: 12px 8px; /* 与其他input的padding保持一致 */
  min-width: 0; /* 允许收缩 */
}

.progress-input::placeholder {
  color: var(--gantt-text-placeholder, #c0c4cc);
}

/* 百分号单位样式 */
.progress-unit {
  font-size: 14px;
  color: var(--gantt-text-secondary, #606266);
  padding: 12px 12px 12px 4px; /* 与input的padding匹配 */
  user-select: none;
  flex-shrink: 0; /* 防止%号被压缩 */
}

/* 暗黑模式样式 */
:global(.gantt-root[data-theme='dark']) .progress-input-group {
  border-color: var(--gantt-border-medium, #4c4d4f);
  background: var(--gantt-bg-primary, #2b2b2b);
}

:global(.gantt-root[data-theme='dark']) .progress-input-group:hover {
  border-color: var(--gantt-primary, #409eff);
}

:global(.gantt-root[data-theme='dark']) .progress-input-group:focus-within {
  border-color: var(--gantt-primary, #409eff);
}

:global(.gantt-root[data-theme='dark']) .progress-input {
  color: var(--gantt-text-primary, #e5eaf3);
  background: transparent;
}

:global(.gantt-root[data-theme='dark']) .progress-input::placeholder {
  color: var(--gantt-text-placeholder, #8b949e);
}

:global(.gantt-root[data-theme='dark']) .progress-unit {
  color: var(--gantt-text-secondary, #a8a8a8);
}

/* 抽屉底部 */
.drawer-footer {
  padding: 16px 24px;
  border-top: 1px solid var(--gantt-border-light, #ebeef5);
  background: var(--gantt-bg-toolbar, #fafafa);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.footer-left {
  display: flex;
  align-items: center;
}

.footer-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* 加载动画 */
.loading-spinner {
  width: 12px;
  height: 12px;
  border: 2px solid transparent;
  border-top: 2px solid currentColor;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

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

/* 消息提示样式 */
.message {
  animation: messageSlideIn 0.3s ease-out;
}

@keyframes messageSlideIn {
  from {
    transform: translateX(100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 暗黑模式样式优化 */
:global(.gantt-root[data-theme='dark']) .drawer-overlay {
  background: rgba(0, 0, 0, 0.7) !important;
}

:global(.gantt-root[data-theme='dark']) .drawer-container {
  box-shadow: -4px 0 15px rgba(0, 0, 0, 0.4) !important;
}

:global(.gantt-root[data-theme='dark']) .drawer-close-btn:hover {
  background: var(--gantt-bg-hover, rgba(255, 255, 255, 0.1)) !important;
  border-radius: 4px;
}

:global(.gantt-root[data-theme='dark']) .form-input:focus,
:global(.gantt-root[data-theme='dark']) .form-select:focus,
:global(.gantt-root[data-theme='dark']) .form-textarea:focus {
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2) !important;
}

:global(.gantt-root[data-theme='dark']) .form-input::placeholder,
:global(.gantt-root[data-theme='dark']) .form-textarea::placeholder {
  color: var(--gantt-text-muted, #9e9e9e) !important;
}

/* v1.9.0 资源分配样式 */
.resource-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* 资源分配标题行 */
.resource-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--gantt-bg-toolbar, #fafafa);
  border-radius: 4px;
  border: 1px solid var(--gantt-border-light, #ebeef5);
}

.resource-header-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--gantt-text-secondary, #606266);
  white-space: nowrap;
  overflow: visible;
}

.resource-header-label:first-child {
  flex: 1;
  min-width: 0;
  text-align: center;
}

.resource-header-label:nth-child(2) {
  width: 100px;
  text-align: center;
}

.resource-header-action {
  width: 48px;
  flex-shrink: 0;
}

.resource-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--gantt-bg-secondary, #f5f7fa);
  border-radius: 4px;
  min-height: 48px;
}

.resource-select {
  flex: 1;
  min-width: 180px;
  max-width: 280px;
  height: 36px;
}

.resource-select option {
  padding: 8px 12px;
}

.capacity-select {
  width: 110px;
  height: 36px;
  flex-shrink: 0;
}

.btn-remove-resource {
  width: 32px;
  height: 32px;
  display: grid;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: var(--gantt-danger, #f56c6c);
  cursor: pointer;
  transition: all 0.2s;
  flex-shrink: 0;
}

.btn-remove-resource:hover {
  background: var(--gantt-danger-light, #fef0f0);
  border-color: var(--gantt-danger, #f56c6c);
  color: var(--gantt-danger, #f56c6c);
}

.btn-add-resource {
  width: 100%;
  padding: 10px;
  background: transparent;
  border: 1px dashed var(--gantt-border-base, #dcdfe6);
  border-radius: 4px;
  color: var(--gantt-primary, #409eff);
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s;
  min-height: 40px;
}

.btn-add-resource:hover {
  border-color: var(--gantt-primary, #409eff);
  background: var(--gantt-primary-light, #ecf5ff);
}

/* 暗黑模式 */
:global(.gantt-root[data-theme='dark']) .resource-header {
  background: var(--gantt-bg-toolbar, rgba(255, 255, 255, 0.03)) !important;
  border-color: var(--gantt-border-light, rgba(255, 255, 255, 0.1)) !important;
}

:global(.gantt-root[data-theme='dark']) .resource-header-label {
  color: var(--gantt-text-secondary, #a8a8a8) !important;
}

:global(.gantt-root[data-theme='dark']) .resource-item {
  background: var(--gantt-bg-secondary, rgba(255, 255, 255, 0.05)) !important;
}

:global(.gantt-root[data-theme='dark']) .btn-remove-resource:hover {
  background: var(--gantt-danger-dark, rgba(245, 108, 108, 0.2)) !important;
}

:global(.gantt-root[data-theme='dark']) .btn-add-resource:hover {
  background: var(--gantt-primary-dark, rgba(64, 158, 255, 0.2)) !important;
}
</style>
