@yesdgq/claude-buddy 1.1.1005 → 1.1.1007

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/assets/config.js CHANGED
@@ -14,6 +14,11 @@ createApp({
14
14
  configPath: '',
15
15
  showHelp: false,
16
16
  currentCli: 'Claude',
17
+ currentLang: 'en',
18
+ languages: [
19
+ { code: 'en', label: 'English' },
20
+ { code: 'zh', label: '中文' }
21
+ ],
17
22
  cliList: [
18
23
  { name: 'Claude', label: 'Claude', icon: 'images/claude.png' },
19
24
  { name: 'Codex', label: 'Codex', icon: 'images/gpt.png' },
@@ -21,10 +26,168 @@ createApp({
21
26
  ],
22
27
  // 拖拽相关状态
23
28
  draggingIndex: null,
24
- dragOverIndex: null
29
+ dragOverIndex: null,
30
+ // 确认对话框
31
+ confirmDialog: {
32
+ show: false,
33
+ message: '',
34
+ onConfirm: null,
35
+ onCancel: null
36
+ },
37
+ // 翻译数据
38
+ translations: {
39
+ en: {
40
+ helpTitle: 'User Guide',
41
+ helpDescription: 'Claude Buddy is an easy-to-use CLI tool that helps you quickly configure API keys, model mappings, and other settings for CLI tools like Claude Code, Codex, and Gemini through a visual interface. It greatly simplifies your usage of these CLI tools.',
42
+ feature1Title: 'API Key Management',
43
+ feature1Desc: 'Easily store, switch, and manage multiple API keys',
44
+ feature2Title: 'Model Mapping',
45
+ feature2Desc: 'Conveniently customize and manage model configurations',
46
+ feature3Title: 'One-time Installation, Permanent Use',
47
+ feature3Desc: 'Local deployment with long-term usage after installation',
48
+ feature4Title: 'Quick Configuration',
49
+ feature4Desc: 'Visual interface, complete settings in seconds',
50
+ feature5Title: 'Developer Friendly',
51
+ feature5Desc: 'Designed for developers focused on coding',
52
+ commandUsageTitle: 'Command Usage',
53
+ command1: 'Open the configuration page to set your API URL and access token',
54
+ command2: 'Launch Claude Code',
55
+ command3: 'View conversation history',
56
+ command4: 'Resume the last conversation',
57
+ command5: 'View Claude-Buddy version',
58
+ command6: 'View Claude version',
59
+ restartNotice: 'After switching or updating configurations, you need to restart Claude Code (CLI tool) for changes to take effect.',
60
+ loading: 'Loading...',
61
+ currentUse: 'Current',
62
+ activate: 'Activate',
63
+ activateThisConfig: 'Activate this configuration',
64
+ emptyConfigCannotActivate: 'Empty configuration cannot be activated',
65
+ deleteThisConfig: 'Delete this configuration',
66
+ emptyConfigCannotDelete: 'Empty configuration cannot be deleted',
67
+ modelManagement: 'Model Management',
68
+ collapse: 'Collapse',
69
+ expand: 'Expand',
70
+ modelNamePlaceholder: 'Model name',
71
+ modelValuePlaceholder: 'Model value',
72
+ deleteThisModel: 'Delete this model',
73
+ addModel: 'Add Model',
74
+ envVariables: 'Environment Variables',
75
+ variableNamePlaceholder: 'Variable name',
76
+ variableValuePlaceholder: 'Variable value',
77
+ deleteThisEnvVar: 'Delete this environment variable',
78
+ addEnvVariable: 'Add Environment Variable',
79
+ addNewConfig: 'Add New Configuration',
80
+ saveConfig: 'Save Configuration',
81
+ saving: 'Saving...',
82
+ reload: 'Reload',
83
+ confirmDeleteWithName: 'Are you sure you want to delete configuration {name}?',
84
+ confirmDeleteWithIndex: 'Are you sure you want to delete configuration #{index}?',
85
+ emptyConfigCannotDeleteToast: 'Empty configuration cannot be deleted',
86
+ configLoadSuccess: 'Configuration loaded successfully',
87
+ configLoadFailed: 'Failed to load configuration',
88
+ pleaseFillConfig: 'Please fill at least one complete configuration',
89
+ configSaveSuccess: 'Configuration saved successfully!',
90
+ configSaveFailed: 'Failed to save configuration',
91
+ configDeleted: 'Configuration deleted',
92
+ deleteFailed: 'Failed to delete',
93
+ configActivated: 'Configuration activated',
94
+ notAvailableYet: 'Not available yet, stay tuned',
95
+ saveFailed: 'Save failed',
96
+ cancel: 'Cancel',
97
+ confirm: 'Confirm'
98
+ },
99
+ zh: {
100
+ helpTitle: '使用说明',
101
+ helpDescription: 'Claude Buddy 是一款简单易用的 CLI 工具,通过可视化方式快速配置 Claude Code、Codex 和 Gemini 等CLI的API密钥、模型映射等信息,可极大的方便和简化您对Claude Code等CLI的使用。',
102
+ feature1Title: 'API 密钥管理',
103
+ feature1Desc: '轻松存储、切换和管理多组API 密钥',
104
+ feature2Title: '模型映射',
105
+ feature2Desc: '便捷地自定义和管理模型配置',
106
+ feature3Title: '一次安装永久使用',
107
+ feature3Desc: '本地部署,安装后可长久使用',
108
+ feature4Title: '快速配置',
109
+ feature4Desc: '可视化界面,几秒钟即可完成设置',
110
+ feature5Title: '开发者友好',
111
+ feature5Desc: '专为专注于编码的开发者打造',
112
+ commandUsageTitle: '命令使用',
113
+ command1: '打开配置页面,配置您的 API 地址和访问令牌(TOKEN)',
114
+ command2: '启动claude code',
115
+ command3: '查看历史会话',
116
+ command4: '继续上次会话',
117
+ command5: '查看Claude-Buddy版本',
118
+ command6: '查看Claude版本',
119
+ restartNotice: '切换或更新配置后,需重启 Claude Code(CLI工具)方可生效。',
120
+ loading: '加载中...',
121
+ currentUse: '当前使用',
122
+ activate: '启用',
123
+ activateThisConfig: '启用此配置',
124
+ emptyConfigCannotActivate: '空配置不能启用',
125
+ deleteThisConfig: '删除此配置',
126
+ emptyConfigCannotDelete: '空配置不能删除',
127
+ modelManagement: '模型管理',
128
+ collapse: '收起',
129
+ expand: '展开',
130
+ modelNamePlaceholder: '模型名称',
131
+ modelValuePlaceholder: '模型值',
132
+ deleteThisModel: '删除此模型',
133
+ addModel: '添加模型',
134
+ envVariables: '环境变量',
135
+ variableNamePlaceholder: '变量名',
136
+ variableValuePlaceholder: '变量值',
137
+ deleteThisEnvVar: '删除此环境变量',
138
+ addEnvVariable: '添加环境变量',
139
+ addNewConfig: '添加新配置',
140
+ saveConfig: '保存配置',
141
+ saving: '保存中...',
142
+ reload: '重新加载',
143
+ confirmDeleteWithName: '确定要删除配置 {name} 吗?',
144
+ confirmDeleteWithIndex: '确定要删除配置 #{index} 吗?',
145
+ emptyConfigCannotDeleteToast: '空配置项不能删除',
146
+ configLoadSuccess: '配置加载成功',
147
+ configLoadFailed: '加载配置失败',
148
+ pleaseFillConfig: '请至少填写一个完整的配置',
149
+ configSaveSuccess: '配置保存成功!',
150
+ configSaveFailed: '保存配置失败',
151
+ configDeleted: '配置已删除',
152
+ deleteFailed: '删除失败',
153
+ configActivated: '配置启用成功',
154
+ notAvailableYet: '暂未开放,敬请期待',
155
+ saveFailed: '保存失败',
156
+ cancel: '取消',
157
+ confirm: '确认'
158
+ }
159
+ }
25
160
  };
26
161
  },
162
+ computed: {
163
+ t() {
164
+ return this.translations[this.currentLang];
165
+ }
166
+ },
27
167
  methods: {
168
+ // 显示确认对话框
169
+ showConfirmDialog(message, onConfirm, onCancel) {
170
+ this.confirmDialog = {
171
+ show: true,
172
+ message,
173
+ onConfirm: () => {
174
+ this.confirmDialog.show = false;
175
+ if (onConfirm) onConfirm();
176
+ },
177
+ onCancel: () => {
178
+ this.confirmDialog.show = false;
179
+ if (onCancel) onCancel();
180
+ }
181
+ };
182
+ },
183
+
184
+ // 切换语言
185
+ setLanguage(langCode) {
186
+ this.currentLang = langCode;
187
+ // 保存语言设置到 localStorage
188
+ localStorage.setItem('ccby-lang', langCode);
189
+ },
190
+
28
191
  // 重置服务器倒计时
29
192
  async resetTimer() {
30
193
  try {
@@ -139,11 +302,11 @@ createApp({
139
302
  // 最后更新 config
140
303
  this.config = config;
141
304
 
142
- this.showToast('配置加载成功');
305
+ this.showToast(this.t.configLoadSuccess);
143
306
  // 重置服务器倒计时
144
307
  this.resetTimer();
145
308
  } catch (err) {
146
- this.showToast('加载配置失败: ' + (err.response?.data?.error || err.message), 'error');
309
+ this.showToast(this.t.configLoadFailed + ': ' + (err.response?.data?.error || err.message), 'error');
147
310
  } finally {
148
311
  this.loading = false;
149
312
  }
@@ -162,7 +325,7 @@ createApp({
162
325
 
163
326
  // 如果过滤后没有配置项,确保至少有一个空配置项在前端显示
164
327
  if (configToSave.AUTH.length === 0 && this.config.AUTH.length > 0) {
165
- this.showToast('请至少填写一个完整的配置', 'error');
328
+ this.showToast(this.t.pleaseFillConfig, 'error');
166
329
  return;
167
330
  }
168
331
 
@@ -170,11 +333,11 @@ createApp({
170
333
  config: configToSave,
171
334
  cliType: this.currentCli.toLowerCase()
172
335
  });
173
- this.showToast('配置保存成功!');
336
+ this.showToast(this.t.configSaveSuccess);
174
337
  // 重置服务器倒计时
175
338
  this.resetTimer();
176
339
  } catch (err) {
177
- this.showToast('保存配置失败: ' + (err.response?.data?.error || err.message), 'error');
340
+ this.showToast(this.t.configSaveFailed + ': ' + (err.response?.data?.error || err.message), 'error');
178
341
  } finally {
179
342
  this.saving = false;
180
343
  }
@@ -198,16 +361,17 @@ createApp({
198
361
  async deleteAuth(index) {
199
362
  // 检查是否是唯一的空配置项
200
363
  if (this.config.AUTH.length === 1 && this.isEmptyConfig(this.config.AUTH[index])) {
201
- this.showToast('空配置项不能删除', 'error');
364
+ this.showToast(this.t.emptyConfigCannotDeleteToast, 'error');
202
365
  return;
203
366
  }
204
367
 
205
368
  const authName = this.config.AUTH[index].name;
206
369
  const confirmMsg = authName
207
- ? `确定要删除配置 ${authName} 吗?`
208
- : `确定要删除配置 #${index + 1} 吗?`;
370
+ ? this.t.confirmDeleteWithName.replace('{name}', authName)
371
+ : this.t.confirmDeleteWithIndex.replace('{index}', index + 1);
209
372
 
210
- if (confirm(confirmMsg)) {
373
+ // 使用自定义确认对话框
374
+ this.showConfirmDialog(confirmMsg, async () => {
211
375
  // 保存要删除的数据,以防保存失败时恢复
212
376
  const deletedAuth = this.config.AUTH[index];
213
377
  const deletedTokenState = this.showTokens[index];
@@ -258,11 +422,11 @@ createApp({
258
422
  config: configToSave,
259
423
  cliType: this.currentCli.toLowerCase()
260
424
  });
261
- this.showToast('配置已删除');
425
+ this.showToast(this.t.configDeleted);
262
426
  // 重置服务器倒计时
263
427
  this.resetTimer();
264
428
  } catch (err) {
265
- this.showToast('删除失败: ' + (err.response?.data?.error || err.message), 'error');
429
+ this.showToast(this.t.deleteFailed + ': ' + (err.response?.data?.error || err.message), 'error');
266
430
  // 如果保存失败,恢复删除的项
267
431
  this.config.AUTH.splice(index, 0, deletedAuth);
268
432
  this.showTokens.splice(index, 0, deletedTokenState);
@@ -270,7 +434,7 @@ createApp({
270
434
  this.showModelSections.splice(index, 0, deletedModelState);
271
435
  this.config.activeIndex = oldActiveIndex;
272
436
  }
273
- }
437
+ });
274
438
  },
275
439
 
276
440
  async setAsActive(index) {
@@ -293,11 +457,11 @@ createApp({
293
457
  config: configToSave,
294
458
  cliType: this.currentCli.toLowerCase()
295
459
  });
296
- this.showToast('配置启用成功');
460
+ this.showToast(this.t.configActivated);
297
461
  // 重置服务器倒计时
298
462
  this.resetTimer();
299
463
  } catch (err) {
300
- this.showToast('保存配置失败: ' + (err.response?.data?.error || err.message), 'error');
464
+ this.showToast(this.t.configSaveFailed + ': ' + (err.response?.data?.error || err.message), 'error');
301
465
  // 如果保存失败,恢复原来的 activeIndex
302
466
  this.config.activeIndex = oldIndex;
303
467
  }
@@ -355,7 +519,7 @@ createApp({
355
519
  // 选择 CLI 类型
356
520
  async selectCli(cliName) {
357
521
  if (cliName === 'Codex' || cliName === 'Gemini') {
358
- this.showToast('暂未开放,敬请期待', 'error');
522
+ this.showToast(this.t.notAvailableYet, 'error');
359
523
  this.resetTimer();
360
524
  return;
361
525
  }
@@ -364,7 +528,7 @@ createApp({
364
528
  // 切换 CLI 时重新加载配置
365
529
  await this.loadConfig(cliName.toLowerCase());
366
530
  } else {
367
- this.showToast('功能暂未开放,敬请期待!', 'error');
531
+ this.showToast(this.t.notAvailableYet + '!', 'error');
368
532
  }
369
533
  },
370
534
 
@@ -458,7 +622,7 @@ createApp({
458
622
  // 重置服务器倒计时
459
623
  this.resetTimer();
460
624
  } catch (err) {
461
- this.showToast('保存失败: ' + (err.response?.data?.error || err.message), 'error');
625
+ this.showToast(this.t.saveFailed + ': ' + (err.response?.data?.error || err.message), 'error');
462
626
  // 恢复原始数据
463
627
  this.config.AUTH = oldAuth;
464
628
  this.config.activeIndex = oldActiveIndex;
@@ -469,6 +633,11 @@ createApp({
469
633
  }
470
634
  },
471
635
  mounted() {
636
+ // 从 localStorage 读取语言设置
637
+ const savedLang = localStorage.getItem('ccby-lang');
638
+ if (savedLang && (savedLang === 'en' || savedLang === 'zh')) {
639
+ this.currentLang = savedLang;
640
+ }
472
641
  this.loadConfig();
473
642
  },
474
643
  updated() {
@@ -112,6 +112,73 @@ code {
112
112
  }
113
113
  }
114
114
 
115
+ /* 确认对话框 */
116
+ .confirm-dialog-overlay {
117
+ position: fixed;
118
+ top: 0;
119
+ left: 0;
120
+ right: 0;
121
+ bottom: 0;
122
+ background-color: rgba(0, 0, 0, 0.5);
123
+ display: flex;
124
+ align-items: center;
125
+ justify-content: center;
126
+ z-index: 10000;
127
+ }
128
+
129
+ .confirm-dialog {
130
+ background: white;
131
+ border-radius: 12px;
132
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
133
+ min-width: 320px;
134
+ max-width: 400px;
135
+ padding: 1.5rem;
136
+ }
137
+
138
+ .confirm-dialog-content {
139
+ margin-bottom: 1.5rem;
140
+ }
141
+
142
+ .confirm-dialog-content p {
143
+ font-size: 1rem;
144
+ color: #1f2937;
145
+ margin: 0;
146
+ line-height: 1.5;
147
+ }
148
+
149
+ .confirm-dialog-actions {
150
+ display: flex;
151
+ gap: 0.75rem;
152
+ justify-content: flex-end;
153
+ }
154
+
155
+ .confirm-dialog-actions button {
156
+ padding: 0.5rem 1rem;
157
+ border: none;
158
+ border-radius: 6px;
159
+ font-size: 0.875rem;
160
+ cursor: pointer;
161
+ transition: all 0.2s;
162
+ }
163
+
164
+ .btn-cancel {
165
+ background-color: #e5e7eb;
166
+ color: #374151;
167
+ }
168
+
169
+ .btn-cancel:hover {
170
+ background-color: #d1d5db;
171
+ }
172
+
173
+ .btn-confirm {
174
+ background-color: #ef4444;
175
+ color: white;
176
+ }
177
+
178
+ .btn-confirm:hover {
179
+ background-color: #dc2626;
180
+ }
181
+
115
182
  /* 容器布局 */
116
183
  .app-container {
117
184
  min-height: 100vh;
@@ -132,6 +199,12 @@ code {
132
199
  margin-bottom: 1.5rem;
133
200
  }
134
201
 
202
+ .title-group {
203
+ display: flex;
204
+ align-items: center;
205
+ gap: 20px;
206
+ }
207
+
135
208
  .page-title {
136
209
  font-size: 2rem;
137
210
  font-weight: bold;
@@ -148,6 +221,34 @@ code {
148
221
  padding: 1.5px;
149
222
  }
150
223
 
224
+ /* 语言选择器 */
225
+ .lang-selector {
226
+ display: flex;
227
+ gap: 2px;
228
+ background-color: #e5e7eb;
229
+ border-radius: 4px;
230
+ padding: 1px;
231
+ margin-left: 0;
232
+ }
233
+
234
+ .lang-btn {
235
+ background: none;
236
+ border: none;
237
+ padding: 4px 8px;
238
+ cursor: pointer;
239
+ border-radius: 4px;
240
+ color: #6b7280;
241
+ font-size: 0.75rem;
242
+ transition: all 0.2s;
243
+ min-width: 50px;
244
+ text-align: center;
245
+ }
246
+
247
+ .lang-btn-active {
248
+ background-color: #3b82f6;
249
+ color: white;
250
+ }
251
+
151
252
  .cli-btn {
152
253
  display: flex;
153
254
  align-items: center;