diff --git a/app/Models/User.php b/app/Models/User.php index 8f868dc68..2a9a1a419 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -559,6 +559,8 @@ class User extends AbstractModel return url("images/avatar/default_openai.png"); case 'ai-claude@bot.system': return url("images/avatar/default_claude.png"); + case 'ai-gemini@bot.system': + return url("images/avatar/default_gemini.png"); case 'bot-manager@bot.system': return url("images/avatar/default_bot.png"); case 'meeting-alert@bot.system': diff --git a/docker-compose.yml b/docker-compose.yml index a36c89335..9a36efb62 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -170,7 +170,7 @@ services: ai: container_name: "dootask-ai-${APP_ID}" - image: "kuaifan/dooai:0.1.4" + image: "kuaifan/dooai:0.1.8" networks: extnetwork: ipv4_address: "${APP_IPPR}.12" @@ -178,7 +178,7 @@ services: okr: container_name: "dootask-okr-${APP_ID}" - image: "kuaifan/doookr:0.0.35" + image: "kuaifan/doookr:0.0.37" environment: TZ: "${TIMEZONE:-PRC}" DOO_TASK_URL: "http://${APP_IPPR}.3" diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 67b5fb81e..41d85076f 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -762,6 +762,7 @@ export default { approvaUserStatus: '', observers: [], + msgChangeCache: {}, unreadOne: 0, // 最早未读消息id topPosLoad: 0, // 置顶跳转加载中 @@ -1586,22 +1587,80 @@ export default { this.sendMsg(`

${item.label}

`) }, + /** + * 消息变化处理 + * @param data + */ onMsgChange(data) { const item = this.allMsgs.find(({type, id}) => type == "text" && id == data.id) if (item) { - const {tail} = this.scrollInfo() - if (data.type === 'append') { - item.msg.text += data.text - } else if (data.type === 'replace') { - item.msg.text = data.text + if (typeof this.msgChangeCache[data.id] === "undefined") { + this.msgChangeCache[data.id] = [] + this.msgChangeCache[`${data.id}_load`] = false } + if (data.type === 'append') { + this.msgChangeCache[data.id].push(...`${data.text}`.split("").map(text => { + return { + type: 'append', + text + } + })) + } else if (data.type === 'replace') { + this.msgChangeCache[data.id] = [{ + type: 'replace', + text: data.text + }] + } + this.onMsgOutput(data.id, item.msg) + } + }, + + /** + * 追加或替换消息 + * @param id + * @param msg + */ + onMsgOutput(id, msg) { + const load = `${id}_load` + const arr = this.msgChangeCache[id] + if (!arr || arr.length === 0) return + + if (this.msgChangeCache[load] === true) return + this.msgChangeCache[load] = true + + try { + const data = arr.shift() + if (!data) { + this.msgChangeCache[load] = false + return + } + + const {type, text} = data + const {tail} = this.scrollInfo() + if (type === 'append') { + msg.text += text + } else if (type === 'replace') { + msg.text = text + } + this.$nextTick(_ => { if (tail <= 10 && tail != this.scrollInfo().tail) { this.operatePreventScroll++ this.$refs.scroller.scrollToBottom() setTimeout(_ => this.operatePreventScroll--, 50) } + + if (arr.length === 0) { + this.msgChangeCache[load] = false + return + } + setTimeout(_ => { + this.msgChangeCache[load] = false + this.onMsgOutput(id, msg) + }, 5) }) + } catch (e) { + this.msgChangeCache[load] = false } },