This commit is contained in:
2025-08-19 12:05:22 +08:00
parent 625178632b
commit 0c3fca167a

View File

@@ -219,6 +219,13 @@ export default {
// 消息显示优化 // 消息显示优化
maxVisibleMessages: 50, // 最大可见消息数量 maxVisibleMessages: 50, // 最大可见消息数量
messageRenderBatch: 20, // 每批渲染的消息数量 messageRenderBatch: 20, // 每批渲染的消息数量
// 鼠标跟踪相关
mouseX: 0, // 鼠标X坐标
mouseY: 0, // 鼠标Y坐标
eyeTrackingEnabled: true, // 是否启用眼睛跟踪
avatarRect: null, // 头像位置信息
eyeUpdateTimer: null, // 眼睛更新定时器
} }
}, },
computed: { computed: {
@@ -255,6 +262,8 @@ export default {
setTimeout(() => { setTimeout(() => {
if (!this.isDestroyed) { if (!this.isDestroyed) {
this.scrollToBottom(false) this.scrollToBottom(false)
// 更新头像位置信息,确保鼠标跟踪正常工作
this.updateAvatarRect()
} }
}, 100) }, 100)
} }
@@ -283,6 +292,9 @@ export default {
// 启动数字人自动眨眼 // 启动数字人自动眨眼
this.startAutoBlinking() this.startAutoBlinking()
// 启动鼠标跟踪
this.startMouseTracking()
// 确保DOM完全渲染后再初始化聊天 // 确保DOM完全渲染后再初始化聊天
this.$nextTick(() => { this.$nextTick(() => {
setTimeout(async () => { setTimeout(async () => {
@@ -321,11 +333,18 @@ export default {
clearTimeout(this.contentUpdateTimer) clearTimeout(this.contentUpdateTimer)
this.contentUpdateTimer = null this.contentUpdateTimer = null
} }
if (this.eyeUpdateTimer) {
clearTimeout(this.eyeUpdateTimer)
this.eyeUpdateTimer = null
}
// 清理数字人相关定时器 // 清理数字人相关定时器
this.stopAutoBlinking() this.stopAutoBlinking()
this.stopAIAnimation() this.stopAIAnimation()
// 停止鼠标跟踪
this.stopMouseTracking()
// 取消正在进行的请求 // 取消正在进行的请求
if (this.currentCancel) { if (this.currentCancel) {
this.currentCancel() this.currentCancel()
@@ -745,6 +764,10 @@ export default {
this.inputMessage = '' this.inputMessage = ''
this.sending = true this.sending = true
// 初始化定时器变量
let streamTimeout = null
let noDataTimeout = null
// 添加到请求队列 // 添加到请求队列
const requestId = Date.now() const requestId = Date.now()
this.requestQueue.push(requestId) this.requestQueue.push(requestId)
@@ -796,7 +819,7 @@ export default {
}) })
// 添加额外的超时保护 // 添加额外的超时保护
const streamTimeout = setTimeout(() => { streamTimeout = setTimeout(() => {
if (cancel) { if (cancel) {
cancel('流式响应超时') cancel('流式响应超时')
} }
@@ -811,7 +834,6 @@ export default {
const { reader, decoder } = response const { reader, decoder } = response
let buffer = '' let buffer = ''
let lastUpdateTime = Date.now() let lastUpdateTime = Date.now()
let noDataTimeout = null
while (true) { while (true) {
// 设置无数据超时检测 // 设置无数据超时检测
@@ -1197,6 +1219,101 @@ export default {
} }
}, },
// 启动鼠标跟踪
startMouseTracking() {
if (!this.eyeTrackingEnabled) return
// 添加鼠标移动监听器
document.addEventListener('mousemove', this.handleMouseMove)
// 获取头像位置信息
this.$nextTick(() => {
this.updateAvatarRect()
})
// 监听窗口大小变化,更新头像位置
window.addEventListener('resize', this.updateAvatarRect)
},
// 停止鼠标跟踪
stopMouseTracking() {
document.removeEventListener('mousemove', this.handleMouseMove)
window.removeEventListener('resize', this.updateAvatarRect)
// 清理眼睛更新定时器
if (this.eyeUpdateTimer) {
clearTimeout(this.eyeUpdateTimer)
this.eyeUpdateTimer = null
}
},
// 处理鼠标移动
handleMouseMove(event) {
if (!this.eyeTrackingEnabled || this.isDestroyed) return
this.mouseX = event.clientX
this.mouseY = event.clientY
// 使用节流避免过于频繁的更新
if (this.eyeUpdateTimer) {
clearTimeout(this.eyeUpdateTimer)
}
this.eyeUpdateTimer = setTimeout(() => {
if (!this.isDestroyed) {
this.updateEyePosition()
}
}, 16) // 约60fps的更新频率
},
// 更新头像位置信息
updateAvatarRect() {
if (this.isDestroyed) return
const avatarElement = this.$el.querySelector('.digital-avatar')
if (avatarElement) {
this.avatarRect = avatarElement.getBoundingClientRect()
}
},
// 更新眼睛位置
updateEyePosition() {
if (!this.avatarRect || this.isDestroyed) return
// 计算头像中心点
const avatarCenterX = this.avatarRect.left + this.avatarRect.width / 2
const avatarCenterY = this.avatarRect.top + this.avatarRect.height / 2
// 计算鼠标相对于头像中心的方向
const deltaX = this.mouseX - avatarCenterX
const deltaY = this.mouseY - avatarCenterY
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
// 避免除零错误
if (distance === 0) return
// 计算单位向量
const unitX = deltaX / distance
const unitY = deltaY / distance
// 根据距离调整眼睛移动幅度
const maxMoveDistance = 1.5 // 最大移动距离(像素)
const sensitivity = Math.min(distance / 100, 1) // 距离越远,眼睛移动越明显
const moveX = unitX * maxMoveDistance * sensitivity
const moveY = unitY * maxMoveDistance * sensitivity
// 应用眼睛位置
const leftEye = this.$el.querySelector('.left-eye')
const rightEye = this.$el.querySelector('.right-eye')
if (leftEye && rightEye) {
// 使用CSS变量来实现更平滑的动画
leftEye.style.transform = `translate(${moveX}px, ${moveY}px)`
rightEye.style.transform = `translate(${moveX}px, ${moveY}px)`
}
},
/** /**
* 处理点赞 * 处理点赞
*/ */
@@ -1724,7 +1841,9 @@ export default {
height: 4px; height: 4px;
background: #333; background: #333;
border-radius: 50%; border-radius: 50%;
transition: all 0.15s ease; transition: height 0.15s ease, background 0.15s ease, transform 0.1s ease-out;
position: relative;
transform-origin: center;
} }
.eye.blink { .eye.blink {