事件系统
AI 小鲸 v2.0 采用了双层事件架构,既保证了内部模块间的解耦通信,又兼容了 Vue 的标准事件机制。
双层事件架构
内部事件层
内部事件通过 ComponentManager 的 on / emit 方法进行通信。这是 Manager 之间以及 Manager 与内部组件之间的主要通信方式。
typescript
// 发布事件
componentManager.emit('send-message', { content: '你好', sessionCode: 'abc123' });
// 订阅事件
componentManager.on('send-message', (payload) => {
console.log('收到消息:', payload.content);
});Vue 事件层
Vue 事件通过标准的 emit 机制向父组件传递。这是组件对外暴露的公共 API。
vue
<!-- 父组件中使用 -->
<ChatBot
@send-message="handleSendMessage"
@receive-start="handleReceiveStart"
@receive-end="handleReceiveEnd"
/>useEventBridge:桥接两层事件
useEventBridge 是连接内部事件与 Vue 事件的桥梁组合式函数。它自动监听 ComponentManager 上的内部事件,并将其转发为 Vue emit 调用。
typescript
import { useEventBridge } from '@blueking/ai-blueking';
// 在 ChatBot 组件内部
const emit = defineEmits([
'send-message',
'receive-start',
'receive-end',
'session-change',
// ...
]);
// 一行代码完成桥接
useEventBridge(componentManager, emit);工作原理
useEventBridge 内部会遍历 EVENT_BRIDGE_MAP,为每个内部事件注册监听器,当事件触发时自动调用对应的 Vue emit。
EVENT_BRIDGE_MAP
EVENT_BRIDGE_MAP 定义了内部事件名到 Vue emit 名的映射关系:
typescript
const EVENT_BRIDGE_MAP: Record<string, string> = {
// UI 事件
'input-focus': 'input-focus',
'input-blur': 'input-blur',
'scroll-to-bottom': 'scroll-to-bottom',
// 业务事件
'send-message': 'send-message',
'receive-start': 'receive-start',
'receive-end': 'receive-end',
'stop-generation': 'stop-generation',
'message-error': 'message-error',
// 头部事件
'header-close': 'close',
'header-clear': 'clear',
'header-toggle-full': 'toggle-fullscreen',
// 选择事件
'selection-change': 'selection-change',
'selection-confirm': 'selection-confirm',
'selection-cancel': 'selection-cancel',
};事件分类
UI 事件
与界面交互相关的事件,不涉及业务逻辑:
| 事件名 | 触发时机 | 载荷 |
|---|---|---|
input-focus | 输入框获得焦点 | 无 |
input-blur | 输入框失去焦点 | 无 |
scroll-to-bottom | 消息列表滚动到底部 | 无 |
业务事件
与核心对话业务相关的事件:
| 事件名 | 触发时机 | 载荷 |
|---|---|---|
send-message | 用户发送消息 | { content: string, property?: IMessageProperty } |
receive-start | 开始接收 AI 回复 | { sessionCode: string } |
receive-end | AI 回复结束 | { sessionCode: string, message: IMessage } |
stop-generation | 用户停止生成 | 无 |
message-error | 消息处理出错 | { error: Error } |
头部事件
与顶部操作栏相关的事件:
| 事件名 | 触发时机 | 载荷 |
|---|---|---|
header-close | 点击关闭按钮 | 无 |
header-clear | 点击清空按钮 | 无 |
header-toggle-full | 点击全屏切换 | { isFullscreen: boolean } |
选择事件
与消息选择模式相关的事件:
| 事件名 | 触发时机 | 载荷 |
|---|---|---|
selection-change | 选择的消息发生变化 | { selectedIds: string[] } |
selection-confirm | 确认选择 | { messages: IMessage[] } |
selection-cancel | 取消选择模式 | 无 |
订阅事件
在 Manager 中订阅
typescript
// 订阅单个事件
componentManager.on('send-message', (payload) => {
console.log('用户发送了:', payload.content);
});
// 订阅一次性事件
componentManager.once('receive-end', (payload) => {
console.log('首次回复完成');
});
// 取消订阅
const handler = (payload) => { /* ... */ };
componentManager.on('send-message', handler);
componentManager.off('send-message', handler);在 Vue 组件中订阅
vue
<template>
<ChatBot
@send-message="onSendMessage"
@receive-start="onReceiveStart"
@receive-end="onReceiveEnd"
@message-error="onMessageError"
/>
</template>
<script setup lang="ts">
const onSendMessage = (payload: { content: string }) => {
console.log('消息已发送:', payload.content);
};
const onReceiveStart = () => {
console.log('开始接收回复...');
};
const onReceiveEnd = (payload: { message: IMessage }) => {
console.log('回复完成:', payload.message);
};
const onMessageError = (payload: { error: Error }) => {
console.error('消息出错:', payload.error);
};
</script>添加自定义事件
当内置事件不能满足需求时,你可以添加自定义事件类型。
步骤一:定义事件
typescript
// types/events.ts
declare module '@blueking/ai-blueking' {
interface ComponentManagerEvents {
// 添加自定义事件类型
'custom-analytics': { action: string; label: string };
'theme-change': { theme: 'light' | 'dark' };
}
}步骤二:在 Manager 中触发
typescript
// 在自定义 Manager 中触发事件
class ThemeManager {
constructor(private componentManager: ComponentManager) {}
switchTheme(theme: 'light' | 'dark') {
// 执行主题切换逻辑...
this.componentManager.emit('theme-change', { theme });
}
}步骤三:扩展 EVENT_BRIDGE_MAP(可选)
如果需要将自定义事件桥接到 Vue emit:
typescript
import { EVENT_BRIDGE_MAP } from '@blueking/ai-blueking';
// 扩展桥接映射
EVENT_BRIDGE_MAP['theme-change'] = 'theme-change';
EVENT_BRIDGE_MAP['custom-analytics'] = 'analytics';步骤四:在父组件中监听
vue
<ChatBot
@theme-change="onThemeChange"
@analytics="onAnalytics"
/>完整事件流示例
以下展示一条消息从用户输入到父组件接收的完整事件流:

这种双层事件架构确保了内部实现的灵活性,同时保持了对外 API 的稳定性和 Vue 生态的一致性。