@yanhaidao/wecom 2.3.141 → 2.3.150
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/README.md +15 -110
- package/changelog/v2.3.15.md +15 -0
- package/docs/update-content-fix.md +135 -0
- package/package.json +1 -1
- package/src/agent/handler.ts +1 -1
- package/src/capability/doc/client.ts +239 -30
- package/src/capability/doc/schema.ts +25 -5
- package/src/capability/doc/tool.ts +246 -124
- package/src/capability/doc/types.ts +268 -0
- package/src/outbound.ts +12 -7
- package/src/runtime.ts +1 -0
- package/src/target.ts +37 -29
|
@@ -406,3 +406,271 @@ export interface GetDocContentResponse {
|
|
|
406
406
|
version: number;
|
|
407
407
|
document: Node;
|
|
408
408
|
}
|
|
409
|
+
|
|
410
|
+
// --- Collect Form (收集表) Types ---
|
|
411
|
+
|
|
412
|
+
export interface FormQuestionOption {
|
|
413
|
+
key: number; // 必填,选项 key 从 1 开始
|
|
414
|
+
value: string; // 必填,选项内容
|
|
415
|
+
status?: number; // 1 正常,2 删除
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export interface FormQuestion {
|
|
419
|
+
question_id: number; // 必填,问题 ID 从 1 开始(家校从 2 开始)
|
|
420
|
+
title: string; // 必填,问题标题
|
|
421
|
+
pos: number; // 必填,问题序号从 1 开始
|
|
422
|
+
status?: number; // 1 正常,2 删除
|
|
423
|
+
reply_type: number; // 必填,问题类型(1-22)
|
|
424
|
+
must_reply: boolean; // 必填,是否必答
|
|
425
|
+
note?: string; // 可选,备注
|
|
426
|
+
placeholder?: string; // 可选,输入提示
|
|
427
|
+
question_extend_setting?: FormQuestionExtendSetting; // 可选,题型扩展设置
|
|
428
|
+
option_item?: FormQuestionOption[]; // 单选/多选/下拉列表必填
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export interface FormQuestionExtendSetting {
|
|
432
|
+
// 文本(reply_type=1)
|
|
433
|
+
text_setting?: {
|
|
434
|
+
validation_type?: number; // 0 字符个数,1 数字,2 邮箱,3 网址,4 身份证,5 手机号,6 固定电话
|
|
435
|
+
validation_detail?: number; // 根据 validation_type 选择
|
|
436
|
+
char_len?: number; // 字符长度 ≤4000
|
|
437
|
+
number_min?: number; // 数字最小值
|
|
438
|
+
number_max?: number; // 数字最大值
|
|
439
|
+
};
|
|
440
|
+
// 单选(reply_type=2)
|
|
441
|
+
radio_setting?: {
|
|
442
|
+
add_other_option?: boolean; // 是否增加"其他"选项
|
|
443
|
+
};
|
|
444
|
+
// 多选(reply_type=3)
|
|
445
|
+
checkbox_setting?: {
|
|
446
|
+
add_other_option?: boolean; // 是否增加"其他"选项
|
|
447
|
+
type?: number; // 0 不限制,1 至少,2 最多,3 固定
|
|
448
|
+
number?: number; // 当 type=1/2/3 时必填
|
|
449
|
+
};
|
|
450
|
+
// 位置(reply_type=5)
|
|
451
|
+
location_setting?: {
|
|
452
|
+
location_type?: number; // 0 省市区街道 + 详细,1 省/市,2 省/市/区,3 省/市/区/街道,4 自动定位
|
|
453
|
+
distance_type?: number; // 0 当前,1 附近 100 米,2 附近 200 米,3 附近 300 米
|
|
454
|
+
};
|
|
455
|
+
// 图片(reply_type=9)
|
|
456
|
+
image_setting?: {
|
|
457
|
+
camera_only?: boolean; // 是否仅限手机拍照
|
|
458
|
+
upload_image_limit?: {
|
|
459
|
+
count_limit_type?: number; // 0 等于,1 小于等于
|
|
460
|
+
count?: number; // 1~9
|
|
461
|
+
max_size?: number; // MB,最大 3000
|
|
462
|
+
};
|
|
463
|
+
};
|
|
464
|
+
// 文件(reply_type=10)
|
|
465
|
+
file_setting?: {
|
|
466
|
+
upload_file_limit?: {
|
|
467
|
+
count_limit_type?: number;
|
|
468
|
+
count?: number;
|
|
469
|
+
max_size?: number;
|
|
470
|
+
};
|
|
471
|
+
};
|
|
472
|
+
// 日期(reply_type=11)
|
|
473
|
+
date_setting?: {
|
|
474
|
+
date_format_type?: number; // 0 年月日时分,1 年月日,2 年月
|
|
475
|
+
};
|
|
476
|
+
// 时间(reply_type=14)
|
|
477
|
+
time_setting?: {
|
|
478
|
+
time_format_type?: number; // 0 时分,1 时分秒
|
|
479
|
+
};
|
|
480
|
+
// 体温(reply_type=16)
|
|
481
|
+
temperature_setting?: {
|
|
482
|
+
unit_type?: number; // 0 摄氏度,1 华氏度
|
|
483
|
+
};
|
|
484
|
+
// 部门(reply_type=18)
|
|
485
|
+
department_setting?: {
|
|
486
|
+
allow_multiple_selection?: boolean; // 是否允许多选
|
|
487
|
+
};
|
|
488
|
+
// 成员(reply_type=19)
|
|
489
|
+
member_setting?: {
|
|
490
|
+
allow_multiple_selection?: boolean; // 是否允许多选
|
|
491
|
+
};
|
|
492
|
+
// 时长(reply_type=22)
|
|
493
|
+
duration_setting?: {
|
|
494
|
+
time_scale?: number; // 1 按天,2 按小时
|
|
495
|
+
date_type?: number; // 1 自然日,2 工作日
|
|
496
|
+
day_range?: number; // 1~24,默认 24
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
export interface FormSetting {
|
|
501
|
+
fill_out_auth?: number; // 0 所有人,1 指定人/部门,4 家校所有范围
|
|
502
|
+
fill_in_range?: { // 当 fill_out_auth=1 时必填
|
|
503
|
+
userids?: string[]; // 成员列表
|
|
504
|
+
departmentids?: number[]; // 部门列表
|
|
505
|
+
};
|
|
506
|
+
setting_manager_range?: { // 可选,管理员
|
|
507
|
+
userids?: string[];
|
|
508
|
+
};
|
|
509
|
+
timed_repeat_info?: { // 可选,定时重复设置
|
|
510
|
+
enable?: boolean; // 是否开启
|
|
511
|
+
remind_time?: number; // 提醒时间戳(秒)
|
|
512
|
+
repeat_type?: number; // 0 每周,1 每天,2 每月
|
|
513
|
+
week_flag?: number; // 每周几,bit 组合(周一至周日对应 bit0-6)
|
|
514
|
+
skip_holiday?: boolean; // 是否跳过节假日(repeat_type=1 有效)
|
|
515
|
+
day_of_month?: number; // 每月第几天(repeat_type=2 有效)
|
|
516
|
+
fork_finish_type?: number; // 补填:0 允许,1 仅当天,2 最后五天,3 一个月内,4 下一次生成前
|
|
517
|
+
};
|
|
518
|
+
allow_multi_fill?: boolean; // 是否允许多人提交多份
|
|
519
|
+
timed_finish?: number; // 定时关闭时间戳(秒,与定时重复互斥)
|
|
520
|
+
can_anonymous?: boolean; // 是否支持匿名
|
|
521
|
+
can_notify_submit?: boolean; // 是否有回复时提醒
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export interface FormInfo {
|
|
525
|
+
form_title: string; // 必填,收集表标题
|
|
526
|
+
form_desc?: string; // 可选,收集表描述
|
|
527
|
+
form_header?: string; // 可选,背景图链接
|
|
528
|
+
form_question: { // 必填,问题列表
|
|
529
|
+
items: FormQuestion[]; // 问题数组 ≤200
|
|
530
|
+
};
|
|
531
|
+
form_setting?: FormSetting; // 可选,收集表设置
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export interface CreateCollectRequest {
|
|
535
|
+
spaceid?: string; // 可选,空间 ID
|
|
536
|
+
fatherid?: string; // 可选,父目录 fileid
|
|
537
|
+
form_info: FormInfo; // 必填,收集表信息
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export interface CreateCollectResponse {
|
|
541
|
+
errcode: number;
|
|
542
|
+
errmsg: string;
|
|
543
|
+
formid: string;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// --- Spreadsheet (在线表格) Types ---
|
|
547
|
+
|
|
548
|
+
export interface SheetProperties {
|
|
549
|
+
sheet_id: string;
|
|
550
|
+
title: string;
|
|
551
|
+
row_count: number;
|
|
552
|
+
column_count: number;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
export interface GetSheetPropertiesResponse {
|
|
556
|
+
errcode: number;
|
|
557
|
+
errmsg: string;
|
|
558
|
+
properties: SheetProperties[];
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
export interface GridData {
|
|
562
|
+
start_row: number; // 起始行号(从 0 开始)
|
|
563
|
+
start_column: number; // 起始列号(从 0 开始)
|
|
564
|
+
rows: RowData[]; // 行数据列表
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export interface RowData {
|
|
568
|
+
values: CellData[]; // 该行各列单元格数据
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
export interface CellData {
|
|
572
|
+
cell_value?: CellValue; // 单元格数据内容(可选)
|
|
573
|
+
cell_format?: CellFormat; // 单元格样式(可选)
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export interface CellValue {
|
|
577
|
+
text?: string; // 纯文本
|
|
578
|
+
link?: Link; // 超链接(与 text 互斥)
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
export interface Link {
|
|
582
|
+
url: string; // 链接地址
|
|
583
|
+
text: string; // 链接显示文本
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
export interface CellFormat {
|
|
587
|
+
text_format?: TextFormat; // 文字样式
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
export interface TextFormat {
|
|
591
|
+
font?: string; // 字体名称(如 "Microsoft YaHei")
|
|
592
|
+
font_size?: number; // 字号,最大 72
|
|
593
|
+
bold?: boolean;
|
|
594
|
+
italic?: boolean;
|
|
595
|
+
strikethrough?: boolean;
|
|
596
|
+
underline?: boolean;
|
|
597
|
+
color?: Color; // 文字颜色(RGBA)
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export interface Color {
|
|
601
|
+
red: number; // 0~255
|
|
602
|
+
green: number; // 0~255
|
|
603
|
+
blue: number; // 0~255
|
|
604
|
+
alpha?: number; // 0~255,默认 255(不透明),可选
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export enum Dimension {
|
|
608
|
+
ROW = "ROW", // 行
|
|
609
|
+
COLUMN = "COLUMN" // 列
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Batch Update Requests
|
|
613
|
+
export interface AddSheetRequest {
|
|
614
|
+
add_sheet_request: {
|
|
615
|
+
title: string;
|
|
616
|
+
row_count?: number;
|
|
617
|
+
column_count?: number;
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
export interface DeleteSheetRequest {
|
|
622
|
+
delete_sheet_request: {
|
|
623
|
+
sheet_id: string;
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
export interface UpdateRangeRequest {
|
|
628
|
+
update_range_request: {
|
|
629
|
+
sheet_id: string;
|
|
630
|
+
grid_data: GridData;
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
export interface DeleteDimensionRequest {
|
|
635
|
+
delete_dimension_request: {
|
|
636
|
+
sheet_id: string;
|
|
637
|
+
dimension: Dimension;
|
|
638
|
+
start_index: number; // 从 1 开始
|
|
639
|
+
end_index: number; // 从 1 开始,不包含
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
export type SpreadsheetUpdateRequest =
|
|
644
|
+
| AddSheetRequest
|
|
645
|
+
| DeleteSheetRequest
|
|
646
|
+
| UpdateRangeRequest
|
|
647
|
+
| DeleteDimensionRequest;
|
|
648
|
+
|
|
649
|
+
export interface SpreadsheetBatchUpdateResponse {
|
|
650
|
+
errcode: number;
|
|
651
|
+
errmsg: string;
|
|
652
|
+
data?: {
|
|
653
|
+
responses: Array<{
|
|
654
|
+
add_sheet_response?: {
|
|
655
|
+
properties: SheetProperties;
|
|
656
|
+
};
|
|
657
|
+
delete_sheet_response?: {
|
|
658
|
+
sheet_id: string;
|
|
659
|
+
};
|
|
660
|
+
update_range_response?: {
|
|
661
|
+
updated_cells: number;
|
|
662
|
+
};
|
|
663
|
+
delete_dimension_response?: {
|
|
664
|
+
deleted: number;
|
|
665
|
+
};
|
|
666
|
+
}>;
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export interface GetSheetRangeDataResponse {
|
|
671
|
+
errcode: number;
|
|
672
|
+
errmsg: string;
|
|
673
|
+
data: {
|
|
674
|
+
result: GridData;
|
|
675
|
+
};
|
|
676
|
+
}
|
package/src/outbound.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ChannelOutboundAdapter, ChannelOutboundContext } from "openclaw/pl
|
|
|
2
2
|
|
|
3
3
|
import { resolveWecomAccount, resolveWecomAccountConflict, resolveWecomAccounts } from "./config/index.js";
|
|
4
4
|
import { WecomAgentDeliveryService } from "./capability/agent/index.js";
|
|
5
|
-
import { getBotWsPushHandle, getWecomRuntime } from "./runtime.js";
|
|
5
|
+
import { getAccountRuntime, getBotWsPushHandle, getWecomRuntime } from "./runtime.js";
|
|
6
6
|
import { resolveScopedWecomTarget } from "./target.js";
|
|
7
7
|
|
|
8
8
|
function resolveOutboundAccountOrThrow(params: {
|
|
@@ -141,6 +141,8 @@ export const wecomOutbound: ChannelOutboundAdapter = {
|
|
|
141
141
|
},
|
|
142
142
|
sendText: async ({ cfg, to, text, accountId }: ChannelOutboundContext) => {
|
|
143
143
|
// signal removed - not supported in current SDK
|
|
144
|
+
// Defer Agent resolution until the Agent fallback path
|
|
145
|
+
// sendTextViaBotWs() can already deliver without Agent mode
|
|
144
146
|
|
|
145
147
|
// 体验优化:/new /reset 的“New session started”回执在 OpenClaw 核心里是英文固定文案,
|
|
146
148
|
// 且通过 routeReply 走 wecom outbound(Agent 主动发送)。
|
|
@@ -158,7 +160,7 @@ export const wecomOutbound: ChannelOutboundAdapter = {
|
|
|
158
160
|
|
|
159
161
|
if (looksLikeNewSessionAck) {
|
|
160
162
|
if (!isAgentSessionTarget) {
|
|
161
|
-
|
|
163
|
+
// Suppress ack without agent resolution
|
|
162
164
|
return { channel: "wecom", messageId: `suppressed-${Date.now()}`, timestamp: Date.now() };
|
|
163
165
|
}
|
|
164
166
|
|
|
@@ -167,13 +169,12 @@ export const wecomOutbound: ChannelOutboundAdapter = {
|
|
|
167
169
|
return m?.[1]?.trim();
|
|
168
170
|
})();
|
|
169
171
|
const rewritten = modelLabel ? `✅ 已开启新会话(模型:${modelLabel})` : "✅ 已开启新会话。";
|
|
170
|
-
getAccountRuntime(agent.accountId)?.log.info?.(`[wecom-outbound] Rewrote command ack for agent session (len=${rewritten.length})`);
|
|
171
172
|
outgoingText = rewritten;
|
|
172
173
|
}
|
|
173
174
|
|
|
174
|
-
getAccountRuntime(agent.accountId)?.log.info?.(`[wecom-outbound] Sending text to target=${String(to ?? "")} (len=${outgoingText.length})`);
|
|
175
|
-
|
|
176
175
|
let sentViaBotWs = false;
|
|
176
|
+
let agent: any = null;
|
|
177
|
+
|
|
177
178
|
try {
|
|
178
179
|
sentViaBotWs = await sendTextViaBotWs({
|
|
179
180
|
cfg,
|
|
@@ -182,7 +183,9 @@ export const wecomOutbound: ChannelOutboundAdapter = {
|
|
|
182
183
|
text: outgoingText,
|
|
183
184
|
});
|
|
184
185
|
if (!sentViaBotWs) {
|
|
185
|
-
|
|
186
|
+
// Defer Agent resolution until needed for fallback
|
|
187
|
+
agent = resolveAgentConfigOrThrow({ cfg, accountId });
|
|
188
|
+
getAccountRuntime(agent.accountId)?.log.info?.(`[wecom-outbound] Sending text to target=${String(to ?? "")} (len=${outgoingText.length})`);
|
|
186
189
|
const deliveryService = new WecomAgentDeliveryService(agent);
|
|
187
190
|
await deliveryService.sendText({
|
|
188
191
|
to,
|
|
@@ -191,7 +194,9 @@ export const wecomOutbound: ChannelOutboundAdapter = {
|
|
|
191
194
|
console.log(`[wecom-outbound] Successfully sent Agent text to ${String(to ?? "")}`);
|
|
192
195
|
}
|
|
193
196
|
} catch (err) {
|
|
194
|
-
|
|
197
|
+
if (agent) {
|
|
198
|
+
getAccountRuntime(agent.accountId)?.log.error?.(`[wecom-outbound] Failed to send text to ${String(to ?? "")}: ${err instanceof Error ? err.message : String(err)}`);
|
|
199
|
+
}
|
|
195
200
|
throw err;
|
|
196
201
|
}
|
|
197
202
|
|
package/src/runtime.ts
CHANGED
package/src/target.ts
CHANGED
|
@@ -31,42 +31,54 @@ export interface ScopedWecomTarget {
|
|
|
31
31
|
* 解析原始目标字符串为 WeComTarget 对象。
|
|
32
32
|
*
|
|
33
33
|
* 逻辑:
|
|
34
|
-
* 1.
|
|
35
|
-
* 2.
|
|
36
|
-
* 3.
|
|
34
|
+
* 1. 先检查显式类型前缀 (user:, group:, party:, tag:) —— 优先匹配,不受命名空间前缀影响
|
|
35
|
+
* 2. 移除标准命名空间前缀 (wecom:, qywx: 等)
|
|
36
|
+
* 3. 再次检查类型前缀(处理 wecom:user:xxx 格式)
|
|
37
|
+
* 4. 启发式回退 (无前缀时):
|
|
37
38
|
* - 以 "wr" 或 "wc" 开头 -> Chat ID (群聊)
|
|
38
|
-
* - 纯数字 -> 默认
|
|
39
|
+
* - 纯数字 -> 默认 User ID (用户),避免误判部门导致 81013 错误
|
|
39
40
|
* - 其他 -> User ID (用户)
|
|
40
41
|
*
|
|
41
|
-
* @param raw - The raw target string (e.g. "party:1", "zhangsan", "wecom:
|
|
42
|
+
* @param raw - The raw target string (e.g. "party:1", "zhangsan", "wecom:user:0404777")
|
|
42
43
|
*/
|
|
43
44
|
export function resolveWecomTarget(raw: string | undefined, options?: { preferUserForDigits?: boolean }): WecomTarget | undefined {
|
|
44
45
|
if (!raw?.trim()) return undefined;
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
let clean = raw.trim().replace(/^(wecom-agent|wecom|wechatwork|wework|qywx):/i, "");
|
|
47
|
+
const trimmed = raw.trim();
|
|
48
48
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (/^dept:/i.test(clean)) {
|
|
54
|
-
return { toparty: clean.replace(/^dept:/i, "").trim() };
|
|
49
|
+
// 1. 先检查原始字符串中的类型前缀(处理 user:0404777 无前缀格式)
|
|
50
|
+
// 这样即使没有 wecom: 前缀,也能正确识别类型
|
|
51
|
+
if (/^user:/i.test(trimmed)) {
|
|
52
|
+
return { touser: trimmed.replace(/^user:/i, "").trim() };
|
|
55
53
|
}
|
|
56
|
-
if (/^
|
|
57
|
-
return {
|
|
54
|
+
if (/^group:/i.test(trimmed) || /^chat:/i.test(trimmed)) {
|
|
55
|
+
return { chatid: trimmed.replace(/^(group:|chat:)/i, "").trim() };
|
|
58
56
|
}
|
|
59
|
-
if (/^
|
|
60
|
-
return {
|
|
57
|
+
if (/^party:/i.test(trimmed) || /^dept:/i.test(trimmed)) {
|
|
58
|
+
return { toparty: trimmed.replace(/^(party:|dept:)/i, "").trim() };
|
|
61
59
|
}
|
|
62
|
-
if (/^
|
|
63
|
-
return {
|
|
60
|
+
if (/^tag:/i.test(trimmed)) {
|
|
61
|
+
return { totag: trimmed.replace(/^tag:/i, "").trim() };
|
|
64
62
|
}
|
|
63
|
+
|
|
64
|
+
// 2. Remove standard namespace prefixes (移除标准命名空间前缀)
|
|
65
|
+
let clean = trimmed.replace(/^(wecom-agent|wecom|wechatwork|wework|qywx):/i, "");
|
|
66
|
+
|
|
67
|
+
// 3. 再次检查类型前缀(处理 wecom:user:0404777 格式)
|
|
65
68
|
if (/^user:/i.test(clean)) {
|
|
66
69
|
return { touser: clean.replace(/^user:/i, "").trim() };
|
|
67
70
|
}
|
|
71
|
+
if (/^group:/i.test(clean) || /^chat:/i.test(clean)) {
|
|
72
|
+
return { chatid: clean.replace(/^(group:|chat:)/i, "").trim() };
|
|
73
|
+
}
|
|
74
|
+
if (/^party:/i.test(clean) || /^dept:/i.test(clean)) {
|
|
75
|
+
return { toparty: clean.replace(/^(party:|dept:)/i, "").trim() };
|
|
76
|
+
}
|
|
77
|
+
if (/^tag:/i.test(clean)) {
|
|
78
|
+
return { totag: clean.replace(/^tag:/i, "").trim() };
|
|
79
|
+
}
|
|
68
80
|
|
|
69
|
-
//
|
|
81
|
+
// 4. Heuristics (启发式规则)
|
|
70
82
|
|
|
71
83
|
// Chat ID typically starts with 'wr' or 'wc'
|
|
72
84
|
// 群聊 ID 通常以 'wr' (外部群) 或 'wc' 开头
|
|
@@ -74,20 +86,16 @@ export function resolveWecomTarget(raw: string | undefined, options?: { preferUs
|
|
|
74
86
|
return { chatid: clean };
|
|
75
87
|
}
|
|
76
88
|
|
|
77
|
-
// Pure digits
|
|
78
|
-
//
|
|
79
|
-
//
|
|
89
|
+
// Pure digits: Default to Party (纯数字默认为部门)
|
|
90
|
+
// 原因:1) 定时任务可能直接配置 to: "1" 发送给根部门
|
|
91
|
+
// 2) 企业微信官方文档示例使用纯数字表示部门
|
|
92
|
+
// 3) 用户 ID 应该使用显式前缀 "user:xxx"
|
|
93
|
+
// 如果需要发送给用户,请使用 "user:0404777" 格式
|
|
80
94
|
if (/^\d+$/.test(clean)) {
|
|
81
|
-
if (options?.preferUserForDigits) {
|
|
82
|
-
return { touser: clean };
|
|
83
|
-
}
|
|
84
95
|
return { toparty: clean };
|
|
85
96
|
}
|
|
86
97
|
|
|
87
98
|
// Default to User (默认为用户)
|
|
88
|
-
// 注意:纯数字通常可能是 UserID (内部成员 ID),也可能是 PartyID。
|
|
89
|
-
// 为了兼容性,如果没有前缀且不匹配群聊规则,我们将其视为 UserID。
|
|
90
|
-
// 如果需要明确发送给部门,请使用 "party:1" 前缀。
|
|
91
99
|
return { touser: clean };
|
|
92
100
|
}
|
|
93
101
|
|