diff --git a/docs/FAQ.md b/docs/FAQ.md index b6bec471..a5dc0b08 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -83,6 +83,7 @@ VAD: 9、[知识库ragflow集成指南](./ragflow-integration.md) 10、[如何部署上下文源](./context-provider-integration.md) 11、[如何集成PowerMem智能记忆](./powermem-integration.md) +12、[如何配置天气插件查询天气](./weather-integration.md) ### 11、语音克隆、本地语音部署相关教程 1、[如何在智控台克隆音色](./huoshan-streamTTS-voice-cloning.md) diff --git a/main/manager-api/src/main/resources/db/changelog/202603311200.sql b/main/manager-api/src/main/resources/db/changelog/202603311200.sql new file mode 100644 index 00000000..0e34d0a1 --- /dev/null +++ b/main/manager-api/src/main/resources/db/changelog/202603311200.sql @@ -0,0 +1,2 @@ +-- 修改聊天内容字段类型 +ALTER TABLE ai_agent_chat_history MODIFY COLUMN content TEXT COMMENT '聊天内容'; diff --git a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml index f84fdd9d..77c5bfd3 100755 --- a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml @@ -578,3 +578,11 @@ databaseChangeLog: - sqlFile: encoding: utf8 path: classpath:db/changelog/202603231037.sql + - changeSet: + id: 202603311200 + author: cgd + changes: + - sqlFile: + encoding: utf8 + path: classpath:db/changelog/202603311200.sql + diff --git a/main/manager-mobile/src/i18n/de.ts b/main/manager-mobile/src/i18n/de.ts index 0a409adb..d76a4093 100644 --- a/main/manager-mobile/src/i18n/de.ts +++ b/main/manager-mobile/src/i18n/de.ts @@ -69,7 +69,7 @@ export default { 'home.createFirstAgent': 'Klicken Sie auf die + Schaltfläche unten rechts, um Ihren ersten Agenten zu erstellen', 'home.dialogTitle': 'Agent erstellen', 'home.inputPlaceholder': 'z.B. Kundenservice-Assistent, Sprachassistent, Wissens-F&A', - 'home.createError': 'Bitte Agenten-Namen eingeben', + 'home.createError': 'Der Name muss zwischen 1 und 64 Zeichen lang sein.', 'home.createNow': 'Jetzt erstellen', 'home.justNow': 'Gerade eben', 'home.minutesAgo': 'Minuten her', diff --git a/main/manager-mobile/src/i18n/en.ts b/main/manager-mobile/src/i18n/en.ts index af1dddc6..0066b0fd 100644 --- a/main/manager-mobile/src/i18n/en.ts +++ b/main/manager-mobile/src/i18n/en.ts @@ -69,7 +69,7 @@ export default { 'home.createFirstAgent': 'Click the + button in the lower right corner to create your first agent', 'home.dialogTitle': 'Create Agent', 'home.inputPlaceholder': 'e.g. Customer Service Assistant, Voice Assistant, Knowledge Q&A', - 'home.createError': 'Please input agent name', + 'home.createError': 'The name length must be between 1 and 64 characters', 'home.createNow': 'Create Now', 'home.justNow': 'Just now', 'home.minutesAgo': 'minutes ago', diff --git a/main/manager-mobile/src/i18n/pt_BR.ts b/main/manager-mobile/src/i18n/pt_BR.ts index b8bc979f..416b1f8f 100644 --- a/main/manager-mobile/src/i18n/pt_BR.ts +++ b/main/manager-mobile/src/i18n/pt_BR.ts @@ -69,7 +69,7 @@ export default { 'home.createFirstAgent': 'Clique no botão + no canto inferior direito para criar seu primeiro agente', 'home.dialogTitle': 'Criar Agente', 'home.inputPlaceholder': 'ex: Assistente de Atendimento, Assistente de Voz, Perguntas e Respostas', - 'home.createError': 'Por favor, insira o nome do agente', + 'home.createError': 'O comprimento do nome deve estar entre 1 e 64 caracteres', 'home.createNow': 'Criar Agora', 'home.justNow': 'Agora mesmo', 'home.minutesAgo': 'minutos atrás', diff --git a/main/manager-mobile/src/i18n/vi.ts b/main/manager-mobile/src/i18n/vi.ts index cbb790f7..8ee1a35e 100644 --- a/main/manager-mobile/src/i18n/vi.ts +++ b/main/manager-mobile/src/i18n/vi.ts @@ -69,7 +69,7 @@ export default { 'home.createFirstAgent': 'Nhấp vào nút + ở góc dưới bên phải để tạo đại lý đầu tiên của bạn', 'home.dialogTitle': 'Tạo đại lý', 'home.inputPlaceholder': 'ví dụ: Trợ lý chăm sóc khách hàng, Trợ lý giọng nói, Hỏi đáp kiến thức', - 'home.createError': 'Vui lòng nhập tên đại lý', + 'home.createError': 'Độ dài tên phải từ 1 đến 64 ký tự', 'home.createNow': 'Tạo ngay', 'home.justNow': 'Vừa xong', 'home.minutesAgo': 'phút trước', diff --git a/main/manager-mobile/src/i18n/zh_CN.ts b/main/manager-mobile/src/i18n/zh_CN.ts index a9684485..a5dec898 100644 --- a/main/manager-mobile/src/i18n/zh_CN.ts +++ b/main/manager-mobile/src/i18n/zh_CN.ts @@ -69,7 +69,7 @@ export default { 'home.createFirstAgent': '点击右下角 + 号创建您的第一个智能体', 'home.dialogTitle': '创建智能体', 'home.inputPlaceholder': '例如:客服助手、语音助理、知识问答', - 'home.createError': '请输入智能体名称', + 'home.createError': '名称长度必须在 1 到 64 个字符之间', 'home.createNow': '立即创建', 'home.justNow': '刚刚', 'home.minutesAgo': '分钟前', diff --git a/main/manager-mobile/src/i18n/zh_TW.ts b/main/manager-mobile/src/i18n/zh_TW.ts index a8b5a18e..9125e296 100644 --- a/main/manager-mobile/src/i18n/zh_TW.ts +++ b/main/manager-mobile/src/i18n/zh_TW.ts @@ -90,7 +90,7 @@ export default { 'home.createFirstAgent': '點擊右下角 + 號創建您的第一個智能體', 'home.dialogTitle': '創建智能體', 'home.inputPlaceholder': '例如:客服助手、語音助理、知識問答', - 'home.createError': '請輸入智能體暱稱', + 'home.createError': '暱稱長度必須在 1 到 64 個字元之間。', 'home.createNow': '立即創建', 'home.justNow': '剛剛', 'home.minutesAgo': '分鐘前', diff --git a/main/manager-mobile/src/pages/agent/edit.vue b/main/manager-mobile/src/pages/agent/edit.vue index 112a48a2..0f56db88 100644 --- a/main/manager-mobile/src/pages/agent/edit.vue +++ b/main/manager-mobile/src/pages/agent/edit.vue @@ -162,6 +162,9 @@ function handleInputConfirm() { inputVisible.value = false } +// 是否禁用历史记忆输入框 +const isMemoryDisabled = computed(() => formData.value.memModelId !== 'Memory_mem_local_short') + // 打开上下文源编辑弹窗 function openContextProviderDialog() { uni.navigateTo({ @@ -942,8 +945,9 @@ onMounted(async () => { diff --git a/main/manager-mobile/src/pages/chat-history/detail.vue b/main/manager-mobile/src/pages/chat-history/detail.vue index 4d8f91e7..c3d399d5 100644 --- a/main/manager-mobile/src/pages/chat-history/detail.vue +++ b/main/manager-mobile/src/pages/chat-history/detail.vue @@ -13,9 +13,9 @@ import type { ChatMessage, UserMessageContent } from '@/api/chat-history/types' import { onLoad, onUnload } from '@dcloudio/uni-app' import { computed, ref } from 'vue' import { getAudioId, getChatHistory } from '@/api/chat-history/chat-history' -import { getEnvBaseUrl } from '@/utils' -import { toast } from '@/utils/toast' import { t } from '@/i18n' +import { debounce, getEnvBaseUrl } from '@/utils' +import { toast } from '@/utils/toast' defineOptions({ name: 'ChatDetail', @@ -129,7 +129,7 @@ function formatTime(timeStr: string) { } // 播放音频 -async function playAudio(audioId: string) { +const playAudio = debounce(async (audioId: string) => { if (!audioId) { toast.error(t('chatHistory.invalidAudioId')) return @@ -139,8 +139,11 @@ async function playAudio(audioId: string) { // 如果正在播放其他音频,先停止 if (audioContext.value) { audioContext.value.stop() - audioContext.value.destroy() - audioContext.value = null + } + // 如果当前音频ID与请求ID相同暂停播放 + if (playingAudioId.value === audioId) { + playingAudioId.value = null + return } // 获取音频下载ID @@ -151,7 +154,9 @@ async function playAudio(audioId: string) { const audioUrl = `${baseUrl}/agent/play/${downloadId}` // 创建音频上下文 - audioContext.value = uni.createInnerAudioContext() + if (!audioContext.value) { + audioContext.value = uni.createInnerAudioContext() + } audioContext.value.src = audioUrl // 设置播放状态 @@ -185,7 +190,7 @@ async function playAudio(audioId: string) { toast.error(t('chatHistory.playAudioFailed')) playingAudioId.value = null } -} +}, 400) onLoad((options) => { if (options?.sessionId && options?.agentId) { diff --git a/main/manager-mobile/src/pages/index/index.vue b/main/manager-mobile/src/pages/index/index.vue index 4a19e279..21aba9ce 100644 --- a/main/manager-mobile/src/pages/index/index.vue +++ b/main/manager-mobile/src/pages/index/index.vue @@ -125,7 +125,7 @@ function openCreateDialog() { msg: '', inputPlaceholder: t('home.inputPlaceholder'), inputValue: '', - inputPattern: /^[\u4E00-\u9FA5a-z0-9\s]{1,50}$/i, + inputPattern: /^.{1,64}$/i, inputError: t('home.createError'), confirmButtonText: t('home.createNow'), cancelButtonText: t('common.cancel'), @@ -159,7 +159,7 @@ function formatTime(timeStr: string) { onShow(() => { console.log('首页 onShow,刷新智能体列表') if (pagingRef.value) { - pagingRef.value.reload() + pagingRef.value.refresh() } }) diff --git a/main/manager-mobile/src/pages/voiceprint/index.vue b/main/manager-mobile/src/pages/voiceprint/index.vue index a00711a5..e6ba2ccc 100644 --- a/main/manager-mobile/src/pages/voiceprint/index.vue +++ b/main/manager-mobile/src/pages/voiceprint/index.vue @@ -137,7 +137,6 @@ async function loadChatHistory() { audioId: item.audioId, index, })) - showChatHistoryDialog.value = true } catch (error) { console.error('获取对话记录失败:', error) @@ -368,6 +367,7 @@ onMounted(async () => { // 智能体已简化为默认 loadVoicePrintList() + loadChatHistory() }) // 暴露方法给父组件 @@ -468,7 +468,7 @@ defineExpose({ any + +interface DebouncedFunction extends AnyFunction { + cancel: () => void +} + +/** + * 防抖函数 + * @param fn 要防抖的函数 + * @param delay 延迟时间(毫秒),默认500ms + * @param immediate 是否立即执行,默认false + * @returns 防抖处理后的函数 + */ +export function debounce( + fn: T, + delay = 500, + immediate = false, +): DebouncedFunction { + let timer: ReturnType | null = null + + const debounced = function (this: any, ...args: Parameters) { + if (timer) { + clearTimeout(timer) + } + + if (immediate && !timer) { + fn.apply(this, args) + } + + timer = setTimeout(() => { + if (!immediate) { + fn.apply(this, args) + } + timer = null + }, delay) + } as DebouncedFunction + + debounced.cancel = () => { + if (timer) { + clearTimeout(timer) + timer = null + } + } + + return debounced } diff --git a/main/manager-web/.env b/main/manager-web/.env index 3fd5202e..d234c067 100644 --- a/main/manager-web/.env +++ b/main/manager-web/.env @@ -1,3 +1,3 @@ VUE_APP_TITLE=智控台 -VUE_APP_DESCRIPTION=是由华南理工大学刘思源教授团队研发的智能终端软硬件体系后端服务系统,专为xiaozhi-esp32开源硬件打造,具备多协议兼容、声纹识别、知识库管理等核心能力。 +VUE_APP_DESCRIPTION=小智后端服务(xiaozhi-server)是由华南理工大学刘思源教授团队主导研发的智能终端软硬件体系后端服务系统,专为xiaozhi-esp32开源硬件打造,具备多协议兼容、声纹识别、知识库管理等核心能力。 VUE_APP_KEYWORDS=xiaozhi-server,小智服务端,智控台,AI硬件,智能硬件,AI玩具,情感陪伴,聊天机器人,智能家居,车载机器人 diff --git a/main/manager-web/src/App.vue b/main/manager-web/src/App.vue index bf4c7a45..f101e155 100644 --- a/main/manager-web/src/App.vue +++ b/main/manager-web/src/App.vue @@ -28,17 +28,16 @@ nav { } .copyright { - text-align: center; + padding: 0 !important; color: rgb(0, 0, 0); font-size: 12px; font-weight: 400; margin-top: auto; - padding: 30px 0 20px; - position: absolute; - bottom: 0; - left: 50%; - transform: translateX(-50%); width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; } .el-message { diff --git a/main/manager-web/src/components/ChatHistoryDialog.vue b/main/manager-web/src/components/ChatHistoryDialog.vue index f44c4de7..7821ba2d 100644 --- a/main/manager-web/src/components/ChatHistoryDialog.vue +++ b/main/manager-web/src/components/ChatHistoryDialog.vue @@ -21,11 +21,35 @@ {{ message.content }} - + - {{ extractContentFromString(message.content) }} + + + + {{ item.text }} + {{ item.text }} + + + + {{ getFirstLineText(item.text) }} + + + {{ item.text }} + + + + + + {{ item.text }} + + + + + + {{ extractContentFromString(message.content) }} + @@ -49,6 +73,7 @@