@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/dist/index.d.ts CHANGED
@@ -1,42 +1,24 @@
1
1
  import { OpenClawPlugin } from 'openclaw/plugin-sdk';
2
2
 
3
3
  /**
4
- * 北森 EHR OpenClaw Plugin
4
+ * 北森 EHR OpenClaw Plugin v2.0.0
5
5
  * 🐉 龙二 开发
6
6
  *
7
- * 功能:加班申请、考勤查询、假期余额、审批状态查询
7
+ * 完全移除 MCP 依赖,直接注册工具
8
8
  */
9
9
 
10
10
  declare const pluginId = "beisen-ehr-plugin";
11
- declare const pluginVersion = "1.1.9";
12
- /**
13
- * 北森 EHR 插件配置接口
14
- */
11
+ declare const pluginVersion = "2.0.0";
15
12
  interface BeisenEHRConfig {
16
- /** 北森 API 地址 */
17
13
  apiUrl?: string;
18
- /** App Key */
19
14
  appKey: string;
20
- /** App Secret */
21
15
  appSecret: string;
22
- /** 员工 ID */
23
16
  staffId: string;
24
- /** 企业租户 ID */
25
17
  tenantId: string;
26
- /** 企业邮箱 */
27
18
  email: string;
28
19
  }
29
- /**
30
- * 默认配置
31
- */
32
20
  declare const defaultConfig: Partial<BeisenEHRConfig>;
33
- /**
34
- * 插件注册函数
35
- */
36
21
  declare function register(api: any): Promise<void>;
37
- /**
38
- * 插件停用函数
39
- */
40
22
  declare function unregister(): Promise<void>;
41
23
  declare const plugin: OpenClawPlugin;
42
24
 
package/dist/index.esm.js CHANGED
@@ -3450,17 +3450,13 @@ var TypeBuilder = /*#__PURE__*/Object.freeze({
3450
3450
  const Type = TypeBuilder;
3451
3451
 
3452
3452
  /**
3453
- * 北森 EHR OpenClaw Plugin
3453
+ * 北森 EHR OpenClaw Plugin v2.0.0
3454
3454
  * 🐉 龙二 开发
3455
3455
  *
3456
- * 功能:加班申请、考勤查询、假期余额、审批状态查询
3456
+ * 完全移除 MCP 依赖,直接注册工具
3457
3457
  */
3458
- // 插件元数据
3459
3458
  const pluginId = 'beisen-ehr-plugin';
3460
- const pluginVersion = '1.1.9';
3461
- /**
3462
- * 默认配置
3463
- */
3459
+ const pluginVersion = '2.0.0';
3464
3460
  const defaultConfig = {
3465
3461
  apiUrl: 'https://openapi.italent.cn',
3466
3462
  };
@@ -3468,17 +3464,14 @@ const defaultConfig = {
3468
3464
  let cachedToken = null;
3469
3465
  let tokenExpiry = 0;
3470
3466
  async function getAccessToken(config) {
3471
- // 如果已有有效 Token,直接返回
3472
3467
  if (cachedToken && Date.now() < tokenExpiry) {
3473
3468
  return cachedToken;
3474
3469
  }
3475
- // 使用 AppKey + AppSecret 获取新 Token(北森官方格式)
3476
3470
  const tokenUrl = `${config.apiUrl || defaultConfig.apiUrl}/token`;
3471
+ console.error(`[BEISEN] 🔑 正在获取 Token: ${tokenUrl}`);
3477
3472
  const response = await fetch(tokenUrl, {
3478
3473
  method: "POST",
3479
- headers: {
3480
- "Content-Type": "application/json",
3481
- },
3474
+ headers: { "Content-Type": "application/json" },
3482
3475
  body: JSON.stringify({
3483
3476
  grant_type: "client_credentials",
3484
3477
  app_key: config.appKey,
@@ -3491,12 +3484,11 @@ async function getAccessToken(config) {
3491
3484
  }
3492
3485
  const data = await response.json();
3493
3486
  cachedToken = data.accessToken || data.access_token;
3494
- // Token 有效期通常 2 小时,提前 5 分钟刷新
3495
3487
  tokenExpiry = Date.now() + (data.expiresIn || data.expires_in || 7200) * 1000 - 5 * 60 * 1000;
3496
- console.error(`🔑 已获取新 Token,有效期至:${new Date(tokenExpiry).toISOString()}`);
3488
+ console.error(`[BEISEN] Token 获取成功,有效期至:${new Date(tokenExpiry).toISOString()}`);
3497
3489
  return cachedToken;
3498
3490
  }
3499
- // ============ 北森 API 客户端 ============
3491
+ // ============ API 客户端 ============
3500
3492
  class BeisenClient {
3501
3493
  constructor(config) {
3502
3494
  this.config = config;
@@ -3511,14 +3503,14 @@ class BeisenClient {
3511
3503
  ...(options.headers || {}),
3512
3504
  };
3513
3505
  const requestBody = options.body ? JSON.stringify(options.body) : undefined;
3514
- console.error(`📡 请求:${options.method || 'GET'} ${url}`);
3515
- console.error(`🔑 Token: ${token ? token.substring(0, 20) + '...' : 'none'}`);
3516
- console.error(`🏢 TenantId: ${this.config.tenantId}`);
3506
+ console.error(`[BEISEN] 📡 ${options.method || 'GET'} ${url}`);
3507
+ console.error(`[BEISEN] 🔑 Token: ${token.substring(0, 20)}...`);
3508
+ console.error(`[BEISEN] 🏢 TenantId: ${this.config.tenantId}`);
3517
3509
  if (requestBody) {
3518
- console.error(`📦 请求体:${requestBody.substring(0, 200)}...`);
3510
+ console.error(`[BEISEN] 📦 Body: ${requestBody.substring(0, 200)}`);
3519
3511
  }
3520
3512
  const controller = new AbortController();
3521
- const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 秒超时
3513
+ const timeoutId = setTimeout(() => controller.abort(), 30000);
3522
3514
  try {
3523
3515
  const response = await fetch(url, {
3524
3516
  ...options,
@@ -3529,19 +3521,21 @@ class BeisenClient {
3529
3521
  clearTimeout(timeoutId);
3530
3522
  if (!response.ok) {
3531
3523
  const errorText = await response.text();
3532
- throw new Error(`北森 API 错误:${response.status} - ${errorText}`);
3524
+ throw new Error(`API 错误:${response.status} - ${errorText}`);
3533
3525
  }
3534
- return response.json();
3526
+ const result = await response.json();
3527
+ console.error(`[BEISEN] ✅ 响应:`, JSON.stringify(result).substring(0, 200));
3528
+ return result;
3535
3529
  }
3536
3530
  catch (error) {
3537
3531
  clearTimeout(timeoutId);
3538
3532
  if (error.name === 'AbortError') {
3539
- throw new Error('北森 API 请求超时(30 秒)');
3533
+ throw new Error('请求超时(30 秒)');
3540
3534
  }
3535
+ console.error(`[BEISEN] ❌ 错误:`, error.message);
3541
3536
  throw error;
3542
3537
  }
3543
3538
  }
3544
- // 提交加班申请(推送至北森系统并发起审批)
3545
3539
  async submitOvertime(data) {
3546
3540
  const overtimeData = {
3547
3541
  staffId: data.staffId,
@@ -3553,91 +3547,56 @@ class BeisenClient {
3553
3547
  if (data.properties) {
3554
3548
  overtimeData.properties = typeof data.properties === 'string' ? data.properties : JSON.stringify(data.properties);
3555
3549
  }
3556
- const payload = {
3557
- attendance_overTime: overtimeData,
3558
- };
3559
3550
  return this.request("/AttendanceOpen/api/v1/AttendanceOvertime/PostOverTimeWithApproval", {
3560
3551
  method: "POST",
3561
- body: payload,
3552
+ body: { attendance_overTime: overtimeData },
3562
3553
  });
3563
3554
  }
3564
- // 查询假期余额
3565
3555
  async getLeaveBalance(staffId, email) {
3566
3556
  return this.request("/AttendanceOpen/api/v1/LeaveBalance/QueryLeaveBalance", {
3567
3557
  method: "POST",
3568
3558
  body: { staffId, email },
3569
3559
  });
3570
3560
  }
3571
- // 查询考勤记录
3572
3561
  async getAttendanceRecords(startDate, endDate, employeeId) {
3573
3562
  return this.request("/api/v1/attendance/records", {
3574
3563
  method: "POST",
3575
3564
  body: { startDate, endDate, employeeId },
3576
3565
  });
3577
3566
  }
3578
- // 查询审批状态
3579
3567
  async getApprovalStatus(applicationId) {
3580
3568
  return this.request(`/api/v1/approval/${applicationId}/status`);
3581
3569
  }
3582
3570
  }
3583
- /**
3584
- * 插件注册函数
3585
- */
3571
+ // ============ 插件注册 ============
3586
3572
  async function register(api) {
3587
- console.error(`🏢 北森 EHR 插件已加载 v${pluginVersion}`);
3588
- // 获取插件配置
3573
+ console.error(`[BEISEN] 🏢 北森 EHR 插件 v${pluginVersion} 正在加载...`);
3589
3574
  const config = api.config?.plugins?.entries?.['beisen-ehr-plugin']?.config;
3590
- if (!config) {
3591
- console.error('⚠️ 插件已安装,但未配置凭证');
3592
- console.error('');
3593
- console.error('📝 请在 OpenClaw 配置中添加:');
3594
- console.error('');
3595
- console.error(' plugins: {');
3596
- console.error(' entries: {');
3597
- console.error(' "beisen-ehr-plugin": {');
3598
- console.error(' enabled: true,');
3599
- console.error(' config: {');
3600
- console.error(' appKey: "your-app-key",');
3601
- console.error(' appSecret: "your-app-secret",');
3602
- console.error(' staffId: "your-staff-id",');
3603
- console.error(' tenantId: "your-tenant-id",');
3604
- console.error(' email: "your-email@company.com"');
3605
- console.error(' }');
3606
- console.error(' }');
3607
- console.error(' }');
3608
- console.error(' }');
3609
- console.error('');
3610
- return;
3611
- }
3612
- // 验证必要配置
3613
- const requiredFields = ['appKey', 'appSecret', 'staffId', 'tenantId', 'email'];
3614
- const missingFields = requiredFields.filter(field => !config[field]);
3615
- if (missingFields.length > 0) {
3616
- console.error(`❌ 缺少必要配置:${missingFields.join(', ')}`);
3617
- console.error('请补充完整配置后重启 Gateway');
3575
+ if (!config || !config.appKey || !config.appSecret || !config.staffId || !config.tenantId || !config.email) {
3576
+ console.error('[BEISEN] ⚠️ 插件已安装,但未配置凭证');
3577
+ console.error('[BEISEN] 📝 请运行:npx @peninsula-med/beisen-ehr-configure');
3618
3578
  return;
3619
3579
  }
3620
- console.error('✅ 北森 EHR 配置验证通过');
3621
- console.error(`📡 API: ${config.apiUrl || defaultConfig.apiUrl}`);
3622
- console.error(`👤 员工:${config.staffId}`);
3623
- console.error(`🏢 企业:${config.tenantId}`);
3624
- // 创建 API 客户端
3580
+ console.error('[BEISEN] ✅ 配置验证通过');
3581
+ console.error(`[BEISEN] 📡 API: ${config.apiUrl || defaultConfig.apiUrl}`);
3582
+ console.error(`[BEISEN] 👤 StaffId: ${config.staffId}`);
3583
+ console.error(`[BEISEN] 🏢 TenantId: ${config.tenantId}`);
3584
+ console.error(`[BEISEN] 📧 Email: ${config.email}`);
3625
3585
  const client = new BeisenClient(config);
3626
3586
  // ============ 注册工具 ============
3627
- // 工具 1: 提交加班申请
3587
+ console.error('[BEISEN] 🔧 正在注册工具...');
3628
3588
  api.registerTool({
3629
3589
  name: 'beisen_submit_overtime',
3630
3590
  description: '提交加班申请到北森 EHR(推送数据并发起审批)',
3631
3591
  parameters: Type.Object({
3632
- startDate: Type.String({ description: '开始时间 (YYYY-MM-DD HH:mm:ss),如:2020-07-17 22:00:00' }),
3633
- stopDate: Type.String({ description: '结束时间 (YYYY-MM-DD HH:mm:ss),如:2020-07-17 23:00:00' }),
3634
- compensationType: Type.Optional(Type.Number({ description: '补偿类型:0=调休假,1=加班费(默认 0)' })),
3635
- properties: Type.Optional(Type.String({ description: '自定义字段 JSON 字符串' })),
3592
+ startDate: Type.String({ description: '开始时间 (YYYY-MM-DD HH:mm:ss)' }),
3593
+ stopDate: Type.String({ description: '结束时间 (YYYY-MM-DD HH:mm:ss)' }),
3594
+ compensationType: Type.Optional(Type.Number({ description: '补偿类型:0=调休假,1=加班费' })),
3595
+ properties: Type.Optional(Type.String({ description: '自定义字段 JSON' })),
3636
3596
  }),
3637
3597
  async execute(_id, params) {
3638
- console.error('🔨 工具调用:beisen_submit_overtime', JSON.stringify(params));
3598
+ console.error(`[BEISEN] 🔨 工具调用:beisen_submit_overtime`, JSON.stringify(params));
3639
3599
  try {
3640
- console.error('📡 正在提交加班申请...');
3641
3600
  const result = await client.submitOvertime({
3642
3601
  staffId: config.staffId,
3643
3602
  email: config.email,
@@ -3646,23 +3605,16 @@ async function register(api) {
3646
3605
  compensationType: params.compensationType,
3647
3606
  properties: params.properties,
3648
3607
  });
3649
- console.error('✅ 加班申请提交成功:', result);
3650
- if (result.code === "200" || result.code === 200) {
3651
- const compTypeText = params.compensationType === 1 ? "加班费" : "调休假";
3652
- return {
3653
- content: [
3654
- {
3655
- type: "text",
3656
- text: `✅ 加班申请已提交!\n\n申请详情:\n- 员工 ID: ${config.staffId}\n- 邮箱:${config.email}\n- 开始:${params.startDate}\n- 结束:${params.stopDate}\n- 补偿类型:${compTypeText}\n- 申请 ID: ${result.data || "待返回"}`,
3657
- },
3658
- ],
3659
- };
3660
- }
3661
- else {
3662
- throw new Error(result.message || `API 返回错误:${result.code}`);
3663
- }
3608
+ const compTypeText = params.compensationType === 1 ? "加班费" : "调休假";
3609
+ return {
3610
+ content: [{
3611
+ type: "text",
3612
+ text: `✅ 加班申请已提交!\n\n- 员工:${config.staffId}\n- 邮箱:${config.email}\n- 时间:${params.startDate} ~ ${params.stopDate}\n- 类型:${compTypeText}`,
3613
+ }],
3614
+ };
3664
3615
  }
3665
3616
  catch (error) {
3617
+ console.error(`[BEISEN] ❌ 提交失败:`, error.message);
3666
3618
  return {
3667
3619
  content: [{ type: "text", text: `❌ 提交失败:${error.message}` }],
3668
3620
  isError: true,
@@ -3670,31 +3622,27 @@ async function register(api) {
3670
3622
  }
3671
3623
  },
3672
3624
  });
3673
- // 工具 2: 查询假期余额
3674
3625
  api.registerTool({
3675
3626
  name: 'beisen_get_leave_balance',
3676
3627
  description: '查询假期余额(年假、调休假等)',
3677
3628
  parameters: Type.Object({}),
3678
3629
  async execute(_id, _params) {
3630
+ console.error(`[BEISEN] 🔨 工具调用:beisen_get_leave_balance`);
3679
3631
  try {
3680
3632
  const result = await client.getLeaveBalance(config.staffId, config.email);
3681
- let balanceText = `📊 假期余额查询\n\n员工:${config.email}\n\n`;
3633
+ let balanceText = `📊 假期余额\n\n员工:${config.email}\n\n`;
3682
3634
  if (result.data && Array.isArray(result.data)) {
3683
3635
  result.data.forEach((item) => {
3684
- balanceText += `• ${item.leaveTypeName || item.typeName || '未知假期'}: ${item.balanceDays || item.balance || 0} 天\n`;
3636
+ balanceText += `• ${item.leaveTypeName || item.typeName || '未知'}: ${item.balanceDays || item.balance || 0} 天\n`;
3685
3637
  });
3686
3638
  }
3687
- else if (result.data) {
3688
- balanceText += JSON.stringify(result.data, null, 2);
3689
- }
3690
3639
  else {
3691
- balanceText += "暂无假期数据";
3640
+ balanceText += "暂无数据";
3692
3641
  }
3693
- return {
3694
- content: [{ type: "text", text: balanceText }],
3695
- };
3642
+ return { content: [{ type: "text", text: balanceText }] };
3696
3643
  }
3697
3644
  catch (error) {
3645
+ console.error(`[BEISEN] ❌ 查询失败:`, error.message);
3698
3646
  return {
3699
3647
  content: [{ type: "text", text: `❌ 查询失败:${error.message}` }],
3700
3648
  isError: true,
@@ -3702,7 +3650,6 @@ async function register(api) {
3702
3650
  }
3703
3651
  },
3704
3652
  });
3705
- // 工具 3: 查询考勤记录
3706
3653
  api.registerTool({
3707
3654
  name: 'beisen_query_attendance',
3708
3655
  description: '查询员工考勤记录',
@@ -3711,18 +3658,15 @@ async function register(api) {
3711
3658
  endDate: Type.String({ description: '结束日期 (YYYY-MM-DD)' }),
3712
3659
  }),
3713
3660
  async execute(_id, params) {
3661
+ console.error(`[BEISEN] 🔨 工具调用:beisen_query_attendance`, JSON.stringify(params));
3714
3662
  try {
3715
3663
  const records = await client.getAttendanceRecords(params.startDate, params.endDate, config.staffId);
3716
3664
  return {
3717
- content: [
3718
- {
3719
- type: "text",
3720
- text: `📅 考勤记录 (${params.startDate} ~ ${params.endDate})\n\n${JSON.stringify(records, null, 2)}`,
3721
- },
3722
- ],
3665
+ content: [{ type: "text", text: `📅 考勤记录\n\n${JSON.stringify(records, null, 2)}` }],
3723
3666
  };
3724
3667
  }
3725
3668
  catch (error) {
3669
+ console.error(`[BEISEN] ❌ 查询失败:`, error.message);
3726
3670
  return {
3727
3671
  content: [{ type: "text", text: `❌ 查询失败:${error.message}` }],
3728
3672
  isError: true,
@@ -3730,7 +3674,6 @@ async function register(api) {
3730
3674
  }
3731
3675
  },
3732
3676
  });
3733
- // 工具 4: 查询审批状态
3734
3677
  api.registerTool({
3735
3678
  name: 'beisen_get_approval_status',
3736
3679
  description: '查询审批状态',
@@ -3738,18 +3681,18 @@ async function register(api) {
3738
3681
  applicationId: Type.String({ description: '申请 ID' }),
3739
3682
  }),
3740
3683
  async execute(_id, params) {
3684
+ console.error(`[BEISEN] 🔨 工具调用:beisen_get_approval_status`, JSON.stringify(params));
3741
3685
  try {
3742
3686
  const status = await client.getApprovalStatus(params.applicationId);
3743
3687
  return {
3744
- content: [
3745
- {
3688
+ content: [{
3746
3689
  type: "text",
3747
- text: `📋 审批状态\n\n申请 ID: ${params.applicationId}\n状态:${status.status || "未知"}\n审批人:${status.approver || "待分配"}\n备注:${status.remark || "无"}`,
3748
- },
3749
- ],
3690
+ text: `📋 审批状态\n\nID: ${params.applicationId}\n状态:${status.status || "未知"}\n审批人:${status.approver || "待分配"}`,
3691
+ }],
3750
3692
  };
3751
3693
  }
3752
3694
  catch (error) {
3695
+ console.error(`[BEISEN] ❌ 查询失败:`, error.message);
3753
3696
  return {
3754
3697
  content: [{ type: "text", text: `❌ 查询失败:${error.message}` }],
3755
3698
  isError: true,
@@ -3757,23 +3700,12 @@ async function register(api) {
3757
3700
  }
3758
3701
  },
3759
3702
  });
3760
- console.error('✅ 已注册 4 个工具:beisen_submit_overtime, beisen_get_leave_balance, beisen_query_attendance, beisen_get_approval_status');
3761
- // 调试:列出所有已注册的工具
3762
- console.error('🔍 工具注册完成,插件 ID:', pluginId);
3763
- console.error('🔍 配置:', JSON.stringify({
3764
- apiUrl: config.apiUrl,
3765
- staffId: config.staffId,
3766
- tenantId: config.tenantId,
3767
- email: config.email,
3768
- }, null, 2));
3703
+ console.error('[BEISEN] ✅ 已注册 4 个工具');
3704
+ console.error('[BEISEN] 🎉 插件加载完成,准备就绪!');
3769
3705
  }
3770
- /**
3771
- * 插件停用函数
3772
- */
3773
3706
  async function unregister() {
3774
- console.error('🏢 北森 EHR 插件已停用');
3707
+ console.error('[BEISEN] 🏢 插件已停用');
3775
3708
  }
3776
- // 导出插件入口
3777
3709
  const plugin = {
3778
3710
  id: pluginId,
3779
3711
  version: pluginVersion,