This commit is contained in:
2025-08-19 11:52:37 +08:00
parent 452c2b50c6
commit 625178632b

View File

@@ -7,14 +7,8 @@
<div class="digital-avatar" :class="{ speaking: isAISpeaking, thinking: isAIThinking }"> <div class="digital-avatar" :class="{ speaking: isAISpeaking, thinking: isAIThinking }">
<div class="avatar-face"> <div class="avatar-face">
<div class="avatar-eyes"> <div class="avatar-eyes">
<div class="eye left-eye" :class="{ blink: isBlinking }" <div class="eye left-eye" :class="{ blink: isBlinking }"></div>
:style="{ transform: `translate(${eyeOffsetX}px, ${eyeOffsetY}px)` }"> <div class="eye right-eye" :class="{ blink: isBlinking }"></div>
<div class="pupil"></div>
</div>
<div class="eye right-eye" :class="{ blink: isBlinking }"
:style="{ transform: `translate(${eyeOffsetX}px, ${eyeOffsetY}px)` }">
<div class="pupil"></div>
</div>
</div> </div>
<div class="avatar-mouth" :class="{ talking: isAISpeaking }"></div> <div class="avatar-mouth" :class="{ talking: isAISpeaking }"></div>
</div> </div>
@@ -211,13 +205,6 @@ export default {
isBlinking: false, // 是否在眨眼 isBlinking: false, // 是否在眨眼
blinkTimer: null, // 眨眼定时器 blinkTimer: null, // 眨眼定时器
speakingTimer: null, // 说话动画定时器 speakingTimer: null, // 说话动画定时器
// 眼睛跟踪鼠标
mouseX: 0, // 鼠标X坐标
mouseY: 0, // 鼠标Y坐标
eyeOffsetX: 0, // 眼睛X偏移
eyeOffsetY: 0, // 眼睛Y偏移
isMouseTracking: true, // 是否启用鼠标跟踪
requestMonitorInterval: null, requestMonitorInterval: null,
maxRequestDuration: 60000, // 最大请求持续时间60秒 maxRequestDuration: 60000, // 最大请求持续时间60秒
@@ -296,9 +283,6 @@ export default {
// 启动数字人自动眨眼 // 启动数字人自动眨眼
this.startAutoBlinking() this.startAutoBlinking()
// 启动鼠标跟踪
this.enableMouseTracking()
// 确保DOM完全渲染后再初始化聊天 // 确保DOM完全渲染后再初始化聊天
this.$nextTick(() => { this.$nextTick(() => {
setTimeout(async () => { setTimeout(async () => {
@@ -338,10 +322,9 @@ export default {
this.contentUpdateTimer = null this.contentUpdateTimer = null
} }
// 清理数字人相关定时器和事件监听器 // 清理数字人相关定时器
this.stopAutoBlinking() this.stopAutoBlinking()
this.stopAIAnimation() this.stopAIAnimation()
this.disableMouseTracking()
// 取消正在进行的请求 // 取消正在进行的请求
if (this.currentCancel) { if (this.currentCancel) {
@@ -1159,8 +1142,6 @@ export default {
startAIThinking() { startAIThinking() {
this.isAIThinking = true this.isAIThinking = true
this.isAISpeaking = false this.isAISpeaking = false
// 思考时启用鼠标跟踪
this.enableMouseTracking()
}, },
// 开始AI说话动画 // 开始AI说话动画
@@ -1168,9 +1149,6 @@ export default {
this.isAIThinking = false this.isAIThinking = false
this.isAISpeaking = true this.isAISpeaking = true
// 说话时禁用鼠标跟踪,眼睛面向前方
this.disableMouseTracking()
// 清除之前的说话定时器 // 清除之前的说话定时器
if (this.speakingTimer) { if (this.speakingTimer) {
clearTimeout(this.speakingTimer) clearTimeout(this.speakingTimer)
@@ -1182,9 +1160,6 @@ export default {
this.isAIThinking = false this.isAIThinking = false
this.isAISpeaking = false this.isAISpeaking = false
// 停止动画后恢复鼠标跟踪
this.enableMouseTracking()
if (this.speakingTimer) { if (this.speakingTimer) {
clearTimeout(this.speakingTimer) clearTimeout(this.speakingTimer)
this.speakingTimer = null this.speakingTimer = null
@@ -1222,69 +1197,6 @@ export default {
} }
}, },
// 鼠标移动事件处理
handleMouseMove(event) {
if (!this.isMouseTracking || this.isDestroyed) return
this.mouseX = event.clientX
this.mouseY = event.clientY
this.updateEyePosition()
},
// 更新眼睛位置
updateEyePosition() {
if (!this.isMouseTracking) return
// 获取数字人头像的位置
const avatarElement = this.$el.querySelector('.digital-avatar')
if (!avatarElement) return
const rect = avatarElement.getBoundingClientRect()
const avatarCenterX = rect.left + rect.width / 2
const avatarCenterY = rect.top + rect.height / 2
// 计算鼠标相对于头像中心的位置
const deltaX = this.mouseX - avatarCenterX
const deltaY = this.mouseY - avatarCenterY
// 计算距离和角度
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
const maxDistance = 100 // 最大跟踪距离
const maxOffset = 1.5 // 眼睛最大偏移量
// 限制跟踪范围
const trackingFactor = Math.min(distance / maxDistance, 1)
// 计算眼睛偏移
this.eyeOffsetX = (deltaX / distance) * maxOffset * trackingFactor
this.eyeOffsetY = (deltaY / distance) * maxOffset * trackingFactor
// 如果距离太近,眼睛回到中心
if (distance < 50) {
this.eyeOffsetX = 0
this.eyeOffsetY = 0
}
},
// 眼睛回到中心位置(说话时使用)
resetEyePosition() {
this.eyeOffsetX = 0
this.eyeOffsetY = 0
},
// 启用鼠标跟踪
enableMouseTracking() {
this.isMouseTracking = true
document.addEventListener('mousemove', this.handleMouseMove)
},
// 禁用鼠标跟踪
disableMouseTracking() {
this.isMouseTracking = false
document.removeEventListener('mousemove', this.handleMouseMove)
this.resetEyePosition()
},
/** /**
* 处理点赞 * 处理点赞
*/ */
@@ -1808,35 +1720,16 @@ export default {
/* 眼睛 */ /* 眼睛 */
.eye { .eye {
width: 8px;
height: 8px;
background: #fff;
border: 1px solid #ddd;
border-radius: 50%;
transition: all 0.15s ease;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.eye.blink {
height: 2px;
background: #666;
border: none;
}
.eye.blink .pupil {
display: none;
}
/* 瞳孔 */
.pupil {
width: 4px; width: 4px;
height: 4px; height: 4px;
background: #333; background: #333;
border-radius: 50%; border-radius: 50%;
transition: transform 0.1s ease; transition: all 0.15s ease;
}
.eye.blink {
height: 1px;
background: #666;
} }
/* 嘴巴 */ /* 嘴巴 */