<template>
  <view class="schedule-page">
    <!-- tab 模式：山水 banner 标题区 -->
    <template v-if="!showTopBar">
      <view class="banner">
        <image class="banner-bg" src="/static/index-backpage.jpg" mode="aspectFill" />
        <view class="banner-veil"></view>
        <StatusBar v-if="showStatusBar" />
        <view class="banner-inner px-4">
          <text class="banner-title block">排班管理</text>
          <text class="banner-sub block">安排班组与车辆的工作日程</text>
        </view>
      </view>
    </template>
    <template v-else>
      <StatusBar v-if="showStatusBar" />
      <TopBar title="排班管理" :show-back="showBack" />
    </template>

    <view class="content-wrap px-4" :class="showTopBar ? 'pt-3 pb-6' : 'pb-24'">
      <!-- 月份切换 + 快捷操作 -->
      <view class="glass-card p-4">
        <view class="month-row">
          <view
            class="month-arrow"
            hover-class="month-arrow-hover"
            :hover-start-time="0"
            :hover-stay-time="120"
            @click="changeMonth(-1)"
          >
            <text class="uni-icons uniui-back month-arrow-icon"></text>
          </view>
          <text class="month-text">{{ currentYear }}年{{ currentMonth }}月</text>
          <view
            class="month-arrow"
            hover-class="month-arrow-hover"
            :hover-start-time="0"
            :hover-stay-time="120"
            @click="changeMonth(1)"
          >
            <text class="uni-icons uniui-arrowright month-arrow-icon"></text>
          </view>
        </view>
        <view class="action-row">
          <view
            class="action-chip"
            hover-class="action-chip-hover"
            :hover-start-time="0"
            :hover-stay-time="120"
            @click="goToToday"
          >
            <text class="uni-icons uniui-calendar-filled action-chip-icon mr-1"></text>
            <text class="action-chip-text">今天</text>
          </view>
          <view
            class="action-chip action-chip-primary"
            hover-class="action-chip-primary-hover"
            :hover-start-time="0"
            :hover-stay-time="120"
            @click="addSchedule"
          >
            <text class="uni-icons uniui-plusempty action-chip-icon-light mr-1"></text>
            <text class="action-chip-text-light">新增排班</text>
          </view>
        </view>
      </view>

      <!-- 日历 -->
      <view class="glass-card p-4">
        <view class="flex mb-2">
          <view v-for="day in weekDays" :key="day" class="flex-1 text-center">
            <text class="weekday-text">{{ day }}</text>
          </view>
        </view>
        <view v-for="(week, weekIndex) in calendarWeeks" :key="weekIndex" class="flex mb-2">
          <view
            v-for="(date, dateIndex) in week"
            :key="dateIndex"
            class="day-cell"
            :class="{
              'day-other': date.isOtherMonth,
              'day-today': date.isToday && !isSelected(date),
              'day-selected': isSelected(date),
            }"
            hover-class="day-hover"
            :hover-start-time="0"
            :hover-stay-time="120"
            @click="selectDate(date)"
          >
            <text
              class="day-num"
              :class="{
                'day-num-today': date.isToday && !isSelected(date),
                'day-num-selected': isSelected(date),
              }"
            >
              {{ date.day }}
            </text>
            <view
              v-if="date.hasSchedule"
              class="day-dot"
              :class="isSelected(date) ? 'day-dot-light' : ''"
            ></view>
          </view>
        </view>
      </view>

      <!-- 排班列表 -->
      <view class="glass-card">
        <view class="section-head">
          <view class="section-bar mr-2"></view>
          <text class="section-title flex-1">{{ selectedDate }} 排班</text>
        </view>

        <view v-if="loading" class="py-10 text-center">
          <text class="empty-text">加载中...</text>
        </view>

        <view v-else-if="daySchedules.length === 0" class="py-2">
          <EmptyState message="该日无排班" />
        </view>

        <view v-else class="schedule-list">
          <view
            v-for="schedule in daySchedules"
            :key="schedule.scheduleId"
            class="schedule-card"
            hover-class="schedule-card-hover"
            :hover-start-time="0"
            :hover-stay-time="120"
            @click="viewSchedule(schedule)"
          >
            <view class="card-header">
              <view class="shift-badge" :class="getShiftBadgeClass(schedule)">
                <text class="uni-icons shift-badge__icon" :class="getShiftBadgeIcon(schedule)"></text>
                <text class="shift-badge__text">{{ schedule.shiftTypeText }}</text>
              </view>
              <view class="status-badge" :class="schedule.statusClass">
                {{ schedule.statusText }}
              </view>
            </view>

            <view class="card-body">
              <text class="team-name">{{ schedule.teamDisplayName || '未命名班组' }}</text>
              <view class="vehicle-line">
                <text class="uni-icons uniui-navigate car-icon"></text>
                <text class="vehicle-text">{{ schedule.vehicleNamesText || '未分配车辆' }}</text>
              </view>
            </view>

            <view class="card-footer">
              <view class="date-line">
                <text class="uni-icons uniui-calendar date-icon"></text>
                <text class="date-text">{{ schedule.workDate }}</text>
              </view>
              <text class="uni-icons uniui-arrowright row-arrow"></text>
            </view>
          </view>
        </view>
      </view>
    </view>

    <!-- 新增排班底部弹窗 -->
    <view v-if="showModal" class="schedule-modal">
      <view class="schedule-modal__overlay" @click="closeModal"></view>
      <view class="schedule-modal__panel">
        <view class="flex justify-between items-center mb-4">
          <text class="modal-title">{{ isDetail ? '排班详情' : '新增排班' }}</text>
          <text class="uni-icons uniui-close modal-close p-2" @click="closeModal"></text>
        </view>

        <view class="mb-4">
          <text class="form-label">选择人员</text>
          <view class="flex flex-wrap gap-2">
            <view
              v-for="s in staffOptions"
              :key="s.value"
              class="staff-chip"
              :class="form.staffIds.includes(s.value) ? 'staff-chip-active' : ''"
              @click="toggleStaff(s.value)"
            >
              {{ s.label }}
            </view>
          </view>
          <text v-if="staffOptions.length === 0" class="empty-text mt-2">加载人员中...</text>
        </view>

        <view class="mb-4">
          <text class="form-label">工作日期</text>
          <picker mode="date" :value="form.workDate" @change="(e: any) => form.workDate = e.detail.value">
            <view class="form-field">
              {{ form.workDate || '请选择日期' }}
            </view>
          </picker>
        </view>

        <view class="mb-4">
          <text class="form-label">排班类型</text>
          <view class="shift-tabs">
            <view
              class="shift-tab"
              :class="form.shiftType === 'day' ? 'shift-tab-active' : ''"
              @click="form.shiftType = 'day'"
            >白班</view>
            <view
              class="shift-tab"
              :class="form.shiftType === 'night' ? 'shift-tab-active' : ''"
              @click="form.shiftType = 'night'"
            >夜班</view>
            <view
              class="shift-tab"
              :class="form.shiftType === 'month_plan' ? 'shift-tab-active' : ''"
              @click="form.shiftType = 'month_plan'"
            >月计划</view>
          </view>
        </view>

        <view class="mb-4">
          <text class="form-label">选择车辆</text>
          <view class="flex flex-wrap gap-2">
            <view
              v-for="v in vehicleOptions"
              :key="v.value"
              class="vehicle-chip"
              :class="form.vehicleIds.includes(v.value) ? 'vehicle-chip-active' : ''"
              @click="toggleVehicle(v.value)"
            >
              {{ v.label }}
            </view>
          </view>
        </view>

        <view class="mb-4">
          <text class="form-label">备注（可选）</text>
          <textarea
            v-model="form.remark"
            class="form-textarea"
            placeholder="请输入备注信息..."
          />
        </view>

        <view class="flex gap-3 mt-4">
          <button
            class="modal-btn modal-btn-cancel"
            hover-class="modal-btn-cancel-hover"
            :hover-start-time="0"
            :hover-stay-time="120"
            @click="closeModal"
          >取消</button>
          <button
            class="modal-btn modal-btn-primary"
            hover-class="modal-btn-primary-hover"
            :hover-start-time="0"
            :hover-stay-time="120"
            @click="submitSchedule"
          >{{ isDetail ? '保存' : '确认' }}</button>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import StatusBar from '../common/StatusBar.vue'
import TopBar from '../common/TopBar.vue'
import EmptyState from '../common/EmptyState.vue'
import { getSchedulesByDate, createSchedule, updateSchedule, getScheduleList } from '@/api/schedule'
import { getTeamSimpleList, getTeamMembers, createTeam, updateTeam } from '@/api/team'
import { getStaffSimpleList } from '@/api/staff'
import { getVehicleSimpleList } from '@/api/vehicle'

withDefaults(
  defineProps<{
    showTopBar?: boolean
    showBack?: boolean
    showStatusBar?: boolean
  }>(),
  {
    showTopBar: true,
    showBack: true,
    showStatusBar: false,
  }
)

const loading = ref(false)
const schedules = ref<any[]>([])
const currentYear = ref(new Date().getFullYear())
const currentMonth = ref(new Date().getMonth() + 1)
const selectedDate = ref('')

const showModal = ref(false)
const isDetail = ref(false)
const currentScheduleId = ref<number | undefined>(undefined)
const teamOptions = ref<Array<{ value: number; label: string }>>([])
const vehicleOptions = ref<Array<{ value: number; label: string }>>([])
const staffOptions = ref<Array<{ value: number; label: string }>>([])

type ShiftType = 'day' | 'night' | 'month_plan' | 'emergency'

const form = ref({
  teamId: undefined as number | undefined,
  teamName: '',
  workDate: '',
  shiftType: 'month_plan' as ShiftType,
  vehicleIds: [] as number[],
  staffIds: [] as number[],
  status: 'scheduled',
  remark: '',
})

const weekDays = ['日', '一', '二', '三', '四', '五', '六']

const calendarWeeks = computed(() => {
  const year = currentYear.value
  const month = currentMonth.value
  const firstDay = new Date(year, month - 1, 1)
  const lastDay = new Date(year, month, 0)
  const firstWeekDay = firstDay.getDay()
  const daysInMonth = lastDay.getDate()

  const weeks: any[] = []
  let currentWeek: any[] = []

  const prevMonthDays = new Date(year, month - 1, 0).getDate()
  for (let i = firstWeekDay - 1; i >= 0; i--) {
    currentWeek.push({
      day: prevMonthDays - i,
      isOtherMonth: true,
      isToday: false,
      hasSchedule: false,
    })
  }

  for (let day = 1; day <= daysInMonth; day++) {
    const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`
    const isToday = dateStr === new Date().toISOString().split('T')[0]
    const hasSchedule = schedules.value.some(s => s.workDate === dateStr)

    currentWeek.push({
      day,
      isOtherMonth: false,
      isToday,
      hasSchedule,
      dateStr,
    })

    if (currentWeek.length === 7) {
      weeks.push(currentWeek)
      currentWeek = []
    }
  }

  if (currentWeek.length > 0) {
    for (let i = 1; currentWeek.length < 7; i++) {
      currentWeek.push({
        day: i,
        isOtherMonth: true,
        isToday: false,
        hasSchedule: false,
      })
    }
    weeks.push(currentWeek)
  }

  return weeks
})

const daySchedules = computed(() => {
  if (!selectedDate.value) return []
  return schedules.value.filter(s => s.workDate === selectedDate.value)
})

function changeMonth(delta: number) {
  let newMonth = currentMonth.value + delta
  if (newMonth > 12) {
    newMonth = 1
    currentYear.value++
  } else if (newMonth < 1) {
    newMonth = 12
    currentYear.value--
  }
  currentMonth.value = newMonth
}

function goToToday() {
  const now = new Date()
  currentYear.value = now.getFullYear()
  currentMonth.value = now.getMonth() + 1
  selectedDate.value = now.toISOString().split('T')[0]
}

function selectDate(date: any) {
  if (!date.isOtherMonth) {
    selectedDate.value = date.dateStr
  }
}

function isSelected(date: any): boolean {
  return date.dateStr === selectedDate.value
}

function getStatusText(status: string) {
  const map: Record<string, string> = {
    idle: '待执行',
    scheduled: '已排班',
    in_progress: '进行中',
    completed: '已完成',
    cancelled: '已取消',
  }
  return map[status] || '待执行'
}

function getVehicleNamesText(schedule: any): string {
  const ids = parseVehicleIds(schedule.vehicleIds)
  if (ids.length === 0) return '未分配车辆'
  return ids
    .map(id => vehicleOptions.value.find(v => v.value === id)?.label || String(id))
    .join('、')
}

function getStaffNamesText(schedule: any): string {
  const ids = parseStaffIds(schedule.staffIds)
  if (ids.length === 0) return ''
  return ids
    .map(id => staffOptions.value.find(s => s.value === id)?.label || String(id))
    .join('、')
}

function toggleVehicle(vehicleId: number) {
  const idx = form.value.vehicleIds.indexOf(vehicleId)
  if (idx >= 0) {
    form.value.vehicleIds.splice(idx, 1)
  } else {
    form.value.vehicleIds.push(vehicleId)
  }
}

async function addSchedule() {
  isDetail.value = false
  currentScheduleId.value = undefined
  resetForm()
  form.value.workDate = selectedDate.value
  showModal.value = true
  if (staffOptions.value.length === 0) {
    try {
      staffOptions.value = await getStaffSimpleList()
    } catch (e) {
      console.error('加载人员失败', e)
    }
  }
  if (vehicleOptions.value.length === 0) {
    try {
      vehicleOptions.value = await getVehicleSimpleList()
    } catch (e) {
      console.error('加载车辆失败', e)
    }
  }
}

const shiftTypeTextMap: Record<string, string> = {
  day: '白班',
  night: '夜班',
  month_plan: '月计划',
  emergency: '应急',
}

function getShiftTypeText(shiftType: string | undefined): string {
  if (!shiftType) return shiftTypeTextMap.month_plan
  return shiftTypeTextMap[shiftType] || shiftType
}

function isEmergencyShift(shiftType: string | undefined): boolean {
  return shiftType === 'emergency' || !!(shiftType && shiftType.includes('应急'))
}

function normalizeShiftType(shiftType: string | undefined): ShiftType {
  if (!shiftType) return 'month_plan'
  if (isEmergencyShift(shiftType)) return 'emergency'
  if (shiftType === 'day' || shiftType === 'night' || shiftType === 'month_plan') return shiftType
  return 'month_plan'
}

const shiftBadgeClassMap: Record<ShiftType, string> = {
  day: 'shift-badge--day',
  night: 'shift-badge--night',
  month_plan: 'shift-badge--month',
  emergency: 'shift-badge--emergency',
}

const shiftBadgeIconMap: Record<ShiftType, string> = {
  day: 'uniui-sunny',
  night: 'uniui-moon',
  month_plan: 'uniui-calendar-filled',
  emergency: 'uniui-info-filled',
}

function getShiftBadgeClass(schedule: any): string {
  return shiftBadgeClassMap[(schedule.shiftTypeNorm as ShiftType) || 'month_plan']
}

function getShiftBadgeIcon(schedule: any): string {
  return shiftBadgeIconMap[(schedule.shiftTypeNorm as ShiftType) || 'month_plan']
}

const statusClassMap: Record<string, string> = {
  idle: 'status-idle',
  scheduled: 'status-scheduled',
  in_progress: 'status-in_progress',
  completed: 'status-completed',
  cancelled: 'status-cancelled',
}

function getStatusClass(status: string | undefined): string {
  return statusClassMap[status || 'idle'] || 'status-idle'
}

async function viewSchedule(schedule: any) {
  isDetail.value = true
  currentScheduleId.value = schedule.scheduleId
  form.value = {
    teamId: schedule.teamId,
    teamName: schedule.teamName || schedule.scheduleName || '',
    workDate: schedule.workDate || '',
    shiftType: normalizeShiftType(schedule.shiftType),
    vehicleIds: parseVehicleIds(schedule.vehicleIds),
    staffIds: parseStaffIds(schedule.staffIds),
    status: schedule.status || 'scheduled',
    remark: schedule.remark || '',
  }
  showModal.value = true
  if (staffOptions.value.length === 0) {
    getStaffSimpleList().then(res => { staffOptions.value = res }).catch(e => console.error('加载人员失败', e))
  }
  if (vehicleOptions.value.length === 0) {
    getVehicleSimpleList().then(res => { vehicleOptions.value = res }).catch(e => console.error('加载车辆失败', e))
  }
  if (form.value.staffIds.length === 0 && form.value.teamId) {
    try {
      const members = await getTeamMembers(form.value.teamId)
      form.value.staffIds = members.map(m => m.staffId)
    } catch (e) {
      console.error('加载班组成员失败', e)
    }
  }
}

function parseStaffIds(ids: string | number[] | undefined): number[] {
  if (!ids) return []
  if (Array.isArray(ids)) return ids.map(Number)
  return ids.split(',').map(s => Number(s.trim())).filter(n => !isNaN(n))
}

function toggleStaff(staffId: number) {
  const idx = form.value.staffIds.indexOf(staffId)
  if (idx >= 0) {
    form.value.staffIds.splice(idx, 1)
  } else {
    form.value.staffIds.push(staffId)
  }
}

function buildTeamName(): string {
  if (form.value.staffIds.length === 0) return '未命名班组'
  const names = form.value.staffIds
    .map(id => staffOptions.value.find(s => s.value === id)?.label || String(id))
    .filter(Boolean)
  return names.length ? `${names.join('、')}班组` : '未命名班组'
}

function parseVehicleIds(ids: string | number[] | undefined): number[] {
  if (!ids) return []
  if (Array.isArray(ids)) return ids.map(Number)
  return ids.split(',').map(s => Number(s.trim())).filter(n => !isNaN(n))
}

function closeModal() {
  showModal.value = false
  isDetail.value = false
  currentScheduleId.value = undefined
}

function resetForm() {
  form.value = {
    teamId: undefined,
    teamName: '',
    workDate: selectedDate.value,
    shiftType: 'month_plan',
    vehicleIds: [],
    staffIds: [],
    status: 'scheduled',
    remark: '',
  }
}

async function submitSchedule() {
  if (form.value.staffIds.length === 0) {
    uni.showToast({ title: '请选择人员', icon: 'none' })
    return
  }
  if (!form.value.workDate) {
    uni.showToast({ title: '请选择工作日期', icon: 'none' })
    return
  }
  try {
    const teamName = buildTeamName()
    const memberIds = form.value.staffIds.join(',')
    const vehicleIds = form.value.vehicleIds.join(',')
    let teamId = form.value.teamId

    const teamPayload = {
      teamName,
      memberIds,
      vehicleIds,
      teamType: 'normal',
      status: 'standby',
      remark: form.value.remark || '',
    }

    if (isDetail.value && teamId) {
      await updateTeam(teamId, teamPayload)
    } else {
      teamId = await createTeam(teamPayload)
    }

    const schedulePayload = {
      teamId,
      scheduleName: teamName,
      workDate: form.value.workDate,
      shiftType: form.value.shiftType,
      vehicleIds,
      staffIds: memberIds,
      status: form.value.status,
      remark: form.value.remark,
    }

    if (isDetail.value && currentScheduleId.value) {
      await updateSchedule(currentScheduleId.value, schedulePayload)
      uni.showToast({ title: '保存成功', icon: 'success' })
    } else {
      await createSchedule(schedulePayload)
      uni.showToast({ title: '新增排班成功', icon: 'success' })
    }
    closeModal()
    resetForm()
    await fetchSchedules()
  } catch (e) {
    console.error(isDetail.value ? '保存排班失败' : '新增排班失败', e)
  }
}

async function fetchSchedules() {
  if (!selectedDate.value) return
  loading.value = true
  try {
    if (teamOptions.value.length === 0) {
      try {
        teamOptions.value = await getTeamSimpleList()
      } catch (e) {
        console.error('加载班组失败', e)
      }
    }
    if (vehicleOptions.value.length === 0) {
      try {
        vehicleOptions.value = await getVehicleSimpleList()
      } catch (e) {
        console.error('加载车辆失败', e)
      }
    }
    if (staffOptions.value.length === 0) {
      try {
        staffOptions.value = await getStaffSimpleList()
      } catch (e) {
        console.error('加载人员失败', e)
      }
    }
    const [dayRes, monthRes] = await Promise.all([
      getSchedulesByDate(selectedDate.value),
      getScheduleList(currentYear.value, currentMonth.value)
    ])
    const dayList = dayRes || []
    const monthList = monthRes?.rows || monthRes || []
    const allSchedules = [...dayList]
    monthList.forEach((s: any) => {
      if (!allSchedules.some((x: any) => x.scheduleId === s.scheduleId)) {
        allSchedules.push(s)
      }
    })
    allSchedules.forEach((s: any) => {
      if (!s.teamName) {
        s.teamName = s.scheduleName || ''
      }
      if (!s.teamName && s.teamId != null) {
        s.teamName = teamOptions.value.find(t => t.value === Number(s.teamId))?.label || ''
      }
      s.vehicleNamesText = getVehicleNamesText(s)
      const staffNamesText = getStaffNamesText(s)
      s.teamDisplayName = s.scheduleName
        || (staffNamesText ? `${staffNamesText}班组` : '')
        || s.teamName
        || '未命名班组'
      s.shiftTypeNorm = normalizeShiftType(s.shiftType)
      s.isEmergency = isEmergencyShift(s.shiftType)
      s.shiftTypeText = getShiftTypeText(s.shiftType)
      s.statusText = getStatusText(s.status)
      s.statusClass = getStatusClass(s.status)
    })
    schedules.value = allSchedules
  } catch (error) {
    console.error('获取排班列表失败:', error)
  } finally {
    loading.value = false
  }
}

watch([selectedDate, currentMonth], fetchSchedules)

onMounted(() => {
  const today = new Date().toISOString().split('T')[0]
  selectedDate.value = today
  fetchSchedules()
})
</script>

<style scoped>
/* ==================== 页面外壳 ==================== */
.schedule-page {
  position: relative;
  max-width: 430px;
  margin: 0 auto;
  min-height: 100vh;
  background-color: #f6fbf9; /* 云雾白 */
}

/* ==================== 顶部 banner（山水背景） ==================== */
.banner {
  position: relative;
  height: 140px;
  overflow: hidden;
  background-color: #dff0e8;
}

.banner-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

.banner-veil {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.5) 0%,
    rgba(255, 255, 255, 0.16) 45%,
    rgba(246, 251, 249, 0.66) 100%
  );
}

.banner-inner {
  position: relative;
  z-index: 2;
  padding-top: 14px;
  padding-bottom: 24px;
}

.banner-title {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: 0.5px;
  color: #1f2937;
}

.banner-sub {
  margin-top: 4px;
  font-size: 12px;
  color: rgba(31, 41, 37, 0.62);
}

/* ==================== 内容区 ==================== */
.content-wrap {
  position: relative;
  z-index: 2;
  margin-top: -18px;
}

/* 磨砂玻璃卡 */
.glass-card {
  background-color: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(164, 216, 152, 0.35);
  border-radius: 24px;
  box-shadow: 0 18px 50px -12px rgba(54, 143, 111, 0.28);
  overflow: hidden;
  margin-bottom: 12px;
}

/* ==================== 月份切换 ==================== */
.month-row {
  display: flex;
  align-items: center;
  justify-content: center;
}

.month-arrow {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(164, 216, 152, 0.16);
}

.month-arrow-hover {
  background-color: rgba(164, 216, 152, 0.3);
}

.month-arrow-icon {
  font-size: 16px;
  color: #368f6f;
}

.month-text {
  margin: 0 16px;
  font-size: 16px;
  font-weight: 700;
  color: #1f2937;
}

/* ==================== 快捷操作 ==================== */
.action-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 14px;
}

.action-chip {
  display: flex;
  align-items: center;
  padding: 7px 18px;
  border-radius: 999px;
  background-color: #ffffff;
  border: 1px solid rgba(164, 216, 152, 0.45);
}

.action-chip-hover {
  background-color: rgba(164, 216, 152, 0.14);
}

.action-chip-icon {
  font-size: 14px;
  color: #368f6f;
}

.action-chip-text {
  font-size: 13px;
  font-weight: 500;
  color: #368f6f;
}

.action-chip-primary {
  background: linear-gradient(135deg, #368f6f 0%, #4ba98a 100%);
  border-color: transparent;
  box-shadow: 0 8px 20px -8px rgba(54, 143, 111, 0.6);
}

.action-chip-primary-hover {
  opacity: 0.88;
}

.action-chip-icon-light {
  font-size: 14px;
  color: #ffffff;
}

.action-chip-text-light {
  font-size: 13px;
  font-weight: 600;
  color: #ffffff;
}

/* ==================== 日历 ==================== */
.weekday-text {
  font-size: 12px;
  color: #9ca3af;
}

.day-cell {
  flex: 1;
  height: 56px;
  margin: 0 4px;
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.day-other {
  opacity: 0.3;
}

.day-today {
  background-color: rgba(164, 216, 152, 0.2);
}

.day-selected {
  background: linear-gradient(135deg, #368f6f 0%, #4ba98a 100%);
  box-shadow: 0 8px 18px -8px rgba(54, 143, 111, 0.65);
}

.day-hover {
  transform: scale(0.94);
}

.day-num {
  font-size: 14px;
  font-weight: 500;
  color: #1f2937;
}

.day-num-today {
  color: #368f6f;
  font-weight: 700;
}

.day-num-selected {
  color: #ffffff;
  font-weight: 700;
}

.day-dot {
  width: 6px;
  height: 6px;
  margin-top: 4px;
  border-radius: 50%;
  background-color: #368f6f;
}

.day-dot-light {
  background-color: #ffffff;
}

/* ==================== 区块标题栏 ==================== */
.section-head {
  display: flex;
  align-items: center;
  padding: 16px 16px 12px;
}

.section-bar {
  width: 4px;
  height: 16px;
  border-radius: 2px;
  background: linear-gradient(180deg, #368f6f 0%, #5ab8d0 100%);
}

.section-title {
  font-size: 16px;
  font-weight: 700;
  color: #1f2937;
}

/* ==================== 排班卡片 ==================== */
.schedule-list {
  padding: 0 16px 16px;
}

.schedule-card {
  background-color: #ffffff;
  border-radius: 18px;
  padding: 14px 16px;
  margin-bottom: 12px;
  border: 1px solid rgba(164, 216, 152, 0.18);
  box-shadow: 0 4px 14px -4px rgba(54, 143, 111, 0.12);
}

.schedule-card-hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 22px -6px rgba(54, 143, 111, 0.18);
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.shift-badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}

.shift-badge__icon {
  margin-right: 4px;
  font-size: 13px;
}

.shift-badge--day {
  color: #368f6f;
  background-color: rgba(54, 143, 111, 0.12);
}

.shift-badge--night {
  color: #2563eb;
  background-color: rgba(37, 99, 235, 0.12);
}

.shift-badge--month {
  color: #8b5cf6;
  background-color: rgba(139, 92, 246, 0.12);
}

.shift-badge--emergency {
  color: #ef4444;
  background-color: rgba(239, 68, 68, 0.1);
}

.status-badge {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}

.status-idle {
  color: #6b7280;
  background-color: #f3f4f6;
}

.status-scheduled {
  color: #368f6f;
  background-color: rgba(54, 143, 111, 0.1);
}

.status-in_progress {
  color: #f59e0b;
  background-color: rgba(245, 158, 11, 0.12);
}

.status-completed {
  color: #6b7280;
  background-color: #f3f4f6;
}

.status-cancelled {
  color: #9ca3af;
  background-color: #f3f4f6;
}

.card-body {
  margin-bottom: 10px;
}

.team-name {
  display: block;
  font-size: 15px;
  font-weight: 700;
  color: #1f2937;
  margin-bottom: 6px;
}

.vehicle-line {
  display: flex;
  align-items: center;
}

.car-icon {
  margin-right: 5px;
  font-size: 13px;
  color: #9ca3af;
}

.vehicle-text {
  font-size: 13px;
  color: #6b7280;
}

.card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 10px;
  border-top: 1px solid rgba(164, 216, 152, 0.12);
}

.date-line {
  display: flex;
  align-items: center;
}

.date-icon {
  margin-right: 4px;
  font-size: 12px;
  color: #9ca3af;
}

.date-text {
  font-size: 12px;
  color: #9ca3af;
}

.row-arrow {
  font-size: 16px;
  color: #c4d0cb;
  flex-shrink: 0;
}

.empty-text {
  font-size: 13px;
  color: #9ca3af;
}

/* ==================== 弹窗 ==================== */
.schedule-modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-bottom: var(--window-bottom, 0);
}

.schedule-modal__overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.5);
}

.schedule-modal__panel {
  position: relative;
  width: 100%;
  max-height: 60vh;
  margin-bottom: 100rpx;
  padding: 32rpx;
  overflow-y: auto;
  background-color: #ffffff;
  border-top-left-radius: 48rpx;
  border-top-right-radius: 48rpx;
}

.modal-title {
  font-size: 16px;
  font-weight: 700;
  color: #1f2937;
}

.modal-close {
  font-size: 18px;
  color: #9ca3af;
}

.form-label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 500;
  color: #6b7280;
}

.form-field {
  padding: 10px 12px;
  border-radius: 12px;
  border: 1px solid #e5e7eb;
  background-color: #ffffff;
  font-size: 14px;
  color: #1f2937;
}

.form-textarea {
  width: 100%;
  min-height: 80px;
  padding: 10px 12px;
  border-radius: 12px;
  border: 1px solid #e5e7eb;
  background-color: #ffffff;
  font-size: 14px;
  color: #1f2937;
}

.shift-tabs {
  display: flex;
  border-radius: 12px;
  border: 1px solid #e5e7eb;
  overflow: hidden;
}

.shift-tab {
  flex: 1;
  padding: 10px 0;
  text-align: center;
  font-size: 14px;
  color: #6b7280;
  background-color: #ffffff;
}

.shift-tab-active {
  background: linear-gradient(135deg, #368f6f 0%, #4ba98a 100%);
  color: #ffffff;
  font-weight: 600;
}

.shift-tab-danger {
  background-color: #ef4444;
  color: #ffffff;
  font-weight: 600;
}

.vehicle-chip {
  padding: 6px 12px;
  border-radius: 10px;
  font-size: 12px;
  color: #6b7280;
  background-color: #ffffff;
  border: 1px solid #e5e7eb;
}

.vehicle-chip-active {
  color: #ffffff;
  background: linear-gradient(135deg, #368f6f 0%, #4ba98a 100%);
  border-color: transparent;
}

.staff-chip {
  padding: 6px 12px;
  border-radius: 10px;
  font-size: 12px;
  color: #6b7280;
  background-color: #ffffff;
  border: 1px solid #e5e7eb;
}

.staff-chip-active {
  color: #ffffff;
  background: linear-gradient(135deg, #368f6f 0%, #4ba98a 100%);
  border-color: transparent;
}

.modal-btn {
  flex: 1;
  padding: 12px 0;
  border-radius: 14px;
  font-size: 14px;
  line-height: 1.4;
}

.modal-btn-cancel {
  background-color: #ffffff;
  color: #6b7280;
  border: 1px solid #e5e7eb;
}

.modal-btn-cancel-hover {
  background-color: #f9fafb;
}

.modal-btn-primary {
  background: linear-gradient(135deg, #368f6f 0%, #4ba98a 100%);
  color: #ffffff;
  font-weight: 600;
  box-shadow: 0 10px 24px -10px rgba(54, 143, 111, 0.7);
}

.modal-btn-primary-hover {
  opacity: 0.88;
}
</style>
