bookingSearch.vue 9.36 KB
<template>
  <el-dialog v-model="show" :close-on-click-modal="false" style="max-width: 700px;min-width: 350px;"  :title="language === 0 ? '预订查询' : 'Reservation Inquiry'"
    align-center  center class="booking-inquiry-dialog" close-icon="CircleClose" destroy-on-close>
    <!-- 查询区域 -->
    <div class="search-container">
      <el-input v-model="query" :placeholder="language === 0 ? '输入邮箱号查询' : 'Enter email to Query'" clearable
        @blur="handleSearch" @empty="handleSearch" @enter="handleSearch" class="search-input" />
      <el-button class="btn-lineG" style="color: #fff" @click="handleSearch">{{
        language == 0 ? '查询' : 'Search'
      }}
      </el-button>
    </div>

    <!-- 标签页 -->
    <el-tabs v-model="activeName" class="tabs-container" @tab-click="handleTabClick">
      <el-tab-pane :label="language === 0 ? '酒店' : 'Hotel'" name="1"></el-tab-pane>
      <el-tab-pane :label="language === 0 ? '化妆' : 'Makeup'" name="2"></el-tab-pane>
      <el-tab-pane :label="language === 0 ? '接送' : 'Transfer'" name="3"></el-tab-pane>
      <el-tab-pane :label="language === 0 ? '旅游' : 'Tour'" name="4"></el-tab-pane>
      <el-tab-pane :label="language === 0 ? '票务' : 'Tickets'" name="5"></el-tab-pane>
    </el-tabs>

    <!-- 加载状态 -->
    <div v-if="loading" class="loading-container">
      <el-loading :text="language === 0 ? '查询中...' : 'Searching...'" />
    </div>

    <!-- 结果列表 -->
    <div v-else class="results-container">
      <!-- 酒店 -->
      <el-card v-for="(item, index) in list" :key="index" class="result-card" v-if="activeName === '1'">
        <p><span class="label">{{ language === 0 ? '酒店名称:' : 'Hotel Name:' }}</span>{{ item.hotelName }}</p>
        <p><span class="label">{{ language === 0 ? '酒店联系人:' : 'Contact Person:' }}</span>{{ item.contact || '-' }}
        </p>
        <p><span class="label">{{ language === 0 ? '预定日期:' : 'Booking Date:' }}</span>{{ item.handleDate }}</p>
        <p><span class="label">{{ language === 0 ? '预定数量:' : 'Quantity:' }}</span>{{ item.roomNum }}</p>
        <p><span class="label">{{ language === 0 ? '入住人:' : 'Guest:' }}</span>{{ item.rzUsers }}</p>
      </el-card>

      <!-- 化妆 -->
      <el-card v-for="(item, index) in list" :key="index" class="result-card" v-if="activeName === '2'">
        <p><span class="label">{{ language === 0 ? '商家名称:' : 'Merchant:' }}</span>{{ item.name }}</p>
        <p><span class="label">{{ language === 0 ? '套餐名称:' : 'Package:' }}</span>{{ item.meal?.packageName || '-' }}</p>
        <p><span class="label">{{ language === 0 ? '工作室联系人:' : 'Studio Contact:' }}</span>{{ item.contacts }}</p>
        <p><span class="label">{{ language === 0 ? '预定数量:' : 'Quantity:' }}</span>{{ item.num }}</p>
        <p><span class="label">{{ language === 0 ? '预定时间:' : 'Booking Time:' }}</span>{{ item.payDate }}</p>
      </el-card>

      <!-- 接送 -->
      <el-card v-for="(item, index) in list" :key="index" class="result-card" v-if="activeName === '3'">
        <p><span class="label">{{ language === 0 ? '出发地:' : 'From:' }}</span>{{ item.resName.split('——')[0] || '-' }}
        </p>
        <p><span class="label">{{ language === 0 ? '终点地:' : 'To:' }}</span>{{ item.resName.split('——')[1] || '-' }}</p>
        <p><span class="label">{{ language === 0 ? '用车日期:' : 'Date:' }}</span>{{ item.revTime }}</p>
        <p><span class="label">{{ language === 0 ? '乘坐人:' : 'Passengers:' }}</span><span v-html="item.person"></span>
        </p>
      </el-card>

      <!-- 旅游 -->
      <el-card v-for="(item, index) in list" :key="index" class="result-card" v-if="activeName === '4'">
        <p><span class="label">{{ language === 0 ? '景点名称:' : 'Attraction:' }}</span>{{ item.name }}</p>
        <p><span class="label">{{ language === 0 ? '景区联系人:' : 'Contact:' }}</span>{{ item.contact }}</p>
        <p><span class="label">{{ language === 0 ? '预约日期:' : 'Booking Date:' }}</span>{{ item.dcStart }}</p>
        <p><span class="label">{{ language === 0 ? '预约人:' : 'Booker:' }}</span>{{ item.contacts }}</p>
        <p><span class="label">{{ language === 0 ? '集合地点:' : 'Meeting Point:' }}</span>{{ item.address || '-' }}
        </p>
        <p><span class="label">{{ language === 0 ? '集合时间:' : 'Meeting Time:' }}</span>{{ item.startTime || '-' }}</p>
      </el-card>

      <!-- 票务 -->
      <el-card v-for="(item, index) in list" :key="index" class="result-card" v-if="activeName === '5'">
        <p><span class="label">{{ language === 0 ? '票型:' : 'Ticket Type:' }}</span>{{ item.ticketTypeStr }}</p>
        <p><span class="label">{{ language === 0 ? '预定日期:' : 'Booking Date:' }}</span>{{ item.ticketTimeName }}</p>
        <p><span class="label">{{ language === 0 ? '场次:' : 'Session:' }}</span>{{ item.sessionTypeName }}</p>
        <p><span class="label">{{ language === 0 ? '场馆:' : 'Venue:' }}</span>{{ item.stadiumName }}</p>
        <p><span class="label">{{ language === 0 ? '区域:' : 'Area:' }}</span>{{ item.ticketName || '-' }}</p>
        <p><span class="label">{{ language === 0 ? '观影人:' : 'Attendees:' }}</span><span v-html="item.customers"></span>
        </p>
      </el-card>

      <!-- 无结果 -->
      <div v-if="list.length === 0" class="empty-container">
        <el-empty :description="language === 0 ? '暂无相关预定记录' : 'No records found'" />
      </div>
    </div>
  </el-dialog>
</template>

<script setup>
import { ref } from 'vue'
import { ElMessage, ElLoading } from 'element-plus'
import {
  orderRoomList,//酒店
  orderMealList,//化妆
  orderCarList,//接送
  orderScenicList,//旅游
  orderTicketList,//票务
} from '@/apiPc/common'
import { useStorage } from '@vueuse/core/index'

// 状态管理
const language = useStorage('language', 0)
const show = ref(false)
const list = ref([])
const loading = ref(false)
const query = ref('')
const cptId = ref()
const activeName = ref('1')

// 处理tab切换
const handleTabClick = (val) => {
  activeName.value = val.paneName
  if (query.value) {
    handleSearch()
  }
}

// 处理搜索
const handleSearch = () => {
  // 验证输入
  if (!query.value) {
    ElMessage.warning(language.value === 0 ? '请输入邮箱号' : 'Enter email to Query')
    return
  }

  // 显示加载状态
  loading.value = true
  list.value = []

  // 根据当前tab调用不同接口
  const params = { createBy: query.value }
  let requestPromise;
  switch (activeName.value) {
    case '1':
      requestPromise = orderRoomList(params)
      break
    case '2':
      requestPromise = orderMealList(params)
      break
    case '3':
      requestPromise = orderCarList(params)
      break
    case '4':
      requestPromise = orderScenicList(params)
      break
    case '5':
      requestPromise = orderTicketList(params)
      break
    default:
      requestPromise = Promise.reject(new Error('Invalid tab'))
  }

  // 处理请求结果
  requestPromise.then(res => {
    loading.value = false
    if (!res.rows || res.rows.length === 0) {
      list.value = []
      ElMessage.info(language.value === 0 ? '未找到结果,请重新查询' : 'No results found')
      return
    }
    list.value = res.rows
  }).catch(e => {
    loading.value = false
    ElMessage.error(language.value === 0 ? '查询失败,请稍后重试' : 'Query failed, please try again later')
    console.error('查询错误:', e)
  })
}

// 打开对话框
const open = (param) => {
  cptId.value = param?.cptId
  show.value = true
  list.value = []
  query.value = ''
  activeName.value = '1'
  loading.value = false
}

// 暴露方法
defineExpose({
  open
})
</script>

<style lang="scss" scoped>
::v-deep .el-dialog.booking-inquiry-dialog  {

    padding: 15px;
  min-width: 300px; 

  @media (min-width: 768px) {
    width: 50% !important; 
    max-width: 1000px !important;
  }

  @media (max-width: 767px) {
      --el-dialog-width: 90% !important; 
    width: 90% !important; 
    max-width: none !important; 
  }
}
::v-deep .el-dialog__wrapper {
  display: flex !important;
  justify-content: center !important;
  align-items: center !important;
}
.search-container {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
  width: 100%;

  .search-input {
    flex: 1;
  }

  .search-btn {
    background-color: #409eff;
    color: white;

    &:hover {
      background-color: #66b1ff;
    }
  }
}

.tabs-container {
  margin-bottom: 20px;
  width: 100%;

  ::v-deep .el-tabs__nav {
    flex-wrap: wrap;
  }

  ::v-deep .el-tabs__item {
    margin-bottom: 5px;
  }
}

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 40px 0;
}

.results-container {
  max-height: 500px;
  overflow-y: auto;
  padding-right: 5px;

  // 滚动条美化
  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-thumb {
    background-color: #ddd;
    border-radius: 3px;
  }
}

.result-card {
  margin-bottom: 15px;
  border-radius: 6px;
  overflow: hidden;

  ::v-deep .el-card__body {
    padding: 15px;
  }

  p {
    margin: 0 0 8px 0;
    line-height: 1.5;
    font-size: 14px;

    .label {
      color: #666;
      font-weight: 500;
    }
  }

  p:last-child {
    margin-bottom: 0;
  }
}

.empty-container {
  padding: 40px 0;
  text-align: center;
}
</style>