From e1eecd0fa54732ce3cb2856ba91a3cd8f13df35a Mon Sep 17 00:00:00 2001 From: lijianxiong <1518062161@qq.com> Date: Mon, 29 Sep 2025 17:58:03 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=96=B0=E5=A2=9E=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=8F=82=E6=95=B0openMode=EF=BC=88=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=89=93=E5=BC=80=E6=A8=A1=E5=BC=8F=EF=BC=89=E4=B8=8EautoClose?= =?UTF-8?q?=EF=BC=88=E6=8F=90=E9=97=AE=E5=AE=8C=E6=88=90=E6=97=B6=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E8=87=AA=E5=8A=A8=E5=85=B3=E9=97=AD=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=EF=BC=89=EF=BC=8C=E5=B9=B6=E5=AE=8C=E6=88=90=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=90=8E=E7=9A=84=E6=95=88=E6=9E=9C=E9=80=82?= =?UTF-8?q?=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 4 +- .../chat-container/chat-container.tsx | 53 ++++++++++++++++++- src/controller/ai-chat/ai-chat.controller.ts | 43 +++++++++++---- src/controller/chat/chat.controller.ts | 5 ++ .../i-chat-options/i-chat-options.ts | 40 +++++++++++++- src/interface/index.ts | 6 ++- vite.config.ts | 2 +- 7 files changed, 138 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 887f2d2..fa9d2d1 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "autosize": "^6.0.1", "cherry-markdown": "^0.8.26", "interactjs": "^1.10.19", + "qx-util": "^0.4.8", "path-browserify": "^1.0.1", "preact": "^10.18.1", "react-tabs": "^6.0.2", @@ -77,7 +78,8 @@ }, "peerDependencies": { "cherry-markdown": "^0.8.26", - "interactjs": "^1.10.19" + "interactjs": "^1.10.19", + "qx-util": "^0.4.8" }, "lint-staged": { "*.ts": "eslint --fix", diff --git a/src/components/chat-container/chat-container.tsx b/src/components/chat-container/chat-container.tsx index 91b8829..a829c2d 100644 --- a/src/components/chat-container/chat-container.tsx +++ b/src/components/chat-container/chat-container.tsx @@ -12,7 +12,11 @@ import { CloseFullScreenSvg, } from '../../icons'; import { AIChatConst } from '../../constants'; -import { IChatToolbarItem, IChatContainerOptions } from '../../interface'; +import { + IChatToolbarItem, + IChatContainerOptions, + IAutoClose, +} from '../../interface'; import { ChatTopics } from '../chat-topics/chat-topics'; import { ChatToolbar } from '../chat-toolbar/chat-toolbar'; import { ChatMinimize } from '../chat-minimize/chat-minimize'; @@ -116,6 +120,22 @@ export interface ChatContainerProps { * @type {IChatContainerOptions} */ containerOptions?: IChatContainerOptions; + + /** + * 自动关闭 + * + * @type {IAutoClose} + * @memberof ChatContainerProps + */ + autoClose?: IAutoClose; + + /** + * @description AI窗口的打开模式 + * - default:默认;minimize:最小化;autoexpand:自动展开 + * @type {('default' | 'minimize' | 'autoexpand')} + * @memberof IChat + */ + openMode?: 'default' | 'minimize' | 'autoexpand'; } interface ChatContainerState { @@ -168,8 +188,37 @@ export class ChatContainer extends Component< // 初始化状态 this.state = { isFullScreen: false, - isMinimize: false, + isMinimize: !!( + props?.openMode === 'minimize' || props?.openMode === 'autoexpand' + ), }; + + props?.aiChat.evt.on('onCompleteMessage', () => { + // 窗口自动关闭 + if (props.autoClose) { + const { mode, duration = 3 } = props.autoClose; + switch (mode) { + case 'minimize': + this.minimize(); + break; + case 'close': + this.close(); + break; + case 'closetime': + setTimeout(() => { + this.close(); + }, duration * 1000); + break; + default: + break; + } + } + + // 窗口的打开模式,请求结束后自动打开 + if (props.openMode === 'autoexpand') { + this.exitMinimize(); + } + }); } ns = new Namespace('chat-container'); diff --git a/src/controller/ai-chat/ai-chat.controller.ts b/src/controller/ai-chat/ai-chat.controller.ts index 1d6b3e7..3ffef3b 100644 --- a/src/controller/ai-chat/ai-chat.controller.ts +++ b/src/controller/ai-chat/ai-chat.controller.ts @@ -1,6 +1,7 @@ /* eslint-disable no-useless-escape */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Signal, signal } from '@preact/signals'; +import { QXEvent } from 'qx-util'; import { ChatMaterial, ChatMessage } from '../../entity'; import { ITopic, @@ -28,6 +29,16 @@ import { AIChatConst } from '../../constants'; * @class AiChatController */ export class AiChatController { + /** + * 事件触发器 + * @type {EventBase} + */ + evt: QXEvent<{ + [p: string]: (...args: any[]) => any; + }> = new QXEvent<{ + [p: string]: (...args: any[]) => any; + }>(); + /** * 聊天记录 * @@ -276,6 +287,19 @@ export class AiChatController { this.messages.value = [...this.messages.value]; await this.asyncToIndexDB(); } + + // AI回答完成时自动回填 + if (this.opts.autoFill === true) { + const message = + chatMsg || this.messages.value[this.messages.value.length - 1]; + if (message.role === 'ASSISTANT' && message.state === 30) + this.backfill(message); + } + + this.evt.emit('onCompleteMessage', { + messageid: id, + completed, + }); } /** @@ -309,15 +333,6 @@ export class AiChatController { } }); } - // AI回答完成时自动回填 - if (this.opts.autoFill === true) { - const message = - i !== -1 - ? this.messages.value[i] - : this.messages.value[this.messages.value.length - 1]; - if (message.role === 'ASSISTANT' && message.state === 30) - this.backfill(message); - } } /** @@ -733,4 +748,14 @@ export class AiChatController { throw new Error(`不支持${type}推荐类型`); } } + + /** + * 销毁 + * + * @return {*} {Promise} + * @memberof AiChatController + */ + async destroyed(): Promise { + this.evt.reset(); + } } diff --git a/src/controller/chat/chat.controller.ts b/src/controller/chat/chat.controller.ts index 1626f99..de86508 100644 --- a/src/controller/chat/chat.controller.ts +++ b/src/controller/chat/chat.controller.ts @@ -184,6 +184,8 @@ export class ChatController { contentToolbarItems: chatOptions.contentToolbarItems, footerToolbarItems: chatOptions.footerToolbarItems, questionToolbarItems: chatOptions.questionToolbarItems, + autoClose: chatOptions.autoClose, + openMode: chatOptions.openMode, close: () => { this.close(); if (chatOptions.closed) { @@ -329,6 +331,9 @@ export class ChatController { this.container.remove(); this.container = undefined; } + this.aiTopicMap.forEach(aiChat => { + aiChat.destroyed(); + }); } } diff --git a/src/interface/i-chat-options/i-chat-options.ts b/src/interface/i-chat-options/i-chat-options.ts index f301df1..8e77e95 100644 --- a/src/interface/i-chat-options/i-chat-options.ts +++ b/src/interface/i-chat-options/i-chat-options.ts @@ -4,6 +4,28 @@ import { IChatToolbarItem } from '../i-chat-toolbar-item/i-chat-toolbar-item'; import { FileUploaderOptions } from '../i-file-uploader-options/i-file-uploader-options'; import { ITopic } from '../i-topic-options/i-topic-options'; +/** + * 自动关闭窗口,用于在提问完成时配置窗口关闭模式 + * + * @export + * @interface IAutoClose + */ +export interface IAutoClose { + /** + * @description 模式 + * - minimize:最小化;close:直接关闭;closetime:定时关闭 + * @type {('minimize' | 'closetime' | 'close')} + */ + mode: 'minimize' | 'close' | 'closetime'; + + /** + * @description 自动关闭延时时间,该值单位为秒(s),当 mode 值为closetime时生效 + * @default 3 + * @type {number} + */ + duration?: number; +} + /** * 聊天数据 * @@ -55,7 +77,23 @@ export interface IChat { * @memberof IChat */ autoQuestion?: boolean; - + + /** + * 自动关闭窗口,用于在提问完成时配置窗口关闭模式 + * + * @type {IAutoClose} + * @memberof IChat + */ + autoClose?: IAutoClose; + + /** + * @description AI窗口的打开模式 + * - default:默认;minimize:默认最小化窗口;autoexpand:默认最小化窗口,当提问完成时自动展开窗口 + * @type {('default' | 'minimize' | 'autoexpand')} + * @memberof IChat + */ + openMode?: 'default' | 'minimize' | 'autoexpand'; + /** * @description 是否自动回填 * - AI回答完成之后是否触发回填,默认关闭 diff --git a/src/interface/index.ts b/src/interface/index.ts index c0a4c24..1f9d4bd 100644 --- a/src/interface/index.ts +++ b/src/interface/index.ts @@ -1,5 +1,9 @@ export type { IChatMessage } from './i-chat-message/i-chat-message'; -export type { IChat, IChatOptions } from './i-chat-options/i-chat-options'; +export type { + IChat, + IChatOptions, + IAutoClose, +} from './i-chat-options/i-chat-options'; export type { IMessageItemProvider } from './i-message-item-provider/i-message-item-provider'; export type { IPortalAsyncAction } from './i-portal-async-action/i-portal-async-action'; export type { IChatToolbarItem } from './i-chat-toolbar-item/i-chat-toolbar-item'; diff --git a/vite.config.ts b/vite.config.ts index 3019b59..4a4f57b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -13,7 +13,7 @@ export default defineConfig({ fileName: format => `index.${format}.js`, }, rollupOptions: { - external: ['cherry-markdown', 'interactjs'], + external: ['cherry-markdown', 'interactjs', 'qx-util'], }, }, server: { -- Gitee