@zzp123/mcp-zentao 1.2.2 → 1.3.1

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.
@@ -0,0 +1,315 @@
1
+ # 剪贴板图片上传脚本
2
+
3
+ 提供三种方案来获取剪贴板图片并上传到禅道系统。
4
+
5
+ ## 📋 方案对比
6
+
7
+ | 方案 | 平台 | 优点 | 缺点 |
8
+ |-----|------|------|------|
9
+ | Node.js | 跨平台 | 与项目集成,无需额外配置 | 需要Node环境 |
10
+ | PowerShell | Windows | 原生支持,无需安装依赖 | 仅Windows |
11
+ | Python | 跨平台 | 简单易用,代码清晰 | 需要Python环境 |
12
+
13
+ ## 🚀 快速开始
14
+
15
+ ### 方案1: Node.js 脚本(推荐)
16
+
17
+ **优点:** 跨平台,与项目无缝集成
18
+
19
+ **依赖:**
20
+ ```bash
21
+ # 安装 clipboardy(可选,用于跨平台剪贴板支持)
22
+ npm install -g clipboardy
23
+ ```
24
+
25
+ **使用方法:**
26
+
27
+ **Windows:**
28
+ ```batch
29
+ set ZENTAO_URL=https://your-zentao-url
30
+ set ZENTAO_USERNAME=your-username
31
+ set ZENTAO_PASSWORD=your-password
32
+ set ZENTAO_UID=optional-uid
33
+
34
+ node scripts/upload-clipboard-image.js
35
+ ```
36
+
37
+ **Mac/Linux:**
38
+ ```bash
39
+ export ZENTAO_URL=https://your-zentao-url
40
+ export ZENTAO_USERNAME=your-username
41
+ export ZENTAO_PASSWORD=your-password
42
+ export ZENTAO_UID=optional-uid
43
+
44
+ node scripts/upload-clipboard-image.js
45
+ ```
46
+
47
+ **特性:**
48
+ - ✅ 自动检测操作系统
49
+ - ✅ Windows: 使用 PowerShell 读取剪贴板
50
+ - ✅ macOS: 使用 pngpaste (需要安装: `brew install pngpaste`)
51
+ - ✅ Linux: 使用 xclip (需要安装: `sudo apt-get install xclip`)
52
+ - ✅ 自动保存到 img 文件夹
53
+ - ✅ 返回禅道文件ID和URL
54
+
55
+ ---
56
+
57
+ ### 方案2: PowerShell 脚本(Windows专用)
58
+
59
+ **优点:** 原生支持,无需安装额外依赖
60
+
61
+ **使用方法:**
62
+ ```powershell
63
+ .\scripts\upload-clipboard-image.ps1 `
64
+ -ZentaoUrl "https://your-zentao-url" `
65
+ -Username "your-username" `
66
+ -Password "your-password" `
67
+ -Uid "optional-uid"
68
+ ```
69
+
70
+ **或者创建批处理文件 `upload.bat`:**
71
+ ```batch
72
+ @echo off
73
+ powershell -ExecutionPolicy Bypass -File "%~dp0scripts\upload-clipboard-image.ps1" ^
74
+ -ZentaoUrl "https://your-zentao-url" ^
75
+ -Username "your-username" ^
76
+ -Password "your-password"
77
+ ```
78
+
79
+ **特性:**
80
+ - ✅ Windows原生支持
81
+ - ✅ 无需安装额外工具
82
+ - ✅ 支持所有图片格式
83
+ - ✅ 自动转换为PNG
84
+ - ✅ 显示图片尺寸
85
+
86
+ ---
87
+
88
+ ### 方案3: Python 脚本(跨平台)
89
+
90
+ **优点:** 简单易用,代码清晰
91
+
92
+ **依赖安装:**
93
+ ```bash
94
+ pip install pillow requests
95
+ ```
96
+
97
+ **使用方法:**
98
+
99
+ **Windows:**
100
+ ```batch
101
+ set ZENTAO_URL=https://your-zentao-url
102
+ set ZENTAO_USERNAME=your-username
103
+ set ZENTAO_PASSWORD=your-password
104
+ set ZENTAO_UID=optional-uid
105
+
106
+ python scripts/upload-clipboard-image.py
107
+ ```
108
+
109
+ **Mac/Linux:**
110
+ ```bash
111
+ export ZENTAO_URL=https://your-zentao-url
112
+ export ZENTAO_USERNAME=your-username
113
+ export ZENTAO_PASSWORD=your-password
114
+ export ZENTAO_UID=optional-uid
115
+
116
+ python scripts/upload-clipboard-image.py
117
+ ```
118
+
119
+ **特性:**
120
+ - ✅ 跨平台支持
121
+ - ✅ 使用 PIL/Pillow 处理图片
122
+ - ✅ 支持剪贴板中的图片或图片文件路径
123
+ - ✅ 显示图片尺寸
124
+ - ✅ 详细的错误提示
125
+
126
+ ---
127
+
128
+ ## 📝 环境变量说明
129
+
130
+ | 变量名 | 必需 | 说明 | 示例 |
131
+ |--------|------|------|------|
132
+ | ZENTAO_URL | 是 | 禅道系统URL | https://zentao.example.com |
133
+ | ZENTAO_USERNAME | 是 | 登录用户名 | admin |
134
+ | ZENTAO_PASSWORD | 是 | 登录密码 | your-password |
135
+ | ZENTAO_UID | 否 | 富文本编辑器关联ID | editor-123 |
136
+
137
+ ## 💡 使用技巧
138
+
139
+ ### 1. 创建快捷命令
140
+
141
+ **Windows (创建 `upload.bat`):**
142
+ ```batch
143
+ @echo off
144
+ REM 设置禅道配置
145
+ set ZENTAO_URL=https://your-zentao-url
146
+ set ZENTAO_USERNAME=your-username
147
+ set ZENTAO_PASSWORD=your-password
148
+
149
+ REM 运行上传脚本
150
+ node "%~dp0scripts\upload-clipboard-image.js"
151
+ pause
152
+ ```
153
+
154
+ **Mac/Linux (创建 `upload.sh`):**
155
+ ```bash
156
+ #!/bin/bash
157
+ # 设置禅道配置
158
+ export ZENTAO_URL=https://your-zentao-url
159
+ export ZENTAO_USERNAME=your-username
160
+ export ZENTAO_PASSWORD=your-password
161
+
162
+ # 运行上传脚本
163
+ node "$(dirname "$0")/scripts/upload-clipboard-image.js"
164
+ ```
165
+
166
+ 然后:
167
+ ```bash
168
+ chmod +x upload.sh
169
+ ./upload.sh
170
+ ```
171
+
172
+ ### 2. 配置文件方式
173
+
174
+ 创建 `.env` 文件:
175
+ ```env
176
+ ZENTAO_URL=https://your-zentao-url
177
+ ZENTAO_USERNAME=your-username
178
+ ZENTAO_PASSWORD=your-password
179
+ ZENTAO_UID=
180
+ ```
181
+
182
+ 然后加载环境变量:
183
+ ```bash
184
+ # Linux/Mac
185
+ source .env
186
+
187
+ # Windows (使用 PowerShell)
188
+ Get-Content .env | ForEach-Object {
189
+ $name, $value = $_.split('=')
190
+ Set-Content env:\$name $value
191
+ }
192
+ ```
193
+
194
+ ### 3. 快捷键绑定
195
+
196
+ 可以将脚本绑定到系统快捷键,实现:
197
+ 1. 截图/复制图片
198
+ 2. 按快捷键
199
+ 3. 自动上传到禅道
200
+
201
+ **Windows AutoHotkey 示例:**
202
+ ```ahk
203
+ ; Ctrl+Shift+U 上传剪贴板图片
204
+ ^+u::
205
+ Run, cmd /c "cd /d C:\path\to\project && upload.bat"
206
+ return
207
+ ```
208
+
209
+ **Mac Automator 示例:**
210
+ 1. 打开 Automator
211
+ 2. 创建"快速操作"
212
+ 3. 添加"运行Shell脚本"
213
+ 4. 输入上传命令
214
+ 5. 在系统偏好设置中设置快捷键
215
+
216
+ ## 🔍 故障排查
217
+
218
+ ### Node.js 方案
219
+
220
+ **问题:** `Error: Cannot find module 'form-data'`
221
+ ```bash
222
+ npm install
223
+ ```
224
+
225
+ **问题:** macOS 提示 `pngpaste: command not found`
226
+ ```bash
227
+ brew install pngpaste
228
+ ```
229
+
230
+ **问题:** Linux 提示 `xclip: command not found`
231
+ ```bash
232
+ # Ubuntu/Debian
233
+ sudo apt-get install xclip
234
+
235
+ # CentOS/RHEL
236
+ sudo yum install xclip
237
+ ```
238
+
239
+ ### PowerShell 方案
240
+
241
+ **问题:** 脚本无法运行
242
+ ```powershell
243
+ # 临时允许脚本执行
244
+ Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
245
+
246
+ # 或使用 -ExecutionPolicy 参数
247
+ powershell -ExecutionPolicy Bypass -File upload-clipboard-image.ps1
248
+ ```
249
+
250
+ ### Python 方案
251
+
252
+ **问题:** `ModuleNotFoundError: No module named 'PIL'`
253
+ ```bash
254
+ pip install pillow
255
+ ```
256
+
257
+ **问题:** `ModuleNotFoundError: No module named 'requests'`
258
+ ```bash
259
+ pip install requests
260
+ ```
261
+
262
+ ## 📸 完整工作流示例
263
+
264
+ 1. **截图或复制图片**
265
+ - Windows: Win+Shift+S 或 PrintScreen
266
+ - Mac: Cmd+Shift+Ctrl+4
267
+ - 或从任意应用复制图片
268
+
269
+ 2. **运行上传脚本**
270
+ ```bash
271
+ # 使用你选择的方案
272
+ node scripts/upload-clipboard-image.js
273
+ # 或
274
+ .\scripts\upload-clipboard-image.ps1 -ZentaoUrl ... -Username ... -Password ...
275
+ # 或
276
+ python scripts/upload-clipboard-image.py
277
+ ```
278
+
279
+ 3. **获取结果**
280
+ ```
281
+ ========================================
282
+ ✓ 上传成功!
283
+ ========================================
284
+ 文件ID: 123
285
+ 访问URL: /zentao/file-read-123.png
286
+ 本地路径: C:\project\img\clipboard_1234567890.png
287
+ ========================================
288
+ ```
289
+
290
+ 4. **在禅道中使用**
291
+ - 复制返回的URL
292
+ - 在需求/Bug/任务描述中插入图片
293
+ - 使用 `![图片](/zentao/file-read-123.png)` 或直接粘贴URL
294
+
295
+ ## 🎯 高级用法
296
+
297
+ ### 批量上传
298
+
299
+ 创建一个循环脚本,持续监听剪贴板变化并自动上传。
300
+
301
+ ### 与富文本编辑器集成
302
+
303
+ 设置 `ZENTAO_UID` 环境变量,将上传的图片关联到特定的编辑器会话。
304
+
305
+ ### 自定义保存路径
306
+
307
+ 修改脚本中的 `imgDir` 变量,将图片保存到自定义位置。
308
+
309
+ ## 📄 许可证
310
+
311
+ MIT
312
+
313
+ ## 🤝 贡献
314
+
315
+ 欢迎提交 Issue 和 Pull Request!
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * 获取剪贴板图片的 base64 编码
5
+ * 可以在 Claude Code 中使用 Bash 工具调用此脚本
6
+ */
7
+
8
+ import { execSync } from 'child_process';
9
+ import { fileURLToPath } from 'url';
10
+ import { dirname, join } from 'path';
11
+ import fs from 'fs';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+
16
+ async function getClipboardBase64() {
17
+ try {
18
+ let base64Data;
19
+
20
+ // Windows: 使用 PowerShell
21
+ if (process.platform === 'win32') {
22
+ const psScript = `
23
+ Add-Type -AssemblyName System.Windows.Forms
24
+ $img = [System.Windows.Forms.Clipboard]::GetImage()
25
+ if ($img -ne $null) {
26
+ $ms = New-Object System.IO.MemoryStream
27
+ $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
28
+ [Convert]::ToBase64String($ms.ToArray())
29
+ } else {
30
+ Write-Error "No image in clipboard"
31
+ exit 1
32
+ }
33
+ `;
34
+
35
+ try {
36
+ base64Data = execSync(`powershell -Command "${psScript.replace(/\n/g, ' ')}"`, {
37
+ encoding: 'utf8',
38
+ maxBuffer: 10 * 1024 * 1024,
39
+ stdio: ['pipe', 'pipe', 'pipe']
40
+ }).trim();
41
+
42
+ if (!base64Data || base64Data.includes('Error')) {
43
+ console.error('ERROR: No image in clipboard');
44
+ process.exit(1);
45
+ }
46
+
47
+ // 输出完整的 data URL
48
+ console.log(`data:image/png;base64,${base64Data}`);
49
+
50
+ } catch (error) {
51
+ console.error('ERROR: Failed to read clipboard image');
52
+ process.exit(1);
53
+ }
54
+ }
55
+ // macOS: 使用 pngpaste
56
+ else if (process.platform === 'darwin') {
57
+ try {
58
+ execSync('which pngpaste', { stdio: 'ignore' });
59
+ const tempFile = join(__dirname, '.temp_clipboard.png');
60
+ execSync(`pngpaste "${tempFile}"`);
61
+ const buffer = fs.readFileSync(tempFile);
62
+ base64Data = buffer.toString('base64');
63
+ fs.unlinkSync(tempFile);
64
+ console.log(`data:image/png;base64,${base64Data}`);
65
+ } catch (error) {
66
+ console.error('ERROR: No image in clipboard or pngpaste not installed');
67
+ console.error('Install: brew install pngpaste');
68
+ process.exit(1);
69
+ }
70
+ }
71
+ // Linux: 使用 xclip
72
+ else {
73
+ try {
74
+ execSync('which xclip', { stdio: 'ignore' });
75
+ const buffer = execSync('xclip -selection clipboard -t image/png -o', {
76
+ maxBuffer: 10 * 1024 * 1024
77
+ });
78
+ base64Data = buffer.toString('base64');
79
+ console.log(`data:image/png;base64,${base64Data}`);
80
+ } catch (error) {
81
+ console.error('ERROR: No image in clipboard or xclip not installed');
82
+ console.error('Install: sudo apt-get install xclip');
83
+ process.exit(1);
84
+ }
85
+ }
86
+
87
+ } catch (error) {
88
+ console.error('ERROR:', error.message);
89
+ process.exit(1);
90
+ }
91
+ }
92
+
93
+ getClipboardBase64();
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * 从剪贴板获取图片并上传到禅道
5
+ * 使用方法: node upload-clipboard-image.js
6
+ *
7
+ * 环境变量:
8
+ * - ZENTAO_URL: 禅道系统URL
9
+ * - ZENTAO_USERNAME: 用户名
10
+ * - ZENTAO_PASSWORD: 密码
11
+ * - ZENTAO_UID: 可选的UID参数
12
+ */
13
+
14
+ import clipboardy from 'clipboardy';
15
+ import fs from 'fs';
16
+ import path from 'path';
17
+ import { fileURLToPath } from 'url';
18
+ import { dirname } from 'path';
19
+
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = dirname(__filename);
22
+
23
+ // 动态导入 ZentaoAPI
24
+ async function uploadClipboardImage() {
25
+ try {
26
+ console.log('正在读取剪贴板内容...');
27
+
28
+ // 检查环境变量
29
+ const zentaoUrl = process.env.ZENTAO_URL;
30
+ const username = process.env.ZENTAO_USERNAME;
31
+ const password = process.env.ZENTAO_PASSWORD;
32
+ const uid = process.env.ZENTAO_UID;
33
+
34
+ if (!zentaoUrl || !username || !password) {
35
+ console.error('错误: 请设置环境变量 ZENTAO_URL, ZENTAO_USERNAME, ZENTAO_PASSWORD');
36
+ console.error('');
37
+ console.error('Windows示例:');
38
+ console.error(' set ZENTAO_URL=https://your-zentao-url');
39
+ console.error(' set ZENTAO_USERNAME=your-username');
40
+ console.error(' set ZENTAO_PASSWORD=your-password');
41
+ console.error(' node upload-clipboard-image.js');
42
+ console.error('');
43
+ console.error('Mac/Linux示例:');
44
+ console.error(' export ZENTAO_URL=https://your-zentao-url');
45
+ console.error(' export ZENTAO_USERNAME=your-username');
46
+ console.error(' export ZENTAO_PASSWORD=your-password');
47
+ console.error(' node upload-clipboard-image.js');
48
+ process.exit(1);
49
+ }
50
+
51
+ // 尝试读取剪贴板图片
52
+ let imageData;
53
+
54
+ // Windows: 使用 PowerShell 读取剪贴板图片
55
+ if (process.platform === 'win32') {
56
+ const { execSync } = await import('child_process');
57
+ try {
58
+ const psScript = `
59
+ Add-Type -AssemblyName System.Windows.Forms
60
+ $img = [System.Windows.Forms.Clipboard]::GetImage()
61
+ if ($img -ne $null) {
62
+ $ms = New-Object System.IO.MemoryStream
63
+ $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
64
+ [Convert]::ToBase64String($ms.ToArray())
65
+ }
66
+ `;
67
+ const base64 = execSync(`powershell -Command "${psScript.replace(/\n/g, ' ')}"`, {
68
+ encoding: 'utf8',
69
+ maxBuffer: 10 * 1024 * 1024
70
+ }).trim();
71
+
72
+ if (base64) {
73
+ imageData = `data:image/png;base64,${base64}`;
74
+ console.log('✓ 从剪贴板读取图片成功 (Windows)');
75
+ } else {
76
+ console.error('错误: 剪贴板中没有图片');
77
+ process.exit(1);
78
+ }
79
+ } catch (error) {
80
+ console.error('错误: 无法读取剪贴板图片', error.message);
81
+ process.exit(1);
82
+ }
83
+ }
84
+ // macOS: 使用 pngpaste
85
+ else if (process.platform === 'darwin') {
86
+ const { execSync } = await import('child_process');
87
+ try {
88
+ // 检查是否安装了 pngpaste
89
+ try {
90
+ execSync('which pngpaste', { stdio: 'ignore' });
91
+ } catch {
92
+ console.error('错误: 请先安装 pngpaste');
93
+ console.error('运行: brew install pngpaste');
94
+ process.exit(1);
95
+ }
96
+
97
+ const tempFile = path.join(__dirname, 'temp_clipboard.png');
98
+ execSync(`pngpaste "${tempFile}"`);
99
+ const buffer = fs.readFileSync(tempFile);
100
+ const base64 = buffer.toString('base64');
101
+ imageData = `data:image/png;base64,${base64}`;
102
+ fs.unlinkSync(tempFile);
103
+ console.log('✓ 从剪贴板读取图片成功 (macOS)');
104
+ } catch (error) {
105
+ console.error('错误: 剪贴板中没有图片或读取失败', error.message);
106
+ process.exit(1);
107
+ }
108
+ }
109
+ // Linux: 使用 xclip
110
+ else {
111
+ const { execSync } = await import('child_process');
112
+ try {
113
+ // 检查是否安装了 xclip
114
+ try {
115
+ execSync('which xclip', { stdio: 'ignore' });
116
+ } catch {
117
+ console.error('错误: 请先安装 xclip');
118
+ console.error('运行: sudo apt-get install xclip (Ubuntu/Debian)');
119
+ console.error('或: sudo yum install xclip (CentOS/RHEL)');
120
+ process.exit(1);
121
+ }
122
+
123
+ const buffer = execSync('xclip -selection clipboard -t image/png -o', {
124
+ maxBuffer: 10 * 1024 * 1024
125
+ });
126
+ const base64 = buffer.toString('base64');
127
+ imageData = `data:image/png;base64,${base64}`;
128
+ console.log('✓ 从剪贴板读取图片成功 (Linux)');
129
+ } catch (error) {
130
+ console.error('错误: 剪贴板中没有图片或读取失败', error.message);
131
+ process.exit(1);
132
+ }
133
+ }
134
+
135
+ // 导入 ZentaoAPI
136
+ const modulePath = path.join(__dirname, '..', 'dist', 'api', 'zentaoApi.js');
137
+ const { ZentaoAPI } = await import(modulePath);
138
+
139
+ // 创建 API 实例
140
+ console.log('正在连接禅道系统...');
141
+ const api = new ZentaoAPI({
142
+ url: zentaoUrl,
143
+ username: username,
144
+ password: password,
145
+ apiVersion: 'v1'
146
+ });
147
+
148
+ // 创建 img 文件夹
149
+ const imgDir = path.join(process.cwd(), 'img');
150
+ if (!fs.existsSync(imgDir)) {
151
+ fs.mkdirSync(imgDir, { recursive: true });
152
+ }
153
+
154
+ // 解析 base64 数据
155
+ const matches = imageData.match(/^data:image\/(\w+);base64,(.+)$/);
156
+ if (!matches) {
157
+ console.error('错误: 无效的图片数据');
158
+ process.exit(1);
159
+ }
160
+
161
+ const ext = matches[1];
162
+ const base64Data = matches[2];
163
+ const buffer = Buffer.from(base64Data, 'base64');
164
+ const filename = `clipboard_${Date.now()}.${ext}`;
165
+
166
+ // 保存到本地
167
+ const savedPath = path.join(imgDir, filename);
168
+ fs.writeFileSync(savedPath, buffer);
169
+ console.log(`✓ 图片已保存到: ${savedPath}`);
170
+
171
+ // 上传到禅道
172
+ console.log('正在上传到禅道...');
173
+ const result = await api.uploadFile({
174
+ file: buffer,
175
+ filename: filename,
176
+ uid: uid
177
+ });
178
+
179
+ console.log('');
180
+ console.log('========================================');
181
+ console.log('✓ 上传成功!');
182
+ console.log('========================================');
183
+ console.log('文件ID:', result.id);
184
+ console.log('访问URL:', result.url);
185
+ console.log('本地路径:', savedPath);
186
+ console.log('========================================');
187
+
188
+ } catch (error) {
189
+ console.error('');
190
+ console.error('========================================');
191
+ console.error('✗ 上传失败');
192
+ console.error('========================================');
193
+ console.error('错误信息:', error.message);
194
+ console.error('========================================');
195
+ process.exit(1);
196
+ }
197
+ }
198
+
199
+ // 运行
200
+ uploadClipboardImage();