chore:微信小程序的语音输入切换到文字输入不会闪

This commit is contained in:
2026-10-09 18:10:31 +08:00
parent e7dd6aff62
commit 5ef5f275f0

View File

@@ -532,9 +532,8 @@
<!-- 语音模式 (PR-VOICE-MODE-ONE-ROW-V2): 整行即白色胶囊(flex),
键盘图标在左、+ 在右、按住说话占中间 —— 不依赖绝对定位, 结构上保证单行 -->
<view
v-if="voiceMode"
class="voice-mode-row"
:class="{ 'is-holding': voiceHolding, 'is-cancelling': voiceHoldCancelling }">
:class="{ 'is-holding': voiceHolding, 'is-cancelling': voiceHoldCancelling, 'hidden-row': !voiceMode }">
<!-- 左侧: 键盘图标 (点击回到文字输入) -->
<view class="voice-side-btn voice-side-left" @click="exitVoiceMode">
<view class="emoji-icon-bg"></view>
@@ -561,7 +560,7 @@
Vue 2 要求 v-if/v-else 紧邻, 否则 v-else 会错配到上一个 v-if (voiceHolding),
导致 voiceMode=true 时 input-row-top 也被显示.
改成显式 v-if="!voiceMode", 避免依赖 v-else 的隐式配对 -->
<view v-if="!voiceMode" class="input-row-top">
<view class="input-row-top" :class="{ 'hidden-row': voiceMode }">
<!-- 默认态左侧: 点击进入语音(按住说话)模式 -->
<!-- PR-FRONTEND-H5-INPUT-FOCUS (2026-09-17): 兄弟节点加 key, 防止 H5 下 Vue 无 key 复用
同标签 view 导致 textarea 被销毁重建、聚焦即失焦(塌回胶囊无法输入) -->
@@ -4146,6 +4145,8 @@ _handleStreamError(msg) {
this.voiceHolding = false
this.voiceHoldCancelling = false
this.inputFocused = false
// 进入语音模式时清掉文字输入态, 避免白卡片背景 + 工具栏残留(切换时闪烁)
this.showTextMode = false
},
// 退出语音模式, 回到文字输入态
@@ -5811,10 +5812,10 @@ _handleStreamError(msg) {
}
}
/* 键盘垫高层:高度变化时平滑过渡 */
/* 键盘垫高层:高度变化不做过渡 —— 切换语音/文字时 hideKeyboard 触发高度变化,
若加 transition 会播放高度动画, 输入区整体跳动, 视觉上就是「频闪/看到上次样式」 */
.keyboard-spacer {
flex-shrink: 0;
transition: height 0.25s ease;
}
/* 输入区域 (新版: 顶部胶囊形输入条 + 底部 5 个图标均匀分布) */
@@ -6004,6 +6005,13 @@ _handleStreamError(msg) {
}
}
/* 语音/文字两态胶囊始终在 DOM 中, 用显隐切换而非 v-if 重建节点。
v-if 在微信小程序会触发节点卸载/重建, 切换瞬间旧节点那帧会闪(看到上次样式)。
!important 用于盖过 .voice-mode-row / .input-row-top 自身的 display:flex */
.hidden-row {
display: none !important;
}
/* 语音模式单行 (PR-VOICE-MODE-ONE-ROW-V2): 整行即白色胶囊(flex布局,不依赖绝对定位)
键盘图标在左 / 按住说话占中间 / + 在右, 与参考稿一致 */
.voice-mode-row {
@@ -6011,7 +6019,9 @@ _handleStreamError(msg) {
display: flex;
align-items: center;
height: 96rpx;
margin: 4rpx 0 8rpx;
/* 上下 margin 为 0: 与默认输入胶囊(.input-row-top margin 0)整块高度一致,
否则语音态多占 12rpx, 切换时聊天列表被顶/拉 12rpx 产生"看到上次样式"的频闪 */
margin: 0;
padding: 0 10rpx 0 24rpx;
border-radius: 999rpx;
background: #ffffff;
@@ -6542,11 +6552,21 @@ _handleStreamError(msg) {
.input-area {
padding: 10rpx 16rpx 12rpx;
.input-card {
/* 卡片内边距/圆角只对文字输入态(白卡片)生效; 默认/语音胶囊保持 flush,
否则默认胶囊会多吃 12+10rpx, 与语音胶囊整块高度差 22rpx, 切换时跳动频闪 */
.input-card.is-text-mode {
padding: 12rpx 14rpx 10rpx;
border-radius: 18rpx;
}
/* 语音模式胶囊: 与默认输入胶囊左右对齐。
默认胶囊在 .input-card 内(左右各收进 14rpx), 而语音模式卡片 padding 被
.is-voice-mode 强制为 0, 胶囊全宽 —— 用同样的水平 margin 补齐, 两端长短一致。
上下 margin 保持 0, 与默认胶囊整块等高, 避免切换时聊天列表跳动 */
.voice-mode-row {
margin: 0 14rpx;
}
.input-row-top {
min-height: 64rpx;