<template>
  <div class="ticket-management-container">
    <!-- 顶部搜索区域 -->
    <div id="topSearchArea" class="top-search-area">
      <!-- 搜索标签行 -->
      <div class="search-labels">
        <div class="search-label">导源日期</div>
        <div class="search-label">状态</div>
        <div class="search-label">患者姓名</div>
        <div class="search-label">就诊卡号</div>
        <div class="search-label">手机号</div>
        <div class="search-label"></div> <!-- 为查询按钮预留空间 -->
      </div>
      
      <!-- 搜索输入行 -->
      <div class="search-inputs">
        <!-- 移动端汉堡菜单按钮 -->
        <div class="hamburger-menu" @click="toggleSidebar" v-if="isMobile">
          <i class="el-icon-menu"></i>
        </div>
        <div id="datePicker" class="date-picker">
          <el-date-picker
            v-model="selectedDate"
            type="date"
            placeholder="选择日期"
            format="YYYY/MM/DD"
            value-format="YYYY-MM-DD"
            :shortcuts="dateShortcuts"
            class="date-picker"
            @change="onDateChange"
          />
        </div>
        <div id="statusFilter" class="status-filter">
          <select id="status-select" class="search-select" v-model="selectedStatus">
            <option value="all">全部</option>
            <option value="unbooked">未预约</option>
            <option value="locked">锁定</option>
            <option value="booked">待缴费</option>
            <option value="checked">已取号</option>
            <option value="cancelled">已停诊</option>
          </select>
        </div>
        <div id="patientSearch" class="patient-search">
          <input id="patient-name-input" class="search-input" placeholder="姓名" v-model="patientName">
        </div>
        <div id="cardSearch" class="card-search">
          <input id="patient-card-input" class="search-input" placeholder="就诊卡号" v-model="patientCard">
        </div>
        <div id="phoneSearch" class="phone-search">
          <input id="patient-phone-input" class="search-input" placeholder="手机号" v-model="patientPhone">
        </div>
        <div class="search-button">
          <button id="search-button" class="search-btn" @click="onSearch" :disabled="isLoading">
            <span v-if="isLoading" class="loading-text">搜索中...</span>
            <span v-else>查询</span>
          </button>
        </div>
      </div>
    </div>

    <!-- 主要内容区域 -->
    <div id="mainContent" class="main-content">
      <!-- 左侧筛选区域 -->
      <div id="leftSidebar" class="left-sidebar" :class="{ 'sidebar-hidden': isMobile && !showSidebar, 'sidebar-mobile': isMobile }">
        <!-- 科室列表 -->
        <div class="section">
          <h3 class="section-title">科室列表</h3>
          <select id="department-list" class="search-select" v-model="selectedDepartment" @change="onDepartmentChange">
            <option value="all">全部科室</option>
            <option v-for="department in departments" :key="department.value" :value="department.value">
              {{ department.label }}
            </option>
          </select>
        </div>

        <!-- 号源类型 -->
        <div class="section">
          <h3 class="section-title">号源类型</h3>
          <div class="radio-group">
            <label>
              <input type="radio" name="type" value="general" v-model="selectedType" @change="onTypeChange">
              <span>普通号</span>
            </label>
            <label>
              <input type="radio" name="type" value="expert" v-model="selectedType" @change="onTypeChange">
              <span>专家号</span>
            </label>
          </div>
        </div>

        <!-- 医生号源列表 -->
        <div class="section">
          <h3 class="section-title">医生号源列表</h3>
          <input id="doctor-search" class="search-input" placeholder="搜索医生姓名" v-model="searchQuery" @input="onDoctorSearch">
          <div class="doctor-list">
            <div class="doctor-item" v-for="doctor in filteredDoctors" :key="doctor.id" :class="{ selected: selectedDoctorId === doctor.id }" @click="selectDoctor(doctor.id)">
              <div class="doctor-name">{{ doctor.name }} <span class="doctor-available">余号：{{ doctor.available }}</span></div>
            </div>
          </div>
        </div>
      </div>

      <!-- 右侧号源卡片区域 -->
      <div class="right-content" :class="{ 'right-content-full': isMobile && !showSidebar }">
        <!-- 使用网格布局的号源卡片列表 -->
        <div class="ticket-grid" v-if="filteredTickets.length > 0">
          <div v-for="(item, index) in filteredTickets" :key="item.slot_id" class="ticket-card" @dblclick="handleDoubleClick(item)" @contextmenu.prevent="handleRightClick($event, item)">
            <div class="ticket-header">
              <div class="ticket-number">{{ index + 1 }}</div>
              <div class="ticket-type-badge" :class="item.ticketType === 'general' ? 'type-general' : 'type-expert'">
                {{ item.ticketType === 'general' ? '普通' : '专家' }}
              </div>
            </div>
            <div class="ticket-time">{{ item.dateTime }}</div>
            <div class="ticket-doctor">{{ item.doctor }}</div>
            <div class="ticket-status" :class="`status-${item.status}`">
              <span class="status-dot"></span>
              {{ item.status }}
            </div>
            <div class="ticket-fee">挂号费: {{ item.fee }}</div>
            <!-- 显示患者信息（如果已预约或已取号） -->
            <div v-if="(item.status === '已预约' || item.status === '已取号') && item.patientName" class="ticket-patient">
              <div class="patient-name">{{ item.patientName }}</div>
              <div class="patient-card">{{ item.patientId }}</div>
            </div>
            <div class="ticket-actions">
              <button class="action-button book-button" @click="openPatientSelectModal(item.slot_id)" :disabled="item.status !== '未预约'" :class="{ 'disabled': item.status !== '未预约' }">
                <i class="el-icon-tickets"></i>
                预约
              </button>
              <button class="action-button cancel-button" @click="confirmCancelConsultation(item)" :disabled="item.status === '已取消'" :class="{ 'disabled': item.status === '已取消' }">
                <i class="el-icon-close"></i>
                停诊
              </button>
              <button class="action-button check-in-button" @click="confirmCheckIn(item)" :disabled="item.status !== '已预约'" :class="{ 'disabled': item.status !== '已预约' }">
                <i class="el-icon-circle-check"></i>
                取号
              </button>
            </div>
          </div>
          <div v-if="hasMore" class="loading-more">
            加载中...
          </div>
          <div v-else class="no-more">
            没有更多数据了
          </div>
        </div>
        <div v-else class="empty-state">
          <div class="empty-text">暂无号源数据</div>
        </div>
      </div>
    </div>

    <!-- 患者选择弹窗 -->
    <div id="patient-select-modal" class="modal" v-if="showPatientModal">
      <div class="modal-content">
        <div class="modal-header">
          <h3>选择患者</h3>
          <button class="close-btn" @click="closePatientSelectModal">&times;</button>
        </div>
        <div class="modal-body">
          <input id="patientName" class="search-input" placeholder="患者姓名" v-model="patientSearchParams.patientName" @input="onPatientSearchInput">
          <input id="medicalCard" class="search-input" placeholder="就诊卡号" v-model="patientSearchParams.medicalCard" @input="onPatientSearchInput">
          <input id="idCard" class="search-input" placeholder="身份证号" v-model="patientSearchParams.idCard" @input="onPatientSearchInput">
          <input id="phone" class="search-input" placeholder="手机号" v-model="patientSearchParams.phone" @input="onPatientSearchInput">
          <button id="patient-search-btn" class="search-btn" @click="searchPatients">查询</button>
          <div class="patient-table-container">
            <table id="patient-table" class="patient-table">
              <thead>
                <tr>
                  <th>序号</th>
                  <th>患者姓名</th>
                  <th>就诊卡号</th>
                  <th>身份证号</th>
                  <th>手机号</th>
                  <th>操作</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(patient, index) in patients" :key="patient.id" :class="{ selected: selectedPatientId === patient.id }" @click="selectPatient(patient.id)">
                  <td>{{ index + 1 }}</td>
                  <td>{{ patient.name }}</td>
                  <td>{{ patient.medicalCard }}</td>
                  <td>{{ patient.idCard }}</td>
                  <td>{{ patient.phone }}</td>
                  <td>
                    <button class="select-btn" @click.stop="selectPatient(patient.id)">选择</button>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
        <div class="modal-footer">
          <button class="confirm-btn" @click="confirmPatientSelection">确认</button>
          <button class="cancel-btn" @click="closePatientSelectModal">取消</button>
        </div>
      </div>
    </div>
    <!-- 右键菜单 -->
    <div
      v-if="contextMenuVisible"
      class="context-menu"
      :style="{
        left: contextMenuPosition.x + 'px',
        top: contextMenuPosition.y + 'px'
      }"
      @click.stop
      @contextmenu.prevent
    >
      <div v-if="selectedTicketForCancel && (selectedTicketForCancel.status === 'booked' || selectedTicketForCancel.status === 'locked' || selectedTicketForCancel.status === 'checked')" class="menu-item" @click="confirmCancelAppointment">
          取消预约
        </div>
    </div>

    <!-- 点击页面其他地方关闭右键菜单 -->
    <div
      v-if="contextMenuVisible"
      class="context-menu-overlay"
      @click="closeContextMenu"
      @contextmenu.prevent
    ></div>
  </div>
</template>

<script>
import { listTicket, bookTicket, cancelTicket, checkInTicket, cancelConsultation } from '@/api/appoinmentmanage/ticket';
import { getPatientList } from '@/api/cardRenewal/api';
import { listDept } from '@/api/appoinmentmanage/dept';
import { ref } from 'vue'
import { ElDatePicker } from 'element-plus'

export default {
  name: 'TicketManage',
  components: {
    ElDatePicker
  },
  
  // 添加全局点击事件监听器，用于关闭右键菜单
  mounted() {
    document.addEventListener('click', this.closeContextMenu);
  },
  
  // 移除事件监听器
  beforeUnmount() {
    document.removeEventListener('click', this.closeContextMenu);
  },
  data() {
    return {
      selectedDate: new Date().toISOString().split('T')[0],
      selectedStatus: 'unbooked',
      selectedDepartment: 'all',
      selectedType: 'general', // 普通号默认选中
      selectedDoctorId: null,
      showPatientModal: false,
      selectedPatientId: null,
      selectedPatient: null,
      currentTicket: null,
      patientName: '',
      patientCard: '',
      patientPhone: '',
      isLoading: false,
      // 移动端相关变量
      isMobile: false,
      showSidebar: false,
      // 分页相关属性
      currentPage: 1,
      pageSize: 20,
      totalTickets: 0,
      hasMore: true,
      // 右键菜单相关
      contextMenuVisible: false,
      contextMenuPosition: { x: 0, y: 0 },
      selectedTicketForCancel: null,
      departments: [
        { value: 'all', label: '全部科室' }
      ],
      doctors: [],
      allTickets: [], // 存储所有原始号源数据
      tickets: [], // 从API获取的真实号源数据
      patients: [], // 从API获取的真实患者数据
      searchQuery: '',
      // 患者搜索相关
      patientSearchParams: {
        patientName: '',
        medicalCard: '',
        idCard: '',
        phone: ''
      },
      dateShortcuts: [
        { text: '今天', value: new Date() },
        { text: '明天', value: () => { const date = new Date(); date.setDate(date.getDate() + 1); return date; } },
        { text: '本周', value: () => { const date = new Date(); const day = date.getDay() || 7; date.setDate(date.getDate() - day + 1); return date; } },
        { text: '下周', value: () => { const date = new Date(); const day = date.getDay() || 7; date.setDate(date.getDate() - day + 8); return date; } },
        { text: '本月', value: () => { const date = new Date(); date.setDate(1); return date; } },
        { text: '下月', value: () => { const date = new Date(); date.setMonth(date.getMonth() + 1); date.setDate(1); return date; } }
      ]
    }
  },
  computed: {
    filteredDoctors() {
      let filtered = [...this.doctors];
      
      // 根据号源类型过滤医生列表
      if (this.selectedType === 'general') {
        filtered = filtered.filter(doctor => doctor.type === 'general');
      } else if (this.selectedType === 'expert') {
        filtered = filtered.filter(doctor => doctor.type === 'expert');
      }
      
      // 根据搜索关键词过滤
      if (this.searchQuery) {
        filtered = filtered.filter(doctor => 
          doctor.name.includes(this.searchQuery)
        );
      }
      
      return filtered;
    },
    filteredTickets() {
      let filtered = [...this.tickets];
      
      // 按日期筛选（如果选择了日期） - 暂时注释掉以排查问题
      // if (this.selectedDate) {
      //   filtered = filtered.filter(ticket => {
      //     // 使用后端返回的dateTime字段进行筛选
      //     if (ticket.dateTime) {
      //       return ticket.dateTime.startsWith(this.selectedDate);
      //     }
      //     return true;
      //   });
      // }
      
      // 按状态筛选 - 暂时注释掉以排查问题
      // if (this.selectedStatus !== 'all') {
      //   // 状态映射表（后端返回中文状态，前端使用英文状态）
      //   const statusMap = {
      //     'unbooked': '未预约',
      //     'locked': '已锁定',
      //     'booked': '已预约',
      //     'checked': '已取号',
      //     'cancelled': '已取消'
      //   };
      //   const chineseStatus = statusMap[this.selectedStatus];
      //   filtered = filtered.filter(ticket => ticket.status === chineseStatus);
      // }
      
      // 按科室筛选 - 暂时注释掉以排查问题
      // if (this.selectedDepartment !== 'all') {
      //   filtered = filtered.filter(ticket => ticket.department === this.selectedDepartment);
      // }
      
      // 按号源类型筛选 - 暂时注释掉以排查问题
      // filtered = filtered.filter(ticket => {
      //   if (this.selectedType === 'general') {
      //     return ticket.ticketType === 'general';
      //   } else if (this.selectedType === 'expert') {
      //     return ticket.ticketType === 'expert';
      //   }
      //   return true;
      // });
      
      // 按医生筛选 - 暂时注释掉以排查问题
      // if (this.selectedDoctorId) {
      //   const selectedDoctor = this.doctors.find(d => d.id === this.selectedDoctorId);
      //   if (selectedDoctor) {
      //     filtered = filtered.filter(ticket => ticket.doctor === selectedDoctor.name);
      //   }
      // }
      
      // 按患者信息筛选（姓名、就诊卡号、手机号） - 暂时注释掉以排查问题
      // if (this.patientName || this.patientCard || this.patientPhone) {
      //   filtered = filtered.filter(ticket => {
      //     const matchesName = !this.patientName || ticket.patientName?.includes(this.patientName);
      //     const matchesCard = !this.patientCard || ticket.patientId?.includes(this.patientCard);
      //     const matchesPhone = !this.patientPhone || ticket.phone?.includes(this.patientPhone);
      //     
      //     return matchesName && matchesCard && matchesPhone;
      //   });
      // }
      
      return filtered;
    },
  },
  methods: {
    selectDoctor(doctorId) {
      this.selectedDoctorId = doctorId
      console.log('Selected doctor:', doctorId)
      // 医生选择后，筛选号源
      this.onSearch();
    },
    onTypeChange() {
      console.log('Type changed:', this.selectedType)
      this.onSearch()
    },
    onDepartmentChange() {
      console.log('Department changed:', this.selectedDepartment)
      this.onSearch()
    },
    onDoctorSearch() {
      console.log('Searching doctor:', this.searchQuery)
      this.onSearch()
    },
    openPatientSelectModal(ticketId) {
      this.currentTicket = this.tickets.find(ticket => ticket.slot_id === ticketId);
      // 打开患者选择弹窗时，查询患者列表
      this.searchPatients();
      this.showPatientModal = true
    },
    
    // 患者搜索
    searchPatients() {
      // 调用真实API获取患者列表
      getPatientList(this.patientSearchParams).then(response => {
        if (response.data && response.data.records) {
          this.patients = response.data.records;
        } else {
          this.patients = [];
        }
      }).catch(error => {
        console.error('获取患者列表失败:', error);
        this.patients = [];
      });
    },
    
    // 监听患者搜索输入变化
    onPatientSearchInput(event) {
      const field = event.target.id;
      const value = event.target.value;
      
      // 根据输入框ID更新对应的搜索参数
      switch(field) {
        case 'patientName':
          this.patientSearchParams.patientName = value;
          break;
        case 'medicalCard':
          this.patientSearchParams.medicalCard = value;
          break;
        case 'idCard':
          this.patientSearchParams.idCard = value;
          break;
        case 'phone':
          this.patientSearchParams.phone = value;
          break;
      }
    },
    
    // 双击未预约卡片触发患者选择流程
    handleDoubleClick(ticket) {
      if (ticket.status === '未预约') {
        this.currentTicket = ticket;
        this.selectedPatientId = null;
        this.showPatientModal = true;
      }
    },
    
    // 右键已预约卡片显示取消预约菜单
    handleRightClick(event, ticket) {
      if (ticket.status === '已预约') {
        this.selectedTicketForCancel = ticket;
        this.contextMenuPosition = { x: event.clientX, y: event.clientY };
        this.contextMenuVisible = true;
      }
    },
    
    // 关闭右键菜单
    closeContextMenu() {
      this.contextMenuVisible = false;
      this.selectedTicketForCancel = null;
    },
    
    // 确认取消预约
    confirmCancelAppointment() {
      if (this.selectedTicketForCancel) {
        // 二次确认
        if (confirm(`确认取消患者的预约？`)) {
          // 调用API取消预约
          this.cancelAppointment(this.selectedTicketForCancel);
        }
        this.closeContextMenu();
      }
    },
    
    // 确认停诊
    confirmCancelConsultation(ticket) {
      // 二次确认
      if (confirm(`确认取消${ticket.doctor}在${ticket.dateTime}的看诊吗？`)) {
        // 调用API处理停诊
        this.cancelConsultation(ticket);
      }
    },
    
    // 处理停诊
    cancelConsultation(ticket) {
      // 使用真实API调用处理停诊
      cancelConsultation(ticket.slot_id).then(response => {
        // API调用成功后，重新获取最新的号源数据
        this.onSearch();
        alert('停诊已处理，该号源已被取消');
      }).catch(error => {
        console.error('停诊处理失败:', error);
        alert('停诊处理失败，请稍后重试。');
      });
    },
    
    // 确认取号
    confirmCheckIn(ticket) {
      // 二次确认
      if (confirm(`确认${ticket.patientName || ''}取号吗？`)) {
        // 调用API处理取号
        this.checkIn(ticket);
      }
    },
    
    // 处理取号
    checkIn(ticket) {
      // 使用真实API调用处理取号
      checkInTicket(ticket.slot_id).then(response => {
        // API调用成功后，重新获取最新的号源数据
        this.onSearch();
        alert('取号成功！');
      }).catch(error => {
        console.error('取号失败:', error);
        alert('取号失败，请稍后重试。');
      });
    },
    
    // 取消预约API调用
    cancelAppointment(ticket) {
        // 使用真实API调用取消预约
        cancelTicket(ticket.slot_id).then(response => {
          // API调用成功后，重新获取最新的号源数据
          this.onSearch();
          // 关闭上下文菜单
          this.closeContextMenu();
          alert('预约已取消，号源已释放');
        }).catch(error => {
          console.error('取消预约失败:', error);
          alert('取消预约失败，请稍后重试。');
        });
      },
    closePatientSelectModal() {
      this.showPatientModal = false
      this.selectedPatientId = null
    },
    selectPatient(patientId) {
      this.selectedPatientId = patientId;
      // 保存选择的患者对象
      this.selectedPatient = this.patients.find(patient => patient.id === patientId);
    },
    confirmPatientSelection() {
      if (this.selectedPatientId && this.selectedPatient) {
        // 这里可以添加确认患者选择后的逻辑
        console.log('Selected patient:', this.selectedPatient, 'for ticket:', this.currentTicket.slot_id)
        
        // 构建预约数据
        const appointmentData = {
          ticketId: Number(this.currentTicket.slot_id),
          patientId: this.selectedPatientId ? Number(this.selectedPatientId) : null,
          patientName: this.selectedPatient.name,
          medicalCard: this.selectedPatient.medicalCard,
          phone: this.selectedPatient.phone
        };
        
        // 使用真实API调用进行预约
        bookTicket(appointmentData).then(response => {
          // API调用成功后，重新获取最新的号源数据
          this.onSearch();
          this.closePatientSelectModal();
          alert('预约成功，号源已锁定。患者到院签到时需缴费取号。');
        }).catch(error => {
          console.error('预约失败:', error);
          alert('预约失败，请稍后重试。');
        });
      } else {
        alert('请选择患者')
      }
    },
    onDateChange() {
      // 日期变化时刷新号源列表
      console.log('Date changed:', this.selectedDate)
      // 重置页码并重新加载数据
      this.currentPage = 1;
      this.onSearch()
    },
    // 切换侧边栏显示/隐藏
    toggleSidebar() {
      this.showSidebar = !this.showSidebar;
    },
    // 检测是否为移动设备
    checkMobileDevice() {
      this.isMobile = window.innerWidth <= 768;
    },
    onSearch() {
      this.isLoading = true
      console.log('Searching with:', {
        date: this.selectedDate,
        status: this.selectedStatus,
        type: this.selectedType,
        name: this.patientName,
        card: this.patientCard,
        phone: this.patientPhone
      });
      
      // 调用真实API获取号源数据
      const queryParams = {
        date: this.selectedDate,
        status: this.selectedStatus,
        type: this.selectedType,
        name: this.patientName,
        card: this.patientCard,
        phone: this.patientPhone,
        page: 1,
        limit: this.pageSize
      };
      
      // 并行调用号源和科室API
      Promise.all([
        listTicket(queryParams),
        listDept()
      ]).then(([ticketResponse, deptResponse]) => {
        // 打印完整的响应数据以便调试
        console.log('完整的号源响应数据:', ticketResponse);
        
        // 处理号源数据
        if (ticketResponse) {
          // 检查是否有records字段（响应拦截器已经返回了res.data，所以直接访问ticketResponse.records）
          if (ticketResponse.records) {
            this.tickets = ticketResponse.records;
            this.totalTickets = ticketResponse.total;
          } else {
            // 如果没有records字段，可能数据直接在对象中
            this.tickets = [ticketResponse];
            this.totalTickets = 1;
          }
          
          // 保存所有原始数据
          this.allTickets = [...this.tickets];
          // 更新医生列表
          this.updateDoctorsList();
          this.hasMore = this.tickets.length < this.totalTickets;
        } else {
          this.tickets = [];
          this.allTickets = [];
          this.totalTickets = 0;
          this.hasMore = false;
        }
        
        // 处理科室数据
        this.updateDepartmentsListFromApi(deptResponse);
        
        this.isLoading = false;
      }).catch(error => {
        console.error('获取数据失败:', error);
        this.tickets = [];
        this.allTickets = [];
        this.totalTickets = 0;
        this.hasMore = false;
        this.departments = [{ value: 'all', label: '全部科室' }];
        this.isLoading = false;
      });
    },

    
    // 从号源数据中更新科室列表（备用方法）
    updateDepartmentsList() {
      const departmentSet = new Set();
      this.tickets.forEach(ticket => {
        departmentSet.add(ticket.department);
      });
      
      // 转换为数组并添加"全部科室"选项
      const departmentArray = Array.from(departmentSet).map(dept => ({
        value: dept,
        label: dept
      }));
      
      this.departments = [
        { value: 'all', label: '全部科室' },
        ...departmentArray
      ];
    },
    
    // 从API获取完整科室列表
    updateDepartmentsListFromApi(deptResponse) {
      // 检查后端返回的数据结构
      let deptList = [];
      if (deptResponse.data) {
        // 适配不同的后端数据结构
        if (Array.isArray(deptResponse.data)) {
          deptList = deptResponse.data;
        } else if (Array.isArray(deptResponse.data.data)) {
          deptList = deptResponse.data.data;
        }
      }
      
      if (deptList.length > 0) {
        // 从API返回的科室数据中提取科室名称
        const departmentArray = deptList
          .filter(dept => dept.deptName) // 确保科室名称存在
          .map(dept => ({
            value: dept.deptName,
            label: dept.deptName
          }))
          .filter((dept, index, self) => 
            index === self.findIndex((d) => d.value === dept.value) // 去重
          );
        
        this.departments = [
          { value: 'all', label: '全部科室' },
          ...departmentArray
        ];
      } else {
        // 如果API调用失败或没有数据，回退到从号源数据中提取
        this.updateDepartmentsList();
      }
    },
    
    // 获取号源状态文本
    getStatusText(status) {
      switch (status) {
        case 'unbooked':
          return '未预约';
        case 'booked':
          return '已预约';
        case 'checked':
          return '已取号';
        case 'cancelled':
          return '已取消';
        case 'locked':
          return '已锁定';
        default:
          return '未知状态';
      }
    },
    
    // 从号源数据中更新医生列表
    updateDoctorsList() {
      const doctorMap = new Map();
      
      // 统计每个医生的余号数量和类型
      this.tickets.forEach(ticket => {
        // 检查ticket对象是否有效
        if (!ticket) return;
        
        // 统计所有号源的医生，不仅仅是未预约的
        if (doctorMap.has(ticket.doctor)) {
          // 如果是未预约状态，增加余号数量
          if (ticket.status === '未预约') {
            doctorMap.get(ticket.doctor).available += 1;
          }
        } else {
          // 根据号源类型设置医生类型
          const doctorType = ticket.ticketType || 'general';
          doctorMap.set(ticket.doctor, { 
            id: Date.now() + Math.random(), 
            name: ticket.doctor, 
            available: ticket.status === '未预约' ? 1 : 0, 
            type: doctorType
          });
        }
      });
      
      // 转换为数组
      this.doctors = Array.from(doctorMap.values());
      
      // 打印医生列表以便调试
      console.log('生成的医生列表:', this.doctors);
    },
    // 加载更多数据
    loadMore() {
      // 已经在加载中，不再重复请求
      if (this.isLoading || !this.hasMore) {
        return;
      }
      
      this.isLoading = true;
      this.currentPage++;
      
      const queryParams = {
        date: this.selectedDate,
        status: this.selectedStatus,
        name: this.patientName,
        card: this.patientCard,
        phone: this.patientPhone,
        page: this.currentPage,
        limit: this.pageSize
      };
      
      listTicket(queryParams).then(response => {
        // 打印完整的响应数据以便调试
        console.log('加载更多的号源响应数据:', response);
        
        // 处理号源数据
        if (response) {
          let newRecords = [];
          
          // 检查是否有records字段（响应拦截器已经返回了res.data，所以直接访问response.records）
          if (response.records) {
            newRecords = response.records;
            this.totalTickets = response.total;
          } else {
            // 如果没有records字段，可能数据直接在对象中
            newRecords = [response];
            this.totalTickets = this.tickets.length + 1;
          }
          
          // 将API返回的数据添加到tickets数组中
          this.tickets = [...this.tickets, ...newRecords];
        }
        
        this.isLoading = false;
        this.hasMore = this.tickets.length < this.totalTickets;
        
        // 更新科室和医生列表
        this.updateDepartmentsList();
        this.updateDoctorsList();
      }).catch(error => {
        console.error('获取号源列表失败:', error);
        this.isLoading = false;
      });
    },
    // 滚动事件处理函数，实现滚动加载

  },
  mounted() {
    // 初始化数据
    this.selectedDate = new Date().toISOString().split('T')[0];
    // 调用onSearch获取初始数据
    this.onSearch();
    // 检测是否为移动设备
    this.checkMobileDevice();
    // 监听窗口大小变化
    window.addEventListener('resize', this.checkMobileDevice);
  },
  beforeUnmount() {
    // 移除窗口大小变化监听
    window.removeEventListener('resize', this.checkMobileDevice);
  }
}
</script>

<style scoped>
/* 颜色变量定义 */
:root {
  --primary-color: #1890FF;
  --secondary-color: #FF6B35;
  --status-unbooked: #5A8DEE;
  --status-booked: #FAAD14;
  --status-checked: #52C41A;
  --status-cancelled: #F5222D;
  --border-color: #d9d9d9;
  --text-primary: #333;
  --text-secondary: #666;
  --text-tertiary: #999;
  --bg-light: #f8f9fa;
  --bg-white: #fff;
  --shadow: 0 2px 8px rgba(90, 141, 238, 0.08);
}

/* 基础样式 */
.ticket-management-container {
  padding: 20px;
  background-color: var(--bg-light);
  min-height: 100vh;
}

/* 顶部搜索区域 */
.top-search-area {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 20px;
  padding: 12px 16px;
  background-color: #FFFFFF;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
  border: 1px solid #E8E8E8;
}

/* 搜索标签行 */
.search-labels {
  display: flex;
  gap: 12px;
  align-items: center;
}

/* 搜索标签样式 */
.search-label {
  font-size: 14px;
  color: #333333;
  font-weight: 500;
  text-align: left;
  flex-grow: 1;
  min-width: 80px;
}

/* 搜索输入行 */
.search-inputs {
  display: flex;
  gap: 12px;
  align-items: center;
}

/* 为输入行的每个容器设置flex-grow，使其均匀分布 */
.search-inputs > div {
  flex-grow: 1;
  min-width: 100px;
}

.hamburger-menu {
  display: none;
  cursor: pointer;
  font-size: 20px;
  color: var(--primary-color);
}

.date-picker {
  width: 100%;
}

/* 搜索控件样式 */
.search-input {
  padding: 6px 12px;
  border: 1px solid #E8E8E8;
  border-radius: 4px;
  font-size: 14px;
  background-color: #FFFFFF;
  width: 100%;
  height: 32px;
  box-sizing: border-box;
}

.search-input:focus {
  border-color: #1890FF;
  outline: none;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}

.search-select {
  padding: 6px 12px;
  border: 1px solid #E8E8E8;
  border-radius: 4px;
  font-size: 14px;
  background-color: #FFFFFF;
  cursor: pointer;
  width: 100%;
  height: 32px;
  box-sizing: border-box;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23999' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 12px;
}

.search-select:focus {
  border-color: #1890FF;
  outline: none;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}

.search-btn {
  padding: 0 16px;
  background-color: #1890FF;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
  height: 32px;
  box-sizing: border-box;
  transition: background-color 0.3s;
}

.search-btn:hover {
  background-color: #40a9ff;
}

.search-btn:active {
  background-color: #096dd9;
}

.search-btn:disabled {
  background-color: #e6f7ff;
  color: #91d5ff;
  cursor: not-allowed;
}

/* 日期选择器样式 */
.date-picker {
  width: 160px;
  z-index: 1;
}

/* 状态筛选器样式 */
.status-filter {
  z-index: 2;
}

.el-date-editor {
  width: 100% !important;
}

.el-date-editor .el-input__inner {
  height: 32px !important;
  border-radius: 4px;
  border: 1px solid #E8E8E8;
  font-size: 14px;
  padding: 0 36px 0 12px !important;
}

.el-date-editor .el-input__inner:focus {
  border-color: #1890FF;
  outline: none;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}

.el-date-editor .el-input__suffix {
  right: 8px !important;
  top: 50%;
  transform: translateY(-50%);
}

.el-date-editor .el-input__suffix-inner {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 主要内容区域 */
.main-content {
  display: flex;
  gap: 20px;
  height: calc(100vh - 104px); /* 减去顶部搜索区域高度和内边距 */
  overflow: hidden;
}

.left-sidebar {
  width: 220px;
  height: 100%;
  background-color: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: var(--shadow);
  flex-shrink: 0;
  transition: all 0.3s ease;
  overflow-y: auto; /* 当内容超出高度时显示滚动条 */
}

/* 移动端侧边栏样式 */
.sidebar-mobile {
  position: fixed;
  left: 0;
  top: 0;
  height: 100vh;
  z-index: 1000;
}

/* 侧边栏隐藏样式 */
.sidebar-hidden {
  transform: translateX(-100%);
}

.right-content {
  flex: 1;
  background-color: white;
  border-radius: 8px;
  padding: 20px;
  transition: all 0.3s ease;
}

/* 移动端右侧内容区占满屏幕 */
.right-content-full {
  width: 100%;
}

  /* 响应式设计 */
  @media (max-width: 768px) {
    /* 顶部搜索区域改为纵向排列 */
    .top-search-area {
      flex-direction: column;
      height: auto;
      padding: 16px;
      gap: 16px;
    }

    /* 汉堡菜单显示 */
    .hamburger-menu {
      display: block;
      align-self: flex-start;
    }

    /* 搜索区域元素宽度100% */
    .date-picker,
    .status-filter,
    .patient-search,
    .card-search,
    .phone-search,
    .search-button,
    .add-patient {
      width: 100%;
    }

    /* 右侧内容区卡片布局调整 */
    .virtual-list {
      grid-template-columns: 1fr;
      gap: 12px;
      padding: 12px;
    }

    /* 左侧边栏默认隐藏 */
    .left-sidebar {
      transform: translateX(-100%);
    }

    /* 右侧内容区占满屏幕 */
     .right-content {
       width: 100%;
     }
   }
   
   /* 确保卡片样式正确应用 */
   .ticket-card {
     box-shadow: var(--shadow);
     overflow: hidden;
     transition: all 0.3s ease;
   }
   
   /* 卡片悬停效果 */
   .ticket-card:hover {
     transform: translateY(-2px);
     box-shadow: 0 4px 16px rgba(90, 141, 238, 0.12);
   }
   
   /* 按钮悬停效果 */
   .search-btn,
   .add-patient-btn {
     transition: all 0.3s ease;
   }
   
   .search-btn:hover,
   .add-patient-btn:hover {
     transform: translateY(-1px);
     box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
   }
   
   /* 输入框焦点效果 */
   .search-input {
     transition: all 0.3s ease;
   }
   
   .search-input:focus {
     border-color: var(--primary-color);
     box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
   }
   
   /* 医生列表项悬停效果 */
   .doctor-item {
     transition: all 0.3s ease;
   }
   
   .doctor-item:hover {
     background-color: rgba(24, 144, 255, 0.05);
     cursor: pointer;
   }
   
   /* 医生列表项选中效果 */
.doctor-item.selected {
  background-color: rgba(24, 144, 255, 0.2);
  border-left: 4px solid var(--primary-color);
  font-weight: 600;
}
   
   /* 加载动画 */
   .loading-container {
     display: flex;
     justify-content: center;
     align-items: center;
     padding: 20px;
     gap: 8px;
     color: var(--primary-color);
   }
   
   .loading-spinner {
     width: 16px;
     height: 16px;
     border: 2px solid rgba(24, 144, 255, 0.2);
     border-top-color: var(--primary-color);
     border-radius: 50%;
     animation: spin 0.8s linear infinite;
   }
   
   @keyframes spin {
     to { transform: rotate(360deg); }
   }

/* 左侧筛选区域 */
.section {
  margin-bottom: 24px;
}

.section-title {
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 12px;
  color: #333;
}

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

.radio-group label {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

.doctor-list {
  margin-top: 12px;
  max-height: calc(100vh - 300px); /* 限制医生列表高度 */
  overflow-y: auto; /* 当内容超出高度时显示滚动条 */
}

.doctor-item {
  padding: 12px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  margin-bottom: 8px;
}

.doctor-item:hover {
  background-color: #f0f7ff;
}

.doctor-item.selected {
  background-color: #e6f2ff;
  border-left: 4px solid var(--primary-color);
}

.doctor-name {
  font-weight: 500;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.doctor-available {
  font-size: 12px;
  color: var(--status-unbooked);
  font-weight: normal;
}

/* 右侧号源卡片网格布局 */
.ticket-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
  padding: 8px;
}

  /* 加载更多样式 */
  .loading-more,
  .no-more {
    grid-column: 1 / -1;
    text-align: center;
    padding: 20px;
    color: #999;
    font-size: 14px;
  }

.empty-state {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 600px;
  color: var(--text-tertiary);
}

.empty-text {
  font-size: 16px;
}

.ticket-card {
  background: white;
  border-radius: 8px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(90, 141, 238, 0.08);
  border: 1px solid #e8e8e8;
  transition: all 0.3s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  min-height: 160px;
}

.ticket-card:hover {
  box-shadow: 0 4px 12px rgba(90, 141, 238, 0.12);
  transform: translateY(-2px);
  border-color: #1890ff;
}

.ticket-number {
  position: absolute;
  top: 12px;
  left: 12px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: #e6f7ff;
  color: #1890ff;
  font-size: 12px;
  font-weight: 500;
  display: flex;
  justify-content: center;
  align-items: center;
}

.ticket-time {
  font-size: 14px;
  color: #333;
  font-weight: 500;
  margin: 8px 0;
}

.ticket-status {
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
  text-align: center;
  min-width: 60px;
  margin-bottom: 8px;
}

.status-unbooked {
  background-color: #e6f3ff;
  color: #1890ff;
}

.status-locked {
  background-color: #fff1f0;
  color: #f5222d;
}

.status-booked {
  background-color: #fff8e6;
  color: #fa8c16;
}

.status-checked {
  background-color: #f6ffed;
  color: #52c41a;
}

.status-cancelled {
  background-color: #fff1f0;
  color: #ff4d4f;
}

.ticket-doctor {
  font-size: 14px;
  color: #333;
  margin-bottom: 8px;
  text-align: center;
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ticket-fee {
  font-size: 14px;
  color: #333;
  margin-bottom: 8px;
}

.ticket-type {
  font-size: 12px;
  color: #999;
  margin-bottom: 12px;
}

.book-button {
      padding: 4px 16px;
      background-color: #1890ff;
      color: white;
      border: none;
      border-radius: 4px;
      font-size: 12px;
      cursor: pointer;
      transition: all 0.3s ease;
      align-self: center;
    }

    .book-button:hover:not(:disabled) {
      background-color: #40a9ff;
    }

    .book-button:disabled {
      background-color: #e6f7ff;
      color: #91d5ff;
      cursor: not-allowed;
    }
    
    .cancel-button {
      background-color: #F56C6C;
      color: white;
      border: none;
      border-radius: 4px;
      padding: 4px 12px;
      cursor: pointer;
      font-size: 14px;
      transition: background-color 0.3s;
      margin-top: 8px;
      align-self: center;
    }

    .cancel-button:hover {
      background-color: #F78989;
    }

    .cancel-button:disabled {
      background-color: #C0C4CC;
      cursor: not-allowed;
    }
    
    .check-in-button {
      background-color: #67C23A;
      color: white;
      border: none;
      border-radius: 4px;
      padding: 4px 12px;
      cursor: pointer;
      font-size: 14px;
      transition: background-color 0.3s;
      margin-top: 8px;
      align-self: center;
    }

    .check-in-button:hover {
      background-color: #85ce61;
    }

    .check-in-button:disabled {
      background-color: #C0C4CC;
      cursor: not-allowed;
    }

/* 患者信息样式 */
.ticket-patient {
  margin-top: 8px;
  padding: 4px;
  background-color: rgba(24, 144, 255, 0.05);
  border-radius: 4px;
  font-size: 12px;
  text-align: center;
  color: #333;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .ticket-grid {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
  }
  
  .ticket-card {
    padding: 12px;
    min-height: 140px;
  }
  
  .ticket-doctor {
    font-size: 13px;
  }
}

/* 弹窗样式 */
.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background-color: white;
  border-radius: 8px;
  width: 80%;
  max-width: 800px;
  max-height: 80vh;
  overflow-y: auto;
}

.modal-header {
  padding: 16px 20px;
  border-bottom: 1px solid #e0e0e0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.modal-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}

.close-btn {
  background: none;
  border: none;
  font-size: 24px;
  cursor: pointer;
  color: #999;
}

.modal-body {
  padding: 20px;
}

.patient-table-container {
  margin-top: 20px;
  overflow-x: auto;
}

.patient-table {
  width: 100%;
  border-collapse: collapse;
}

.patient-table th,
.patient-table td {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid #e0e0e0;
}

.patient-table th {
  background-color: #f5f5f5;
  font-weight: 600;
}

.patient-table tr:hover {
  background-color: #fafafa;
}

.patient-table tr.selected {
  background-color: #e6f2ff;
}

.select-btn {
  padding: 4px 12px;
  background-color: var(--primary-color);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}

.modal-footer {
  padding: 16px 20px;
  border-top: 1px solid var(--border-color);
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* 右键菜单样式 */
.context-menu {
  position: fixed;
  background-color: white;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  z-index: 1001;
}

.menu-item {
  padding: 8px 16px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.2s;
}

.menu-item:hover {
  background-color: #f5f5f5;
}

.context-menu-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
}

.confirm-btn {
  padding: 8px 20px;
  background-color: var(--primary-color);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.cancel-btn {
  padding: 8px 20px;
  background-color: #f5f5f5;
  color: #666;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  cursor: pointer;
}

.loading-text {
  display: flex;
  align-items: center;
}

.search-btn:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}
</style>