<script setup> 
 | 
import { ref, onMounted, nextTick } from 'vue' 
 | 
import dayjs from 'dayjs' 
 | 
import UQRCode from 'uqrcodejs' 
 | 
import { getLargeScreenData } from '@/utils/request' 
 | 
import duration from 'dayjs/plugin/duration' 
 | 
dayjs.extend(duration) 
 | 
import VScaleScreen from 'v-scale-screen' 
 | 
  
 | 
const qrcode = ref('') 
 | 
const contentList = ref([]) 
 | 
const contentTempList = ref([]) 
 | 
const page = ref(1) 
 | 
const timer = ref() 
 | 
  
 | 
const callList = ref([]) 
 | 
const activeCall = ref({}) 
 | 
const pageCall = ref(0) 
 | 
const timerCall = ref() 
 | 
  
 | 
const initData = () => { 
 | 
  getLargeScreenData().then(res => { 
 | 
    if (res.data && res.data.allList) { 
 | 
      contentList.value = res.data.allList.map((item, index) => { 
 | 
        item.index = index + 1 
 | 
        if (item.optTime) { 
 | 
          item.optTimeTemp = dayjs(item.optTime).format('HH:mm') 
 | 
          if(item.status == 4){ 
 | 
            if(item.optTime >= new Date().getTime()){ 
 | 
              item.optTimeTemp = dayjs.duration(item.optTime - new Date().getTime()).format('HH:mm') 
 | 
            }else{ 
 | 
              item.optTimeTemp = '-' 
 | 
            } 
 | 
          } 
 | 
          // item.optTimeTemp = dayjs.duration(Math.abs(new Date().getTime() - item.optTime)).format('HH:mm') 
 | 
        } 
 | 
        return item 
 | 
      }) 
 | 
      clearInterval(timer.value) 
 | 
      setInitContent() 
 | 
    } 
 | 
    if (res.data && res.data.waitWorkList) { 
 | 
      callList.value = res.data.waitWorkList 
 | 
    } 
 | 
    qrcode.value = res.data.qrCode 
 | 
    initQrcode() 
 | 
    clearInterval(timerCall.value) 
 | 
    setInitCall() 
 | 
  }) 
 | 
} 
 | 
  
 | 
const frequencyFn = (length) => { 
 | 
  if (length <= 16) { // 2 
 | 
    return 30 * 1000 
 | 
  } else if (length <= 24) { // 3 
 | 
    return 20 * 1000 
 | 
  } else if (length <= 32) {// 4 
 | 
    return 15 * 1000 
 | 
  } else if (length <= 48) {// 6 
 | 
    return 10 * 1000 
 | 
  } else if (length <= 60) {// 10 
 | 
    return 6 * 1000 
 | 
  } else { 
 | 
    return 4 * 1000 
 | 
  } 
 | 
} 
 | 
const frequencyCallFn = (length) => { 
 | 
  if (length <= 10) { // 2 
 | 
    return 6 * 1000 
 | 
  } else if (length <= 20) { // 3 
 | 
    return 3 * 1000 
 | 
  } else { 
 | 
    return 2 * 1000 
 | 
  } 
 | 
} 
 | 
const setInitContent = () => { 
 | 
  if (contentList.value && contentList.value.length > 0) { 
 | 
    contentTempList.value = contentList.value.slice(0, 8) 
 | 
    if (page.value * 8 >= contentList.value.length) { 
 | 
      page.value = 1 
 | 
    } else { 
 | 
      page.value++ 
 | 
    } 
 | 
    timer.value = setInterval(() => { 
 | 
      if (page.value * 8 >= contentList.value.length) { 
 | 
        page.value = 1 
 | 
      } else { 
 | 
        page.value++ 
 | 
      } 
 | 
      contentTempList.value = contentList.value.slice((page.value - 1) * 8, page.value * 8) 
 | 
    }, frequencyFn(contentList.value.length)) 
 | 
  } 
 | 
} 
 | 
const setInitCall = () => { 
 | 
  if (callList.value && callList.value.length > 0) { 
 | 
    activeCall.value = callList.value[0] 
 | 
    timerCall.value = setInterval(() => { 
 | 
      if (pageCall.value >= callList.value.length - 1) { 
 | 
        pageCall.value = 0 
 | 
      } else { 
 | 
        pageCall.value++ 
 | 
      } 
 | 
      activeCall.value = callList.value[pageCall.value] 
 | 
    }, frequencyCallFn(callList.value.length)) 
 | 
  } 
 | 
} 
 | 
  
 | 
onMounted(() => { 
 | 
  initData() 
 | 
  setInterval(() => { 
 | 
    initData() 
 | 
  }, 60 * 1000) 
 | 
}) 
 | 
  
 | 
const initQrcode = () => { 
 | 
  var qr = new UQRCode() 
 | 
  // 设置二维码内容 
 | 
  qr.data = qrcode.value 
 | 
  qr.size = 268 
 | 
  // 调用制作二维码方法 
 | 
  qr.make() 
 | 
  var canvas = document.getElementById("qrcode") 
 | 
  var canvasContext = canvas.getContext("2d") 
 | 
  qr.canvasContext = canvasContext 
 | 
  qr.drawCanvas() 
 | 
} 
 | 
  
 | 
const statusMap = { 
 | 
  0: '待确认', 
 | 
  1: '待签到', 
 | 
  2: '等待叫号', 
 | 
  3: '入园等待', 
 | 
  4: '已叫号', // 已叫号 月台等待 
 | 
  5: '作业中', 
 | 
  6: '作业完成', 
 | 
  7: '转移中', 
 | 
  8: '异常挂起', 
 | 
  9: '已授权离园', 
 | 
  10: '已离园', 
 | 
  11: '已过号', 
 | 
  12: '已取消', 
 | 
} 
 | 
const weekMap = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] 
 | 
const newWeek = ref(weekMap[new Date().getDay()]) 
 | 
const newDate = ref(dayjs().format('YYYY-MM-DD')) 
 | 
const newTime = ref(dayjs().format('HH:mm')) 
 | 
setInterval(() => { 
 | 
  newWeek.value = weekMap[new Date().getDay()] 
 | 
  newDate.value = dayjs().format('YYYY-MM-DD') 
 | 
  newTime.value = dayjs().format('HH:mm') 
 | 
}, 1000) 
 | 
  
 | 
const isFullscreen = ref(false) 
 | 
const handleFull = () => { 
 | 
  if (!isFullscreen.value) { 
 | 
    handleFullScreen() 
 | 
  } else { 
 | 
    cancelFullscreen() 
 | 
  } 
 | 
} 
 | 
const handler = () => { 
 | 
  isFullscreen.value = document.fullscreenElement !== null 
 | 
  if (!isFullscreen) { 
 | 
    // 退出全屏时候解除监听,不然每次监听都会添加一次绑定 
 | 
    document.removeEventListener("fullscreenchange", handler) 
 | 
  } 
 | 
} 
 | 
document.addEventListener("fullscreenchange", handler) 
 | 
const handleFullScreen = () => { 
 | 
  let elem = document.documentElement 
 | 
  // 尝试启用全屏模式 
 | 
  if (elem.requestFullscreen) { 
 | 
    elem.requestFullscreen() 
 | 
  } else if (elem.mozRequestFullScreen) { // 兼容 Firefox 
 | 
    elem.mozRequestFullScreen() 
 | 
  } else if (elem.webkitRequestFullscreen) { // 兼容 Chrome, Safari 和 Opera 
 | 
    elem.webkitRequestFullscreen() 
 | 
  } else if (elem.msRequestFullscreen) { // 兼容 IE/Edge 
 | 
    elem.msRequestFullscreen() 
 | 
  } 
 | 
} 
 | 
function cancelFullscreen() { 
 | 
  if (document.exitFullscreen) { 
 | 
    document.exitFullscreen() 
 | 
  } else if (document.msExitFullscreen) { 
 | 
    document.msExitFullscreen() 
 | 
  } else if (document.mozCancelFullScreen) { 
 | 
    document.mozCancelFullScreen() 
 | 
  } else if (document.webkitExitFullscreen) { 
 | 
    document.webkitExitFullscreen() 
 | 
  } 
 | 
} 
 | 
  
 | 
</script> 
 | 
<template> 
 | 
  <v-scale-screen width="1920" height="1080"> 
 | 
    <div class="main_app"> 
 | 
      <div class="main_header"> 
 | 
        <img class="bg" src="@/assets/images/call/title@2x.png" alt=""> 
 | 
        <div class="title">安泰智慧物流园区-车辆叫号大屏</div> 
 | 
        <div class="time_wrap" @click="handleFull"> 
 | 
          <div class="left"> 
 | 
            <div class="week">{{ newWeek }}</div> 
 | 
            <div class="date">{{ newDate }}</div> 
 | 
          </div> 
 | 
          <div class="time">{{ newTime }}</div> 
 | 
        </div> 
 | 
      </div> 
 | 
      <div class="main_content"> 
 | 
        <div class="list"> 
 | 
          <div class="line header"> 
 | 
            <div class="item no">序号</div> 
 | 
            <div class="item">车牌号</div> 
 | 
            <div class="item status">状态</div> 
 | 
            <div class="item">停靠月台</div> 
 | 
            <div class="item">时间</div> 
 | 
          </div> 
 | 
          <div class="line" v-for="(item, index) in contentTempList" :key="index"> 
 | 
            <div class="item no">{{ item.index }}</div> 
 | 
            <div class="item">{{ item.carCodeFront }}</div> 
 | 
            <div class="item"> 
 | 
              <div :class="{ 
 | 
                call_ed: item.status == 4, 
 | 
                underway: item.status == 5, 
 | 
                padding: item.status == 2 || item.status == 3, 
 | 
              }" class="status">{{ statusMap[item.status] }}</div> 
 | 
            </div> 
 | 
            <div class="item">{{ item.platformName || '-' }}</div> 
 | 
            <div class="item"> 
 | 
              <div v-if="item.optTimeTemp" class="time_place"> 
 | 
                {{ item.status == 4 ? '剩余等待时间' : '预计完成时间' }} 
 | 
              </div> 
 | 
              <div>{{ item.optTimeTemp || '-' }}</div> 
 | 
            </div> 
 | 
          </div> 
 | 
        </div> 
 | 
        <div class="current"> 
 | 
          <div class="tip_wrap"> 
 | 
            <img src="@/assets/images/call/ic_left@2x.png" class="icon icon_l" alt=""> 
 | 
            <img src="@/assets/images/call/ic_right@2x.png" class="icon icon_r" alt=""> 
 | 
            <div v-if="callList.length > 0" class="current_plat"> 
 | 
              <div class="id_card">{{ activeCall.carCodeFront }}</div> 
 | 
              <div class="no">({{ activeCall.signNum }})</div> 
 | 
              <div class="place"> 
 | 
                <span>前往</span> 
 | 
                <span class="plat"> {{ activeCall.platformName }} </span> 
 | 
                <span>作业</span> 
 | 
              </div> 
 | 
            </div> 
 | 
            <div v-else class="empty"> 
 | 
              <div class="title">温馨提示</div> 
 | 
              <div class="line">1、请司机根据叫号屏提示入园</div> 
 | 
              <div class="line">2、未叫号车辆请耐心等待</div> 
 | 
              <div class="line">3、请有序排队入园</div> 
 | 
              <div class="line">4、装卸货结束禁止在园区逗留</div> 
 | 
              <div class="line">5、请遵守园区安全规章制度</div> 
 | 
            </div> 
 | 
          </div> 
 | 
          <div class="qrcode_wrap"> 
 | 
            <div class="qrcode"> 
 | 
              <canvas id="qrcode" width="268" height="268"></canvas> 
 | 
            </div> 
 | 
            <div class="title">请扫码签到</div> 
 | 
          </div> 
 | 
        </div> 
 | 
      </div> 
 | 
      <div class="main_footer"> 
 | 
        <img src="@/assets/images/call/ic_news@2x.png" class="icon" alt=""> 
 | 
        <div class="title">请根据队列提示信息,依次等候进场</div> 
 | 
        <div class="icon"></div> 
 | 
      </div> 
 | 
    </div> 
 | 
  </v-scale-screen> 
 | 
  
 | 
</template> 
 | 
  
 | 
<style lang="scss" scoped> 
 | 
div { 
 | 
  box-sizing: border-box; 
 | 
} 
 | 
  
 | 
.main_app { 
 | 
  color: #fff; 
 | 
  width: 1920px; 
 | 
  height: 1080px; 
 | 
  overflow: hidden; 
 | 
  background-color: #092030; 
 | 
  position: relative; 
 | 
  display: flex; 
 | 
  flex-direction: column; 
 | 
  justify-content: space-between; 
 | 
  
 | 
  .main_header { 
 | 
    width: 100%; 
 | 
    flex: 10.3; 
 | 
    position: relative; 
 | 
    display: flex; 
 | 
    align-items: center; 
 | 
    justify-content: space-between; 
 | 
    padding: 0 50px; 
 | 
    z-index: 11; 
 | 
  
 | 
    .title { 
 | 
      font-weight: 800; 
 | 
      font-size: 48px; 
 | 
    } 
 | 
  
 | 
    .time_wrap { 
 | 
      display: flex; 
 | 
      align-items: center; 
 | 
  
 | 
      .date { 
 | 
        font-weight: 500; 
 | 
        font-size: 20px; 
 | 
        text-align: right; 
 | 
      } 
 | 
  
 | 
      .week { 
 | 
        font-weight: 500; 
 | 
        font-size: 20px; 
 | 
        text-align: right; 
 | 
      } 
 | 
  
 | 
      .time { 
 | 
        font-weight: 500; 
 | 
        font-size: 50px; 
 | 
        margin-left: 15px; 
 | 
      } 
 | 
    } 
 | 
  
 | 
    .bg { 
 | 
      position: absolute; 
 | 
      top: 0; 
 | 
      left: 0; 
 | 
      width: 100%; 
 | 
      height: 100%; 
 | 
      object-fit: cover; 
 | 
      z-index: -1; 
 | 
    } 
 | 
  } 
 | 
  
 | 
  .main_content { 
 | 
    flex: 82.2; 
 | 
    display: flex; 
 | 
    padding: 30px 20px; 
 | 
    position: relative; 
 | 
  
 | 
    .list { 
 | 
      flex: 5; 
 | 
      margin-right: 20px; 
 | 
      display: flex; 
 | 
      flex-direction: column; 
 | 
  
 | 
      .line { 
 | 
        display: flex; 
 | 
        align-items: center; 
 | 
        height: 11.1%; 
 | 
  
 | 
        &:nth-of-type(2n) { 
 | 
          background: rgba(255, 255, 255, 0); 
 | 
        } 
 | 
  
 | 
        &:nth-of-type(2n + 1) { 
 | 
          background: rgba(0, 237, 255, 0.13); 
 | 
        } 
 | 
  
 | 
        .item { 
 | 
          display: flex; 
 | 
          justify-content: center; 
 | 
          align-items: center; 
 | 
          flex-direction: column; 
 | 
          font-weight: 500; 
 | 
          font-size: 30px; 
 | 
          flex: 10; 
 | 
          height: 100%; 
 | 
  
 | 
          .time_place { 
 | 
            font-weight: 500; 
 | 
            font-size: 22px; 
 | 
          } 
 | 
  
 | 
          .status { 
 | 
            /* padding: 0 28px; */ 
 | 
            width: 170px; 
 | 
            height: 72%; 
 | 
            border-radius: 8px; 
 | 
            display: flex; 
 | 
            justify-content: center; 
 | 
            align-items: center; 
 | 
          } 
 | 
  
 | 
          .underway { 
 | 
            background-color: #51b2ce; 
 | 
          } 
 | 
  
 | 
          .call_ed { 
 | 
            background-color: #f2a43a; 
 | 
          } 
 | 
  
 | 
          .padding { 
 | 
            background-color: #1c485a; 
 | 
          } 
 | 
        } 
 | 
  
 | 
        .no { 
 | 
          flex: 5; 
 | 
        } 
 | 
  
 | 
      } 
 | 
  
 | 
      .header { 
 | 
        .item { 
 | 
          font-size: bold; 
 | 
          font-size: 36px; 
 | 
        } 
 | 
  
 | 
        background: linear-gradient(180deg, #00B5D1 0%, #003C57 100%) !important; 
 | 
      } 
 | 
    } 
 | 
  
 | 
    .current { 
 | 
      /* height: calc( 100vh - 192px ); */ 
 | 
      flex: 2; 
 | 
      display: flex; 
 | 
      flex-direction: column; 
 | 
  
 | 
      .tip_wrap { 
 | 
        margin-bottom: 20px; 
 | 
        width: 100%; 
 | 
        position: relative; 
 | 
        /* flex-shrink: 0; */ 
 | 
        flex: 1; 
 | 
  
 | 
        .current_plat { 
 | 
          display: flex; 
 | 
          flex-direction: column; 
 | 
          align-items: center; 
 | 
          justify-content: center; 
 | 
          padding: 30px 40px; 
 | 
          color: #FFA000; 
 | 
          height: 100%; 
 | 
  
 | 
          .id_card { 
 | 
            font-weight: 500; 
 | 
            font-size: 68px; 
 | 
          } 
 | 
  
 | 
          .no { 
 | 
            margin: 8px 0; 
 | 
            font-weight: 500; 
 | 
            font-size: 52px; 
 | 
          } 
 | 
  
 | 
          .place { 
 | 
            font-weight: 500; 
 | 
            font-size: 36px; 
 | 
          } 
 | 
  
 | 
          .plat { 
 | 
            color: #fff; 
 | 
            margin: 0 6px; 
 | 
          } 
 | 
        } 
 | 
  
 | 
        .empty { 
 | 
          display: flex; 
 | 
          flex-direction: column; 
 | 
          justify-content: center; 
 | 
          font-weight: 500; 
 | 
          font-size: 26px; 
 | 
          height: 100%; 
 | 
  
 | 
          .title { 
 | 
            text-align: center; 
 | 
            font-weight: bold; 
 | 
            font-size: 32px; 
 | 
            margin-bottom: 16px; 
 | 
          } 
 | 
  
 | 
          .line { 
 | 
            margin-bottom: 8px; 
 | 
            padding-left: 32px; 
 | 
          } 
 | 
        } 
 | 
  
 | 
        .icon { 
 | 
          position: absolute; 
 | 
          width: 52px; 
 | 
          height: 52px; 
 | 
        } 
 | 
  
 | 
        .icon_l { 
 | 
          left: 0; 
 | 
          top: 0; 
 | 
        } 
 | 
  
 | 
        .icon_r { 
 | 
          right: 0; 
 | 
          bottom: 0; 
 | 
        } 
 | 
      } 
 | 
  
 | 
      .qrcode_wrap { 
 | 
        width: 100%; 
 | 
        flex: 1; 
 | 
        /* flex-shrink: 0; */ 
 | 
        background-color: #51b2ce; 
 | 
        display: flex; 
 | 
        flex-direction: column; 
 | 
        align-items: center; 
 | 
        justify-content: center; 
 | 
  
 | 
        .qrcode { 
 | 
          padding: 6px 6px 4px; 
 | 
          background-color: #fff; 
 | 
        } 
 | 
  
 | 
        .title { 
 | 
          margin-top: 16px; 
 | 
          font-weight: bold; 
 | 
          font-size: 28px; 
 | 
          color: #111111; 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
  } 
 | 
  
 | 
  .main_footer { 
 | 
    background-color: #1D8D9E; 
 | 
    flex: 7.4; 
 | 
    display: flex; 
 | 
    align-items: center; 
 | 
    padding: 0 50px; 
 | 
  
 | 
    .icon { 
 | 
      width: 52px; 
 | 
      height: 52px; 
 | 
    } 
 | 
  
 | 
    .title { 
 | 
      flex: 1; 
 | 
      text-align: center; 
 | 
      font-weight: 500; 
 | 
      font-size: 37px; 
 | 
    } 
 | 
  } 
 | 
  
 | 
} 
 | 
</style> 
 |