ding-ai-minutes-bridge
v0.0.9
Published
钉钉 AI 听记桌面端开放 SDK,提供跨 iframe 调用桌面端 JSAPI 的能力
Maintainers
Readme
@ali/ding-ai-minutes-bridge
钉钉 AI 听记桌面端开放 SDK,提供跨 iframe 调用桌面端 JSAPI 的能力。
安装
npm install @ali/ding-ai-minutes-bridge
# 或
pnpm install @ali/ding-ai-minutes-bridge快速开始
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// 调用桌面端 JSAPI
const result = await AIMinutesBridge.call('methodName', { key: 'value' })API 文档
初始化配置
// 方式1: 初始化后调用
AIMinutesBridge.init({ enableLog: true })
// 方式2: 链式调用
const result = await AIMinutesBridge
.init({ enableLog: true })
.call('methodName', params)常用方法示例
requestAuthCode 获取免登码
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// 打开调试日志
AIMinutesBridge.init({ enableLog: true })
try {
// 由于请求由听记域名(https://shanji.dingtalk.com)代理申请,请将https://shanji.dingtalk.com 加入微应用的端内免登地址
const result = await AIMinutesBridge.call('requestAuthCode', {
corpId: 'ding12345' // 填入当前 corpId
});
console.log('requestAuthCode success, result', result);
} catch (error) {
console.log('requestAuthCode errror', error);
}getCurrentTheme 获取当前主题
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
try {
const result = await AIMinutesBridge.call('getCurrentTheme', {});
console.log('getCurrentTheme success, result', result);
} catch (error) {
console.log('getCurrentTheme errror', error);
}webPageSizeChange 页面尺寸变化
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
try {
const result = await AIMinutesBridge.call('webPageSizeChange', {
height: 1100,
});
console.log('webPageSizeChange success, result', result);
} catch (error) {
console.log('webPageSizeChange errror', error);
}subscribeEvent 订阅事件
订阅事件,当事件触发时会收到回调通知。默认使用 flash_minutes_bridge namespace。
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// 使用默认 namespace ('flash_minutes_bridge') 订阅事件
const result = await AIMinutesBridge.subscribeEvent(
'webPageSizeChange', // eventName
(data) => { // 事件处理器
console.log('收到事件数据:', data);
}
);
// 使用自定义 namespace 订阅事件
const result2 = await AIMinutesBridge.subscribeEvent(
'customEvent', // eventName
(data) => { // 事件处理器
console.log('收到事件数据:', data);
},
{
namespace: 'my_custom_namespace' // 自定义 namespace(可选)
}
);
if (result.success) {
console.log('订阅成功:', result.message);
} else {
console.log('订阅失败:', result.message);
}参数说明:
eventName: string- 事件名称(必填)handler: (data: unknown) => void- 事件触发时的回调函数(必填)namespace?: string- channel 命名空间,默认为'flash_minutes_bridge'(可选)
注意:
- SDK 内部会自动生成唯一的
callbackId用于标识此次订阅 - 同一个
namespace+eventName+callbackId组合只能订阅一次 - 订阅成功后,当事件触发时,宿主页面会推送事件数据到 iframe
unsubscribeEvent 取消订阅事件
取消已订阅的事件监听。
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// 取消订阅(需要知道订阅时使用的 callbackId)
const result = await AIMinutesBridge.unsubscribeEvent(
'flash_minutes', // namespace
'webPageSizeChange', // eventName
callbackId // 订阅时使用的 callbackId
);
if (result.success) {
console.log('取消订阅成功:', result.message);
} else {
console.log('取消订阅失败:', result.message);
}注意:
- 目前
subscribeEvent方法不返回callbackId,如果需要取消订阅,建议:- 使用
AIMinutesBridge.call('subscribeEvent', {...})方式手动传入callbackId - 或仅在页面卸载时调用
cleanup()清理所有订阅
- 使用
publishEvent 发布事件
向指定 eventName 发布事件,所有订阅了该事件的 iframe 页面(除了发布者自己)都会收到通知。默认使用 flash_minutes_bridge namespace。
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// 使用默认 namespace ('flash_minutes_bridge') 发布自定义事件
const result = await AIMinutesBridge.publishEvent(
'customEvent', // eventName
{ message: 'Hello', timestamp: Date.now() } // 事件数据
);
// 使用自定义 namespace 发布事件
const result2 = await AIMinutesBridge.publishEvent(
'customEvent', // eventName
{ message: 'Hello' }, // 事件数据
'my_custom_namespace' // 自定义 namespace(可选)
);
console.log(`事件已推送到 ${result.pushCount} 个订阅者`);参数说明:
eventName: string- 事件名称(必填)data: unknown- 任意类型的事件数据(必填)namespace?: string- channel 命名空间,默认为'flash_minutes_bridge'(可选)
返回值:
success: boolean- 是否发布成功pushCount: number- 成功推送到的订阅者数量message: string- 响应消息
注意:
- 发布者自身不会收到该事件的通知
flash_minutes_bridgenamespace 已默认加入白名单,无需额外配置
cleanup 清理资源
在页面卸载前调用,清理所有事件订阅和 SDK 资源。
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// 页面卸载前清理资源
window.addEventListener('beforeunload', () => {
AIMinutesBridge.cleanup();
});页面间通信完整示例
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// ========== 页面 A(发布者)==========
async function initPageA() {
AIMinutesBridge.init({ enableLog: true });
// 发布事件
document.getElementById('sendBtn')?.addEventListener('click', async () => {
const result = await AIMinutesBridge.publishEvent(
'my_app',
'message',
{ from: 'Page A', text: 'Hello Page B!' }
);
console.log(`消息已发送给 ${result.pushCount} 个接收者`);
});
}
// ========== 页面 B(订阅者)==========
async function initPageB() {
AIMinutesBridge.init({ enableLog: true });
// 订阅事件
await AIMinutesBridge.subscribeEvent(
'message',
(data) => {
console.log('收到消息:', data);
// 输出: { from: 'Page A', text: 'Hello Page B!' }
}
);
}其他 jsapi
其他jsapi 为内应用调用,三方页面无法使用
call(methodName, params)
调用桌面端 JSAPI。
const result = await AIMinutesBridge.call('methodName', { param1: 'value1' })参数:
methodName: string- 方法名params?: unknown- 参数对象
返回: Promise<T> - 返回 Promise,resolve 时获取结果
init(config)
初始化 SDK 配置,支持链式调用。
AIMinutesBridge.init({ enableLog: true })setLogEnabled(enabled)
动态设置日志开关,支持链式调用。
AIMinutesBridge.setLogEnabled(true)getVersion()
获取 SDK 版本号。
const version = AIMinutesBridge.getVersion() // "1.0.0"isInIframe()
检查当前是否在 iframe 中运行。
const inIframe = AIMinutesBridge.isInIframe() // true/false类型导入
import type {
BridgeConfig,
BridgeMessage,
MessagePayload,
MessageResult,
ReceivedMessage,
EventPushMessage,
EventHandler,
EventSubscription,
// API 参数类型
RequestAuthCodeParams,
GetCurrentThemeParams,
WebPageSizeChangeParams,
SubscribeEventParams,
SubscribeEventResult,
UnsubscribeEventParams,
UnsubscribeEventResult,
PublishEventParams,
PublishEventResult,
} from '@ali/ding-ai-minutes-bridge'页面间通信完整示例
场景:两个 iframe 页面互相通信
使用 默认 namespace 'flash_minutes_bridge' 进行页面间通信:
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// ========== 页面 A(作为发布者)==========
async function initPublisher() {
AIMinutesBridge.init({ enableLog: true });
// 点击按钮发布事件(使用默认 namespace 'flash_minutes_bridge')
document.getElementById('sendBtn')?.addEventListener('click', async () => {
const result = await AIMinutesBridge.publishEvent(
'newMessage', // eventName
{
from: 'Page A',
text: 'Hello from Page A!',
timestamp: Date.now()
}
);
console.log(`消息已发送给 ${result.pushCount} 个接收者`);
});
// 页面卸载前清理
window.addEventListener('beforeunload', () => {
AIMinutesBridge.cleanup();
});
}
// ========== 页面 B(作为订阅者)==========
async function initSubscriber() {
AIMinutesBridge.init({ enableLog: true });
// 订阅消息事件(使用默认 namespace 'flash_minutes_bridge')
await AIMinutesBridge.subscribeEvent(
'newMessage', // eventName
(data) => {
console.log('收到来自 Page A 的消息:', data);
// 在页面上展示消息
displayMessage(data);
}
);
// 也可以同时发布自己的消息
document.getElementById('replyBtn')?.addEventListener('click', async () => {
await AIMinutesBridge.publishEvent(
'newMessage', // eventName
{
from: 'Page B',
text: 'Hi Page A!',
timestamp: Date.now()
}
);
});
// 页面卸载前清理
window.addEventListener('beforeunload', () => {
AIMinutesBridge.cleanup();
});
}使用自定义 namespace
如果需要使用自定义 namespace,可以传递第三个参数:
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// 使用自定义 namespace 发布事件
await AIMinutesBridge.publishEvent(
'syncData', // eventName
{ updated: true }, // data
'my_custom_app'
);
// 使用自定义 namespace 订阅事件
await AIMinutesBridge.subscribeEvent(
'syncData', // eventName
(data) => { // handler
console.log('收到同步数据:', data);
},
{
namespace: 'my_custom_app',
}
);缓存消息
如果需要缓存消息,即先 pub 消息,后 sub 消息,可以传递第三个参数:
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
// 使用 useCache 发布事件
await AIMinutesBridge.publishEvent(
'syncData', // eventName
{ updated: true }, // data
);
// 后订阅事件也能收到数据
await AIMinutesBridge.subscribeEvent(
'syncData', // eventName
(data) => { // handler
console.log('收到同步数据:', data);
},
{
useCache: true, // 使用缓存
}
);双向通信(一个页面既是发布者也是订阅者)
import AIMinutesBridge from '@ali/ding-ai-minutes-bridge'
async function initBidirectional() {
AIMinutesBridge.init({ enableLog: true });
// 订阅来自其他页面的消息(使用默认 namespace)
await AIMinutesBridge.subscribeEvent(
'syncData',
(data) => {
console.log('收到同步数据:', data);
updateUI(data);
}
);
// 当本地数据变化时,发布事件通知其他页面
document.getElementById('input')?.addEventListener('change', async (e) => {
await AIMinutesBridge.publishEvent(
'syncData',
{
field: 'input',
value: e.target.value,
source: 'page1'
}
);
});
}
## 注意事项
1. **iframe 环境**: 此 SDK 必须在 iframe 中运行,通过 `postMessage` 与父窗口通信
2. **默认 namespace**: `subscribeEvent` 和 `publishEvent` 默认使用 `'flash_minutes_bridge'` namespace,该 namespace 已加入宿主页面白名单,无需额外配置
3. **事件订阅/发布**: 订阅和发布的事件需要宿主页面(听记桌面端)支持
4. **权限控制**: 使用自定义 namespace 时,需要确保该 namespace 在宿主页面的白名单中
5. **资源清理**: 建议在页面卸载时调用 `cleanup()` 方法,避免内存泄漏
6. **发布者排除**: 发布事件时,发布者自身不会收到该事件的通知
7. **跨页面通信**: 通过 `publishEvent` 和 `subscribeEvent` 可以实现多个 iframe 页面之间的双向通信