diff --git a/src/app.tsx b/src/app.tsx index accf552d89b9bab73b4aeed624efe33d3cb076cc..1b1b1df10a586a67bd2f6d10721e303377799cd4 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,6 +1,5 @@ import './app.scss'; import { chat } from './controller'; -import { CopySvg } from './icons'; import { createUUID } from './utils'; export function App() { @@ -13,7 +12,7 @@ export function App() { setTimeout(() => { ai.addMessage({ messageid: id, - state: 10, + state: 20, role: 'ASSISTANT', content: '# 标题', type: 'DEFAULT', @@ -49,66 +48,19 @@ export function App() { setTimeout(() => { ai.addMessage({ messageid: id, - state: 30, + state: 20, role: 'ASSISTANT', content: '\n\n# markdown', type: 'DEFAULT', }); resolve(true); - }, 1000); - }, 1000); - }, 1000); - }, 1000); - }, 1000); + }, 500); + }, 500); + }, 500); + }, 500); + }, 500); }); }, - contentToolbarItems: [ - { - label: '测试', - icon: , - onClick: (e, message) => { - console.log('测试', e, message); - }, - }, - { - label:
测试行为2
, - icon: , - disabled: true, - onClick: (e, message) => { - console.log('测试行为2', e, message); - }, - }, - { - label: () =>
测试行为3
, - icon: , - onClick: (e, message) => { - console.log('测试行为3', e, message); - }, - }, - ], - footerToolbarItems: [ - { - label: '测试行为1', - onClick: (e, message) => { - console.log('测试行为1', e, message); - }, - }, - { - label:
测试行为2
, - icon: , - disabled: true, - onClick: (e, message) => { - console.log('测试行为2', e, message); - }, - }, - { - label: () =>
测试行为3
, - icon: , - onClick: (e, message) => { - console.log('测试行为3', e, message); - }, - }, - ], }); }; diff --git a/src/components/chat-container/chat-container.scss b/src/components/chat-container/chat-container.scss index e88e234bb00d18696d0cac19b133caf701e2866c..fea53f14cef2a6c0ef96545db793d4ebccdfb60c 100644 --- a/src/components/chat-container/chat-container.scss +++ b/src/components/chat-container/chat-container.scss @@ -11,67 +11,77 @@ $ai-chat: ( 'hover-background-color': rgb(184 184 184 / 31%), 'hover-border-color': #e5e5e5, // 默认圆角 - 'border-radius': 5px + 'border-radius': 5px, + // 样式2 + 'color-2': #4d6bfe, + 'background-color-2': rgb(219 234 254), + 'hover-background-color-2': #c3daf8 ); @include b(chat-container) { @include set-component-css-var('ai-chat', $ai-chat); - position: absolute; - z-index: 1000; - display: flex; - flex-direction: column; - background-color: #{getCssVar('ai-chat', 'background-color')}; - border: 1px solid #{getCssVar('ai-chat', 'border-color')}; - border-radius: #{getCssVar('ai-chat', 'border-radius')}; - - * { - box-sizing: border-box; - } - - svg { - display: inline-block; - width: 1em; - height: 1em; - font-size: 1.5em; /* 设置字体大小 */ - vertical-align: middle; - fill: currentcolor; - } - @include when(hidden) { - display: none; + @include e(dialog) { + position: absolute; + z-index: 1000; + display: flex; + flex-direction: column; + background-color: #{getCssVar('ai-chat', 'background-color')}; + border: 1px solid #{getCssVar('ai-chat', 'border-color')}; + border-radius: #{getCssVar('ai-chat', 'border-radius')}; + + * { + box-sizing: border-box; + } + + svg { + display: inline-block; + width: 1em; + height: 1em; + font-size: 1.5em; /* 设置字体大小 */ + vertical-align: middle; + fill: currentcolor; + } + @include when(hidden) { + display: none; + } } -} - -@include b(chat-container-minimize) { - @include set-component-css-var('ai-chat', $ai-chat); - - position: absolute; - z-index: 99999; - display: flex; - align-items: center; - justify-content: center; - width: 56px; - height: 56px; - color: #{getCssVar('ai-chat', 'color')}; - cursor: pointer; - background-color: #{getCssVar('ai-chat', 'background-color')}; - border: 1px solid #{getCssVar('ai-chat', 'border-color')}; - border-radius: 50%; - &:hover { - color: #{getCssVar('ai-chat', 'hover-color')}; + @include e(minimize) { + position: absolute; + z-index: 99999; + display: flex; + align-items: center; + justify-content: center; + width: 56px; + height: 56px; + color: #{getCssVar('ai-chat', 'color')}; cursor: pointer; - background-color: #{getCssVar('ai-chat', 'hover-background-color')}; - } - - svg { - display: inline-block; - vertical-align: middle; - fill: currentcolor; + background-color: #{getCssVar('ai-chat', 'background-color')}; + border: 1px solid #{getCssVar('ai-chat', 'border-color')}; + border-radius: 50%; + + &:hover { + color: #{getCssVar('ai-chat', 'hover-color')}; + cursor: pointer; + background-color: #{getCssVar('ai-chat', 'hover-background-color')}; + } + + svg { + display: inline-block; + vertical-align: middle; + fill: currentcolor; + } + + @include when(hidden) { + display: none; + } } - @include when(hidden) { - display: none; + @include e(toolbar) { + display: flex; + justify-content: center; + margin: 8px; } } @@ -132,6 +142,13 @@ $ai-chat: ( height: 100%; } +@include b(chat-container-main__default) { + display: flex; + flex-direction: column; + flex-grow: 1; + height: calc(100% - 60px); +} + @include b(chat-container-content) { flex-grow: 1; overflow: hidden; diff --git a/src/components/chat-container/chat-container.tsx b/src/components/chat-container/chat-container.tsx index 240cb69c14fcfa4225d71d0c35bf1d0f6ac61da6..c1d9603dd152b120a83117689102bb72302ecbeb 100644 --- a/src/components/chat-container/chat-container.tsx +++ b/src/components/chat-container/chat-container.tsx @@ -13,8 +13,9 @@ import { } from '../../icons'; import { AIChatConst } from '../../constants'; import { IChatToolbarItem } from '../../interface'; -import './chat-container.scss'; import { ChatTopics } from '../chat-topics/chat-topics'; +import { ChatToolbar } from '../chat-toolbar/chat-toolbar'; +import './chat-container.scss'; export interface ChatContainerProps { /** @@ -354,6 +355,7 @@ export class ChatContainer extends Component< * @memberof ChatContainer */ minimize(): void { + this.closeFullScreen(); this.setState({ isMinimize: true }); this.props.minimize(true); } @@ -381,12 +383,12 @@ export class ChatContainer extends Component< render() { return ( -
+
@@ -453,18 +455,38 @@ export class ChatContainer extends Component<
- +
+
) : ( -
+
- +
+
@@ -474,9 +496,10 @@ export class ChatContainer extends Component<
diff --git a/src/components/chat-message-item/markdown-message/markdown-message.scss b/src/components/chat-message-item/markdown-message/markdown-message.scss index f746334b5ffa7be9877acaa94ce6287a174ba2b7..c21199e1f1b64fd87ce917adca93c00edca187d9 100644 --- a/src/components/chat-message-item/markdown-message/markdown-message.scss +++ b/src/components/chat-message-item/markdown-message/markdown-message.scss @@ -9,6 +9,10 @@ .cherry-previewer { padding: 8px; border: 0; + figure > svg { + min-height: 100px; + width: 100%; + } } .anchor { @@ -50,7 +54,6 @@ font-weight: 800; color: #{getCssVar('ai-chat', 'color')}; } - } @keyframes circle { diff --git a/src/components/chat-toolbar-item/chat-toolbar-item.scss b/src/components/chat-toolbar-item/chat-toolbar-item.scss deleted file mode 100644 index a5355d3bc2c7f1dcddf91d6bf57b80dd784b6d57..0000000000000000000000000000000000000000 --- a/src/components/chat-toolbar-item/chat-toolbar-item.scss +++ /dev/null @@ -1,77 +0,0 @@ -@include b(chat-toolbar-item) { - display: flex; - cursor: pointer; - align-items: center; - white-space: nowrap; - @include e(icon) { - display: flex; - flex-shrink: 0; - align-items: center; - } - @include e(label) { - display: flex; - align-items: center; - } -} - -@include b(chat-toolbar-item-style2) { - gap: 6px; - z-index: 1; - font-size: 14px; - width: fit-content; - padding: 2px 14px; - line-height: 28px; - border-radius: 12px; - color: #{getCssVar('ai-chat', 'color-2')}; - background-color: #{getCssVar('ai-chat', 'background-color-2')}; - &:hover { - background-color: #{getCssVar('ai-chat', 'hover-background-color-2')}; - } - @include when(disabled) { - pointer-events: none; - color: #{getCssVar('ai-chat', 'disabled-color')}; - } -} - -@include b(chat-toolbar-item-default) { - width: 32px; - height: 32px; - padding: 6px; - font-size: 12px; - overflow: hidden; - border-radius: 15px; - transition: all 0.3s ease; - border: 1px solid #{getCssVar('ai-chat', 'border-color')}; - - @include e(icon) { - width: 18px; - height: 18px; - } - - @include e(label) { - font-size: 14px; - margin-left: 8px; - width: calc(100% - 32px); - > * { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - } - - &:hover { - width: 68px; - color: #{getCssVar('ai-chat', 'hover-color')}; - background-color: #{getCssVar('ai-chat', 'hover-background-color')}; - } - - @include when(disabled) { - pointer-events: none; - color: #{getCssVar('ai-chat', 'disabled-color')}; - } - - @include when(loading) { - pointer-events: none; - animation: loading-change 0.8s infinite; - } -} diff --git a/src/components/chat-toolbar-item/chat-toolbar-item.tsx b/src/components/chat-toolbar-item/chat-toolbar-item.tsx deleted file mode 100644 index 75f044b3553a97fd3e5ec8c68ed98f29d01e791f..0000000000000000000000000000000000000000 --- a/src/components/chat-toolbar-item/chat-toolbar-item.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { Namespace } from '@ibiz-template/scss-utils'; -import { IChatToolbarItem } from '../../interface'; -import './chat-toolbar-item.scss'; - -export interface ChatToolbarItemProps { - /** - * 用户自定义工具栏 - * - * @type {IChatToolbarItem} - * @memberof ChatToolbarItemProps - */ - item: IChatToolbarItem; - - /** - * 业务数据 - * - * @type {*} - * @memberof ChatActionItemProps - */ - data: any; - - /** - * 工具栏类型 - * - * @type {('question' | 'answer' | 'dialogue')} ( 提问 | 回答 | 对话 ) - * @memberof ChatToolbarItemProps - */ - type: 'question' | 'answer' | 'dialogue'; -} - -const ns = new Namespace('chat-toolbar-item'); - -export const ChatToolbarItem = (props: ChatToolbarItemProps) => { - const { item, data, type } = props; - - const hidden = (): boolean => { - if (typeof item.hidden === 'function') return item.hidden(data); - return item.hidden === true; - }; - - if (hidden()) return
; - - const disabled = (): boolean => { - if (typeof item.disabled === 'function') return item.disabled(data); - return item.disabled === true; - }; - - const style = type !== 'dialogue' ? 'default' : 'style2'; - - return ( -
item.onClick?.(e, data)} - > -
- {typeof item.icon === 'function' ? item.icon() : item.icon} -
-
- {typeof item.label === 'function' ? item.label() : item.label} -
-
- ); -}; diff --git a/src/components/chat-toolbar/chat-toolbar.scss b/src/components/chat-toolbar/chat-toolbar.scss index 8f61dba19a4aac25e4059ffeb22bf8a00c169cfc..d5c52412d41dbad4715270ef7802eafa1b48dd38 100644 --- a/src/components/chat-toolbar/chat-toolbar.scss +++ b/src/components/chat-toolbar/chat-toolbar.scss @@ -1,9 +1,95 @@ @include b(chat-toolbar) { display: flex; align-items: center; - .#{bem(chat-toolbar-item)} { + + @include e(item) { + display: flex; + cursor: pointer; + align-items: center; + white-space: nowrap; + &:not(:first-child) { margin-left: 6px; } + + @include m(icon) { + width: 18px; + height: 18px; + display: flex; + flex-shrink: 0; + font-size: 18px; + align-items: center; + justify-content: center; + } + + @include m(label) { + display: flex; + align-items: center; + } + + @include when(disabled) { + cursor: not-allowed; + } + + @include when(loading) { + pointer-events: none; + animation: loading-change 0.8s infinite; + } + } + + @include e(circle) { + .#{bem(chat-toolbar, item)} { + width: 32px; + height: 32px; + padding: 6px; + font-size: 12px; + overflow: hidden; + border-radius: 15px; + transition: all 0.3s ease; + border: 1px solid #{getCssVar('ai-chat', 'border-color')}; + + &.is-disabled { + color: #{getCssVar('ai-chat', 'disabled-color')}; + } + + &:hover:not(.is-disabled) { + width: 68px; + color: #{getCssVar('ai-chat', 'hover-color')}; + background-color: #{getCssVar('ai-chat', 'hover-background-color')}; + } + + .#{bem(chat-toolbar, item, label)} { + font-size: 14px; + margin-left: 8px; + width: calc(100% - 32px); + > * { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + } + } + + @include e(default) { + .#{bem(chat-toolbar, item)} { + gap: 6px; + z-index: 1; + font-size: 14px; + width: fit-content; + padding: 2px 14px; + line-height: 28px; + border-radius: 12px; + color: #{getCssVar('ai-chat', 'color-2')}; + background-color: #{getCssVar('ai-chat', 'background-color-2')}; + + &.is-disabled { + background-color: #{getCssVar('ai-chat', 'disabled-color')}; + } + + &:hover:not(.is-disabled) { + background-color: #{getCssVar('ai-chat', 'hover-background-color-2')}; + } + } } -} \ No newline at end of file +} diff --git a/src/components/chat-toolbar/chat-toolbar.tsx b/src/components/chat-toolbar/chat-toolbar.tsx index 755921f545a8e470b205f4ecbd43eb37cb14a2a2..c95cc56f17e475cb85addc0c737891c8f5a6c241 100644 --- a/src/components/chat-toolbar/chat-toolbar.tsx +++ b/src/components/chat-toolbar/chat-toolbar.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { h } from 'preact'; import { Namespace } from '../../utils'; import { IChatToolbarItem } from '../../interface'; -import { ChatToolbarItem } from '../chat-toolbar-item/chat-toolbar-item'; import { AiChatController } from '../../controller'; import { CopySvg, @@ -59,7 +59,7 @@ const ns = new Namespace('chat-toolbar'); export const ChatToolbar = (props: ChatToolbarProps) => { const { controller, items = [], data, type, className } = props; let toolbarItems: IChatToolbarItem[] = []; - let toolbarItemType: 'question' | 'answer' | 'dialogue' = 'answer'; + let style: 'default' | 'circle' = 'default'; /** * 底部默认工具栏 * @@ -129,6 +129,7 @@ export const ChatToolbar = (props: ChatToolbarProps) => { ]; if (type === 'content') { + style = 'circle'; switch (data.type) { case 'DEFAULT': if (data.role === 'ASSISTANT') { @@ -144,20 +145,45 @@ export const ChatToolbar = (props: ChatToolbarProps) => { break; } } else { - toolbarItemType = 'dialogue'; toolbarItems = [...FooterDefaultItems, ...items]; } + const hidden = (item: IChatToolbarItem): boolean => { + if (typeof item.hidden === 'function') return item.hidden(data); + return item.hidden === true; + }; + + const disabled = (item: IChatToolbarItem): boolean => { + if (typeof item.disabled === 'function') return item.disabled(data); + return item.disabled === true; + }; + + const handleItemClick = (e: MouseEvent, item: IChatToolbarItem): void => { + if (disabled(item)) return; + item.onClick?.(e, controller.context, controller.params, data); + }; + return ( -
+
{toolbarItems.map((item, index) => { + if (hidden(item)) return; return ( - + className={`${ns.e('item')} ${ns.is( + 'disabled', + disabled(item), + )} ${ns.is('loading', data.state === 20)} ${className || ''}`} + title={item.title} + onClick={e => handleItemClick(e, item)} + > +
+ {typeof item.icon === 'function' ? item.icon(h) : item.icon} +
+
+ {typeof item.label === 'function' ? item.label(h) : item.label} +
+
); })}
diff --git a/src/controller/chat/chat.controller.ts b/src/controller/chat/chat.controller.ts index 85906c13c84e0e60149cc977e04062779017a5c9..2157bf7f86e5896b3acacd07da87d61392ae1745 100644 --- a/src/controller/chat/chat.controller.ts +++ b/src/controller/chat/chat.controller.ts @@ -132,17 +132,25 @@ export class ChatController { close: () => { this.close(); if (chatOptions.closed) { - chatOptions.closed(); + chatOptions.closed(chatOptions.context, chatOptions.params); } }, fullscreen: (target: boolean) => { if (chatOptions.fullscreen) { - chatOptions.fullscreen(target); + chatOptions.fullscreen( + target, + chatOptions.context, + chatOptions.params, + ); } }, minimize: (target: boolean) => { if (chatOptions.minimize) { - chatOptions.minimize(target); + chatOptions.minimize( + target, + chatOptions.context, + chatOptions.params, + ); } }, }), @@ -188,17 +196,17 @@ export class ChatController { close: () => { this.close(); if (opts.closed) { - opts.closed(); + opts.closed(opts.context, opts.params); } }, fullscreen: (target: boolean) => { if (opts.fullscreen) { - opts.fullscreen(target); + opts.fullscreen(target, opts.context, opts.params); } }, minimize: (target: boolean) => { if (opts.minimize) { - opts.minimize(target); + opts.minimize(target, opts.context, opts.params); } }, }), diff --git a/src/interface/i-chat-options/i-chat-options.ts b/src/interface/i-chat-options/i-chat-options.ts index a60fd2288bb738b3b5682924da72b6e4955a4b71..e129c13914768518ce3784d69c9c640dfa06de40 100644 --- a/src/interface/i-chat-options/i-chat-options.ts +++ b/src/interface/i-chat-options/i-chat-options.ts @@ -112,12 +112,13 @@ export interface IChatOptions extends IChat { ): Promise; /** - * 窗口关闭后回调 + * 窗口关闭 * - * @author chitanda - * @date 2023-10-15 19:10:25 + * @param {object} context + * @param {object} params + * @memberof IChatOptions */ - closed?(): void; + closed?(context: object, params: object): void; /** * 聊天窗任意位置点击操作 @@ -136,16 +137,20 @@ export interface IChatOptions extends IChat { /** * 全屏操作 * - * @param {boolean} target true为打开,false为关闭 + * @param {boolean} target + * @param {object} context + * @param {object} params * @memberof IChatOptions */ - fullscreen?(target: boolean): void; + fullscreen?(target: boolean, context: object, params: object): void; /** * 最小化操作 * - * @param {boolean} target true为最小化,false为退出最小化 + * @param {boolean} target + * @param {object} context + * @param {object} params * @memberof IChatOptions */ - minimize?(target: boolean): void; + minimize?(target: boolean, context: object, params: object): void; } diff --git a/src/interface/i-chat-toolbar-item/i-chat-toolbar-item.ts b/src/interface/i-chat-toolbar-item/i-chat-toolbar-item.ts index 5364e7b85ae44283cc234c11eeff8fb3ba323261..2e06df5d01100a703a4889bb6d1868b0859d5699 100644 --- a/src/interface/i-chat-toolbar-item/i-chat-toolbar-item.ts +++ b/src/interface/i-chat-toolbar-item/i-chat-toolbar-item.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable no-shadow */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { VNode } from 'preact'; @@ -13,7 +14,7 @@ export interface IChatToolbarItem { * * @memberof IChatToolbarItem */ - label?: string | VNode | (() => VNode); + label?: string | VNode | ((h: Function) => VNode); /** * 提示信息 * @@ -26,19 +27,19 @@ export interface IChatToolbarItem { * * @memberof IChatToolbarItem */ - icon?: string | VNode | (() => VNode); + icon?: string | VNode | ((h: Function) => VNode); /** * 是否禁用 * * @memberof IChatToolbarItem */ - disabled?: boolean | ((data: any) => boolean); + disabled?: boolean | ((data: object) => boolean); /** * 是否隐藏 * * @memberof IChatToolbarItem */ - hidden?: boolean | ((data: any) => boolean); + hidden?: boolean | ((data: object) => boolean); /** * 自定义类名 * @@ -51,5 +52,10 @@ export interface IChatToolbarItem { * * @memberof IChatToolbarItem */ - onClick?: (e: MouseEvent, data?: any) => void; + onClick?: ( + e: MouseEvent, + context: object, + params: object, + data?: object, + ) => void; }