@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 +14 -130
- package/dist/index.cjs.js +60 -128
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -21
- package/dist/index.esm.js +60 -128
- package/dist/index.esm.js.map +1 -1
- package/openclaw.plugin.json +12 -47
- package/package.json +4 -27
package/README.md
CHANGED
|
@@ -1,152 +1,36 @@
|
|
|
1
|
-
# 北森 EHR OpenClaw 插件 🐉
|
|
1
|
+
# 北森 EHR OpenClaw 插件 v2.0.0 🐉
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
完全重写的北森 EHR 插件,移除所有 MCP 依赖。
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
### 方式一:一键安装(推荐)
|
|
5
|
+
## 一键安装
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
|
-
#
|
|
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. 重启
|
|
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
|
|
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
|
-
**版本**:
|
|
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 = '
|
|
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(
|
|
3492
|
+
console.error(`[BEISEN] ✅ Token 获取成功,有效期至:${new Date(tokenExpiry).toISOString()}`);
|
|
3501
3493
|
return cachedToken;
|
|
3502
3494
|
}
|
|
3503
|
-
// ============
|
|
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(
|
|
3519
|
-
console.error(
|
|
3520
|
-
console.error(
|
|
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(
|
|
3514
|
+
console.error(`[BEISEN] 📦 Body: ${requestBody.substring(0, 200)}`);
|
|
3523
3515
|
}
|
|
3524
3516
|
const controller = new AbortController();
|
|
3525
|
-
const timeoutId = setTimeout(() => controller.abort(), 30000);
|
|
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(
|
|
3528
|
+
throw new Error(`API 错误:${response.status} - ${errorText}`);
|
|
3537
3529
|
}
|
|
3538
|
-
|
|
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('
|
|
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:
|
|
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(
|
|
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('✅
|
|
3625
|
-
console.error(
|
|
3626
|
-
console.error(
|
|
3627
|
-
console.error(
|
|
3628
|
-
|
|
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
|
-
|
|
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)
|
|
3637
|
-
stopDate: Type.String({ description: '结束时间 (YYYY-MM-DD HH:mm:ss)
|
|
3638
|
-
compensationType: Type.Optional(Type.Number({ description: '补偿类型:0=调休假,1
|
|
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(
|
|
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
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
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 = `📊
|
|
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 || '
|
|
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\
|
|
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
|
|
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('🏢
|
|
3711
|
+
console.error('[BEISEN] 🏢 插件已停用');
|
|
3779
3712
|
}
|
|
3780
|
-
// 导出插件入口
|
|
3781
3713
|
const plugin = {
|
|
3782
3714
|
id: pluginId,
|
|
3783
3715
|
version: pluginVersion,
|