From 796047fbe84d51816f44be535501415d3c66dd9d Mon Sep 17 00:00:00 2001
From: yxh <172933527@qq.com>
Date: 星期日, 21 六月 2026 23:24:37 +0800
Subject: [PATCH] yxh
---
big.html | 689 ++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 556 insertions(+), 133 deletions(-)
diff --git a/big.html b/big.html
index 48e44da..a2fb0ab 100644
--- a/big.html
+++ b/big.html
@@ -1,9 +1,10 @@
-<!doctype html>
+锘�<!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" />
+ <meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>澶у巺</title>
<style>
@@ -11,28 +12,37 @@
margin: 0;
padding: 0;
box-sizing: border-box;
- font-family: "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
+ /* Android 6 鍙敤涓枃瀛椾綋 */
+ ;
+ font-family: "Droid Sans Fallback", "Noto Sans CJK SC", "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
}
/* 1. 鍏ㄥ眬娣辫壊鑳屾櫙 */
body {
background: #001f3f;
- /* 娣辫摑鑹茶儗鏅紝閫傚悎澶у睆 */
color: #fff;
height: 100vh;
overflow: hidden;
+ display: -webkit-box;
+ display: -webkit-flex;
display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
flex-direction: column;
font-size: 14px;
}
- /* 2. 椤堕儴鏍� - 绠�鍖栬竟妗嗭紝娣辫壊涓婚 */
+ /* 2. 椤堕儴鏍� */
.top-header {
+ display: -webkit-box;
+ display: -webkit-flex;
display: flex;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
align-items: center;
padding: 15px 30px;
background: rgba(0, 30, 60, 0.9);
- /* 娣辫壊鍗婇�忔槑 */
white-space: nowrap;
position: relative;
border-bottom: 1px solid #003366;
@@ -47,6 +57,7 @@
.top-header .title-text {
position: absolute;
left: 50%;
+ -webkit-transform: translateX(-50%);
transform: translateX(-50%);
font-size: 32px;
font-weight: bold;
@@ -55,47 +66,125 @@
}
.top-header .time-info {
- font-size: 24px;
+ font-size: 20px;
color: #aaa;
margin-left: auto;
z-index: 2;
+ text-align: right;
+ line-height: 1.3;
}
- /* 3. 涓讳綋鍐呭 */
- .main-content {
- flex: 1;
+ .time-info-inner {
+ display: -webkit-box;
+ display: -webkit-flex;
display: flex;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ }
+
+ .time-left {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-flex-direction: column;
+ flex-direction: column;
+ text-align: right;
+ line-height: 1.3;
+ }
+
+ .time-right {
+ margin-left: 8px;
+ }
+
+ .top-header .time-info .time-clock {
+ font-size: 36px;
+ font-weight: bold;
+ color: #ffcc00;
+ line-height: 1.1;
+ }
+
+ /* 3. 涓讳綋鍐呭锛坓ap 鏇挎崲涓� margin 鍏煎鏃� Chrome锛� */
+ .main-content {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ flex: 1;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
+ flex-direction: column;
padding: 15px 20px;
overflow: hidden;
- gap: 10px;
}
- /* 鍒楀鍣� - 绉婚櫎闃村奖鍜屽渾瑙掞紝鏇寸畝娲� */
- .column-box {
+ /* 鍒楄瀹瑰櫒 */
+ .columns-row {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ flex: 1;
+ display: -webkit-box;
+ display: -webkit-flex;
display: flex;
+ overflow: hidden;
+ }
+
+ .columns-row>.column-box {
+ margin-left: 3px;
+ margin-right: 3px;
+ }
+
+ .columns-row>.column-box:first-child {
+ margin-left: 0;
+ }
+
+ .columns-row>.column-box:last-child {
+ margin-right: 0;
+ }
+
+ /* 鍒楀鍣� */
+ .column-box {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
flex-direction: column;
background: rgba(10, 40, 80, 0.5);
- /* 娣辫壊鍗婇�忔槑鑳屾櫙 */
border-radius: 0;
- padding: 10px;
+ padding: 6px;
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
flex: 1;
min-width: 0;
border: 1px solid #003366;
}
.column-box.col-wide {
+ -webkit-box-flex: 2.5;
+ -webkit-flex: 2.5;
flex: 2.5;
}
.column-box.col-normal {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
flex: 1;
}
- /* 鏍囬鏍峰紡 - 绠�鍖栦笅鍒掔嚎 */
- .col-title {
- font-size: 22px;
+ /* 鏍囬琛� */
+ .col-title-line {
+ font-size: 28px;
font-weight: bold;
color: #4da6ff;
+ text-align: center;
+ }
+
+ .col-title {
padding-bottom: 8px;
border-bottom: 1px solid #003366;
margin-bottom: 10px;
@@ -103,57 +192,85 @@
}
.col-subtitle {
- font-size: 14px;
- color: #999;
+ font-size: 24px;
+ font-weight: bold;
+ color: #ffcc00;
text-align: center;
+ min-height: 20px;
+ /* 鍗充娇涓虹┖涔熶繚鐣欓珮搴︼紝闃叉鏍囬鏍忛珮浣庝笉骞� */
+ line-height: 1.4;
+ word-break: keep-all;
}
/* 鎮h�呭垪琛� */
.patient-list {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
flex: 1;
overflow-y: auto;
- padding-right: 5px;
- }
-
- /* 銆愬叧閿慨鏀广�戠1鏍忓己鍒朵竴琛�2涓� */
- #col-0 {
+ padding-right: 2px;
+ display: -webkit-box;
+ display: -webkit-flex;
display: flex;
- flex-wrap: wrap;
+ -webkit-align-content: flex-start;
align-content: flex-start;
}
- /* 绗�2-5鏍忎繚鎸佸崟鍒� */
- .col-normal .patient-list {
- display: flex;
+ /* 涓�琛屼袱涓紙甯歌蹇冪數鍥俱�佸姩鎬佸績鐢碉級 */
+ .patient-list.two-per-row {
+ -webkit-flex-wrap: wrap;
+ flex-wrap: wrap;
+ }
+
+ .patient-list.two-per-row .patient-item {
+ width: 46%;
+ margin: 0 2%;
+ }
+
+ /* 涓�琛屼竴涓� */
+ .patient-list.one-per-row {
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
flex-direction: column;
}
- /* 4. 鎮h�呴」鐩� - 鏋佺畝妯″紡 */
+ .patient-list.one-per-row .patient-item {
+ width: 100%;
+ }
+
+ /* 鎮h�呴」鐩� */
.patient-item {
- font-size: 22px;
- padding: 8px 5px;
+ font-size: 28px;
+ padding: 4px 3px;
+ display: -webkit-box;
+ display: -webkit-flex;
display: flex;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
align-items: center;
color: #fff;
line-height: 1.4;
}
- /* 銆愪紭鍖栦慨鏀广�戠1鏍忥細澧炲姞鍒楅棿璺濓紝鏀瑰杽鎷ユ尋鎰� */
- #col-0 .patient-item {
- width: 45%;
- /* 1. 缂╁噺瀹藉害锛屼负闂撮殧鐣欏嚭绌洪棿 */
- font-size: 20px;
- margin: 0 2.5%;
- /* 2. 娣诲姞宸﹀彸澶栬竟璺濓紝涓ゅ垪涔嬮棿鎬婚棿闅斾负5% */
- }
-
.p-number {
color: #ffcc00;
font-weight: bold;
- margin-right: 8px;
+ margin-right: 6px;
+ -webkit-flex-shrink: 0;
+ flex-shrink: 0;
}
.p-name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-weight: bold;
+ }
+
+ .p-name-wrap {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
@@ -163,15 +280,43 @@
.p-room {
color: #4da6ff;
font-weight: bold;
- font-size: 18px;
- margin-left: 5px;
+ font-size: 22px;
+ margin-left: 4px;
+ -webkit-flex-shrink: 0;
+ flex-shrink: 0;
}
- /* 5. 搴曢儴鏍� - 灞呬腑鏄剧ず */
+ /* 杩囧彿鎮h�咃細鎺掑湪鍒楀唴锛岃瑙夊急鍖� */
+ .patient-item.missed {
+ color: #aa8888;
+ }
+
+ .patient-item.missed .p-number {
+ color: #cc9966;
+ }
+
+ .patient-item.missed .p-name {
+ color: #aa8888;
+ }
+
+ .patient-item.missed .p-missed-tag {
+ color: #ff6666;
+ font-size: 22px;
+ margin-left: 4px;
+ -webkit-flex-shrink: 0;
+ flex-shrink: 0;
+ }
+
+ /* 搴曢儴鏍� */
.bottom-footer {
+ display: -webkit-box;
+ display: -webkit-flex;
display: flex;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
justify-content: center;
- /* 灞呬腑 */
+ -webkit-box-align: center;
+ -webkit-align-items: center;
align-items: center;
padding: 10px 30px;
background: rgba(0, 30, 60, 0.9);
@@ -185,7 +330,26 @@
text-align: center;
}
- /* 婊氬姩鏉$編鍖� - 缁嗕竴鐐� */
+ /* 娴嬭瘯璇煶鎸夐挳 */
+ #test-voice-btn {
+ margin-left: 20px;
+ background-color: #007bff;
+ color: white;
+ border: none;
+ padding: 10px 20px;
+ border-radius: 6px;
+ font-size: 16px;
+ cursor: pointer;
+ font-weight: bold;
+ -webkit-flex-shrink: 0;
+ flex-shrink: 0;
+ }
+
+ #test-voice-btn:hover {
+ background-color: #0056b3;
+ }
+
+ /* 婊氬姩鏉� */
.patient-list::-webkit-scrollbar {
width: 4px;
}
@@ -195,16 +359,23 @@
border-radius: 2px;
}
- /* 6. 璋冭瘯妗嗘牱寮� */
+ /* 璋冭瘯闈㈡澘 */
.debug-panel {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
+ flex-direction: column;
position: fixed;
right: 15px;
bottom: 70px;
- width: 350px;
- height: 200px;
- background: rgba(0, 0, 0, 0.9);
+ width: 380px;
+ height: 220px;
+ background: rgba(0, 0, 0, 0.92);
color: #0f0;
- border-radius: 4px;
+ border-radius: 6px;
font-family: monospace;
font-size: 12px;
z-index: 9999;
@@ -212,8 +383,14 @@
}
.debug-header {
+ display: -webkit-box;
+ display: -webkit-flex;
display: flex;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
justify-content: space-between;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
align-items: center;
padding: 5px;
background: #333;
@@ -235,6 +412,8 @@
}
.debug-body {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
flex: 1;
padding: 5px;
overflow-y: auto;
@@ -255,7 +434,7 @@
<!-- 椤堕儴鏍� -->
<div class="top-header">
<img src="logo.png" alt="logo" />
- <span class="title-text">鏈嶅姟澶у巺鎺掑垪</span>
+ <span class="title-text">蹇冪數璇婂尯澶у巺</span>
<span class="time-info" id="headerTime"></span>
</div>
@@ -264,14 +443,14 @@
<!-- 搴曢儴鏍� -->
<div class="bottom-footer">
- <!-- 娓╅Θ鎻愮ず璇眳涓� -->
- <div class="footer-tip">娓╅Θ鎻愮ず锛氳鍚埌鍛煎彨鍚庡墠寰�瀵瑰簲璇婂</div>
+ <div class="footer-tip">娓╅Θ鎻愮ず锛氬惉鍒板懠鍙悗璇峰墠寰�瀵瑰簲璇婂锛岃繃鍙锋偅鑰呭埌瀵艰瘖鍙板鐞嗭紒</div>
+ <button id="test-voice-btn" onclick="testVoice()">娴嬭瘯璇煶</button>
</div>
<!-- 璋冭瘯闈㈡澘 -->
- <div class="debug-panel" id="debugPanel">
+ <div class="debug-panel" id="debugPanel" >
<div class="debug-header">
- <span>馃洜锔� 杩愯鏃ュ織</span>
+ <span>[璋冭瘯] 杩愯鏃ュ織</span>
<button onclick="document.getElementById('debugBody').innerHTML=''">娓呯┖</button>
</div>
<div class="debug-body" id="debugBody"></div>
@@ -279,57 +458,135 @@
<script src="./static/jquery.min.js"></script>
<script>
- // ================= 璋冭瘯鏃ュ織鍑芥暟 =================
+ // ================= 璋冭瘯鏃ュ織 =================
function logDebug(msg) {
var now = new Date();
- var timeStr = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
- var logHtml = '<div class="debug-line"><span class="debug-time">[' + timeStr + ']</span>' + msg + '</div>';
+ function pad(num) { return num < 10 ? '0' + num : '' + num; }
+ var timeStr = pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds());
+ var logHtml = '<div class="debug-line"><span class="debug-time">[' + timeStr + ']</span> ' + msg + '</div>';
console.log("[" + timeStr + "] " + msg);
- var $body = $("#debugBody");
- $body.append(logHtml);
- $body.scrollTop($body[0].scrollHeight);
+ var body = document.getElementById("debugBody");
+ if (body) {
+ body.insertAdjacentHTML("beforeend", logHtml);
+ // requestAnimationFrame 纭繚 DOM 鏇存柊鍚庡啀婊氬姩
+ requestAnimationFrame(function () {
+ body.scrollTop = body.scrollHeight;
+ });
+ }
}
// ================= 搴旂敤鐘舵�� =================
+ // 鍛煎彨鍙彿娆℃暟鍙傛暟锛氬懠鍙偅鑰呭氨璇婃椂閲嶅鎾姤鐨勬鏁帮紝榛樿 2 娆�
+ var CALL_TIMES = 2;
+ // 涓�琛屼袱涓偅鑰呯殑鍒楃储寮曪紙甯歌蹇冪數鍥俱�佸姩鎬佸績鐢碉級
+ var TWO_PER_ROW_COLS = [0, 1];
+ // 椋熼亾鐢电敓鐞嗘槸鍚︽樉绀猴紙false 闅愯棌锛宼rue 鏄剧ず锛�
+ var SHOW_COL_ESOPHAGEAL = false;
var appState = {
- columnTitles: ["甯歌蹇冪數鍥�", "鍔ㄦ�佸績鐢�", "骞虫澘杩愬姩蹇冪數", "椋熼亾鐢电敓鐞�", "鍔ㄨ剦纭寲鐩戞祴"],
- columnSubTitles: ["搴婅竟蹇冪數鍥�(甯歌+棰戣氨)M / 蹇冪數鍚戦噺鍥綨", "鍔ㄦ�佽鍘婥", "", "", ""],
+ columnTitles: ["甯歌蹇冪數鍥�/蹇冪數鍚戦噺鍥�", "鍔ㄦ�佸績鐢�/琛�鍘�", "骞虫澘杩愬姩蹇冪數", "椋熼亾鐢电敓鐞�", "鍔ㄨ剦纭寲鐩戞祴"],
+ columnSubTitles: ["1鍙�-2鍙疯瘖瀹�", "2鍙疯瘖瀹�", "4鍙疯瘖瀹�", "6鍙疯瘖瀹�", "5鍙疯瘖瀹�"],
patients: [],
- apiBaseUrl: "http://192.168.3.12/admin-api",
+ // apiBaseUrl: "http://192.168.3.12/admin-api",
+ apiBaseUrl: "http://10.0.2.193/admin-api",
pollTimer: null,
- callRepeatTimes: 2,
spokenPatients: {},
ttsQueue: [],
- isSpeaking: false
+ isSpeaking: false,
+ };
+
+ var patStatus = {
+ 3: "宸茶繃鍙�-鎺掗槦", 5: "宸茶繃鍙�", 7: "宸茶繃鍙�-瀹夎", 10: "鎺掗槦涓�", 12: "浜插拰",
+ 13: "浜插拰-瀹夎", 15: "宸插彫鍥�", 20: "鍊欒瘖涓�", 30: "灏辫瘖涓�", 33: "宸查鐢�",
+ 34: "宸插彫鍥�-瀹夎", 36: "瀹夎涓�", 40: "宸插氨璇�"
};
// ================= 璇煶鎾姤 =================
+ // Android WebView GC 淇濇姢锛氬叏灞�鎸佹湁 utterance 寮曠敤锛岄槻姝㈣鍥炴敹瀵艰嚧鏃犲0
+ var _gCurrentUtterance = null;
+
function processTtsQueue() {
if (appState.isSpeaking || appState.ttsQueue.length === 0) return;
appState.isSpeaking = true;
var text = appState.ttsQueue.shift();
- logDebug("馃攰 寮�濮嬫挱鎶�: " + text);
+ logDebug("[鎾姤] " + text);
- var utterance = new SpeechSynthesisUtterance(text);
- utterance.onend = function () {
- appState.isSpeaking = false;
- processTtsQueue();
- };
- utterance.onerror = function () {
- appState.isSpeaking = false;
- processTtsQueue();
- };
-
+ // 浼樺厛灏濊瘯璁惧鍘熺敓 TTS 鎺ュ彛 (wowjoy)
if (typeof wowjoy !== 'undefined' && typeof wowjoy.speek === 'function') {
try {
wowjoy.speek(text);
+ logDebug("[鎾姤] wowjoy.speek 宸茶皟鐢�");
setTimeout(function () { appState.isSpeaking = false; processTtsQueue(); }, 4000);
return;
- } catch (e) { logDebug("鉂� wowjoy 璋冪敤澶辫触: " + e.message); }
+ } catch (e) { logDebug("[wowjoy澶辫触] " + e.message); }
}
- if (window.speechSynthesis) { window.speechSynthesis.speak(utterance); }
- else { appState.isSpeaking = false; processTtsQueue(); }
+ if (!window.speechSynthesis) {
+ logDebug("[TTS] 娴忚鍣ㄤ笉鏀寔璇煶鍚堟垚");
+ appState.isSpeaking = false;
+ processTtsQueue();
+ return;
+ }
+
+ // 浠呭湪鏈夎闊虫鍦ㄦ挱鏀炬椂鎵� cancel锛岄伩鍏嶄笉蹇呰鐨勪腑鏂�
+ if (window.speechSynthesis.speaking) {
+ logDebug("[鎾姤] cancel 褰撳墠鎾斁");
+ window.speechSynthesis.cancel();
+ }
+
+ var utterance = new SpeechSynthesisUtterance(text);
+ utterance.rate = 0.85;
+ utterance.volume = 1.0;
+ // Android WebView GC 淇濇姢锛氬瓨鍏ㄥ眬寮曠敤
+ _gCurrentUtterance = utterance;
+
+ utterance.onstart = function () {
+ logDebug("[鎾姤] onstart 瑙﹀彂");
+ };
+ utterance.onend = function () {
+ logDebug("[鎾姤] onend 瑙﹀彂");
+ _gCurrentUtterance = null;
+ appState.isSpeaking = false;
+ // 寤惰繜涓�涓嬭寮曟搸瀹屽叏閲婃斁
+ setTimeout(function () { processTtsQueue(); }, 200);
+ };
+ utterance.onerror = function (e) {
+ logDebug("[TTS閿欒] " + (e.error || "unknown"));
+ _gCurrentUtterance = null;
+ appState.isSpeaking = false;
+ setTimeout(function () { processTtsQueue(); }, 200);
+ };
+
+ // 纭繚璇煶鍖呭凡鍔犺浇 (Android 涓� getVoices 鍙兘鍒濆涓虹┖)
+ var voices = window.speechSynthesis.getVoices();
+ if (voices.length > 0) {
+ utterance.voice = voices[0];
+ logDebug("[鎾姤] 浣跨敤璇煶: " + voices[0].name + " lang=" + voices[0].lang);
+ } else {
+ logDebug("[鎾姤] getVoices 涓虹┖, 绛夊緟 voiceschanged 浜嬩欢");
+ var voicesLoaded = false;
+ var onVoicesChange = function () {
+ if (voicesLoaded) return;
+ voicesLoaded = true;
+ var v2 = window.speechSynthesis.getVoices();
+ if (v2.length > 0) {
+ utterance.voice = v2[0];
+ logDebug("[鎾姤] 璇煶鍔犺浇瀹屾垚: " + v2[0].name);
+ }
+ window.speechSynthesis.speak(utterance);
+ };
+ window.speechSynthesis.addEventListener('voiceschanged', onVoicesChange);
+ // 濡傛灉 1s 鍐呮病瑙﹀彂锛岀洿鎺� speak
+ setTimeout(function () {
+ if (!voicesLoaded) {
+ logDebug("[鎾姤] voiceschanged 瓒呮椂, 鐩存帴 speak");
+ window.speechSynthesis.speak(utterance);
+ }
+ }, 1000);
+ return;
+ }
+
+ window.speechSynthesis.speak(utterance);
+ logDebug("[鎾姤] speak 宸茶皟鐢�");
}
function speak(text) {
@@ -338,46 +595,179 @@
processTtsQueue();
}
- // ================= 娓叉煋鍑芥暟 =================
- function renderMainContent() {
- var $main = $("#mainContent");
- $main.empty();
+ // ================= 璇煶娴嬭瘯 =================
+ function testVoice() {
+ logDebug("[璇煶娴嬭瘯] ========== 寮�濮� ==========");
+ var testText = "娴嬭瘯璇煶鎾姤";
- for (var i = 0; i < appState.columnTitles.length; i++) {
- var titleHtml = '<div class="col-title-line">' + appState.columnTitles[i] + '</div>';
- if (appState.columnSubTitles[i]) {
- titleHtml += '<div class="col-subtitle">' + appState.columnSubTitles[i] + '</div>';
+ // 1. 妫�娴� wowjoy 鍘熺敓鎺ュ彛
+ var hasWowjoy = (typeof wowjoy !== 'undefined');
+ logDebug("[璇煶娴嬭瘯] wowjoy 瀵硅薄瀛樺湪=" + hasWowjoy);
+ if (hasWowjoy) {
+ logDebug("[璇煶娴嬭瘯] wowjoy.speek 绫诲瀷=" + (typeof wowjoy.speek));
+ if (typeof wowjoy.speek === 'function') {
+ try {
+ wowjoy.speek(testText);
+ logDebug("[璇煶娴嬭瘯] wowjoy.speek 宸茶皟鐢紝娉ㄦ剰鍚澶囧0闊�");
+ } catch (e) {
+ logDebug("[璇煶娴嬭瘯] wowjoy.speek 寮傚父: " + e.message);
+ }
+ }
+ }
+
+ // 2. 妫�娴� SpeechSynthesis
+ var hasSpeech = (typeof window.speechSynthesis !== 'undefined');
+ logDebug("[璇煶娴嬭瘯] speechSynthesis 瀵硅薄瀛樺湪=" + hasSpeech);
+
+ if (hasSpeech) {
+ var syn = window.speechSynthesis;
+ logDebug("[璇煶娴嬭瘯] speaking=" + syn.speaking + " pending=" + syn.pending + " paused=" + syn.paused);
+
+ var voices = syn.getVoices();
+ logDebug("[璇煶娴嬭瘯] getVoices 杩斿洖 " + voices.length + " 涓闊冲寘");
+ for (var v = 0; v < Math.min(voices.length, 5); v++) {
+ logDebug("[璇煶娴嬭瘯] 璇煶[" + v + "] " + voices[v].name + " lang=" + voices[v].lang + " local=" + voices[v].localService);
}
- var colClass = (i === 0) ? 'col-wide' : 'col-normal';
- // 娉ㄦ剰锛氳繖閲屼笉鍐嶇粰绗�1鏍忓姞 col-flex锛岀敱 CSS #col-0 寮哄埗鎺у埗
- var colHtml = '<div class="column-box ' + colClass + '">' +
- '<div class="col-title">' + titleHtml + '</div>' +
- '<div class="patient-list" id="col-' + i + '"></div>' +
- '</div>';
- $main.append(colHtml);
+ // 濡傛灉 voices 涓虹┖锛岀瓑寰呭姞杞藉悗鍐嶆挱
+ function doSpeakTest() {
+ var v2 = syn.getVoices();
+ var u = new SpeechSynthesisUtterance(testText);
+ u.rate = 0.85;
+ u.volume = 1.0;
+ if (v2.length > 0) {
+ u.voice = v2[0];
+ logDebug("[璇煶娴嬭瘯] 閫夋嫨璇煶: " + v2[0].name);
+ }
+ // GC 淇濇姢
+ window._testUtterance = u;
+ u.onstart = function() { logDebug("[璇煶娴嬭瘯] onstart 瑙﹀彂 鉁�"); };
+ u.onend = function() { logDebug("[璇煶娴嬭瘯] onend 瑙﹀彂 鉁�"); window._testUtterance = null; };
+ u.onerror = function(e) { logDebug("[璇煶娴嬭瘯] onerror: " + (e.error || "unknown")); window._testUtterance = null; };
+
+ if (syn.speaking) {
+ logDebug("[璇煶娴嬭瘯] 鏈夎闊虫鍦ㄦ挱鏀撅紝鍏� cancel");
+ syn.cancel();
+ setTimeout(function () { syn.speak(u); logDebug("[璇煶娴嬭瘯] speak 宸茶皟鐢�(寤惰繜)"); }, 300);
+ } else {
+ syn.speak(u);
+ logDebug("[璇煶娴嬭瘯] speak 宸茶皟鐢�");
+ }
+ }
+
+ if (voices.length === 0) {
+ logDebug("[璇煶娴嬭瘯] 璇煶鍒楄〃涓虹┖锛岀瓑寰� voiceschanged...");
+ var loaded = false;
+ var handler = function () {
+ if (loaded) return;
+ loaded = true;
+ logDebug("[璇煶娴嬭瘯] voiceschanged 瑙﹀彂, 璇煶鏁�=" + syn.getVoices().length);
+ doSpeakTest();
+ };
+ syn.addEventListener('voiceschanged', handler);
+ setTimeout(function () {
+ if (!loaded) {
+ logDebug("[璇煶娴嬭瘯] voiceschanged 瓒呮椂(2s), 寮哄埗娴嬭瘯");
+ doSpeakTest();
+ }
+ }, 2000);
+ } else {
+ doSpeakTest();
+ }
}
+
+ if (!hasWowjoy && !hasSpeech) {
+ logDebug("[璇煶娴嬭瘯] 鏃犱换浣� TTS 寮曟搸鍙敤锛�");
+ }
+ logDebug("[璇煶娴嬭瘯] ========== 缁撴潫 ==========");
}
- function renderPatients() {
- for (var i = 0; i < appState.columnTitles.length; i++) {
- $("#col-" + i).empty();
- }
+ // ================= 娓叉煋锛氭爣棰樻鏋讹紙浠呭垵濮嬪寲涓�娆★級=================
+ function initLayout() {
+ logDebug("[甯冨眬] initLayout 寮�濮�, 鍒楁暟=" + appState.columnTitles.length);
+ var main = document.getElementById("mainContent");
+ if (!main) { logDebug("[甯冨眬] mainContent 鍏冪礌鏈壘鍒�!"); return; }
+ var html = '<div class="columns-row">';
+ var visibleCount = 0;
- for (var c = 0; c < appState.patients.length; c++) {
- var colData = appState.patients[c];
- if (Array.isArray(colData)) {
- var $col = $("#col-" + c);
- for (var p = 0; p < colData.length; p++) {
- var pat = colData[p];
- var roomHtml = pat.roomName ? '<span class="p-room">(' + pat.roomName + ')</span>' : '';
- var itemHtml = '<div class="patient-item">' +
- '<span class="p-number">' + (pat.bookSeqNum || '') + '</span>' +
- '<span class="p-name">' + (pat.patName || '') + '</span>' +
- roomHtml +
- '</div>';
- $col.append(itemHtml);
- }
+ for (var i = 0; i < appState.columnTitles.length; i++) {
+ // 椋熼亾鐢电敓鐞嗭細閫氳繃 SHOW_COL_ESOPHAGEAL 鎺у埗鏄鹃殣
+ if (i === 3 && !SHOW_COL_ESOPHAGEAL) {
+ logDebug("[甯冨眬] 鍒�" + i + " 椋熼亾鐢电敓鐞� 宸查殣钘�");
+ continue;
+ }
+
+ var subtitle = appState.columnSubTitles[i] || " ";
+ // 涓�琛屼袱涓殑鍒楃敤 col-wide锛屽惁鍒� col-normal
+ var isTwoPerRow = TWO_PER_ROW_COLS.indexOf(i) !== -1;
+ var colClass = isTwoPerRow ? 'col-wide' : 'col-normal';
+ var rowClass = isTwoPerRow ? 'two-per-row' : 'one-per-row';
+ logDebug("[甯冨眬] 鍒�" + i + " " + appState.columnTitles[i] + " class=" + colClass + " row=" + rowClass);
+ html += '<div class="column-box ' + colClass + '">' +
+ '<div class="col-title">' +
+ '<div class="col-title-line">' + appState.columnTitles[i] + '</div>' +
+ '<div class="col-subtitle">' + subtitle + '</div>' +
+ '</div>' +
+ '<div class="patient-list ' + rowClass + '" id="col-' + i + '"></div>' +
+ '</div>';
+ visibleCount++;
+ }
+ html += '</div>';
+ main.innerHTML = html;
+ logDebug("[甯冨眬] initLayout 瀹屾垚, 鍙鍒�=" + visibleCount);
+ }
+
+ // ================= 娓叉煋锛氭偅鑰呭垪琛紙diff 鏇存柊锛屽彧鏀瑰彉鍖栫殑鍒楋級=================
+ function desensitizeName(name) {
+ if (!name || name.length < 2) return name || '';
+ return name.charAt(0) + '*' + name.substring(2);
+ }
+
+ function isMissedStatus(status) {
+ var s = parseInt(status, 10);
+ return s === 3 || s === 5 || s === 7;
+ }
+
+ function buildColumnHtml(colData) {
+ if (!Array.isArray(colData) || colData.length === 0) return "";
+ var h = "";
+ for (var p = 0; p < colData.length; p++) {
+ var pat = colData[p];
+ var missedClass = isMissedStatus(pat.status) ? ' missed' : '';
+ var roomHtml = (!isMissedStatus(pat.status) && pat.roomName) ? '<span class="p-room">' + pat.roomName + '</span>' : '';
+ h += '<div class="patient-item' + missedClass + '">' +
+ '<span class="p-number">' + (pat.seqNum || '') + '</span>' +
+ '<span class="p-name-wrap"><span class="p-name">' + desensitizeName(pat.patName) + '</span>' + roomHtml +
+ (missedClass ? '<span class="p-missed-tag">杩囧彿</span>' : '') + '</span>' +
+ '</div>';
+ }
+ return h;
+ }
+ function isSameColumn(a, b) {
+ if (!Array.isArray(a) || !Array.isArray(b)) return a === b;
+ if (a.length !== b.length) return false;
+ for (var i = 0; i < a.length; i++) {
+ if (a[i].patId !== b[i].patId) return false;
+ if (a[i].roomName !== b[i].roomName) return false;
+ if (parseInt(a[i].status, 10) !== parseInt(b[i].status, 10)) return false;
+ }
+ return true;
+ }
+
+ function updatePatients(dataList) {
+ for (var i = 0; i < appState.columnTitles.length; i++) {
+ var newData = (dataList && dataList[i]) ? dataList[i] : [];
+ var oldData = appState.patients[i];
+
+ // diff锛氭暟鎹湭鍙樺寲鍒欒烦杩囪鍒� DOM 鎿嶄綔
+ if (isSameColumn(oldData, newData)) continue;
+
+ var col = document.getElementById("col-" + i);
+ if (col) {
+ col.innerHTML = buildColumnHtml(newData);
+ logDebug("[鏇存柊] 鍒�" + i + " " + appState.columnTitles[i] + " 鍒锋柊 " + newData.length + " 浜�");
+ } else {
+ logDebug("[鏇存柊] 鍒�" + i + " DOM涓嶅瓨鍦�(鍙兘宸查殣钘�)");
}
}
}
@@ -404,12 +794,12 @@
}
if (!oldPat || !oldPat.roomName) {
var repeatText = "";
- for (var r = 0; r < appState.callRepeatTimes; r++) {
- repeatText += "璇� " + newPat.bookSeqNum + " 鍙� " + newPat.patName + " 鍒� " + newPat.roomName + " 灏辫瘖銆�";
- }
- speak(repeatText);
+ repeatText += "璇� " + newPat.seqNum + " 鍙� " + newPat.patName + " 鍒� " + newPat.roomName + " 灏辫瘖銆�";
+ for (var r = 0; r < CALL_TIMES; r++) {
+ speak(repeatText);
+ }
appState.spokenPatients[newPat.patId] = true;
- logDebug("馃敂 鍔犲叆鎾姤闃熷垪: " + newPat.patName);
+ logDebug("[鎺掗槦] " + newPat.patName + " -> " + newPat.roomName);
}
}
}
@@ -420,51 +810,84 @@
// ================= 鏁版嵁鑾峰彇 =================
function fetchQueueData() {
var url = appState.apiBaseUrl + "/ecg/screen/big-screen-data";
+ logDebug("[璇锋眰] GET " + url);
$.ajax({
url: url,
type: "GET",
dataType: "json",
timeout: 5000,
success: function (res) {
+ logDebug("[鍝嶅簲] code=" + (res ? res.code : "null"));
var dataList = [];
if (res && res.code === 0 && res.data) {
for (var i = 0; i < appState.columnTitles.length; i++) {
var key = i.toString();
dataList[i] = (res.data[key] && Array.isArray(res.data[key])) ? res.data[key] : [];
+ logDebug("[鏁版嵁] 鍒�" + i + " " + appState.columnTitles[i] + " 鎮h�呮暟=" + dataList[i].length);
}
+ } else {
+ logDebug("[鍝嶅簲] 寮傚父 code=" + (res ? res.code : "null") + " msg=" + (res ? res.msg : ""));
}
+ // 鍏� diff 鏇存柊 DOM锛屽啀鎾姤锛屾渶鍚庝繚瀛樻暟鎹敤浜庝笅娆″姣�
+ updatePatients(dataList);
checkAndSpeakNewRooms(appState.patients, dataList);
appState.patients = dataList;
- renderPatients();
- if (window.performance && window.performance.memory) {
- var usedMB = (window.performance.memory.usedJSHeapSize / 1048576).toFixed(2);
- logDebug("馃捑 鍐呭瓨: " + usedMB + " MB");
- }
+ // Android 6 WebView 閫氬父涓嶆敮鎸� performance.memory锛屽畨鍏ㄥ畧鍗�
+ try {
+ if (window.performance && window.performance.memory) {
+ var usedMB = (window.performance.memory.usedJSHeapSize / 1048576).toFixed(2);
+ logDebug("[鍐呭瓨] " + usedMB + " MB");
+ }
+ } catch (e) { }
},
error: function (err) {
- logDebug("鉂� 璇锋眰澶辫触: " + err.statusText);
+ logDebug("[璇锋眰澶辫触] status=" + err.status + " " + (err.statusText || "缃戠粶閿欒") + " url=" + url);
}
});
}
// ================= 鍒濆鍖� =================
- $(document).ready(function () {
- renderMainContent();
+ function onReady() {
+ logDebug("[鍒濆鍖朷 onReady 寮�濮�");
+ logDebug("[鐜] speechSynthesis=" + (typeof window.speechSynthesis !== 'undefined') + " wowjoy=" + (typeof wowjoy !== 'undefined'));
+ try {
+ initLayout();
+ logDebug("[鍒濆鍖朷 initLayout 瀹屾垚");
+ } catch (e) { logDebug("[鍒濆鍖朷 initLayout 寮傚父: " + e.message); }
updateHeaderTime();
setInterval(updateHeaderTime, 1000);
- fetchQueueData();
+ try {
+ fetchQueueData();
+ logDebug("[鍒濆鍖朷 棣栨 fetchQueueData 宸插彂璧�");
+ } catch (e) { logDebug("[鍒濆鍖朷 fetchQueueData 寮傚父: " + e.message); }
appState.pollTimer = setInterval(fetchQueueData, 5000);
- logDebug("鉁� 绯荤粺鍚姩");
- });
+ logDebug("[绯荤粺] 鍚姩瀹屾垚 - Android 6.0.1 杞闂撮殧5s");
+ }
function updateHeaderTime() {
var now = new Date();
var weekDays = ["鏄熸湡鏃�", "鏄熸湡涓�", "鏄熸湡浜�", "鏄熸湡涓�", "鏄熸湡鍥�", "鏄熸湡浜�", "鏄熸湡鍏�"];
function padZero(num) { return num < 10 ? '0' + num : '' + num; }
- var dateStr = now.getFullYear() + "骞�" + padZero(now.getMonth() + 1) + "鏈�" + padZero(now.getDate()) + "鏃� " + weekDays[now.getDay()];
+ var dateStr = now.getFullYear() + "骞�" + padZero(now.getMonth() + 1) + "鏈�" + padZero(now.getDate()) + "鏃�";
+ var weekStr = weekDays[now.getDay()];
var timeStr = padZero(now.getHours()) + ":" + padZero(now.getMinutes());
- $("#headerTime").text(dateStr + " " + timeStr);
+ var el = document.getElementById("headerTime");
+ // 鏄熸湡鍜屾棩鏈熷悇鍗犱竴琛屽湪宸︼紝鏃堕棿澶у瓧鍦ㄥ彸璺ㄤ袱琛�
+ if (el) el.innerHTML = '<div class="time-info-inner"><div class="time-left"><div>' + weekStr + '</div><div>' + dateStr + '</div></div><div class="time-right"><span class="time-clock">' + timeStr + '</span></div></div>';
+ }
+
+ // 鍏煎 DOM ready锛圓ndroid 6 鏌愪簺 WebView 鍙兘娌℃湁 $锛�
+ logDebug("[鍏ュ彛] readyState=" + document.readyState + " jQuery=" + (typeof $ !== 'undefined'));
+ if (typeof $ !== 'undefined') {
+ logDebug("[鍏ュ彛] 浣跨敤 jQuery.ready");
+ $(document).ready(onReady);
+ } else if (document.readyState === 'complete' || document.readyState === 'interactive') {
+ logDebug("[鍏ュ彛] DOM宸插氨缁�, setTimeout瑙﹀彂");
+ setTimeout(onReady, 1);
+ } else {
+ logDebug("[鍏ュ彛] 鐩戝惉 DOMContentLoaded");
+ document.addEventListener('DOMContentLoaded', onReady);
}
</script>
</body>
--
Gitblit v1.9.3