<!DOCTYPE html> 
 | 
<html lang="zh-CN"> 
 | 
<head> 
 | 
  <meta charset="UTF-8"> 
 | 
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> 
 | 
  <title>金华人民医院大屏叫号系统</title> 
 | 
  <style> 
 | 
    /* 基础样式 */ 
 | 
    * { 
 | 
      margin: 0; 
 | 
      padding: 0; 
 | 
      box-sizing: border-box; 
 | 
      font-family: 'Helvetica Neue', Arial, sans-serif; 
 | 
    } 
 | 
     
 | 
    body { 
 | 
      background: linear-gradient(135deg, #e6f0f8, #d9e4f0); 
 | 
      color: #4a5568; 
 | 
      height: 100vh; 
 | 
      overflow: hidden; 
 | 
    } 
 | 
     
 | 
    .bigscreen-container { 
 | 
      height: 100%; 
 | 
      display: flex; 
 | 
      flex-direction: column; 
 | 
      padding: 8px; 
 | 
    } 
 | 
     
 | 
    /* 医院标题样式 */ 
 | 
    .hospital-header { 
 | 
      display: flex; 
 | 
      justify-content: center; 
 | 
      align-items: center; 
 | 
      background: rgba(255, 255, 255, 0.9); 
 | 
      border-radius: 12px; 
 | 
      padding: 12px; 
 | 
      margin-bottom: 8px; 
 | 
      font-size: 22px; 
 | 
      font-weight: bold; 
 | 
      color: #4a7dff; 
 | 
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); 
 | 
    } 
 | 
     
 | 
    .hospital-header img { 
 | 
      margin-right: 8px; 
 | 
      height: 40px; 
 | 
    } 
 | 
     
 | 
    .running-indicator { 
 | 
      width: 12px; 
 | 
      height: 12px; 
 | 
      border-radius: 50%; 
 | 
      margin-left: 12px; 
 | 
      transition: background-color 0.3s; 
 | 
    } 
 | 
     
 | 
    /* 列标题区域 */ 
 | 
    .column-header { 
 | 
      display: flex; 
 | 
      background: rgba(255, 255, 255, 0.9); 
 | 
      border-radius: 12px; 
 | 
      padding: 12px 0; 
 | 
      margin-bottom: 8px; 
 | 
      font-size: 20px; 
 | 
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); 
 | 
    } 
 | 
     
 | 
    .column-title { 
 | 
      flex: 1; 
 | 
      min-width: 0; 
 | 
      text-align: center; 
 | 
      padding: 0 12px; 
 | 
      border-left: 1px solid rgba(91, 140, 255, 0.2); 
 | 
    } 
 | 
     
 | 
    .column-title:first-child { 
 | 
      border-left: none; 
 | 
      flex: 2; /* 第一个房间标题占两列宽度 */ 
 | 
    } 
 | 
     
 | 
    /* 患者列表区域 */ 
 | 
    .patient-list-container { 
 | 
      display: flex; 
 | 
      flex-grow: 1; 
 | 
      background: rgba(255, 255, 255, 0.9); 
 | 
      border-radius: 12px; 
 | 
      padding: 12px 0; 
 | 
      margin-bottom: 8px; 
 | 
      font-size: 18px; 
 | 
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); 
 | 
      overflow-y: auto; 
 | 
    } 
 | 
     
 | 
    .patient-column { 
 | 
      flex: 1; 
 | 
      min-width: 0; 
 | 
      padding: 0 12px; 
 | 
      border-left: 1px solid rgba(91, 140, 255, 0.2); 
 | 
    } 
 | 
     
 | 
    .patient-column:first-child { 
 | 
      border-left: none; 
 | 
      flex: 2; /* 第一个房间占两列宽度 */ 
 | 
    } 
 | 
     
 | 
    /* 第一个房间分成两列的特殊样式 */ 
 | 
    .first-room-columns { 
 | 
      display: flex; 
 | 
      flex: 2; 
 | 
      min-width: 0; 
 | 
    } 
 | 
     
 | 
    .first-room-column { 
 | 
      flex: 1; 
 | 
      min-width: 0; 
 | 
      padding: 0 12px; 
 | 
    } 
 | 
     
 | 
    .first-room-column:first-child { 
 | 
      border-right: 1px solid rgba(91, 140, 255, 0.2); 
 | 
    } 
 | 
     
 | 
    /* 患者项样式 - 优化后的布局 */ 
 | 
    .patient-item { 
 | 
      padding: 10px 8px; 
 | 
      margin-bottom: 8px; 
 | 
      border-radius: 8px; 
 | 
      transition: all 0.3s; 
 | 
      background: rgba(255, 255, 255, 0.8); 
 | 
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); 
 | 
    } 
 | 
     
 | 
    .patient-item:hover { 
 | 
      background: rgba(91, 140, 255, 0.1); 
 | 
    } 
 | 
     
 | 
    .patient-info-row { 
 | 
      display: flex; 
 | 
      width: 100%; 
 | 
      margin-bottom: 4px; 
 | 
    } 
 | 
     
 | 
    .patient-number-name { 
 | 
      display: flex; 
 | 
      flex-wrap: wrap; 
 | 
    } 
 | 
     
 | 
    .patient-number { 
 | 
      color: #5b8cff; 
 | 
      font-weight: bold; 
 | 
      margin-right: 10px; 
 | 
      min-width: 80px; 
 | 
    } 
 | 
     
 | 
    .patient-name { 
 | 
      flex: 1; 
 | 
      min-width: 100px; 
 | 
    } 
 | 
     
 | 
    .patient-status { 
 | 
      width: 100%; 
 | 
      color: #67c23a; 
 | 
      margin-top: 4px; 
 | 
    } 
 | 
     
 | 
    .warning-row { 
 | 
      background-color: rgba(230, 162, 60, 0.1); 
 | 
      color: #e6a23c; 
 | 
    } 
 | 
     
 | 
    /* 底部控制区域 */ 
 | 
    .footer-controls { 
 | 
      display: flex; 
 | 
      justify-content: center; 
 | 
      align-items: center; 
 | 
      background: rgba(255, 255, 255, 0.9); 
 | 
      border-radius: 12px; 
 | 
      padding: 12px; 
 | 
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); 
 | 
    } 
 | 
     
 | 
    .welcome-btn { 
 | 
      background: rgba(91, 140, 255, 0.1); 
 | 
      color: #4a7dff; 
 | 
      border: none; 
 | 
      border-radius: 8px; 
 | 
      padding: 10px 20px; 
 | 
      font-size: 16px; 
 | 
      cursor: pointer; 
 | 
    } 
 | 
     
 | 
    .welcome-btn:hover { 
 | 
      background: rgba(91, 140, 255, 0.2); 
 | 
    } 
 | 
     
 | 
    /* 滚动条样式 */ 
 | 
    .patient-list-container::-webkit-scrollbar { 
 | 
      width: 6px; 
 | 
    } 
 | 
     
 | 
    .patient-list-container::-webkit-scrollbar-track { 
 | 
      background: rgba(0, 0, 0, 0.05); 
 | 
      border-radius: 4px; 
 | 
    } 
 | 
     
 | 
    .patient-list-container::-webkit-scrollbar-thumb { 
 | 
      background: rgba(91, 140, 255, 0.4); 
 | 
      border-radius: 4px; 
 | 
    } 
 | 
     
 | 
    /* 响应式调整 */ 
 | 
    @media (max-width: 1200px) { 
 | 
      .hospital-header { 
 | 
        font-size: 18px; 
 | 
      } 
 | 
      .column-header { 
 | 
        font-size: 16px; 
 | 
      } 
 | 
      .patient-list-container { 
 | 
        font-size: 14px; 
 | 
      } 
 | 
      .patient-number { 
 | 
        min-width: 60px; 
 | 
      } 
 | 
    } 
 | 
     
 | 
    @media (max-width: 768px) { 
 | 
      .hospital-header { 
 | 
        font-size: 16px; 
 | 
        padding: 8px; 
 | 
      } 
 | 
      .column-header { 
 | 
        flex-direction: column; 
 | 
        padding: 8px 0; 
 | 
      } 
 | 
      .column-title { 
 | 
        min-width: 100%; 
 | 
        padding: 8px 0; 
 | 
        border-left: none; 
 | 
        border-bottom: 1px solid rgba(91, 140, 255, 0.2); 
 | 
      } 
 | 
      .patient-list-container { 
 | 
        flex-direction: column; 
 | 
      } 
 | 
      .patient-column, .first-room-columns { 
 | 
        min-width: 100%; 
 | 
        padding: 8px 0; 
 | 
        border-left: none; 
 | 
        border-bottom: 1px solid rgba(91, 140, 255, 0.2); 
 | 
      } 
 | 
      .first-room-column { 
 | 
        padding: 0 8px; 
 | 
      } 
 | 
    } 
 | 
  </style> 
 | 
</head> 
 | 
<body> 
 | 
  <div class="bigscreen-container"> 
 | 
    <!-- 顶部医院标题 --> 
 | 
    <div class="hospital-header"> 
 | 
      <img src="./static/jinhua.png"/> 
 | 
      <span>金华人民医院</span> 
 | 
      <div class="running-indicator" id="runningIndicator"></div> 
 | 
    </div> 
 | 
     
 | 
    <!-- 列标题区域 --> 
 | 
    <div class="column-header" id="columnHeader"> 
 | 
      <!-- 列标题将通过JS动态生成 --> 
 | 
    </div> 
 | 
     
 | 
    <!-- 患者列表区域 --> 
 | 
    <div class="patient-list-container" id="patientListContainer"> 
 | 
      <!-- 患者列表将通过JS动态生成 --> 
 | 
    </div> 
 | 
     
 | 
    <div class="footer-controls"> 
 | 
      <button class="welcome-btn" id="welcomeBtn">欢迎语</button> 
 | 
    </div> 
 | 
  </div> 
 | 
  
 | 
  <script src="./static/jquery.min.js"></script> 
 | 
  <script> 
 | 
    // 应用状态 
 | 
    var appState = { 
 | 
      runningIndicator: 0, 
 | 
      displayColInfo: { 
 | 
        "0": ["常规心电图A", "床边心电图(常规+频谱)M", "常规心电图-心电向量图N"], 
 | 
        "1": ["动态心电B", "动态血压C"], 
 | 
        "2": ["平板运动心电D"], 
 | 
        "3": ["食道电生理F"], 
 | 
        "4": ["动脉硬化监测E"] 
 | 
      }, 
 | 
      mapColumnVsPatients: new Map(), 
 | 
      curSpeakPat: null, 
 | 
      timer: null, 
 | 
      speechSynthesis: window.speechSynthesis || null, 
 | 
      // apiBaseUrl: 'http://localhost:48080/admin-api' 
 | 
        apiBaseUrl: 'http://10.0.2.193/admin-api' 
 | 
    }; 
 | 
  
 | 
    // 页面加载完成后初始化 
 | 
    $(document).ready(function() { 
 | 
      // 初始化事件监听 
 | 
      $('#welcomeBtn').click(function() { 
 | 
        speak('欢迎使用金华人民医院叫号系统'); 
 | 
      }); 
 | 
  
 | 
      // 初始化数据 
 | 
      updateColumnHeader(); 
 | 
      startScrolling(); 
 | 
  
 | 
      // 初始化语音合成 
 | 
      if (appState.speechSynthesis) { 
 | 
        appState.speechSynthesis.onend = onSpeachEndEvent; 
 | 
      } 
 | 
    }); 
 | 
  
 | 
    // 更新列标题显示 
 | 
    function updateColumnHeader() { 
 | 
      var $header = $('#columnHeader'); 
 | 
      $header.empty(); 
 | 
  
 | 
      // 按照固定顺序显示五个房间的标题 
 | 
      for (var i = 0; i < 5; i++) { 
 | 
        var disColId = i.toString(); 
 | 
        var disNameList = appState.displayColInfo[disColId] || []; 
 | 
        var isFirstColumn = disColId === "0"; 
 | 
         
 | 
        var $title = $('<div class="column-title' + (isFirstColumn ? ' double-column' : '') + '"></div>'); 
 | 
         
 | 
        disNameList.forEach(function(dispName) { 
 | 
          $title.append('<div>' + dispName + '</div>'); 
 | 
        }); 
 | 
         
 | 
        $header.append($title); 
 | 
      } 
 | 
    } 
 | 
  
 | 
    // 获取患者列表 
 | 
    function getList() { 
 | 
      // 这里替换为实际的API调用 
 | 
      $.ajax({ 
 | 
        url: appState.apiBaseUrl + '/ecg/screen/big-screen-data', 
 | 
        type: 'GET', 
 | 
        dataType: 'json', 
 | 
        success: function(response) { 
 | 
          // 确保数据按照五个房间的顺序排列 
 | 
          var data = response.data || response; 
 | 
          appState.mapColumnVsPatients = new Map(); 
 | 
           
 | 
          // 按照固定顺序处理五个房间的数据 
 | 
          for (var i = 0; i < 5; i++) { 
 | 
            var roomId = i.toString(); 
 | 
            appState.mapColumnVsPatients.set(roomId, data[roomId] || []); 
 | 
          } 
 | 
           
 | 
          updatePatientList(); 
 | 
        }, 
 | 
        error: function(xhr, status, error) { 
 | 
          console.error('获取患者列表失败:', error); 
 | 
          // 使用模拟数据作为后备 
 | 
          appState.mapColumnVsPatients = generateMockPatients(); 
 | 
          updatePatientList(); 
 | 
        } 
 | 
      }); 
 | 
    } 
 | 
  
 | 
    // 更新患者列表显示 
 | 
    function updatePatientList() { 
 | 
      var $container = $('#patientListContainer'); 
 | 
      $container.empty(); 
 | 
  
 | 
      // 按照固定顺序显示五个房间的患者数据 
 | 
      for (var i = 0; i < 5; i++) { 
 | 
        var disColId = i.toString(); 
 | 
        var patients = appState.mapColumnVsPatients.get(disColId) || []; 
 | 
        var isFirstColumn = disColId === "0"; 
 | 
         
 | 
        if (isFirstColumn) { 
 | 
          // 第一个房间特殊处理 
 | 
          if (patients.length > 10) { 
 | 
            // 超过10人,分成两列 
 | 
            var $firstRoomColumns = $('<div class="first-room-columns"></div>'); 
 | 
             
 | 
            // 第一列(前10条) 
 | 
            var $firstCol = $('<div class="first-room-column"></div>'); 
 | 
            patients.slice(0, 10).forEach(function(item, itemIndex) { 
 | 
              $firstCol.append(createPatientItem(item)); 
 | 
            }); 
 | 
            $firstRoomColumns.append($firstCol); 
 | 
             
 | 
            // 第二列(剩余数据) 
 | 
            var $secondCol = $('<div class="first-room-column"></div>'); 
 | 
            patients.slice(10).forEach(function(item, itemIndex) { 
 | 
              $secondCol.append(createPatientItem(item, itemIndex + 10)); 
 | 
            }); 
 | 
            $firstRoomColumns.append($secondCol); 
 | 
             
 | 
            $container.append($firstRoomColumns); 
 | 
          } else { 
 | 
            // 不超过10人,单列显示但占两列宽度 
 | 
            var $col = $('<div class="patient-column" style="flex:2"></div>'); 
 | 
            patients.forEach(function(item, itemIndex) { 
 | 
              $col.append(createPatientItem(item, itemIndex)); 
 | 
            }); 
 | 
            $container.append($col); 
 | 
          } 
 | 
        } else { 
 | 
          // 其他房间单列显示 
 | 
          var $col = $('<div class="patient-column"></div>'); 
 | 
          patients.forEach(function(item, itemIndex) { 
 | 
            $col.append(createPatientItem(item, itemIndex)); 
 | 
          }); 
 | 
          $container.append($col); 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
  
 | 
    // 创建患者项 - 优化后的版本 
 | 
    function createPatientItem(item, index) { 
 | 
      var statusClass = getItemCssClass(item); 
 | 
      var $item = $('<div class="patient-item ' + statusClass + '"></div>'); 
 | 
       
 | 
      // 号码和姓名在一行 
 | 
      var $numberNameRow = $('<div class="patient-info-row patient-number-name"></div>'); 
 | 
      $numberNameRow.append('<span class="patient-number">' + getCheckTypeSeqPrefix(item.bookCheckType) + item.bookSeqNum + '</span>'); 
 | 
      $numberNameRow.append('<span class="patient-name">' + nameDesensitize(item.patName) + '</span>'); 
 | 
      $item.append($numberNameRow); 
 | 
       
 | 
      // 状态在下一行 
 | 
      var $statusRow = $('<div class="patient-info-row"></div>'); 
 | 
      $statusRow.append('<span class="patient-status">' + queueStatusConvert(item.status) + '</span>'); 
 | 
      $item.append($statusRow); 
 | 
       
 | 
      return $item; 
 | 
    } 
 | 
  
 | 
    // 开始定时刷新 
 | 
    function startScrolling() { 
 | 
      getList(); 
 | 
      appState.timer = setInterval(function() { 
 | 
        appState.runningIndicator++; 
 | 
        $('#runningIndicator').css('backgroundColor', appState.runningIndicator % 2 === 0 ? '#67c23a' : '#e6a23c'); 
 | 
        getList(); 
 | 
        console.log(appState.curSpeakPat,'555'); 
 | 
         
 | 
        if (appState.curSpeakPat == null) { 
 | 
        console.log(appState.curSpeakPat,'666'); 
 | 
          initiateSpeak(); 
 | 
        } 
 | 
      }, 5000); 
 | 
    } 
 | 
  
 | 
    // 语音结束事件 
 | 
    function onSpeachEndEvent(event) { 
 | 
      console.log("Speech ended... " + event.currentTarget.text); 
 | 
       
 | 
      // 这里替换为实际的API调用 
 | 
      $.ajax({ 
 | 
        url: appState.apiBaseUrl + '/ecg/call/update', 
 | 
        method: 'PUT', 
 | 
        data: {  
 | 
          id: appState.curSpeakPat.id, 
 | 
          called: 1 
 | 
        }, 
 | 
        success: function() { 
 | 
          initiateSpeak(); 
 | 
        }, 
 | 
        error: function(xhr, status, error) { 
 | 
          console.error('更新叫号状态失败:', error); 
 | 
        } 
 | 
      }); 
 | 
    } 
 | 
  
 | 
    // 叫号功能 
 | 
    function initiateSpeak() { 
 | 
      // 这里替换为实际的API调用 
 | 
            speak("请、" + '吴龙' + "到" + '康复科' + "就诊"); 
 | 
  
 | 
      // $.ajax({ 
 | 
      //   url: appState.apiBaseUrl + '/ecg/call/next', 
 | 
      //   type: 'GET', 
 | 
      //   dataType: 'json', 
 | 
      //   success: function(response) { 
 | 
      //     appState.curSpeakPat = response.data || response; 
 | 
      //     if (appState.curSpeakPat != null && appState.curSpeakPat.called === 0) { 
 | 
      //       console.log(111); 
 | 
             
 | 
      //       speak("请、" + appState.curSpeakPat.patName + "到" + appState.curSpeakPat.roomName + "就诊"); 
 | 
      //     } 
 | 
      //   }, 
 | 
      //   error: function(xhr, status, error) { 
 | 
      //     console.error('获取下一个叫号失败:', error); 
 | 
      //   } 
 | 
      // }); 
 | 
    } 
 | 
  
 | 
    // 语音播报 
 | 
    function speak(msg) { 
 | 
  
 | 
      if (!appState.speechSynthesis) { 
 | 
        console.warn("当前浏览器不支持语音合成"); 
 | 
        return; 
 | 
      } 
 | 
  
 | 
      // 取消当前正在进行的语音 
 | 
      appState.speechSynthesis.cancel(); 
 | 
  
 | 
      var speech = new SpeechSynthesisUtterance(); 
 | 
      speech.text = msg + "。。。" + msg + "。。。" + msg + "。。。"; 
 | 
      speech.pitch = 1; 
 | 
      speech.rate = 0.9; 
 | 
      speech.volume = 100; 
 | 
      speech.lang = 'zh-CN'; 
 | 
      speech.onend = onSpeachEndEvent; 
 | 
      appState.speechSynthesis.speak(speech); 
 | 
    } 
 | 
  
 | 
    // 工具函数 
 | 
    function nameDesensitize(patName) { 
 | 
      if (!patName) return ''; 
 | 
      if (patName.length === 2) { 
 | 
        return patName.substring(0, 1) + '*'; 
 | 
      } else if (patName.length === 3) { 
 | 
        return patName.substring(0, 1) + '*' + patName.substring(2, 3); 
 | 
      } else if (patName.length > 3) { 
 | 
        return patName.substring(0, 1) + '*' + '*' + patName.substring(3, patName.length); 
 | 
      } 
 | 
      return patName; 
 | 
    } 
 | 
  
 | 
    function getItemCssClass(item) { 
 | 
      if (item.status === 5 || item.status === 7) { 
 | 
        return "warning-row"; 
 | 
      } 
 | 
      return ""; 
 | 
    } 
 | 
  
 | 
    function queueStatusConvert(status) { 
 | 
      var statusMap = { 
 | 
        3: '已过号-排队', 
 | 
        5: '已过号', 
 | 
        7: '已过号-安装', 
 | 
        10: '排队中', 
 | 
        12: '亲和', 
 | 
        13: '亲和-安装', 
 | 
        15: '已召回', 
 | 
        20: '候诊中', 
 | 
        30: '就诊中', 
 | 
        33: '已领用', 
 | 
        34: '已召回-安装', 
 | 
        36: '安装中', 
 | 
        40: '已就诊' 
 | 
      }; 
 | 
      return statusMap[status] || '未知状态'; 
 | 
    } 
 | 
  
 | 
    function getCheckTypeSeqPrefix(type) { 
 | 
      var types = { 
 | 
        1: 'A001', 
 | 
        2: 'A002', 
 | 
        3: 'A003', 
 | 
        4: 'A004' 
 | 
      }; 
 | 
      return types[type] || ''; 
 | 
    } 
 | 
  
 | 
    // 生成模拟患者数据 
 | 
    function generateMockPatients() { 
 | 
      var mockData = { 
 | 
        "0": generateMockPatientsForRoom(15, "常规心电图A"), 
 | 
        "1": generateMockPatientsForRoom(8, "动态心电B"), 
 | 
        "2": generateMockPatientsForRoom(5, "平板运动心电D"), 
 | 
        "3": generateMockPatientsForRoom(3, "食道电生理F"), 
 | 
        "4": generateMockPatientsForRoom(4, "动脉硬化监测E") 
 | 
      }; 
 | 
      return new Map(Object.entries(mockData)); 
 | 
    } 
 | 
  
 | 
    function generateMockPatientsForRoom(count, checkTypeName) { 
 | 
      var mockPatients = []; 
 | 
      var names = ['张三', '李四', '王五', '赵六', '钱七', '孙八', '周九', '吴十']; 
 | 
      var rooms = ['心电图室1', '心电图室2', '动态心电室', '心电监护室']; 
 | 
      var statuses = [5, 7, 10, 12, 13, 15, 20, 30, 33, 34, 36, 40]; 
 | 
      var checkTypes = [1, 2, 3, 4]; 
 | 
       
 | 
      for (var i = 0; i < count; i++) { 
 | 
        mockPatients.push({ 
 | 
          id: i + 1, 
 | 
          patName: names[Math.floor(Math.random() * names.length)], 
 | 
          roomName: rooms[Math.floor(Math.random() * rooms.length)], 
 | 
          bedNo: '床' + (Math.floor(Math.random() * 20) + 1), 
 | 
          status: statuses[Math.floor(Math.random() * statuses.length)], 
 | 
          bookCheckType: checkTypes[Math.floor(Math.random() * checkTypes.length)], 
 | 
          bookSeqNum: Math.floor(Math.random() * 50) + 1, 
 | 
          called: 0, 
 | 
          checkTypeName: checkTypeName 
 | 
        }); 
 | 
      } 
 | 
       
 | 
      return mockPatients; 
 | 
    } 
 | 
  </script> 
 | 
</body> 
 | 
</html> 
 |