@peninsula-med/beisen-ehr-plugin 1.1.9 → 2.0.0

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 CHANGED
@@ -1,152 +1,36 @@
1
- # 北森 EHR OpenClaw 插件 🐉
1
+ # 北森 EHR OpenClaw 插件 v2.0.0 🐉
2
2
 
3
- 北森 EHR 系统集成插件,支持加班申请、考勤查询、假期余额等功能。
3
+ 完全重写的北森 EHR 插件,移除所有 MCP 依赖。
4
4
 
5
- ## 快速开始
6
-
7
- ### 方式一:一键安装(推荐)
5
+ ## 一键安装
8
6
 
9
7
  ```bash
10
- # 安装插件(自动配置工具 allowlist)
8
+ # 1. 安装插件(自动配置 allowlist)
11
9
  openclaw plugins install @peninsula-med/beisen-ehr-plugin@latest
12
10
 
13
- # 配置凭证(交互式输入)
14
- npx @peninsula-med/beisen-ehr-configure
15
-
16
- # 重启 Gateway
17
- openclaw gateway restart
18
- ```
19
-
20
- ✅ 安装时会自动配置工具 allowlist,无需手动编辑配置文件!
21
-
22
- ```bash
23
- # 1. 安装插件
24
- openclaw plugins install @peninsula-med/beisen-ehr-plugin
25
-
26
- # 2. 运行配置向导(交互式输入凭证)
11
+ # 2. 配置凭证
27
12
  npx @peninsula-med/beisen-ehr-configure
28
13
 
29
- # 3. 重启 Gateway
30
- openclaw gateway restart
31
- ```
32
-
33
- ### 方式二:一键安装 + 配置(适合脚本化)
34
-
35
- ```bash
36
- openclaw plugins install @peninsula-med/beisen-ehr-plugin && \
37
- npx @peninsula-med/beisen-ehr-configure && \
14
+ # 3. 重启
38
15
  openclaw gateway restart
39
16
  ```
40
17
 
41
- ### 方式三:手动配置
42
-
43
- ```bash
44
- # 1. 安装插件
45
- openclaw plugins install @peninsula-med/beisen-ehr-plugin
18
+ ## 测试
46
19
 
47
- # 2. 编辑配置文件(~/.openclaw/config.json)
48
20
  ```
49
-
50
- 在配置文件中添加:
51
-
52
- ```json5
53
- {
54
- plugins: {
55
- entries: {
56
- "beisen-ehr-plugin": {
57
- enabled: true,
58
- config: {
59
- apiUrl: "https://openapi.italent.cn", // 可选,默认就是这个
60
- appKey: "your-app-key",
61
- appSecret: "your-app-secret",
62
- staffId: "your-staff-id",
63
- tenantId: "your-tenant-id",
64
- email: "your-email@company.com"
65
- }
66
- }
67
- }
68
- }
69
- }
21
+ 帮我查一下假期余额
70
22
  ```
71
23
 
72
- 然后重启:
24
+ ## 调试
73
25
 
26
+ 查看日志:
74
27
  ```bash
75
- openclaw gateway restart
28
+ openclaw gateway logs
76
29
  ```
77
30
 
78
- ## 配置说明
79
-
80
- | 字段 | 说明 | 必填 |
81
- |------|------|------|
82
- | `apiUrl` | 北森 API 地址 | 否(默认 `https://openapi.italent.cn`) |
83
- | `appKey` | App Key(从北森管理员获取) | 是 |
84
- | `appSecret` | App Secret(从北森管理员获取) | 是 |
85
- | `staffId` | 员工 ID | 是 |
86
- | `tenantId` | 企业租户 ID | 是 |
87
- | `email` | 企业邮箱 | 是 |
88
-
89
- ## 可用工具
90
-
91
- 插件提供以下工具供 AI 调用:
92
-
93
- 1. **beisen_submit_overtime** - 提交加班申请
94
- 2. **beisen_get_leave_balance** - 查询假期余额
95
- 3. **beisen_query_attendance** - 查询考勤记录
96
- 4. **beisen_get_approval_status** - 查询审批状态
97
-
98
- ## 配置向导
99
-
100
- 独立的配置工具,支持交互式输入凭证:
101
-
102
- ```bash
103
- npx @peninsula-med/beisen-ehr-configure
104
- ```
105
-
106
- 功能:
107
- - 🎯 交互式引导配置
108
- - 🔐 安全保存凭证到 OpenClaw 配置文件
109
- - ✅ 自动验证配置
110
- - 💾 自动备份旧配置
111
-
112
- ## 开发
113
-
114
- ### 本地开发
115
-
116
- ```bash
117
- # 安装依赖
118
- pnpm install
119
-
120
- # 开发模式(监听变化自动构建)
121
- pnpm dev
122
-
123
- # 生产构建
124
- pnpm build
125
-
126
- # 发布到 npm
127
- pnpm publish:release
128
- ```
129
-
130
- ### 本地测试
131
-
132
- 使用 `--link` 安装本地插件:
133
-
134
- ```bash
135
- openclaw plugins install -l /path/to/beisen-ehr-plugin
136
- ```
137
-
138
- ## 注意事项
139
-
140
- - 凭证信息需要联系北森管理员获取
141
- - Token 会自动管理,有效期 2 小时,自动刷新
142
- - 所有 API 请求都会记录到 Gateway 日志中
143
-
144
- ## 技术支持
145
-
146
- 遇到问题?联系龙二 🐉
31
+ 应该看到 `[BEISEN]` 开头的日志。
147
32
 
148
33
  ---
149
34
 
150
- **版本**: 1.1.0
151
- **作者**: 龙二 🐉
152
- **License**: MIT
35
+ **版本**: 2.0.0
36
+ **作者**: 龙二 🐉
package/dist/index.cjs.js CHANGED
@@ -3454,17 +3454,13 @@ var TypeBuilder = /*#__PURE__*/Object.freeze({
3454
3454
  const Type = TypeBuilder;
3455
3455
 
3456
3456
  /**
3457
- * 北森 EHR OpenClaw Plugin
3457
+ * 北森 EHR OpenClaw Plugin v2.0.0
3458
3458
  * 🐉 龙二 开发
3459
3459
  *
3460
- * 功能:加班申请、考勤查询、假期余额、审批状态查询
3460
+ * 完全移除 MCP 依赖,直接注册工具
3461
3461
  */
3462
- // 插件元数据
3463
3462
  const pluginId = 'beisen-ehr-plugin';
3464
- const pluginVersion = '1.1.9';
3465
- /**
3466
- * 默认配置
3467
- */
3463
+ const pluginVersion = '2.0.0';
3468
3464
  const defaultConfig = {
3469
3465
  apiUrl: 'https://openapi.italent.cn',
3470
3466
  };
@@ -3472,17 +3468,14 @@ const defaultConfig = {
3472
3468
  let cachedToken = null;
3473
3469
  let tokenExpiry = 0;
3474
3470
  async function getAccessToken(config) {
3475
- // 如果已有有效 Token,直接返回
3476
3471
  if (cachedToken && Date.now() < tokenExpiry) {
3477
3472
  return cachedToken;
3478
3473
  }
3479
- // 使用 AppKey + AppSecret 获取新 Token(北森官方格式)
3480
3474
  const tokenUrl = `${config.apiUrl || defaultConfig.apiUrl}/token`;
3475
+ console.error(`[BEISEN] 🔑 正在获取 Token: ${tokenUrl}`);
3481
3476
  const response = await fetch(tokenUrl, {
3482
3477
  method: "POST",
3483
- headers: {
3484
- "Content-Type": "application/json",
3485
- },
3478
+ headers: { "Content-Type": "application/json" },
3486
3479
  body: JSON.stringify({
3487
3480
  grant_type: "client_credentials",
3488
3481
  app_key: config.appKey,
@@ -3495,12 +3488,11 @@ async function getAccessToken(config) {
3495
3488
  }
3496
3489
  const data = await response.json();
3497
3490
  cachedToken = data.accessToken || data.access_token;
3498
- // Token 有效期通常 2 小时,提前 5 分钟刷新
3499
3491
  tokenExpiry = Date.now() + (data.expiresIn || data.expires_in || 7200) * 1000 - 5 * 60 * 1000;
3500
- console.error(`🔑 已获取新 Token,有效期至:${new Date(tokenExpiry).toISOString()}`);
3492
+ console.error(`[BEISEN] Token 获取成功,有效期至:${new Date(tokenExpiry).toISOString()}`);
3501
3493
  return cachedToken;
3502
3494
  }
3503
- // ============ 北森 API 客户端 ============
3495
+ // ============ API 客户端 ============
3504
3496
  class BeisenClient {
3505
3497
  constructor(config) {
3506
3498
  this.config = config;
@@ -3515,14 +3507,14 @@ class BeisenClient {
3515
3507
  ...(options.headers || {}),
3516
3508
  };
3517
3509
  const requestBody = options.body ? JSON.stringify(options.body) : undefined;
3518
- console.error(`📡 请求:${options.method || 'GET'} ${url}`);
3519
- console.error(`🔑 Token: ${token ? token.substring(0, 20) + '...' : 'none'}`);
3520
- console.error(`🏢 TenantId: ${this.config.tenantId}`);
3510
+ console.error(`[BEISEN] 📡 ${options.method || 'GET'} ${url}`);
3511
+ console.error(`[BEISEN] 🔑 Token: ${token.substring(0, 20)}...`);
3512
+ console.error(`[BEISEN] 🏢 TenantId: ${this.config.tenantId}`);
3521
3513
  if (requestBody) {
3522
- console.error(`📦 请求体:${requestBody.substring(0, 200)}...`);
3514
+ console.error(`[BEISEN] 📦 Body: ${requestBody.substring(0, 200)}`);
3523
3515
  }
3524
3516
  const controller = new AbortController();
3525
- const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 秒超时
3517
+ const timeoutId = setTimeout(() => controller.abort(), 30000);
3526
3518
  try {
3527
3519
  const response = await fetch(url, {
3528
3520
  ...options,
@@ -3533,19 +3525,21 @@ class BeisenClient {
3533
3525
  clearTimeout(timeoutId);
3534
3526
  if (!response.ok) {
3535
3527
  const errorText = await response.text();
3536
- throw new Error(`北森 API 错误:${response.status} - ${errorText}`);
3528
+ throw new Error(`API 错误:${response.status} - ${errorText}`);
3537
3529
  }
3538
- return response.json();
3530
+ const result = await response.json();
3531
+ console.error(`[BEISEN] ✅ 响应:`, JSON.stringify(result).substring(0, 200));
3532
+ return result;
3539
3533
  }
3540
3534
  catch (error) {
3541
3535
  clearTimeout(timeoutId);
3542
3536
  if (error.name === 'AbortError') {
3543
- throw new Error('北森 API 请求超时(30 秒)');
3537
+ throw new Error('请求超时(30 秒)');
3544
3538
  }
3539
+ console.error(`[BEISEN] ❌ 错误:`, error.message);
3545
3540
  throw error;
3546
3541
  }
3547
3542
  }
3548
- // 提交加班申请(推送至北森系统并发起审批)
3549
3543
  async submitOvertime(data) {
3550
3544
  const overtimeData = {
3551
3545
  staffId: data.staffId,
@@ -3557,91 +3551,56 @@ class BeisenClient {
3557
3551
  if (data.properties) {
3558
3552
  overtimeData.properties = typeof data.properties === 'string' ? data.properties : JSON.stringify(data.properties);
3559
3553
  }
3560
- const payload = {
3561
- attendance_overTime: overtimeData,
3562
- };
3563
3554
  return this.request("/AttendanceOpen/api/v1/AttendanceOvertime/PostOverTimeWithApproval", {
3564
3555
  method: "POST",
3565
- body: payload,
3556
+ body: { attendance_overTime: overtimeData },
3566
3557
  });
3567
3558
  }
3568
- // 查询假期余额
3569
3559
  async getLeaveBalance(staffId, email) {
3570
3560
  return this.request("/AttendanceOpen/api/v1/LeaveBalance/QueryLeaveBalance", {
3571
3561
  method: "POST",
3572
3562
  body: { staffId, email },
3573
3563
  });
3574
3564
  }
3575
- // 查询考勤记录
3576
3565
  async getAttendanceRecords(startDate, endDate, employeeId) {
3577
3566
  return this.request("/api/v1/attendance/records", {
3578
3567
  method: "POST",
3579
3568
  body: { startDate, endDate, employeeId },
3580
3569
  });
3581
3570
  }
3582
- // 查询审批状态
3583
3571
  async getApprovalStatus(applicationId) {
3584
3572
  return this.request(`/api/v1/approval/${applicationId}/status`);
3585
3573
  }
3586
3574
  }
3587
- /**
3588
- * 插件注册函数
3589
- */
3575
+ // ============ 插件注册 ============
3590
3576
  async function register(api) {
3591
- console.error(`🏢 北森 EHR 插件已加载 v${pluginVersion}`);
3592
- // 获取插件配置
3577
+ console.error(`[BEISEN] 🏢 北森 EHR 插件 v${pluginVersion} 正在加载...`);
3593
3578
  const config = api.config?.plugins?.entries?.['beisen-ehr-plugin']?.config;
3594
- if (!config) {
3595
- console.error('⚠️ 插件已安装,但未配置凭证');
3596
- console.error('');
3597
- console.error('📝 请在 OpenClaw 配置中添加:');
3598
- console.error('');
3599
- console.error(' plugins: {');
3600
- console.error(' entries: {');
3601
- console.error(' "beisen-ehr-plugin": {');
3602
- console.error(' enabled: true,');
3603
- console.error(' config: {');
3604
- console.error(' appKey: "your-app-key",');
3605
- console.error(' appSecret: "your-app-secret",');
3606
- console.error(' staffId: "your-staff-id",');
3607
- console.error(' tenantId: "your-tenant-id",');
3608
- console.error(' email: "your-email@company.com"');
3609
- console.error(' }');
3610
- console.error(' }');
3611
- console.error(' }');
3612
- console.error(' }');
3613
- console.error('');
3614
- return;
3615
- }
3616
- // 验证必要配置
3617
- const requiredFields = ['appKey', 'appSecret', 'staffId', 'tenantId', 'email'];
3618
- const missingFields = requiredFields.filter(field => !config[field]);
3619
- if (missingFields.length > 0) {
3620
- console.error(`❌ 缺少必要配置:${missingFields.join(', ')}`);
3621
- console.error('请补充完整配置后重启 Gateway');
3579
+ if (!config || !config.appKey || !config.appSecret || !config.staffId || !config.tenantId || !config.email) {
3580
+ console.error('[BEISEN] ⚠️ 插件已安装,但未配置凭证');
3581
+ console.error('[BEISEN] 📝 请运行:npx @peninsula-med/beisen-ehr-configure');
3622
3582
  return;
3623
3583
  }
3624
- console.error('✅ 北森 EHR 配置验证通过');
3625
- console.error(`📡 API: ${config.apiUrl || defaultConfig.apiUrl}`);
3626
- console.error(`👤 员工:${config.staffId}`);
3627
- console.error(`🏢 企业:${config.tenantId}`);
3628
- // 创建 API 客户端
3584
+ console.error('[BEISEN] ✅ 配置验证通过');
3585
+ console.error(`[BEISEN] 📡 API: ${config.apiUrl || defaultConfig.apiUrl}`);
3586
+ console.error(`[BEISEN] 👤 StaffId: ${config.staffId}`);
3587
+ console.error(`[BEISEN] 🏢 TenantId: ${config.tenantId}`);
3588
+ console.error(`[BEISEN] 📧 Email: ${config.email}`);
3629
3589
  const client = new BeisenClient(config);
3630
3590
  // ============ 注册工具 ============
3631
- // 工具 1: 提交加班申请
3591
+ console.error('[BEISEN] 🔧 正在注册工具...');
3632
3592
  api.registerTool({
3633
3593
  name: 'beisen_submit_overtime',
3634
3594
  description: '提交加班申请到北森 EHR(推送数据并发起审批)',
3635
3595
  parameters: Type.Object({
3636
- startDate: Type.String({ description: '开始时间 (YYYY-MM-DD HH:mm:ss),如:2020-07-17 22:00:00' }),
3637
- stopDate: Type.String({ description: '结束时间 (YYYY-MM-DD HH:mm:ss),如:2020-07-17 23:00:00' }),
3638
- compensationType: Type.Optional(Type.Number({ description: '补偿类型:0=调休假,1=加班费(默认 0)' })),
3639
- properties: Type.Optional(Type.String({ description: '自定义字段 JSON 字符串' })),
3596
+ startDate: Type.String({ description: '开始时间 (YYYY-MM-DD HH:mm:ss)' }),
3597
+ stopDate: Type.String({ description: '结束时间 (YYYY-MM-DD HH:mm:ss)' }),
3598
+ compensationType: Type.Optional(Type.Number({ description: '补偿类型:0=调休假,1=加班费' })),
3599
+ properties: Type.Optional(Type.String({ description: '自定义字段 JSON' })),
3640
3600
  }),
3641
3601
  async execute(_id, params) {
3642
- console.error('🔨 工具调用:beisen_submit_overtime', JSON.stringify(params));
3602
+ console.error(`[BEISEN] 🔨 工具调用:beisen_submit_overtime`, JSON.stringify(params));
3643
3603
  try {
3644
- console.error('📡 正在提交加班申请...');
3645
3604
  const result = await client.submitOvertime({
3646
3605
  staffId: config.staffId,
3647
3606
  email: config.email,
@@ -3650,23 +3609,16 @@ async function register(api) {
3650
3609
  compensationType: params.compensationType,
3651
3610
  properties: params.properties,
3652
3611
  });
3653
- console.error('✅ 加班申请提交成功:', result);
3654
- if (result.code === "200" || result.code === 200) {
3655
- const compTypeText = params.compensationType === 1 ? "加班费" : "调休假";
3656
- return {
3657
- content: [
3658
- {
3659
- type: "text",
3660
- text: `✅ 加班申请已提交!\n\n申请详情:\n- 员工 ID: ${config.staffId}\n- 邮箱:${config.email}\n- 开始:${params.startDate}\n- 结束:${params.stopDate}\n- 补偿类型:${compTypeText}\n- 申请 ID: ${result.data || "待返回"}`,
3661
- },
3662
- ],
3663
- };
3664
- }
3665
- else {
3666
- throw new Error(result.message || `API 返回错误:${result.code}`);
3667
- }
3612
+ const compTypeText = params.compensationType === 1 ? "加班费" : "调休假";
3613
+ return {
3614
+ content: [{
3615
+ type: "text",
3616
+ text: `✅ 加班申请已提交!\n\n- 员工:${config.staffId}\n- 邮箱:${config.email}\n- 时间:${params.startDate} ~ ${params.stopDate}\n- 类型:${compTypeText}`,
3617
+ }],
3618
+ };
3668
3619
  }
3669
3620
  catch (error) {
3621
+ console.error(`[BEISEN] ❌ 提交失败:`, error.message);
3670
3622
  return {
3671
3623
  content: [{ type: "text", text: `❌ 提交失败:${error.message}` }],
3672
3624
  isError: true,
@@ -3674,31 +3626,27 @@ async function register(api) {
3674
3626
  }
3675
3627
  },
3676
3628
  });
3677
- // 工具 2: 查询假期余额
3678
3629
  api.registerTool({
3679
3630
  name: 'beisen_get_leave_balance',
3680
3631
  description: '查询假期余额(年假、调休假等)',
3681
3632
  parameters: Type.Object({}),
3682
3633
  async execute(_id, _params) {
3634
+ console.error(`[BEISEN] 🔨 工具调用:beisen_get_leave_balance`);
3683
3635
  try {
3684
3636
  const result = await client.getLeaveBalance(config.staffId, config.email);
3685
- let balanceText = `📊 假期余额查询\n\n员工:${config.email}\n\n`;
3637
+ let balanceText = `📊 假期余额\n\n员工:${config.email}\n\n`;
3686
3638
  if (result.data && Array.isArray(result.data)) {
3687
3639
  result.data.forEach((item) => {
3688
- balanceText += `• ${item.leaveTypeName || item.typeName || '未知假期'}: ${item.balanceDays || item.balance || 0} 天\n`;
3640
+ balanceText += `• ${item.leaveTypeName || item.typeName || '未知'}: ${item.balanceDays || item.balance || 0} 天\n`;
3689
3641
  });
3690
3642
  }
3691
- else if (result.data) {
3692
- balanceText += JSON.stringify(result.data, null, 2);
3693
- }
3694
3643
  else {
3695
- balanceText += "暂无假期数据";
3644
+ balanceText += "暂无数据";
3696
3645
  }
3697
- return {
3698
- content: [{ type: "text", text: balanceText }],
3699
- };
3646
+ return { content: [{ type: "text", text: balanceText }] };
3700
3647
  }
3701
3648
  catch (error) {
3649
+ console.error(`[BEISEN] ❌ 查询失败:`, error.message);
3702
3650
  return {
3703
3651
  content: [{ type: "text", text: `❌ 查询失败:${error.message}` }],
3704
3652
  isError: true,
@@ -3706,7 +3654,6 @@ async function register(api) {
3706
3654
  }
3707
3655
  },
3708
3656
  });
3709
- // 工具 3: 查询考勤记录
3710
3657
  api.registerTool({
3711
3658
  name: 'beisen_query_attendance',
3712
3659
  description: '查询员工考勤记录',
@@ -3715,18 +3662,15 @@ async function register(api) {
3715
3662
  endDate: Type.String({ description: '结束日期 (YYYY-MM-DD)' }),
3716
3663
  }),
3717
3664
  async execute(_id, params) {
3665
+ console.error(`[BEISEN] 🔨 工具调用:beisen_query_attendance`, JSON.stringify(params));
3718
3666
  try {
3719
3667
  const records = await client.getAttendanceRecords(params.startDate, params.endDate, config.staffId);
3720
3668
  return {
3721
- content: [
3722
- {
3723
- type: "text",
3724
- text: `📅 考勤记录 (${params.startDate} ~ ${params.endDate})\n\n${JSON.stringify(records, null, 2)}`,
3725
- },
3726
- ],
3669
+ content: [{ type: "text", text: `📅 考勤记录\n\n${JSON.stringify(records, null, 2)}` }],
3727
3670
  };
3728
3671
  }
3729
3672
  catch (error) {
3673
+ console.error(`[BEISEN] ❌ 查询失败:`, error.message);
3730
3674
  return {
3731
3675
  content: [{ type: "text", text: `❌ 查询失败:${error.message}` }],
3732
3676
  isError: true,
@@ -3734,7 +3678,6 @@ async function register(api) {
3734
3678
  }
3735
3679
  },
3736
3680
  });
3737
- // 工具 4: 查询审批状态
3738
3681
  api.registerTool({
3739
3682
  name: 'beisen_get_approval_status',
3740
3683
  description: '查询审批状态',
@@ -3742,18 +3685,18 @@ async function register(api) {
3742
3685
  applicationId: Type.String({ description: '申请 ID' }),
3743
3686
  }),
3744
3687
  async execute(_id, params) {
3688
+ console.error(`[BEISEN] 🔨 工具调用:beisen_get_approval_status`, JSON.stringify(params));
3745
3689
  try {
3746
3690
  const status = await client.getApprovalStatus(params.applicationId);
3747
3691
  return {
3748
- content: [
3749
- {
3692
+ content: [{
3750
3693
  type: "text",
3751
- text: `📋 审批状态\n\n申请 ID: ${params.applicationId}\n状态:${status.status || "未知"}\n审批人:${status.approver || "待分配"}\n备注:${status.remark || "无"}`,
3752
- },
3753
- ],
3694
+ text: `📋 审批状态\n\nID: ${params.applicationId}\n状态:${status.status || "未知"}\n审批人:${status.approver || "待分配"}`,
3695
+ }],
3754
3696
  };
3755
3697
  }
3756
3698
  catch (error) {
3699
+ console.error(`[BEISEN] ❌ 查询失败:`, error.message);
3757
3700
  return {
3758
3701
  content: [{ type: "text", text: `❌ 查询失败:${error.message}` }],
3759
3702
  isError: true,
@@ -3761,23 +3704,12 @@ async function register(api) {
3761
3704
  }
3762
3705
  },
3763
3706
  });
3764
- console.error('✅ 已注册 4 个工具:beisen_submit_overtime, beisen_get_leave_balance, beisen_query_attendance, beisen_get_approval_status');
3765
- // 调试:列出所有已注册的工具
3766
- console.error('🔍 工具注册完成,插件 ID:', pluginId);
3767
- console.error('🔍 配置:', JSON.stringify({
3768
- apiUrl: config.apiUrl,
3769
- staffId: config.staffId,
3770
- tenantId: config.tenantId,
3771
- email: config.email,
3772
- }, null, 2));
3707
+ console.error('[BEISEN] ✅ 已注册 4 个工具');
3708
+ console.error('[BEISEN] 🎉 插件加载完成,准备就绪!');
3773
3709
  }
3774
- /**
3775
- * 插件停用函数
3776
- */
3777
3710
  async function unregister() {
3778
- console.error('🏢 北森 EHR 插件已停用');
3711
+ console.error('[BEISEN] 🏢 插件已停用');
3779
3712
  }
3780
- // 导出插件入口
3781
3713
  const plugin = {
3782
3714
  id: pluginId,
3783
3715
  version: pluginVersion,