From 33e48294eb2206d5e0565fd8b1b24f8c36f78c43 Mon Sep 17 00:00:00 2001 From: Teng <461587751@qq.com> Date: Mon, 19 Jan 2026 17:35:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 20 +-- common/websocket.js | 100 +++++++++--- common/websocketManager.js | 46 ++++-- component/public/calendarsimple.vue | 2 +- pages/NursingNew/component/index.vue | 2 +- .../NursingNew/component/invoicing/index.vue | 8 +- pages/NursingNew/component/nurse/bigindex.css | 150 +++++++++++------- pages/NursingNew/component/nurse/bigindex.vue | 58 +++++-- pages/Warehouse/index/component/index.vue | 4 +- pages/login/newanimationpage.vue | 2 +- 10 files changed, 274 insertions(+), 118 deletions(-) diff --git a/App.vue b/App.vue index ed118e3..f32e35b 100644 --- a/App.vue +++ b/App.vue @@ -41,19 +41,19 @@ }, onShow() { - console.log('App Show'); - if (uni.getStorageSync('userInfo')) { - // 重置重连计数,确保立即重连 - connectWs() - } + // console.log('App Show'); + // if (uni.getStorageSync('userInfo')) { + // // 重置重连计数,确保立即重连 + // connectWs() + // } }, onHide() { - console.log('App Hide'); - if (uni.getStorageSync('userInfo')) { - // 可选择关闭 socket,或只是停止心跳 - closeWs() - } + // console.log('App Hide'); + // if (uni.getStorageSync('userInfo')) { + // // 可选择关闭 socket,或只是停止心跳 + // closeWs() + // } } } diff --git a/common/websocket.js b/common/websocket.js index 3558ec6..4995b45 100644 --- a/common/websocket.js +++ b/common/websocket.js @@ -2,15 +2,18 @@ // 带中文日志与消息体打印选项的 WsRequest(替换你当前文件即可) class WsRequest { + // 静态:防止重复全局绑定 + static _globalBound = false; + constructor(url = '', options = {}) { this.url = url || ''; this.options = Object.assign({ header: {}, protocols: [], debug: true, - lang: 'zh', // 'zh' 或 'en',控制日志语言(默认中文) - showMessageBody: true, // 是否在日志中显示收到消息的完整 JSON(默认 true) - filterPing: true, // 是否过滤掉 ping/pong 日志(默认 true) + lang: 'zh', // 'zh' 或 'en' + showMessageBody: true, + filterPing: true, heartbeatInterval: 30000, heartbeatTimeout: 15000, pingMessage: { type: 'ping' }, @@ -30,7 +33,18 @@ class WsRequest { this._hbTimeoutTimer = null; this._subscriptions = new Map(); - if (this.options.bindGlobal) this._bindGlobalSocketEvents(); + // 是否允许自动重连(主动 close 时设为 false) + this._shouldReconnect = true; + this._manualClose = false; + + // 如果要求全局绑定且还没绑定过,则绑定一次(静态控制) + if (this.options.bindGlobal && !WsRequest._globalBound) { + this._bindGlobalSocketEvents(); + WsRequest._globalBound = true; + } else if (this.options.bindGlobal && WsRequest._globalBound) { + // 已由其他实例绑定,跳过 + } + if (this.options.autoConnect) setTimeout(() => this.open(), 0); } @@ -69,10 +83,9 @@ class WsRequest { return this.options.lang === 'zh' ? zh[key] || key : en[key] || key; } - // 简单统一日志 + // 简单统一日志(恢复 console 输出,便于调试) log(...args) { if (!this.options.debug) return; - // 如果是对象,格式化输出以便控制台可读 const out = args.map(a => { if (typeof a === 'object') { try { return JSON.stringify(a, null, 2); } catch (e) { return String(a); } @@ -86,32 +99,63 @@ class WsRequest { open() { if (!this.url) { this.log(this._label('open'), this._label('noUrl') || 'no url'); return; } if (this.connected) { this.log(this._label('alreadyConnected')); return; } + this.log(this._label('open'), this.url); + + // 主动 open:允许后续自动重连(如果被之前的手动关闭禁止过,open 表示想要恢复) + this._shouldReconnect = true; + this._manualClose = false; + try { const task = uni.connectSocket({ url: this.url, header: this.options.header, protocols: this.options.protocols }); if (task && typeof task.onOpen === 'function') { this._bindSocketTask(task); } else { this.log(this._label('connectNoTask')); - // 依赖全局回调,_bindGlobalSocketEvents 已经绑定则会处理 onOpen/onMessage + // 依赖全局回调,已在构造时绑定 } } catch (e) { console.error(e); } } - close(code = 1000, reason = 'client close') { + /** + * close(code, reason, manual) + * manual: 是否为手动/意图性关闭(默认 true) + * - manual === true 时将禁止自动重连(用于用户主动关闭) + * - manual === false 时视为异常或内部触发的关闭(允许重连) + */ + close(code = 1000, reason = 'client close', manual = true) { + // 标记手动关闭以禁止后续自动重连 + if (manual) { + this._shouldReconnect = false; + this._manualClose = true; + } else { + // 非手动关闭(例如心跳超时)则保持 _shouldReconnect 原有值(通常为 true) + this._manualClose = false; + } + this._stopHeartbeat(); try { if (this.socketTask && typeof this.socketTask.close === 'function') { - this.socketTask.close({ code, reason }); + try { + this.socketTask.close({ code, reason }); + } catch (e) { + // 某些平台 socketTask.close 可能会抛错 + this.log(this._label('closeError'), e); + // 尝试全局 close + if (typeof uni.closeSocket === 'function') uni.closeSocket(); + } } else if (typeof uni.closeSocket === 'function') { uni.closeSocket(); } } catch (e) { this.log(this._label('closeError'), e); } + this.connected = false; + // 清理 socketTask 引用,释放资源,防止重复使用导致 FD 泄漏 + this.socketTask = null; } send(payload) { @@ -150,6 +194,10 @@ class WsRequest { this._startHeartbeat(); this._flushQueue(); this.options.onOpen && this.options.onOpen(res); + + // 打开时允许后续重连(如果连接成功) + this._shouldReconnect = true; + this._manualClose = false; }); task.onMessage(msg => { @@ -161,6 +209,7 @@ class WsRequest { this.connected = false; this._stopHeartbeat(); this.options.onClose && this.options.onClose(res); + // 仅当允许重连时才触发重连逻辑 this._tryReconnect(); }); @@ -182,15 +231,13 @@ class WsRequest { } const type = (data && data.type) || '__default__'; - // 过滤 ping/pong (若你想看 ping/pong,把 filterPing 设为 false) + // 过滤 ping/pong const isPing = data && (data.type === 'ping' || data.type === 'pong' || (typeof data === 'string' && (data === 'ping' || data === 'pong'))); if (isPing && this.options.filterPing) { - // 仍更新 lastPong,但不打印消息体,除非 showMessageBody 强制 true if (this.options.debug && this.options.showMessageBody === false) { this.log(this._label('onMessage'), type); } } else { - // 打印消息类型与(可选)格式化消息体 if (this.options.debug) { if (this.options.showMessageBody) { let bodyStr; @@ -202,13 +249,12 @@ class WsRequest { } } - // 外部回调与订阅异步派发 if (this.options.onMessage) setTimeout(() => this.options.onMessage(data, msg), 0); setTimeout(() => this._dispatch(type, data, msg), 0); } _bindGlobalSocketEvents() { - // 解绑默认全局再绑定,避免重复 + // 解绑默认全局再绑定,避免重复(但是本函数只会被调用一次,受静态保护) try { uni.offSocketOpen && uni.offSocketOpen(); } catch (e) {} try { uni.offSocketMessage && uni.offSocketMessage(); } catch (e) {} try { uni.offSocketClose && uni.offSocketClose(); } catch (e) {} @@ -223,12 +269,15 @@ class WsRequest { this._startHeartbeat(); this._flushQueue(); this.options.onOpen && this.options.onOpen(res); + + // 同上,打开时允许重连 + this._shouldReconnect = true; + this._manualClose = false; }); } catch (e) {} try { uni.onSocketMessage(msg => { - // 全局收到消息也走统一处理 if (this.options.debug) this.log(this._label('globalOnMessage')); this._handleIncoming(msg); }); @@ -267,7 +316,8 @@ class WsRequest { const since = Date.now() - this._lastPongAt; if (since > this.options.heartbeatTimeout) { this.log(this._label('hbTimeout'), since); - try { this.close(); } catch (e) { this.log('hb close fail', e); } + // 由心跳触发的关闭视为“异常/内部”关闭 — 传 manual = false 以允许重连 + try { this.close(1000, 'hb timeout', false); } catch (e) { this.log('hb close fail', e); } } }, this.options.heartbeatTimeout); }, this.options.heartbeatInterval); @@ -279,14 +329,26 @@ class WsRequest { } _tryReconnect() { + // 先检查是否允许自动重连(主动关闭时应被禁用) + if (!this._shouldReconnect) { + this.log(this._label('reconnectScheduled'), 'reconnect disabled (manual close)'); + return; + } + if (this.reconnectAttempts >= this.options.maxReconnectAttempts) { this.log(this._label('reconnectScheduled'), 'exhausted'); return; } this.reconnectAttempts++; - const delay = Math.min(this.options.reconnectDelayBase * Math.pow(1.5, this.reconnectAttempts - 1), 30000); - this.log(this._label('reconnectScheduled'), delay + 'ms', 'attempt', this.reconnectAttempts); + + // 指数退避 + jitter(避免同时大量重连) + const base = this.options.reconnectDelayBase || 1000; + const delay = Math.min(base * Math.pow(1.5, this.reconnectAttempts - 1), 30000); + const jitter = Math.floor(Math.random() * 401) - 200; // -200 .. +200 ms + const finalDelay = Math.max(0, Math.floor(delay) + jitter); + + this.log(this._label('reconnectScheduled'), finalDelay + 'ms', 'attempt', this.reconnectAttempts); setTimeout(() => { this.socketTask = null; this.connectIfForeground(); - }, delay); + }, finalDelay); } connectIfForeground() { diff --git a/common/websocketManager.js b/common/websocketManager.js index 9e1c30b..c4c6f9d 100644 --- a/common/websocketManager.js +++ b/common/websocketManager.js @@ -3,25 +3,49 @@ import WsRequest from '@/common/websocket.js'; let globalWs = null; -const initWs = (url, options) => { - // 如果已经有 WebSocket 实例,直接返回 - if (globalWs) return globalWs; +const initWs = (url, options = {}) => { + // 如果已经有 WebSocket 实例且 URL 相同,直接返回 + if (globalWs) { + if (globalWs.url === url) { + return globalWs; + } + // 否则先将旧实例以“手动关闭”方式关闭并清理,避免旧实例干扰 + try { + globalWs._shouldReconnect = false; + globalWs.close(1000, 'reinit', true); + } catch (e) { + // 忽略关闭错误 + } + globalWs = null; + } - globalWs = new WsRequest(url, options); + // 强烈建议:全局只 bind 一次(WsRequest 内部已用静态保护) + const opt = Object.assign({ bindGlobal: true }, options); + globalWs = new WsRequest(url, opt); return globalWs; }; const connectWs = () => { - if (globalWs) { - globalWs.reconnectAttempts = 0; // 重置重连计数 - globalWs.open(); // 打开 WebSocket 连接 - } + if (!globalWs) return; + // 如果已经连接,直接返回,避免重复 open + if (globalWs.connected) return; + // 明确表示这是一次主动连接请求,允许自动重连 + globalWs.reconnectAttempts = 0; + globalWs._shouldReconnect = true; + globalWs._manualClose = false; + globalWs.open(); }; -const closeWs = () => { - if (globalWs) { - globalWs.close(); // 关闭 WebSocket 连接 +const closeWs = (manual = true) => { + if (!globalWs) return; + // 主动关闭时先禁止自动重连 + if (manual) { + globalWs._shouldReconnect = false; } + // 传 manual 参数到 close,以便内部区分是否允许重连 + globalWs.close(1000, 'manager close', !!manual); + // 如果你想下次重新 init 时创建新实例,可以把 globalWs 置空 + // globalWs = null; }; export { initWs, connectWs, closeWs }; diff --git a/component/public/calendarsimple.vue b/component/public/calendarsimple.vue index 817a23a..147f594 100644 --- a/component/public/calendarsimple.vue +++ b/component/public/calendarsimple.vue @@ -43,7 +43,7 @@ // 支持对象和旧类型(String/Date/Number) const props = defineProps({ modelValue: { - type: [String, Date, Number, Object], + default: null } }); diff --git a/pages/NursingNew/component/index.vue b/pages/NursingNew/component/index.vue index 32554d0..badbadc 100644 --- a/pages/NursingNew/component/index.vue +++ b/pages/NursingNew/component/index.vue @@ -1186,7 +1186,7 @@ },200) }) onHide(() => { - playall.value = false; + photoplay.value = false; }) const filteredMenu = (index : number) => { return leftMenuArray.value.filter(item => Number(item.areaFlag) - 1 == index); diff --git a/pages/NursingNew/component/invoicing/index.vue b/pages/NursingNew/component/invoicing/index.vue index ce86fb6..c6ab0c0 100644 --- a/pages/NursingNew/component/invoicing/index.vue +++ b/pages/NursingNew/component/invoicing/index.vue @@ -1728,12 +1728,12 @@ } const savePackagelist = ref([]); onMounted(() => { - // if(uni.getStorageSync('elderId')===null){ - // uni.setStorageSync('elderId', ""); - // } + if(uni.getStorageSync('elderId')===null){ + uni.setStorageSync('elderId', ""); + } savePackagelist.value = uni.getStorageSync('Packagelist') || [] let res = uni.getStorageSync('saveTree2') - console.log("啥啊啊啊啊",savePackagelist.value,res) + // console.log("啥啊啊啊啊",myArray) let goodArray = [] myArray.forEach((element : any) => { diff --git a/pages/NursingNew/component/nurse/bigindex.css b/pages/NursingNew/component/nurse/bigindex.css index 7f3fd73..8c3526d 100644 --- a/pages/NursingNew/component/nurse/bigindex.css +++ b/pages/NursingNew/component/nurse/bigindex.css @@ -465,39 +465,60 @@ width: 100%; height: 100rpx; display: flex; - align-items: center; + /* align-items: center; */ /* background-color: red; */ .order-month { margin-left: 30rpx; font-size: 37rpx; font-weight: 800; - width: 100rpx; + width: 105rpx; + /* background-color: green; */ + height: 100rpx; + display: flex; + align-items: center; + position: relative; + .order-month-right{ + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + height: 60%; + width: 10rpx; + background: linear-gradient(to right, #ececec, white); + } } .order-day { width: 440rpx; height: 100rpx; + /* background-color: red; */ .days-father { display: flex; align-items: center; font-size: 31rpx; + margin-top: 20rpx; .days { - height: 75rpx; - min-width: 75rpx; + height: 59rpx; + min-width: 59rpx; + + margin: 0 8rpx; display: flex; justify-content: center; align-items: center; - + /* background-color: red; */ + border-radius: 50%; /* color: #BBBABA; */ } .targetdays { - height: 75rpx; - min-width: 75rpx; + height: 59rpx; + min-width: 59rpx; + + margin: 0 8rpx; display: flex; justify-content: center; align-items: center; @@ -517,46 +538,51 @@ position: relative; .history-spe { - min-width: 86%; + min-width: 88%; height: 100%; - margin-left: 14%; + margin-left: 11%; background-color: #F7F8F9; border-radius: 25rpx; padding-top: 10rpx; padding-left: 20rpx; /* position: relative; */ + .history-left-jiao { position: absolute; - right: 0; - top: 0; - width: 85rpx; + right: 30rpx; + top: 15rpx; + width: 100rpx; height: 45rpx; - background-color: #D9E5FF; + background-color: #4690FF; display: flex; align-items: center; justify-content: center; - border-top-right-radius: 25rpx; - border-bottom-left-radius: 25rpx; - color: #3C9CFD; - font-size: 19rpx; + border: 2rpx solid #4690FF; + margin-top: 20rpx; + margin-right: 30rpx; + border-radius: 10rpx; + color: #fff; + font-size: 27rpx; font-weight: 600; } .history-left-jiao-error { position: absolute; - right: 0; - top: 0; - width: 85rpx; + right: 30rpx; + top: 15rpx; + width: 100rpx; height: 45rpx; background-color: #FFEBEB; display: flex; align-items: center; justify-content: center; - border-top-right-radius: 25rpx; - border-bottom-left-radius: 25rpx; + border: 2rpx solid #F76E6E; + margin-top: 20rpx; + margin-right: 30rpx; + border-radius: 10rpx; color: #F76E6E; - font-size: 19rpx; + font-size: 27rpx; font-weight: 600; } } @@ -564,27 +590,37 @@ /* background-color: red; */ .history-title { width: 100%; - height: 70rpx; + height: 80rpx; display: flex; align-items: center; padding: 0 30rpx; justify-content: space-between; - - + .history-left { - font-size: 30rpx; + .history-blue{ + width: 8rpx; + height: 25rpx; + margin-top: 8rpx; + border-radius: 10rpx; + background-color: #0089FE; + margin-right: 15rpx; + } + + font-size: 33rpx; margin-top: 10rpx; + display:flex; + position: relative; } .history-right { margin-top: 0.5vw; width: 7vw; - height: 2.5vw; + height: 2.8vw; background: linear-gradient(to bottom, #009DEF, #0076FF); display: flex; justify-content: center; align-items: center; - border-radius: 40rpx; + border-radius: 10rpx; color: #fff; font-size: 28rpx; position: relative; @@ -594,13 +630,14 @@ .history-items { width: 100%; margin-top: 15rpx; - height: 440rpx; + height: 570rpx; + /* background-color: red; */ .history-item { /* margin-left: 1%; */ width: 95%; - height: 120rpx; - margin-bottom: 13rpx; + height: 176rpx; + margin-bottom: 20rpx; position: relative; display: flex; align-items: center; @@ -609,6 +646,7 @@ .history-left { /* margin-left: 58rpx; */ width: 120rpx; + } .history-right { @@ -655,10 +693,10 @@ .history-shu-up { position: absolute; - left: 32rpx; + left: 33rpx; bottom: calc(50% + 13rpx); width: 3rpx; - height: 110rpx; + height: 173rpx; background-color: #E5E5E5; transition: height 0.3s ease; @@ -669,8 +707,8 @@ left: 20rpx; top: 50%; transform: translateY(-50%); - width: 26.5rpx; - height: 26.5rpx; + width: 30rpx; + height: 30rpx; border-radius: 50%; border: 4.5rpx solid #D0D1D1; z-index: 1; @@ -681,30 +719,31 @@ .order-future { width: 100%; - height: 640rpx; - margin-top: -12rpx; + height: 480rpx; + /* margin-top: -12rpx; */ position: relative; + /* background-color: red; */ .future-items { width: 100%; height: 100%; .future-fonts { - font-size: 27rpx; + font-size: 30rpx; display: flex; } .future-item-target { width: 90%; margin-left: 5%; - height: 152rpx; - margin-bottom: 10rpx; + height: 140rpx; + margin-bottom: 20rpx; background-color: #F7F8F9; border-radius: 30rpx; /* padding: 25rpx; */ - padding-top: 25rpx; + padding-top: 20rpx; padding-left: 25rpx; - font-size: 25rpx; + font-size: 30rpx; color: #555555; position: relative; border: 2rpx solid #4690FF; @@ -715,14 +754,14 @@ .future-item { width: 90%; margin-left: 5%; - height: 152rpx; - margin-bottom: 10rpx; + height: 140rpx; + margin-bottom: 20rpx; background-color: #F7F8F9; border-radius: 30rpx; /* padding: 25rpx; */ - padding-top: 25rpx; + padding-top: 20rpx; padding-left: 25rpx; - font-size: 25rpx; + font-size: 30rpx; color: #555555; position: relative; border: 2rpx solid #F7F8F9; @@ -732,13 +771,13 @@ .future-time { width: 100%; - margin-top: 20rpx; + margin-top: 12rpx; height: 50rpx; display: flex; align-items: center; .time { - font-size: 48rpx; + font-size: 52rpx; font-weight: 800; color: black; } @@ -747,7 +786,7 @@ } } -.future-tag { +/* .future-tag { position: absolute; right: 23rpx; top: 23rpx; @@ -761,7 +800,7 @@ display: flex; justify-content: center; align-items: center; -} +} */ .future-info { position: absolute; @@ -876,14 +915,14 @@ .time-right-bad { color: #666666; - font-size: 24rpx; + font-size: 27rpx; margin-left: 10rpx; margin-top: 10rpx; } .time-right-blue { color: #4690FF; - font-size: 24rpx; + font-size: 27rpx; margin-left: 10rpx; margin-top: 10rpx; display: flex; @@ -951,10 +990,15 @@ .serviceContent { color: #999999; margin-top: 20rpx; + font-size: 25rpx; } .weight-time { font-weight: 600; font-size: 32rpx; margin-top: -5rpx; +} +.spec-shu{ + margin: 0 7rpx; + color: #BABABA; } \ No newline at end of file diff --git a/pages/NursingNew/component/nurse/bigindex.vue b/pages/NursingNew/component/nurse/bigindex.vue index 3a3c066..552d3e4 100644 --- a/pages/NursingNew/component/nurse/bigindex.vue +++ b/pages/NursingNew/component/nurse/bigindex.vue @@ -108,6 +108,9 @@ {{ selectdata.month }}月 + + + @@ -128,7 +131,17 @@ {{ item.directiveName }} - {{ ` | ` +item.serviceDuration + `分钟` }} + + | + + + + 每天 + + + | + + {{ item.serviceDuration + `分钟` }} @@ -145,9 +158,9 @@ - + @@ -157,15 +170,24 @@ {{ item.directiveName }} - {{ ` | ` +item.serviceDuration + `分钟` }} + + | + + + 每天 + + + | + + {{ item.serviceDuration + `分钟` }} @@ -182,9 +204,7 @@ - - {{ item.cycleType }} - + @@ -222,7 +242,9 @@ + + 服务指令 @@ -241,7 +263,7 @@ {{ item.rightshow }} @@ -262,7 +284,7 @@ + v-show="secondListTargetShow === index" + + > {{ item.rightshow }} @@ -509,12 +533,13 @@ } daysarray.value = Array.from({ length: endDay }, (_, i) => String(i + 1).padStart(2, '0')) // console.log("啥", daysarray.value) - movetime.value = (Number(selectdata.value.day) - 3) * 25 + movetime.value = (Number(selectdata.value.day) - 3) * 37.5 } const daytarget = ref(0) const clickday = (item : string, index : number) => { selectdata.value.day = item; - movetime.value = (index - 2) * 25 + selectdata.value = JSON.parse(JSON.stringify(selectdata.value)) + movetime.value = (index - 2) * 37.5 getTable() } const facedonghua = ref(false) @@ -822,8 +847,8 @@ getDirectiveOrders(time).then((data) => { firstListTarget.value = -1; secondListTarget.value = -1; - // console.log("所有", data.result.all) - // console.log("未来", data.result.future) + // console.log("所有", time,uni.getStorageSync('serverUrl'),uni.getStorageSync('nuId'),uni.getStorageSync('elderId')) + // console.log("未来", uni.getStorageSync('token')) data.result.current.forEach((element : any) => { element.tagtype = 0 }) @@ -845,6 +870,7 @@ } }) downmenuarray.value = [...data.result.history] + console.log("aaaaa", downmenuarray.value) timearr.value = Array.from({ length: 24 }, (_, hour) => ({ positioning: hour.toString(), children: minuteArr.map(() => ({ diff --git a/pages/Warehouse/index/component/index.vue b/pages/Warehouse/index/component/index.vue index f18a711..751f756 100644 --- a/pages/Warehouse/index/component/index.vue +++ b/pages/Warehouse/index/component/index.vue @@ -884,7 +884,7 @@ nuId:nuId } queryCountByType(data).then(res=>{ - console.log(res) + // console.log(res) hldyobj.value = res.result }) } @@ -1077,7 +1077,7 @@ const getmenu = () => { queryPadPageList().then((res => { leftMenuArray.value = res.result.records; - console.log(leftMenuArray.value ) + console.log(leftMenuArray.value) filteredMenu(2).forEach((element : any, index : number) => { if (element.nuId === uni.getStorageSync('NUall').nuId) { menutarget.value = index; diff --git a/pages/login/newanimationpage.vue b/pages/login/newanimationpage.vue index ae3936f..9b71fa4 100644 --- a/pages/login/newanimationpage.vue +++ b/pages/login/newanimationpage.vue @@ -141,7 +141,7 @@ if (len === 10) return '1.3vw' // 恰好10字 if (len < 10) return '1.5vw' // 少于10字 if (len <= 15) return '1.1vw' // 11~15字 - return '0.9vw' // 超过15字 + return '0.9vw' // 超过15字1 }) onHide(() => { playall.value = false;