Skip to content

事件系统

AI 小鲸 v2.0 采用了双层事件架构,既保证了内部模块间的解耦通信,又兼容了 Vue 的标准事件机制。

双层事件架构

内部事件层

内部事件通过 ComponentManageron / 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-endAI 回复结束{ 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 生态的一致性。

All Rights Reserved. 腾讯蓝鲸 版权所有