olivebot/gui/static/js/chat.js
2024-12-10 16:23:32 +08:00

207 lines
7.6 KiB
JavaScript

// static/js/chat.js
new Vue({
el: '#chat-app',
delimiters: ['[[', ']]'],
data() {
return {
socket: null,
messages: [],
newMessage: '',
status: '', // 用于显示“聆听中...”或“思考中...”
isRecording: false,
recognition: null
};
},
created() {
this.initSocket();
this.initSpeechRecognition();
this.startLive(); // 页面加载后自动启动 live 模式
},
methods: {
initSocket() {
// 初始化 SocketIO 连接
this.socket = io.connect('http://' + document.domain + ':' + location.port + '/');
this.socket.on('connect', () => {
console.log('Connected to SocketIO server');
});
this.socket.on('receive_message', (data) => {
this.addMessage(data.type, data.content, data.username, data.timetext);
});
this.socket.on('load_messages', (data) => {
data.forEach(message => {
this.addMessage(message.type, message.content, message.username, message.timetext);
});
});
this.socket.on('disconnect', () => {
console.log('Disconnected from SocketIO server');
});
},
initSpeechRecognition() {
if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
this.recognition = new SpeechRecognition();
this.recognition.lang = 'zh-CN';
this.recognition.interimResults = false;
this.recognition.maxAlternatives = 1;
this.recognition.onstart = () => {
this.isRecording = true;
this.status = '聆听中...';
this.$set(this, 'recordIconSrc', '/static/images/recording.png');
};
this.recognition.onresult = (event) => {
const transcript = event.results[0][0].transcript;
this.addMessage('user', transcript, '您');
this.socket.emit('send_message', {
username: '您',
message: transcript,
type: 'user'
});
this.status = '思考中...';
setTimeout(() => {
this.status = '';
}, 2000);
};
this.recognition.onerror = (event) => {
console.error('语音识别错误:', event.error);
this.status = '语音识别失败';
this.isRecording = false;
this.$set(this, 'recordIconSrc', '/static/images/record.png');
};
this.recognition.onend = () => {
this.isRecording = false;
this.$set(this, 'recordIconSrc', '/static/images/record.png');
};
} else {
alert('当前浏览器不支持语音识别功能');
}
},
toggleChat() {
const chatContainer = document.getElementById('chat-container');
const toggleButton = document.getElementById('toggle-chat');
if (chatContainer.classList.contains('hidden')) {
chatContainer.classList.remove('hidden');
toggleButton.textContent = '关闭聊天';
} else {
chatContainer.classList.add('hidden');
toggleButton.textContent = '打开聊天';
}
},
toggleRecording() {
if (this.recognition) {
if (!this.isRecording) {
this.recognition.start();
} else {
this.recognition.stop();
}
}
},
sendMessage() {
const message = this.newMessage.trim();
if (message === '') return;
this.addMessage('user', message, '您');
this.socket.emit('send_message', {
username: '您',
message: message,
type: 'user'
});
this.newMessage = '';
this.status = '思考中...';
setTimeout(() => {
this.status = '';
}, 2000);
},
addMessage(type, content, username, timestamp) {
const message = { type, content, username, timetext: timestamp };
this.messages.push(message);
// 只保留最近三条消息
if (this.messages.length > 3) {
this.messages.shift();
}
// 滚动到最新消息
this.$nextTick(() => {
const messagesDiv = document.getElementById('messages');
if (messagesDiv) {
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
});
},
getCurrentTime() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
startLive() {
// 调用启动 live 模式的 API
fetch('/api/start-live', {
method: 'POST'
})
.then(response => response.json())
.then(data => {
if (data.result === 'successful') {
this.$notify({
title: '成功',
message: '已开启 live 模式!',
type: 'success',
});
} else {
this.$notify({
title: '失败',
message: data.message || '启动 live 模式失败',
type: 'error',
});
}
})
.catch(error => {
console.error('启动 live 模式时出错:', error);
this.$notify({
title: '错误',
message: '启动 live 模式时出错',
type: 'error',
});
});
},
stopLive() {
// 调用停止 live 模式的 API
fetch('/api/stop-live', {
method: 'POST'
})
.then(response => response.json())
.then(data => {
if (data.result === 'successful') {
this.$notify({
title: '成功',
message: '已关闭 live 模式!',
type: 'success',
});
} else {
this.$notify({
title: '失败',
message: data.message || '停止 live 模式失败',
type: 'error',
});
}
})
.catch(error => {
console.error('停止 live 模式时出错:', error);
this.$notify({
title: '错误',
message: '停止 live 模式时出错',
type: 'error',
});
});
}}})