207 lines
7.6 KiB
JavaScript
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',
|
|
});
|
|
});
|
|
}}})
|