优化
This commit is contained in:
@@ -219,6 +219,13 @@ export default {
|
||||
// 消息显示优化
|
||||
maxVisibleMessages: 50, // 最大可见消息数量
|
||||
messageRenderBatch: 20, // 每批渲染的消息数量
|
||||
|
||||
// 鼠标跟踪相关
|
||||
mouseX: 0, // 鼠标X坐标
|
||||
mouseY: 0, // 鼠标Y坐标
|
||||
eyeTrackingEnabled: true, // 是否启用眼睛跟踪
|
||||
avatarRect: null, // 头像位置信息
|
||||
eyeUpdateTimer: null, // 眼睛更新定时器
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -255,6 +262,8 @@ export default {
|
||||
setTimeout(() => {
|
||||
if (!this.isDestroyed) {
|
||||
this.scrollToBottom(false)
|
||||
// 更新头像位置信息,确保鼠标跟踪正常工作
|
||||
this.updateAvatarRect()
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
@@ -283,6 +292,9 @@ export default {
|
||||
// 启动数字人自动眨眼
|
||||
this.startAutoBlinking()
|
||||
|
||||
// 启动鼠标跟踪
|
||||
this.startMouseTracking()
|
||||
|
||||
// 确保DOM完全渲染后再初始化聊天
|
||||
this.$nextTick(() => {
|
||||
setTimeout(async () => {
|
||||
@@ -321,11 +333,18 @@ export default {
|
||||
clearTimeout(this.contentUpdateTimer)
|
||||
this.contentUpdateTimer = null
|
||||
}
|
||||
if (this.eyeUpdateTimer) {
|
||||
clearTimeout(this.eyeUpdateTimer)
|
||||
this.eyeUpdateTimer = null
|
||||
}
|
||||
|
||||
// 清理数字人相关定时器
|
||||
this.stopAutoBlinking()
|
||||
this.stopAIAnimation()
|
||||
|
||||
// 停止鼠标跟踪
|
||||
this.stopMouseTracking()
|
||||
|
||||
// 取消正在进行的请求
|
||||
if (this.currentCancel) {
|
||||
this.currentCancel()
|
||||
@@ -745,6 +764,10 @@ export default {
|
||||
this.inputMessage = ''
|
||||
this.sending = true
|
||||
|
||||
// 初始化定时器变量
|
||||
let streamTimeout = null
|
||||
let noDataTimeout = null
|
||||
|
||||
// 添加到请求队列
|
||||
const requestId = Date.now()
|
||||
this.requestQueue.push(requestId)
|
||||
@@ -796,7 +819,7 @@ export default {
|
||||
})
|
||||
|
||||
// 添加额外的超时保护
|
||||
const streamTimeout = setTimeout(() => {
|
||||
streamTimeout = setTimeout(() => {
|
||||
if (cancel) {
|
||||
cancel('流式响应超时')
|
||||
}
|
||||
@@ -811,7 +834,6 @@ export default {
|
||||
const { reader, decoder } = response
|
||||
let buffer = ''
|
||||
let lastUpdateTime = Date.now()
|
||||
let noDataTimeout = null
|
||||
|
||||
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;
|
||||
background: #333;
|
||||
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 {
|
||||
|
Reference in New Issue
Block a user