@jiexiaoyin/wecom-api 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jiexiaoyin/wecom-api",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "企业微信 API OpenClaw 插件,提供 32+ API 模块和事件回调处理",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -1,10 +1,12 @@
1
1
  # WeCom API Skill
2
2
 
3
- 企业微信 API 调用技能,支持消息发送、客户管理、审批、会议、打卡、通讯录、素材等操作。
3
+ 企业微信 API 调用技能,支持客户管理、审批、会议、打卡、通讯录、素材等操作。
4
+
5
+ > 💡 注意:消息发送统一由 @sunnoy/wecom 通道处理,本技能不暴露发送消息相关动作。媒体上传下载也由 @sunnoy/wecom 统一处理。
4
6
 
5
7
  ## 触发方式
6
8
 
7
- 当用户提到企业微信相关操作时自动触发,如"发送消息"、"查询客户"、"创建会议"等。
9
+ 当用户提到企业微信相关操作时自动触发,如"查询客户"、"创建会议"、"查打卡记录"等。
8
10
 
9
11
  ## 参数说明
10
12
 
@@ -24,20 +26,6 @@
24
26
 
25
27
  ## 支持的动作
26
28
 
27
- ### 💬 消息发送
28
-
29
- | 动作 | 说明 |
30
- |------|------|
31
- | `send_message` | 发送文本消息(兼容旧名) |
32
- | `send_text` | 发送文本消息 |
33
- | `send_text_card` | 发送文本卡片 |
34
- | `send_markdown` | 发送 Markdown 消息 |
35
- | `send_template_card` | 发送模板卡片 |
36
- | `send_image` | 发送图片消息 |
37
- | `send_file` | 发送文件消息 |
38
- | `send_video` | 发送视频消息 |
39
- | `send_news` | 发送图文消息 |
40
-
41
29
  ### 👥 客户联系
42
30
 
43
31
  | 动作 | 说明 |
@@ -118,15 +106,6 @@
118
106
  | `delete_event` | 删除日程 |
119
107
  | `add_event_attendees` | 添加参与者 |
120
108
 
121
- ### 📁 素材
122
-
123
- | 动作 | 说明 |
124
- |------|------|
125
- | `upload_image` | 上传图片 |
126
- | `upload_media` | 上传媒体文件 |
127
- | `get_media` | 下载媒体文件 |
128
- | `get_high_definition_voice` | 获取高清语音 |
129
-
130
109
  ### 📱 应用
131
110
 
132
111
  | 动作 | 说明 |
@@ -152,7 +131,6 @@
152
131
  ## 使用示例
153
132
 
154
133
  ```
155
- 发送消息给张三,内容是测试
156
134
  查一下张三的客户列表
157
135
  查询昨天的打卡记录
158
136
  创建一个会议,主题是周会,时间是明天下午2点
@@ -161,4 +139,6 @@
161
139
  获取审批列表,3月1日到3月7日
162
140
  给李四添加客户备注
163
141
  查一下客户群列表
142
+ 获取假期余额
143
+ 查一下客户流失统计
164
144
  ```
@@ -234,34 +234,6 @@ async function executeAction(action, params) {
234
234
  try {
235
235
  switch (action) {
236
236
 
237
- // ========== 消息发送 ==========
238
- case 'send_message':
239
- return await wecom.message.sendText(args.userId, args.content, args.agentId);
240
-
241
- case 'send_text':
242
- return await wecom.message.sendText(args.toUser, args.content, args.agentId);
243
-
244
- case 'send_text_card':
245
- return await wecom.message.sendTextCard(args.toUser, args.title, args.content, args.agentId);
246
-
247
- case 'send_markdown':
248
- return await wecom.message.sendMarkdown(args.toUser, args.content, args.agentId);
249
-
250
- case 'send_template_card':
251
- return await wecom.message.sendTemplateCard(args.toUser, args.templateCard, args.agentId);
252
-
253
- case 'send_image':
254
- return await wecom.message.sendImage(args.toUser, args.mediaId, args.agentId);
255
-
256
- case 'send_file':
257
- return await wecom.message.sendFile(args.toUser, args.mediaId, args.agentId);
258
-
259
- case 'send_video':
260
- return await wecom.message.sendVideo(args.toUser, args.mediaId, args.agentId);
261
-
262
- case 'send_news':
263
- return await wecom.message.sendNews(args.toUser, args.articles, args.agentId);
264
-
265
237
  // ========== 客户联系 ==========
266
238
  case 'get_customer_list':
267
239
  return await wecom.contact.getCustomerList(args.userId, args.cursor);
@@ -451,19 +423,6 @@ async function executeAction(action, params) {
451
423
  case 'add_event_attendees':
452
424
  return await wecom.schedule.addEventAttendees(args.scheduleId, args.attendees);
453
425
 
454
- // ========== 素材 ==========
455
- case 'upload_image':
456
- return await wecom.media.uploadImage(args.filePath);
457
-
458
- case 'upload_media':
459
- return await wecom.media.uploadMedia(args.filePath, args.type);
460
-
461
- case 'get_media':
462
- return await wecom.media.getMedia(args.mediaId, args.savePath);
463
-
464
- case 'get_high_definition_voice':
465
- return await wecom.media.getHighDefinitionVoice(args.mediaId, args.savePath);
466
-
467
426
  // ========== 应用 ==========
468
427
  case 'get_agent_list':
469
428
  return await wecom.app.getAgentList();
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * 回调处理模块
3
3
  * 企业微信回调消息处理框架
4
- *
5
- * 功能:
4
+ *
5
+ * 功能:
6
6
  * 1. 统一回调入口 - 处理所有企业微信回调事件
7
7
  * 2. 事件记录 - 自动记录所有回调事件
8
8
  * 3. 事件分发 - 根据事件类型自动调用对应处理器
9
9
  * 4. 响应生成 - 自动生成响应消息
10
- *
11
- * 使用方式:
10
+ *
11
+ * 使用方式:
12
12
  * const callback = new Callback(config);
13
13
  * callback.on('change_contact', async (event) => { ... });
14
14
  * callback.handle(req, res);
@@ -27,31 +27,31 @@ class Callback extends EventEmitter {
27
27
  this.encodingAESKey = config.encodingAESKey || '';
28
28
  this.corpId = config.corpId || '';
29
29
  this.agentId = config.agentId || '';
30
-
30
+
31
31
  // 事件记录存储
32
32
  this.eventHistory = [];
33
33
  this.maxHistorySize = config.maxHistorySize || 1000;
34
-
34
+
35
35
  // 事件处理器映射
36
36
  this.handlers = {};
37
37
 
38
- // 审批模块(用于获取审批详情)
38
+ // 审批模块(用于获取审批详情)
39
39
  this.approval = new Approval(config);
40
-
40
+
41
41
  // 初始化默认处理器
42
42
  this._initDefaultHandlers();
43
-
43
+
44
44
  // 加载已有事件历史
45
45
  this.loadEventHistory();
46
46
  }
47
47
 
48
48
  // ========== 初始化默认处理器 ==========
49
-
49
+
50
50
  _initDefaultHandlers() {
51
51
  // 通讯录事件
52
52
  this.handlers['change_contact'] = 'handleContactChange';
53
53
  this.handlers['change_external_contact'] = 'handleExternalContactChange';
54
-
54
+
55
55
  // 客户联系事件
56
56
  this.handlers['add_external_contact'] = 'handleAddExternalContact';
57
57
  this.handlers['del_external_contact'] = 'handleDelExternalContact';
@@ -59,70 +59,58 @@ class Callback extends EventEmitter {
59
59
  this.handlers['add_half_external_contact'] = 'handleAddHalfExternalContact';
60
60
  this.handlers['del_follow_user'] = 'handleDelFollowUser';
61
61
  this.handlers['transfer_fail'] = 'handleTransferFail';
62
-
62
+
63
63
  // 客户群事件
64
64
  this.handlers['create_chat'] = 'handleCreateChat';
65
65
  this.handlers['update_chat'] = 'handleUpdateChat';
66
66
  this.handlers['dismiss_chat'] = 'handleDismissChat';
67
-
68
- // 消息事件
69
- this.handlers['user_click'] = 'handleUserClick';
70
- this.handlers['view'] = 'handleUserView';
71
- this.handlers['scancode_push'] = 'handleScanCodePush';
72
- this.handlers['scancode_waitmsg'] = 'handleScanCodeWaitMsg';
73
- this.handlers['pic_sysphoto'] = 'handlePicSysPhoto';
74
- this.handlers['pic_photo_or_album'] = 'handlePicPhotoOrAlbum';
75
- this.handlers['pic_weixin'] = 'handlePicWeixin';
76
- this.handlers['location_select'] = 'handleLocationSelect';
77
- this.handlers['enter_agent'] = 'handleEnterAgent';
78
- this.handlers['message'] = 'handleMessage';
79
-
67
+
80
68
  // 审批事件
81
69
  this.handlers['submit_approval'] = 'handleSubmitApproval';
82
70
  this.handlers['sys_approval_change'] = 'handleSysApprovalChange';
83
71
  this.handlers['Approval'] = 'handleApproval';
84
-
72
+
85
73
  // 打卡事件
86
74
  this.handlers['checkin'] = 'handleCheckin';
87
75
  this.handlers['report_checkin'] = 'handleReportCheckin';
88
-
76
+
89
77
  // 会议事件
90
78
  this.handlers['meeting_start'] = 'handleMeetingStart';
91
79
  this.handlers['meeting_end'] = 'handleMeetingEnd';
92
80
  this.handlers['meeting_created'] = 'handleMeetingCreated';
93
81
  this.handlers['meeting_cancelled'] = 'handleMeetingCancelled';
94
-
82
+
95
83
  // 回调验证事件
96
84
  this.handlers['url_verification'] = 'handleUrlVerification';
97
85
  this.handlers['callback_verification'] = 'handleCallbackVerification';
98
-
99
- // ========== 客户联系回调(新增)==========
86
+
87
+ // ========== 客户联系回调(新增)==========
100
88
  // 联系我相关
101
89
  this.handlers['add_contact_way'] = 'handleAddContactWay';
102
90
  this.handlers['del_contact_way'] = 'handleDelContactWay';
103
-
91
+
104
92
  // 入群方式相关
105
93
  this.handlers['add_join_way'] = 'handleAddJoinWay';
106
94
  this.handlers['del_join_way'] = 'handleDelJoinWay';
107
-
95
+
108
96
  // 客服消息相关
109
97
  this.handlers['kf_msg_push'] = 'handleKfMsgPush';
110
98
  this.handlers['kf_msg_send'] = 'handleKfMsgSend';
111
99
  this.handlers['msg_dialogice_send'] = 'handleMsgDialogiceSend';
112
-
113
- // ========== 通讯录变更回调(新增)==========
100
+
101
+ // ========== 通讯录变更回调(新增)==========
114
102
  this.handlers['change_member'] = 'handleChangeMember';
115
103
  this.handlers['change_department'] = 'handleChangeDepartment';
116
104
  this.handlers['change_tag'] = 'handleChangeTag';
117
-
118
- // ========== 会议回调(补充)==========
105
+
106
+ // ========== 会议回调(补充)==========
119
107
  this.handlers['meeting_ended'] = 'handleMeetingEnded';
120
108
  this.handlers['meetingParticipantJoin'] = 'handleMeetingParticipantJoin';
121
109
  this.handlers['meetingParticipantLeave'] = 'handleMeetingParticipantLeave';
122
-
110
+
123
111
  // ========== 直播回调 ==========
124
112
  this.handlers['living_status'] = 'handleLivingStatus';
125
-
113
+
126
114
  // ========== 微盘回调 ==========
127
115
  this.handlers['change_psm'] = 'handleChangePsm';
128
116
  this.handlers['change_disk'] = 'handleChangeDisk';
@@ -131,7 +119,7 @@ class Callback extends EventEmitter {
131
119
  // ========== 消息验证 ==========
132
120
 
133
121
  /**
134
- * 验证 URL(用于首次配置回调)
122
+ * 验证 URL(用于首次配置回调)
135
123
  * @param {string} msgSignature 签名
136
124
  * @param {string} timestamp 时间戳
137
125
  * @param {string} nonce 随机字符串
@@ -233,7 +221,7 @@ class Callback extends EventEmitter {
233
221
  const xml = await this.parseXML(xmlContent);
234
222
  console.log('[wecom-api] parseMessage xml keys:', Object.keys(xml));
235
223
  console.log('[wecom-api] parseMessage xml:', JSON.stringify(xml).substring(0, 500));
236
-
224
+
237
225
  const message = {
238
226
  ToUserName: xml.ToUserName,
239
227
  FromUserName: xml.FromUserName,
@@ -271,28 +259,28 @@ class Callback extends EventEmitter {
271
259
  // ========== 统一回调入口 ==========
272
260
 
273
261
  /**
274
- * 处理企业微信回调请求(统一入口)
262
+ * 处理企业微信回调请求(统一入口)
275
263
  * @param {object} params 请求参数
276
264
  * @param {string} params.msgSignature 签名
277
265
  * @param {string} params.timestamp 时间戳
278
266
  * @param {string} params.nonce 随机字符串
279
- * @param {string} params.echostr 加密字符串(验证URL时)
267
+ * @param {string} params.echostr 加密字符串(验证URL时)
280
268
  * @param {string} params.xmlBody XML请求体
281
269
  * @returns {Promise<object>} 处理结果
282
270
  */
283
271
  async handle(params) {
284
272
  const { msgSignature, timestamp, nonce, echostr, xmlBody } = params;
285
-
286
- // URL验证模式(首次配置回调)
273
+
274
+ // URL验证模式(首次配置回调)
287
275
  if (echostr) {
288
276
  return this._handleUrlVerification(msgSignature, timestamp, nonce, echostr);
289
277
  }
290
-
278
+
291
279
  // 消息处理模式
292
280
  if (xmlBody) {
293
281
  return this._handleMessage(msgSignature, timestamp, nonce, xmlBody);
294
282
  }
295
-
283
+
296
284
  throw new Error('缺少必要参数');
297
285
  }
298
286
 
@@ -301,7 +289,7 @@ class Callback extends EventEmitter {
301
289
  */
302
290
  async _handleUrlVerification(msgSignature, timestamp, nonce, echostr) {
303
291
  const result = this.verifyURL(msgSignature, timestamp, nonce, echostr);
304
-
292
+
305
293
  if (result.success) {
306
294
  // 记录事件
307
295
  this._recordEvent({
@@ -309,13 +297,13 @@ class Callback extends EventEmitter {
309
297
  success: true,
310
298
  timestamp: Date.now()
311
299
  });
312
-
300
+
313
301
  return {
314
302
  type: 'success',
315
303
  body: result.echostr
316
304
  };
317
305
  }
318
-
306
+
319
307
  return {
320
308
  type: 'error',
321
309
  message: result.message
@@ -324,28 +312,30 @@ class Callback extends EventEmitter {
324
312
 
325
313
  /**
326
314
  * 处理消息事件
315
+ * 注意:消息类事件(text/image/voice等)由 @sunnoy/wecom 统一处理
316
+ * 这里只处理事件类消息(有 Event 字段)
327
317
  */
328
318
  async _handleMessage(msgSignature, timestamp, nonce, xmlBody) {
329
- console.log('[wecom-api] _handleMessage called');
330
- console.log('[wecom-api] xmlBody preview:', xmlBody ? xmlBody.substring(0, 300) : 'missing');
331
319
  const xml = await this.parseXML(xmlBody);
332
- console.log('[wecom-api] parsed xml Encrypt length:', xml.Encrypt ? xml.Encrypt.length : 'null');
333
320
  const encrypt = xml.Encrypt;
334
-
321
+
335
322
  // 验证签名
336
- console.log('[wecom-api] 验证签名');
337
323
  if (!this.verifyMessage(msgSignature, timestamp, nonce, encrypt)) {
338
324
  throw new Error('签名验证失败');
339
325
  }
340
-
326
+
341
327
  // 解密消息
342
- console.log('[wecom-api] decrypting...');
343
328
  const decryptedXml = this.decrypt(encrypt);
344
329
  const message = await this.parseMessage(decryptedXml);
345
-
330
+
331
+ // 非事件消息(text/image/voice等)由 @sunnoy/wecom 处理,直接返回成功
332
+ if (!message.Event) {
333
+ return { type: 'success', body: 'success' };
334
+ }
335
+
346
336
  // 记录事件
347
337
  const eventRecord = this._recordEvent({
348
- type: message.Event || message.MsgType,
338
+ type: message.Event,
349
339
  msgType: message.MsgType,
350
340
  fromUserName: message.FromUserName,
351
341
  createTime: message.CreateTime,
@@ -355,22 +345,17 @@ class Callback extends EventEmitter {
355
345
  raw: message,
356
346
  timestamp: Date.now()
357
347
  });
358
-
348
+
359
349
  // 触发事件
360
- this.emit(message.Event || message.MsgType, message, eventRecord);
361
-
350
+ this.emit(message.Event, message, eventRecord);
351
+
362
352
  // 调用对应处理器
363
- const handlerName = this.handlers[message.Event || message.MsgType];
353
+ const handlerName = this.handlers[message.Event];
364
354
  if (handlerName && typeof this[handlerName] === 'function') {
365
355
  await this[handlerName](message, eventRecord);
366
356
  }
367
-
368
- // 返回成功响应
369
- return {
370
- type: 'success',
371
- body: 'success',
372
- message: message // 返回解析后的消息对象
373
- };
357
+
358
+ return { type: 'success', body: 'success', message };
374
359
  }
375
360
 
376
361
  // ========== 事件记录 ==========
@@ -385,21 +370,21 @@ class Callback extends EventEmitter {
385
370
  ...event,
386
371
  timestamp: event.timestamp || Date.now()
387
372
  };
388
-
373
+
389
374
  this.eventHistory.unshift(record);
390
-
375
+
391
376
  // 限制历史记录数量
392
377
  if (this.eventHistory.length > this.maxHistorySize) {
393
378
  this.eventHistory.pop();
394
379
  }
395
-
380
+
396
381
  // 根据类型分别保存到不同文件
397
382
  if (record.type === 'text' || record.msgType === 'text') {
398
383
  this._appendToFile('message_history.jsonl', record);
399
384
  } else {
400
385
  this._appendToFile('event_history.jsonl', record);
401
386
  }
402
-
387
+
403
388
  return record;
404
389
  }
405
390
 
@@ -412,13 +397,13 @@ class Callback extends EventEmitter {
412
397
  */
413
398
  getEventHistory(options = {}) {
414
399
  let { type, limit = 100, offset = 0 } = options;
415
-
400
+
416
401
  let history = this.eventHistory;
417
-
402
+
418
403
  if (type) {
419
404
  history = history.filter(e => e.type === type);
420
405
  }
421
-
406
+
422
407
  return history.slice(offset, offset + limit);
423
408
  }
424
409
 
@@ -469,8 +454,8 @@ class Callback extends EventEmitter {
469
454
  }
470
455
 
471
456
  /**
472
- * 加载事件历史(兼容旧数组格式 + 新增追加格式)
473
- * 文本消息从 message_history.jsonl 加载,事件从 event_history.jsonl 加载
457
+ * 加载事件历史(兼容旧数组格式 + 新增追加格式)
458
+ * 文本消息从 message_history.jsonl 加载,事件从 event_history.jsonl 加载
474
459
  */
475
460
  loadEventHistory() {
476
461
  try {
@@ -478,12 +463,12 @@ class Callback extends EventEmitter {
478
463
  const path = require('path');
479
464
  const dataDir = '/root/.openclaw/extensions/wecom-api/data';
480
465
  const records = [];
481
-
466
+
482
467
  const files = ['event_history.jsonl', 'message_history.jsonl'];
483
-
468
+
484
469
  for (const filename of files) {
485
470
  const filePath = path.join(dataDir, filename);
486
-
471
+
487
472
  if (!fs.existsSync(filePath)) {
488
473
  // 尝试旧格式数组文件
489
474
  const oldPath = path.join(dataDir, 'event_history.jsonl');
@@ -497,17 +482,17 @@ class Callback extends EventEmitter {
497
482
  }
498
483
  continue;
499
484
  }
500
-
485
+
501
486
  const raw = fs.readFileSync(filePath, 'utf8').trim();
502
487
  if (!raw) continue;
503
-
488
+
504
489
  const fileRecords = raw.split('\n')
505
490
  .filter(line => line.trim())
506
491
  .map(line => JSON.parse(line));
507
492
  records.push(...fileRecords);
508
493
  console.log('[wecom-api] 加载', filename, ':', fileRecords.length, '条');
509
494
  }
510
-
495
+
511
496
  // 按时间倒序
512
497
  records.sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));
513
498
  this.eventHistory = records.slice(0, this.maxHistorySize);
@@ -518,34 +503,34 @@ class Callback extends EventEmitter {
518
503
  }
519
504
 
520
505
  /**
521
- * 加载事件历史从文件(兼容旧数组格式 + 新追加格式)
506
+ * 加载事件历史从文件(兼容旧数组格式 + 新追加格式)
522
507
  */
523
508
  loadEventHistory() {
524
509
  try {
525
510
  const fs = require('fs');
526
511
  const path = require('path');
527
512
  const filePath = '/root/.openclaw/extensions/wecom-api/data/event_history.jsonl';
528
-
513
+
529
514
  if (!fs.existsSync(filePath)) {
530
515
  return;
531
516
  }
532
-
517
+
533
518
  const raw = fs.readFileSync(filePath, 'utf8').trim();
534
519
  if (!raw) {
535
520
  return;
536
521
  }
537
-
538
- // 兼容旧格式(JSON 数组)
522
+
523
+ // 兼容旧格式(JSON 数组)
539
524
  if (raw.startsWith('[')) {
540
525
  this.eventHistory = JSON.parse(raw);
541
526
  } else {
542
- // 新格式:每行一个 JSON 对象
527
+ // 新格式:每行一个 JSON 对象
543
528
  this.eventHistory = raw.split('\n')
544
529
  .filter(line => line.trim())
545
530
  .map(line => JSON.parse(line))
546
- .reverse(); // reverse 让最新的在前面(与 unshift 一致)
531
+ .reverse(); // reverse 让最新的在前面(与 unshift 一致)
547
532
  }
548
-
533
+
549
534
  console.log('[wecom-api] 已加载事件历史:', this.eventHistory.length, '条');
550
535
  } catch (e) {
551
536
  console.log('[wecom-api] 加载事件历史失败:', e.message);
@@ -558,7 +543,7 @@ class Callback extends EventEmitter {
558
543
  * 通讯录变更事件
559
544
  */
560
545
  /**
561
- * 通讯录变更事件(通用)
546
+ * 通讯录变更事件(通用)
562
547
  * 关键字段: ChangeType(1=新增 2=更新 3=删除), UserID, Name, Department
563
548
  */
564
549
  async handleContactChange(event, record) {
@@ -714,30 +699,8 @@ class Callback extends EventEmitter {
714
699
  /**
715
700
  * 用户点击菜单
716
701
  */
717
- async handleUserClick(event, record) {
718
- console.log('[Callback] 用户点击:', event);
719
- this.emit('menu:click', event, record);
720
- return { handled: true };
721
- }
722
-
723
- /**
724
- * 用户点击链接
725
- */
726
- async handleUserView(event, record) {
727
- console.log('[Callback] 用户点击链接:', event);
728
- return { handled: true };
729
- }
730
-
731
- /**
732
- * 扫码事件
733
- */
734
- async handleScanCodePush(event, record) {
735
- console.log('[Callback] 扫码:', event);
736
- return { handled: true };
737
- }
738
-
739
702
  /**
740
- * 审批事件(提交)
703
+ * 审批事件(提交)
741
704
  */
742
705
  /**
743
706
  * 审批提交事件
@@ -763,7 +726,7 @@ class Callback extends EventEmitter {
763
726
  }
764
727
 
765
728
  /**
766
- * 审批变更事件(官方 key: sys_approval_change
729
+ * 审批变更事件(官方 key: sys_approval_change)
767
730
  * 关键字段: ApprovalId, SpStatus, OpenSpid
768
731
  */
769
732
  async handleSysApprovalChange(event, record) {
@@ -781,7 +744,7 @@ class Callback extends EventEmitter {
781
744
  }
782
745
 
783
746
  /**
784
- * 审批通过/变更事件(兼容旧 key: Approval
747
+ * 审批通过/变更事件(兼容旧 key: Approval)
785
748
  */
786
749
  async handleApproval(event, record) {
787
750
  const approvalId = event.ApprovalId || event.approval_id || '';
@@ -829,7 +792,7 @@ class Callback extends EventEmitter {
829
792
  const spNoList = idListRes?.sp_no_list || [];
830
793
 
831
794
  if (spNoList.length === 0) {
832
- console.log('[Callback] 未找到审批单(' + trigger + '');
795
+ console.log('[Callback] 未找到审批单(' + trigger + ')');
833
796
  return;
834
797
  }
835
798
 
@@ -1038,7 +1001,7 @@ class Callback extends EventEmitter {
1038
1001
 
1039
1002
 
1040
1003
  /**
1041
- * 会议真正结束(历史记录生成后)
1004
+ * 会议真正结束(历史记录生成后)
1042
1005
  */
1043
1006
  async handleMeetingEnded(event, record) {
1044
1007
  console.log('[Callback] 会议结束(历史记录):', event);
@@ -1130,7 +1093,7 @@ class Callback extends EventEmitter {
1130
1093
  */
1131
1094
  _buildReply(toUser, fromUser, msgType, content) {
1132
1095
  let contentXml = '';
1133
-
1096
+
1134
1097
  switch (msgType) {
1135
1098
  case 'text':
1136
1099
  contentXml = `<Content><![CDATA[${content.content}]]></Content>`;