easycode-ai 1.1.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/LICENSE +202 -0
- package/README.md +1344 -0
- package/bundle/assets/help/cli-help-knowledge.md +1971 -0
- package/bundle/assets/sounds/confirmation-required.wav +0 -0
- package/bundle/assets/sounds/response-complete.wav +0 -0
- package/bundle/assets/sounds/selection-made.wav +0 -0
- package/bundle/dvcode.js +14 -0
- package/bundle/easycode.js +7450 -0
- package/bundle/fix-binary-permissions.js +215 -0
- package/bundle/login/templates/authSelectPage.html +1123 -0
- package/bundle/login/templates/deepv.ico +0 -0
- package/bundle/login/templates/feishu.ico +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/darwin-arm64-rg +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/darwin-x64-rg +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/linux-arm-rg +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/linux-arm64-rg +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/linux-x64-rg +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/rg.exe +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/win32-arm64-rg.exe +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/win32-ia32-rg.exe +0 -0
- package/bundle/node_modules/@vscode/ripgrep/bin/win32-x64-rg.exe +0 -0
- package/bundle/node_modules/@vscode/ripgrep/lib/download.js +357 -0
- package/bundle/node_modules/@vscode/ripgrep/lib/index.d.ts +1 -0
- package/bundle/node_modules/@vscode/ripgrep/lib/index.js +42 -0
- package/bundle/node_modules/@vscode/ripgrep/lib/postinstall.js +121 -0
- package/bundle/node_modules/@vscode/ripgrep/package.json +24 -0
- package/bundle/sandbox-macos-permissive-closed.sb +26 -0
- package/bundle/sandbox-macos-permissive-open.sb +19 -0
- package/bundle/sandbox-macos-permissive-proxied.sb +31 -0
- package/bundle/sandbox-macos-restrictive-closed.sb +87 -0
- package/bundle/sandbox-macos-restrictive-open.sb +90 -0
- package/bundle/sandbox-macos-restrictive-proxied.sb +92 -0
- package/package.json +156 -0
|
@@ -0,0 +1,1123 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title data-i18n="auth.page.title">Choose Authentication Method</title>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
* {
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 0;
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
body {
|
|
14
|
+
font-family: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
|
|
15
|
+
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
|
16
|
+
min-height: 100vh;
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
padding: 40px 20px;
|
|
21
|
+
color: #1e293b;
|
|
22
|
+
line-height: 1.6;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.container {
|
|
26
|
+
background: #ffffff;
|
|
27
|
+
border-radius: 20px;
|
|
28
|
+
padding: 64px 48px;
|
|
29
|
+
max-width: 480px;
|
|
30
|
+
width: 100%;
|
|
31
|
+
box-shadow:
|
|
32
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.05),
|
|
33
|
+
0 2px 4px -1px rgba(0, 0, 0, 0.03);
|
|
34
|
+
border: 1px solid #f1f5f9;
|
|
35
|
+
text-align: center;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.title {
|
|
39
|
+
font-size: 36px;
|
|
40
|
+
font-weight: 800;
|
|
41
|
+
color: #0f172a;
|
|
42
|
+
margin-bottom: 16px;
|
|
43
|
+
letter-spacing: -0.025em;
|
|
44
|
+
line-height: 1.2;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.subtitle {
|
|
48
|
+
color: #64748b;
|
|
49
|
+
font-size: 18px;
|
|
50
|
+
font-weight: 400;
|
|
51
|
+
margin-bottom: 48px;
|
|
52
|
+
line-height: 1.5;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.auth-button {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: flex-start;
|
|
59
|
+
gap: 16px;
|
|
60
|
+
width: 100%;
|
|
61
|
+
padding: 20px 32px;
|
|
62
|
+
margin: 20px 0;
|
|
63
|
+
border: none;
|
|
64
|
+
border-radius: 12px;
|
|
65
|
+
font-size: 17px;
|
|
66
|
+
font-weight: 600;
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
text-decoration: none;
|
|
69
|
+
transition: all 0.15s ease;
|
|
70
|
+
position: relative;
|
|
71
|
+
font-family: inherit;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.feishu-btn {
|
|
75
|
+
background: #ffffff;
|
|
76
|
+
color: #374151;
|
|
77
|
+
border: 2px solid #e5e7eb;
|
|
78
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.feishu-btn:hover {
|
|
82
|
+
background: #f9fafb;
|
|
83
|
+
border-color: #0ea5e9;
|
|
84
|
+
color: #0ea5e9;
|
|
85
|
+
transform: translateY(-1px);
|
|
86
|
+
box-shadow: 0 4px 12px rgba(14, 165, 233, 0.15);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.feishu-btn:active {
|
|
90
|
+
transform: translateY(0);
|
|
91
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.deepvlab-btn {
|
|
95
|
+
background: #ffffff;
|
|
96
|
+
color: #374151;
|
|
97
|
+
border: 2px solid #e5e7eb;
|
|
98
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.deepvlab-btn:hover {
|
|
102
|
+
background: #f9fafb;
|
|
103
|
+
border-color: #1e293b;
|
|
104
|
+
color: #1e293b;
|
|
105
|
+
transform: translateY(-1px);
|
|
106
|
+
box-shadow: 0 4px 12px rgba(30, 41, 59, 0.15);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.deepvlab-btn:active {
|
|
110
|
+
transform: translateY(0);
|
|
111
|
+
box-shadow: 0 2px 4px rgba(30, 41, 59, 0.1);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.cheetah-btn {
|
|
115
|
+
background: #ffffff;
|
|
116
|
+
color: #374151;
|
|
117
|
+
border: 2px solid #e5e7eb;
|
|
118
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.cheetah-btn:hover {
|
|
122
|
+
background: #f9fafb;
|
|
123
|
+
border-color: #ff6b35;
|
|
124
|
+
color: #ff6b35;
|
|
125
|
+
transform: translateY(-1px);
|
|
126
|
+
box-shadow: 0 4px 12px rgba(255, 107, 53, 0.15);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.cheetah-btn:active {
|
|
130
|
+
transform: translateY(0);
|
|
131
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.vipcard-btn {
|
|
135
|
+
background: #ffffff;
|
|
136
|
+
color: #374151;
|
|
137
|
+
border: 2px solid #e5e7eb;
|
|
138
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.vipcard-btn:hover {
|
|
142
|
+
background: #f9fafb;
|
|
143
|
+
border-color: #f59e0b;
|
|
144
|
+
color: #d97706;
|
|
145
|
+
transform: translateY(-1px);
|
|
146
|
+
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.15);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.vipcard-btn:active {
|
|
150
|
+
transform: translateY(0);
|
|
151
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.icon {
|
|
155
|
+
width: 22px;
|
|
156
|
+
height: 22px;
|
|
157
|
+
display: inline-block;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.description {
|
|
161
|
+
color: #94a3b8;
|
|
162
|
+
font-size: 15px;
|
|
163
|
+
line-height: 1.6;
|
|
164
|
+
margin-top: 40px;
|
|
165
|
+
padding: 24px;
|
|
166
|
+
background: #f8fafc;
|
|
167
|
+
border-radius: 12px;
|
|
168
|
+
border: 1px solid #e2e8f0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.hidden {
|
|
172
|
+
display: none !important;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* 消息提示样式 */
|
|
176
|
+
.message-overlay {
|
|
177
|
+
position: fixed;
|
|
178
|
+
top: 0;
|
|
179
|
+
left: 0;
|
|
180
|
+
width: 100%;
|
|
181
|
+
height: 100%;
|
|
182
|
+
background: rgba(0, 0, 0, 0.5);
|
|
183
|
+
display: flex;
|
|
184
|
+
justify-content: center;
|
|
185
|
+
align-items: center;
|
|
186
|
+
z-index: 1000;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.message-box {
|
|
190
|
+
background: white;
|
|
191
|
+
border-radius: 12px;
|
|
192
|
+
padding: 32px;
|
|
193
|
+
max-width: 500px;
|
|
194
|
+
width: 90%;
|
|
195
|
+
text-align: center;
|
|
196
|
+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
|
197
|
+
animation: messageSlideIn 0.3s ease-out;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@keyframes messageSlideIn {
|
|
201
|
+
from {
|
|
202
|
+
opacity: 0;
|
|
203
|
+
transform: translateY(-20px) scale(0.95);
|
|
204
|
+
}
|
|
205
|
+
to {
|
|
206
|
+
opacity: 1;
|
|
207
|
+
transform: translateY(0) scale(1);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.message-icon {
|
|
212
|
+
width: 64px;
|
|
213
|
+
height: 64px;
|
|
214
|
+
margin: 0 auto 16px;
|
|
215
|
+
border-radius: 50%;
|
|
216
|
+
display: flex;
|
|
217
|
+
align-items: center;
|
|
218
|
+
justify-content: center;
|
|
219
|
+
font-size: 32px;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.message-icon.success {
|
|
223
|
+
background: #dcfce7;
|
|
224
|
+
color: #16a34a;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.message-icon.error {
|
|
228
|
+
background: #fef2f2;
|
|
229
|
+
color: #dc2626;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.message-title {
|
|
233
|
+
font-size: 20px;
|
|
234
|
+
font-weight: 600;
|
|
235
|
+
margin-bottom: 8px;
|
|
236
|
+
color: #1f2937;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.message-content {
|
|
240
|
+
font-size: 14px;
|
|
241
|
+
color: #6b7280;
|
|
242
|
+
margin-bottom: 24px;
|
|
243
|
+
line-height: 1.5;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.message-button {
|
|
247
|
+
background: #3b82f6;
|
|
248
|
+
color: white;
|
|
249
|
+
border: none;
|
|
250
|
+
border-radius: 8px;
|
|
251
|
+
padding: 12px 24px;
|
|
252
|
+
font-size: 14px;
|
|
253
|
+
font-weight: 500;
|
|
254
|
+
cursor: pointer;
|
|
255
|
+
transition: all 0.2s ease;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.message-button:hover {
|
|
259
|
+
background: #2563eb;
|
|
260
|
+
transform: translateY(-1px);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.message-button:active {
|
|
264
|
+
transform: translateY(0);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* 中国IP限制消息样式 */
|
|
268
|
+
.china-message {
|
|
269
|
+
background: #fef2f2;
|
|
270
|
+
border: 2px solid #fecaca;
|
|
271
|
+
border-radius: 12px;
|
|
272
|
+
padding: 24px;
|
|
273
|
+
margin: 20px 0;
|
|
274
|
+
text-align: center;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.china-message-icon {
|
|
278
|
+
width: 48px;
|
|
279
|
+
height: 48px;
|
|
280
|
+
margin: 0 auto 16px;
|
|
281
|
+
background: #dc2626;
|
|
282
|
+
border-radius: 50%;
|
|
283
|
+
display: flex;
|
|
284
|
+
align-items: center;
|
|
285
|
+
justify-content: center;
|
|
286
|
+
color: white;
|
|
287
|
+
font-size: 24px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.china-message-title {
|
|
291
|
+
font-size: 20px;
|
|
292
|
+
font-weight: 600;
|
|
293
|
+
color: #dc2626;
|
|
294
|
+
margin-bottom: 12px;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.china-message-content {
|
|
298
|
+
color: #7f1d1d;
|
|
299
|
+
font-size: 14px;
|
|
300
|
+
line-height: 1.6;
|
|
301
|
+
margin-bottom: 8px;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.auth-buttons-container {
|
|
305
|
+
/* 用于控制所有登录按钮的显示/隐藏 */
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* 加载中样式 */
|
|
309
|
+
.loading-container {
|
|
310
|
+
display: flex;
|
|
311
|
+
flex-direction: column;
|
|
312
|
+
align-items: center;
|
|
313
|
+
padding: 40px 20px;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.loading-spinner {
|
|
317
|
+
width: 40px;
|
|
318
|
+
height: 40px;
|
|
319
|
+
border: 3px solid #e2e8f0;
|
|
320
|
+
border-top: 3px solid #3b82f6;
|
|
321
|
+
border-radius: 50%;
|
|
322
|
+
animation: spin 1s linear infinite;
|
|
323
|
+
margin-bottom: 16px;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@keyframes spin {
|
|
327
|
+
0% { transform: rotate(0deg); }
|
|
328
|
+
100% { transform: rotate(360deg); }
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.loading-text {
|
|
332
|
+
color: #64748b;
|
|
333
|
+
font-size: 16px;
|
|
334
|
+
font-weight: 500;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* 猎豹OA表单样式 */
|
|
338
|
+
.cheetah-form {
|
|
339
|
+
margin-top: 24px;
|
|
340
|
+
padding: 24px;
|
|
341
|
+
background: #f8fafc;
|
|
342
|
+
border-radius: 12px;
|
|
343
|
+
border: 1px solid #e2e8f0;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.cheetah-form h3 {
|
|
347
|
+
margin: 0 0 20px 0;
|
|
348
|
+
color: #1e293b;
|
|
349
|
+
font-size: 18px;
|
|
350
|
+
font-weight: 600;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.form-group {
|
|
354
|
+
margin-bottom: 16px;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.form-group label {
|
|
358
|
+
display: block;
|
|
359
|
+
margin-bottom: 6px;
|
|
360
|
+
color: #374151;
|
|
361
|
+
font-weight: 500;
|
|
362
|
+
font-size: 14px;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.form-group input {
|
|
366
|
+
width: 100%;
|
|
367
|
+
padding: 12px 16px;
|
|
368
|
+
border: 1px solid #d1d5db;
|
|
369
|
+
border-radius: 8px;
|
|
370
|
+
font-size: 14px;
|
|
371
|
+
transition: all 0.2s ease;
|
|
372
|
+
background: white;
|
|
373
|
+
box-sizing: border-box;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.form-group input:focus {
|
|
377
|
+
outline: none;
|
|
378
|
+
border-color: #ff6b35;
|
|
379
|
+
box-shadow: 0 0 0 3px rgba(255, 107, 53, 0.1);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/* VIP卡表单特殊样式 */
|
|
383
|
+
.vipcard-form .form-group input:focus {
|
|
384
|
+
border-color: #f59e0b;
|
|
385
|
+
box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.vipcard-form .btn-primary {
|
|
389
|
+
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.vipcard-form .btn-primary:hover:not(:disabled) {
|
|
393
|
+
background: linear-gradient(135deg, #d97706 0%, #b45309 100%);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.vipcard-hint {
|
|
397
|
+
font-size: 12px;
|
|
398
|
+
color: #9ca3af;
|
|
399
|
+
margin-top: 8px;
|
|
400
|
+
text-align: left;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.form-actions {
|
|
404
|
+
display: flex;
|
|
405
|
+
gap: 12px;
|
|
406
|
+
margin-top: 20px;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.btn-primary, .btn-secondary {
|
|
410
|
+
flex: 1;
|
|
411
|
+
padding: 12px 20px;
|
|
412
|
+
border-radius: 8px;
|
|
413
|
+
font-size: 14px;
|
|
414
|
+
font-weight: 500;
|
|
415
|
+
cursor: pointer;
|
|
416
|
+
transition: all 0.2s ease;
|
|
417
|
+
border: none;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.btn-primary {
|
|
421
|
+
background: linear-gradient(135deg, #ff6b35 0%, #f7931e 100%);
|
|
422
|
+
color: white;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.btn-primary:hover:not(:disabled) {
|
|
426
|
+
background: linear-gradient(135deg, #e55a2b 0%, #de831a 100%);
|
|
427
|
+
transform: translateY(-1px);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.btn-primary:disabled {
|
|
431
|
+
background: linear-gradient(135deg, #d1d5db 0%, #9ca3af 100%);
|
|
432
|
+
cursor: not-allowed;
|
|
433
|
+
opacity: 0.6;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.btn-secondary {
|
|
437
|
+
background: #f1f5f9;
|
|
438
|
+
color: #64748b;
|
|
439
|
+
border: 1px solid #e2e8f0;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.btn-secondary:hover:not(:disabled) {
|
|
443
|
+
background: #e2e8f0;
|
|
444
|
+
color: #475569;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.btn-secondary:disabled {
|
|
448
|
+
background: #f8fafc;
|
|
449
|
+
color: #cbd5e1;
|
|
450
|
+
cursor: not-allowed;
|
|
451
|
+
opacity: 0.6;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
@media (max-width: 480px) {
|
|
455
|
+
body {
|
|
456
|
+
padding: 20px 16px;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.container {
|
|
460
|
+
padding: 40px 32px;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.title {
|
|
464
|
+
font-size: 32px;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.subtitle {
|
|
468
|
+
font-size: 16px;
|
|
469
|
+
margin-bottom: 36px;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.auth-button {
|
|
473
|
+
padding: 18px 24px;
|
|
474
|
+
font-size: 16px;
|
|
475
|
+
gap: 12px;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.description {
|
|
479
|
+
margin-top: 32px;
|
|
480
|
+
padding: 20px;
|
|
481
|
+
font-size: 14px;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* 加载动画 */
|
|
486
|
+
@keyframes fadeInUp {
|
|
487
|
+
from {
|
|
488
|
+
opacity: 0;
|
|
489
|
+
transform: translateY(20px);
|
|
490
|
+
}
|
|
491
|
+
to {
|
|
492
|
+
opacity: 1;
|
|
493
|
+
transform: translateY(0);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.container {
|
|
498
|
+
animation: fadeInUp 0.4s ease;
|
|
499
|
+
}
|
|
500
|
+
</style>
|
|
501
|
+
</head>
|
|
502
|
+
<body>
|
|
503
|
+
<div class="container">
|
|
504
|
+
<h1 class="title" data-i18n="auth.page.title">Choose Authentication</h1>
|
|
505
|
+
<p class="subtitle" data-i18n="auth.page.description">Select your preferred login method to continue</p>
|
|
506
|
+
|
|
507
|
+
<!-- 加载中效果 -->
|
|
508
|
+
<div id="loading-container" class="loading-container">
|
|
509
|
+
<div class="loading-spinner"></div>
|
|
510
|
+
<div class="loading-text" data-i18n="auth.loading.text">Checking access permissions...</div>
|
|
511
|
+
</div>
|
|
512
|
+
|
|
513
|
+
<!-- 中国IP限制消息 -->
|
|
514
|
+
<div id="china-message" class="china-message hidden">
|
|
515
|
+
<div class="china-message-icon">⚠️</div>
|
|
516
|
+
<div class="china-message-title" data-i18n="auth.china.restriction.title">Access Restricted</div>
|
|
517
|
+
<div id="china-message-content" class="china-message-content">
|
|
518
|
+
<!-- 动态加载后台消息 -->
|
|
519
|
+
</div>
|
|
520
|
+
</div>
|
|
521
|
+
|
|
522
|
+
<!-- 登录按钮容器 -->
|
|
523
|
+
<div id="auth-buttons-container" class="auth-buttons-container hidden">
|
|
524
|
+
<!-- 飞书登录按钮区域(动态生成,支持多租户) -->
|
|
525
|
+
<div id="feishu-buttons-container"></div>
|
|
526
|
+
|
|
527
|
+
<button class="auth-button deepvlab-btn" onclick="startDeepvlabAuth()">
|
|
528
|
+
<img class="icon" src="https://res.ainirobot.com/orics/down/v2_k005_20250904_52ad718e/deepv.ico" alt="DeepV" />
|
|
529
|
+
<span data-i18n="auth.deepvlab.button">DeepVlab Unified Login</span>
|
|
530
|
+
</button>
|
|
531
|
+
|
|
532
|
+
<button id="cheetah-btn" class="auth-button cheetah-btn hidden" onclick="startCheetahAuth()">
|
|
533
|
+
<img class="icon" src="https://www.cmcm.com/favicon.ico" alt="Cheetah" />
|
|
534
|
+
<span data-i18n="auth.cheetah.button">Cheetah OA Login</span>
|
|
535
|
+
</button>
|
|
536
|
+
|
|
537
|
+
<button id="vipcard-btn" class="auth-button vipcard-btn" onclick="startVipCardAuth()">
|
|
538
|
+
<span class="icon" style="font-size: 20px;">🎫</span>
|
|
539
|
+
<span data-i18n="auth.vipcard.button">VIP Card Login</span>
|
|
540
|
+
</button>
|
|
541
|
+
|
|
542
|
+
<!-- 猎豹OA登录表单 -->
|
|
543
|
+
<div id="cheetah-form" class="cheetah-form hidden">
|
|
544
|
+
<h3 data-i18n="auth.cheetah.form.title">Cheetah OA Login</h3>
|
|
545
|
+
<form id="cheetah-login-form" onsubmit="submitCheetahAuth(event)">
|
|
546
|
+
<div class="form-group">
|
|
547
|
+
<label for="cheetah-email" data-i18n="auth.cheetah.form.email">Email:</label>
|
|
548
|
+
<input type="email" id="cheetah-email" name="email" required placeholder="user@cmcm.com" />
|
|
549
|
+
</div>
|
|
550
|
+
<div class="form-group">
|
|
551
|
+
<label for="cheetah-password" data-i18n="auth.cheetah.form.password">Password:</label>
|
|
552
|
+
<input type="password" id="cheetah-password" name="password" required />
|
|
553
|
+
</div>
|
|
554
|
+
<div class="form-actions">
|
|
555
|
+
<button type="button" class="btn-secondary" onclick="cancelCheetahAuth()" data-i18n="auth.cheetah.form.cancel">Cancel</button>
|
|
556
|
+
<button type="submit" class="btn-primary" data-i18n="auth.cheetah.form.submit">Login</button>
|
|
557
|
+
</div>
|
|
558
|
+
</form>
|
|
559
|
+
</div>
|
|
560
|
+
|
|
561
|
+
<!-- VIP卡登录表单 -->
|
|
562
|
+
<div id="vipcard-form" class="cheetah-form vipcard-form hidden">
|
|
563
|
+
<h3 data-i18n="auth.vipcard.form.title">VIP Card Activation & Login</h3>
|
|
564
|
+
<form id="vipcard-login-form" onsubmit="submitVipCardAuth(event)">
|
|
565
|
+
<div class="form-group">
|
|
566
|
+
<label for="vipcard-code" data-i18n="auth.vipcard.form.code">Redemption Code:</label>
|
|
567
|
+
<input type="text" id="vipcard-code" name="code" required placeholder="VIP-XXXXXXXX" style="text-transform: uppercase;" />
|
|
568
|
+
<div class="vipcard-hint" data-i18n="auth.vipcard.form.hint">Enter the code from your VIP card</div>
|
|
569
|
+
</div>
|
|
570
|
+
<div class="form-actions">
|
|
571
|
+
<button type="button" class="btn-secondary" onclick="cancelVipCardAuth()" data-i18n="auth.vipcard.form.cancel">Cancel</button>
|
|
572
|
+
<button type="submit" class="btn-primary" data-i18n="auth.vipcard.form.submit">Activate & Login</button>
|
|
573
|
+
</div>
|
|
574
|
+
</form>
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
|
|
578
|
+
<div class="description" data-i18n="auth.page.instruction">
|
|
579
|
+
Choose your authentication method and we will guide you through the secure login process
|
|
580
|
+
</div>
|
|
581
|
+
</div>
|
|
582
|
+
|
|
583
|
+
<script>
|
|
584
|
+
// 国际化翻译对象
|
|
585
|
+
const translations = {
|
|
586
|
+
en: {
|
|
587
|
+
'auth.page.title': 'Choose Authentication',
|
|
588
|
+
'auth.page.description': 'Select your preferred login method to continue',
|
|
589
|
+
'auth.feishu.button': 'Feishu Login',
|
|
590
|
+
'auth.deepvlab.button': 'DeepVlab Unified Login',
|
|
591
|
+
'auth.cheetah.button': 'Cheetah OA Login',
|
|
592
|
+
'auth.cheetah.form.title': 'Cheetah OA Login',
|
|
593
|
+
'auth.cheetah.form.email': 'Email',
|
|
594
|
+
'auth.cheetah.form.password': 'Password',
|
|
595
|
+
'auth.cheetah.form.cancel': 'Cancel',
|
|
596
|
+
'auth.cheetah.form.submit': 'Login',
|
|
597
|
+
'auth.cheetah.form.submitting': 'Logging in...',
|
|
598
|
+
'auth.page.instruction': 'Choose your authentication method and we will guide you through the secure login process',
|
|
599
|
+
'auth.loading.text': 'Checking access permissions...',
|
|
600
|
+
'auth.china.restriction.title': 'Access Restricted',
|
|
601
|
+
'auth.feishu.start.error': 'Failed to start Feishu authentication, please try again',
|
|
602
|
+
'auth.deepvlab.start.error': 'Failed to start DeepVlab authentication, please try again',
|
|
603
|
+
'auth.cheetah.start.error': 'Failed to login with Cheetah OA, please check your credentials',
|
|
604
|
+
'auth.message.success.title': 'Login Successful!',
|
|
605
|
+
'auth.message.success.content': 'You have successfully logged in with Cheetah OA. You can now close this window and continue using DeepV Code.',
|
|
606
|
+
'auth.message.success.button': 'Close',
|
|
607
|
+
'auth.message.error.login.title': 'Login Failed',
|
|
608
|
+
'auth.message.error.login.content': 'Cheetah OA authentication failed. Please check your credentials and try again.',
|
|
609
|
+
'auth.message.error.login.button': 'Try Again',
|
|
610
|
+
'auth.message.error.input.title': 'Input Required',
|
|
611
|
+
'auth.message.error.input.content': 'Please fill in both email and password fields.',
|
|
612
|
+
'auth.message.error.input.button': 'OK',
|
|
613
|
+
'auth.message.error.connection.title': 'Connection Error',
|
|
614
|
+
'auth.message.error.connection.content': 'Unable to connect to authentication server. Please check your network connection and try again.',
|
|
615
|
+
'auth.message.error.connection.button': 'Retry',
|
|
616
|
+
'auth.message.error.feishu.content': 'Unable to start Feishu authentication. Please check your network connection and try again.',
|
|
617
|
+
'auth.message.error.deepvlab.content': 'Unable to start DeepVlab authentication. Please check your network connection and try again.',
|
|
618
|
+
'auth.vipcard.button': 'VIP Card Login',
|
|
619
|
+
'auth.vipcard.form.title': 'VIP Card Activation & Login',
|
|
620
|
+
'auth.vipcard.form.code': 'Redemption Code',
|
|
621
|
+
'auth.vipcard.form.hint': 'Enter the code from your VIP card',
|
|
622
|
+
'auth.vipcard.form.cancel': 'Cancel',
|
|
623
|
+
'auth.vipcard.form.submit': 'Activate & Login',
|
|
624
|
+
'auth.vipcard.form.submitting': 'Processing...',
|
|
625
|
+
'auth.vipcard.success.title': 'Activation Successful!',
|
|
626
|
+
'auth.vipcard.success.content': 'Your VIP card has been activated and you are now logged in. You can close this window and continue using DeepV Code.',
|
|
627
|
+
'auth.vipcard.error.empty': 'Please enter the redemption code.',
|
|
628
|
+
'auth.vipcard.error.invalid': 'Invalid or expired redemption code. Please check and try again.'
|
|
629
|
+
},
|
|
630
|
+
zh: {
|
|
631
|
+
'auth.page.title': '选择认证方式',
|
|
632
|
+
'auth.page.description': '选择您偏好的登录方式以继续',
|
|
633
|
+
'auth.feishu.button': '飞书登录',
|
|
634
|
+
'auth.deepvlab.button': 'DeepVlab统一登录',
|
|
635
|
+
'auth.cheetah.button': '猎豹OA登录',
|
|
636
|
+
'auth.cheetah.form.title': '猎豹OA登录',
|
|
637
|
+
'auth.cheetah.form.email': '邮箱',
|
|
638
|
+
'auth.cheetah.form.password': '密码',
|
|
639
|
+
'auth.cheetah.form.cancel': '取消',
|
|
640
|
+
'auth.cheetah.form.submit': '登录',
|
|
641
|
+
'auth.cheetah.form.submitting': '登录中...',
|
|
642
|
+
'auth.page.instruction': '选择您的认证方式,我们将引导您完成安全的登录流程',
|
|
643
|
+
'auth.loading.text': '正在检查访问权限...',
|
|
644
|
+
'auth.china.restriction.title': '访问受限',
|
|
645
|
+
'auth.feishu.start.error': '飞书认证启动失败,请重试',
|
|
646
|
+
'auth.deepvlab.start.error': 'DeepVlab认证启动失败,请重试',
|
|
647
|
+
'auth.cheetah.start.error': '猎豹OA登录失败,请检查您的凭据',
|
|
648
|
+
'auth.message.success.title': '登录成功!',
|
|
649
|
+
'auth.message.success.content': '您已成功使用猎豹OA登录。现在可以关闭此窗口并继续使用DeepV Code。',
|
|
650
|
+
'auth.message.success.button': '关闭',
|
|
651
|
+
'auth.message.error.login.title': '登录失败',
|
|
652
|
+
'auth.message.error.login.content': '猎豹OA认证失败。请检查您的凭据并重试。',
|
|
653
|
+
'auth.message.error.login.button': '重试',
|
|
654
|
+
'auth.message.error.input.title': '需要输入',
|
|
655
|
+
'auth.message.error.input.content': '请填写邮箱和密码字段。',
|
|
656
|
+
'auth.message.error.input.button': '确定',
|
|
657
|
+
'auth.message.error.connection.title': '连接错误',
|
|
658
|
+
'auth.message.error.connection.content': '无法连接到认证服务器。请检查您的网络连接并重试。',
|
|
659
|
+
'auth.message.error.connection.button': '重试',
|
|
660
|
+
'auth.message.error.feishu.content': '无法启动飞书认证。请检查您的网络连接并重试。',
|
|
661
|
+
'auth.message.error.deepvlab.content': '无法启动DeepVlab认证。请检查您的网络连接并重试。',
|
|
662
|
+
'auth.vipcard.button': 'VIP卡登录',
|
|
663
|
+
'auth.vipcard.form.title': 'VIP卡激活与登录',
|
|
664
|
+
'auth.vipcard.form.code': '兑换码',
|
|
665
|
+
'auth.vipcard.form.hint': '请输入VIP卡上的兑换码',
|
|
666
|
+
'auth.vipcard.form.cancel': '取消',
|
|
667
|
+
'auth.vipcard.form.submit': '激活并登录',
|
|
668
|
+
'auth.vipcard.form.submitting': '处理中...',
|
|
669
|
+
'auth.vipcard.success.title': '激活成功!',
|
|
670
|
+
'auth.vipcard.success.content': '您的VIP卡已激活并完成登录。现在可以关闭此窗口并继续使用DeepV Code。',
|
|
671
|
+
'auth.vipcard.error.empty': '请输入兑换码。',
|
|
672
|
+
'auth.vipcard.error.invalid': '兑换码无效或已过期,请检查后重试。'
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
// 获取浏览器语言
|
|
677
|
+
function getBrowserLanguage() {
|
|
678
|
+
const lang = navigator.language || navigator.userLanguage;
|
|
679
|
+
return lang.startsWith('zh') ? 'zh' : 'en';
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// 翻译函数
|
|
683
|
+
function t(key) {
|
|
684
|
+
const locale = getBrowserLanguage();
|
|
685
|
+
return translations[locale][key] || translations.en[key] || key;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// 初始化页面文本
|
|
689
|
+
function initI18n() {
|
|
690
|
+
document.querySelectorAll('[data-i18n]').forEach(element => {
|
|
691
|
+
const key = element.getAttribute('data-i18n');
|
|
692
|
+
element.textContent = t(key);
|
|
693
|
+
// 同时更新title属性(如果是title标签)
|
|
694
|
+
if (element.tagName === 'TITLE') {
|
|
695
|
+
document.title = t(key);
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// 消息提示函数
|
|
701
|
+
function showMessage(type, title, content, buttonText = 'OK', options = {}) {
|
|
702
|
+
const { closable = true } = options;
|
|
703
|
+
|
|
704
|
+
// 创建消息覆盖层
|
|
705
|
+
const overlay = document.createElement('div');
|
|
706
|
+
overlay.className = 'message-overlay';
|
|
707
|
+
|
|
708
|
+
// 创建消息框
|
|
709
|
+
const messageBox = document.createElement('div');
|
|
710
|
+
messageBox.className = 'message-box';
|
|
711
|
+
|
|
712
|
+
// 图标
|
|
713
|
+
const icon = document.createElement('div');
|
|
714
|
+
icon.className = `message-icon ${type}`;
|
|
715
|
+
icon.innerHTML = type === 'success' ? '✓' : '✕';
|
|
716
|
+
|
|
717
|
+
// 标题
|
|
718
|
+
const titleEl = document.createElement('div');
|
|
719
|
+
titleEl.className = 'message-title';
|
|
720
|
+
titleEl.textContent = title;
|
|
721
|
+
|
|
722
|
+
// 内容
|
|
723
|
+
const contentEl = document.createElement('div');
|
|
724
|
+
contentEl.className = 'message-content';
|
|
725
|
+
contentEl.textContent = content;
|
|
726
|
+
|
|
727
|
+
// 组装消息框
|
|
728
|
+
messageBox.appendChild(icon);
|
|
729
|
+
messageBox.appendChild(titleEl);
|
|
730
|
+
messageBox.appendChild(contentEl);
|
|
731
|
+
|
|
732
|
+
// 按钮(仅在允许关闭时显示)
|
|
733
|
+
if (closable) {
|
|
734
|
+
const button = document.createElement('button');
|
|
735
|
+
button.className = 'message-button';
|
|
736
|
+
button.textContent = buttonText;
|
|
737
|
+
button.onclick = () => {
|
|
738
|
+
document.body.removeChild(overlay);
|
|
739
|
+
};
|
|
740
|
+
messageBox.appendChild(button);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
overlay.appendChild(messageBox);
|
|
744
|
+
|
|
745
|
+
// 添加到页面
|
|
746
|
+
document.body.appendChild(overlay);
|
|
747
|
+
|
|
748
|
+
// 点击覆盖层关闭(仅在允许关闭时)
|
|
749
|
+
if (closable) {
|
|
750
|
+
overlay.onclick = (e) => {
|
|
751
|
+
if (e.target === overlay) {
|
|
752
|
+
document.body.removeChild(overlay);
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// 页面加载时初始化i18n和检查登录权限
|
|
759
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
760
|
+
initI18n();
|
|
761
|
+
checkFeishuAllowed(); // 这个函数会自动调用checkCheetahAllowed
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
function checkFeishuAllowed() {
|
|
765
|
+
console.log('🔍 开始检查飞书登录权限...');
|
|
766
|
+
console.log('📡 调用API: /api/backend/feishu-allowed');
|
|
767
|
+
|
|
768
|
+
// Call the backend server to check if Feishu login is allowed
|
|
769
|
+
fetch('/api/backend/feishu-allowed')
|
|
770
|
+
.then(response => {
|
|
771
|
+
console.log('🌐 接口响应状态:', response.status);
|
|
772
|
+
console.log('✅ 进入第一个then块');
|
|
773
|
+
return response.json();
|
|
774
|
+
})
|
|
775
|
+
.then(data => {
|
|
776
|
+
console.log('✅ 进入第二个then块 - 开始处理数据');
|
|
777
|
+
console.log('📋 后台接口返回完整数据:', JSON.stringify(data, null, 2));
|
|
778
|
+
|
|
779
|
+
// 隐藏加载中效果
|
|
780
|
+
console.log('🔄 开始隐藏loading效果...');
|
|
781
|
+
const loadingContainer = document.getElementById('loading-container');
|
|
782
|
+
console.log('🔍 loading容器元素:', loadingContainer);
|
|
783
|
+
if (loadingContainer) {
|
|
784
|
+
console.log('⏳ loading容器存在,添加hidden类');
|
|
785
|
+
loadingContainer.classList.add('hidden');
|
|
786
|
+
// 双重保险:直接设置display样式
|
|
787
|
+
loadingContainer.style.display = 'none';
|
|
788
|
+
console.log('✅ loading hidden类已添加,display设置为none');
|
|
789
|
+
console.log('🎨 loading容器当前className:', loadingContainer.className);
|
|
790
|
+
console.log('🎨 loading容器当前style.display:', loadingContainer.style.display);
|
|
791
|
+
} else {
|
|
792
|
+
console.error('❌ 未找到loading容器元素!');
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// 检查是否是中国IP且不允许登录
|
|
796
|
+
if (data.isChina && !data.feishuLoginAllowed && data.messages && data.messages.length > 0) {
|
|
797
|
+
console.log('🇨🇳 检测到中国IP且不允许登录,显示限制消息');
|
|
798
|
+
|
|
799
|
+
// 显示中国IP限制消息
|
|
800
|
+
const chinaMessage = document.getElementById('china-message');
|
|
801
|
+
const chinaMessageContent = document.getElementById('china-message-content');
|
|
802
|
+
|
|
803
|
+
if (chinaMessage && chinaMessageContent) {
|
|
804
|
+
// 填充消息内容
|
|
805
|
+
chinaMessageContent.innerHTML = data.messages.map(msg => `<p>${msg}</p>`).join('');
|
|
806
|
+
|
|
807
|
+
// 显示消息框
|
|
808
|
+
chinaMessage.classList.remove('hidden');
|
|
809
|
+
console.log('✅ 已显示中国IP限制消息');
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// 登录按钮保持隐藏状态(默认就是隐藏的)
|
|
813
|
+
} else {
|
|
814
|
+
console.log('✅ 非中国IP,显示登录选项');
|
|
815
|
+
|
|
816
|
+
// 显示登录按钮容器
|
|
817
|
+
const authButtonsContainer = document.getElementById('auth-buttons-container');
|
|
818
|
+
if (authButtonsContainer) {
|
|
819
|
+
authButtonsContainer.classList.remove('hidden');
|
|
820
|
+
console.log('✅ 已显示登录按钮容器');
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// DeepVlab登录始终可用(没有hidden类,会自动显示)
|
|
824
|
+
console.log('✅ DeepVlab登录始终可用');
|
|
825
|
+
|
|
826
|
+
// 根据权限显示飞书登录按钮(动态获取租户列表)
|
|
827
|
+
if (data.feishuLoginAllowed) {
|
|
828
|
+
loadFeishuTenants();
|
|
829
|
+
} else {
|
|
830
|
+
console.log('🚫 飞书登录被禁用,保持飞书按钮隐藏');
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// 检查猎豹OA登录权限(使用相同的数据)
|
|
834
|
+
checkCheetahAllowed(data);
|
|
835
|
+
}
|
|
836
|
+
})
|
|
837
|
+
.catch(error => {
|
|
838
|
+
console.error('❌ 检查飞书登录权限失败:', error);
|
|
839
|
+
console.log('🔄 进入catch块 - API调用失败');
|
|
840
|
+
|
|
841
|
+
// 隐藏加载中效果
|
|
842
|
+
console.log('🔄 catch块中开始隐藏loading效果...');
|
|
843
|
+
const loadingContainer = document.getElementById('loading-container');
|
|
844
|
+
console.log('🔍 catch块中loading容器元素:', loadingContainer);
|
|
845
|
+
if (loadingContainer) {
|
|
846
|
+
console.log('⏳ catch块中loading容器存在,添加hidden类');
|
|
847
|
+
loadingContainer.classList.add('hidden');
|
|
848
|
+
// 双重保险:直接设置display样式
|
|
849
|
+
loadingContainer.style.display = 'none';
|
|
850
|
+
console.log('✅ catch块中loading hidden类已添加,display设置为none');
|
|
851
|
+
} else {
|
|
852
|
+
console.error('❌ catch块中未找到loading容器元素!');
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// 出错时显示登录按钮容器(保守处理)
|
|
856
|
+
const authButtonsContainer = document.getElementById('auth-buttons-container');
|
|
857
|
+
if (authButtonsContainer) {
|
|
858
|
+
authButtonsContainer.classList.remove('hidden');
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
console.log('🔄 失败时显示所有登录选项');
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function checkCheetahAllowed(data) {
|
|
866
|
+
console.log('🔍 开始检查猎豹OA登录权限...');
|
|
867
|
+
|
|
868
|
+
// 使用与飞书相同的权限检查逻辑
|
|
869
|
+
if (data && !data.isChina && data.feishuLoginAllowed) {
|
|
870
|
+
console.log('✅ 猎豹OA登录已允许,显示登录按钮');
|
|
871
|
+
// 显示猎豹OA登录按钮
|
|
872
|
+
const cheetahBtn = document.getElementById('cheetah-btn');
|
|
873
|
+
if (cheetahBtn) {
|
|
874
|
+
cheetahBtn.classList.remove('hidden');
|
|
875
|
+
console.log('✅ 猎豹OA登录按钮已显示');
|
|
876
|
+
} else {
|
|
877
|
+
console.warn('⚠️ 未找到猎豹OA登录按钮元素');
|
|
878
|
+
}
|
|
879
|
+
} else {
|
|
880
|
+
console.log('🚫 猎豹OA登录被禁用,保持按钮隐藏');
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function loadFeishuTenants() {
|
|
885
|
+
fetch('/api/backend/feishu-tenants')
|
|
886
|
+
.then(function(resp) { return resp.json(); })
|
|
887
|
+
.then(function(tenants) {
|
|
888
|
+
renderFeishuButtons(tenants);
|
|
889
|
+
})
|
|
890
|
+
.catch(function() {
|
|
891
|
+
console.log('⚠️ 无法获取租户列表,显示默认飞书按钮');
|
|
892
|
+
renderFeishuButtons([{ appId: '', label: t('auth.feishu.button'), tenantKey: 'main' }]);
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
function renderFeishuButtons(tenants) {
|
|
897
|
+
var container = document.getElementById('feishu-buttons-container');
|
|
898
|
+
if (!container) return;
|
|
899
|
+
container.innerHTML = '';
|
|
900
|
+
if (!tenants || tenants.length === 0) {
|
|
901
|
+
tenants = [{ appId: '', label: t('auth.feishu.button'), tenantKey: 'main' }];
|
|
902
|
+
}
|
|
903
|
+
tenants.forEach(function(tenant) {
|
|
904
|
+
var btn = document.createElement('button');
|
|
905
|
+
btn.className = 'auth-button feishu-btn';
|
|
906
|
+
btn.innerHTML = '<img class="icon" src="https://res.ainirobot.com/orics/down/v2_k005_20250904_c768e6a4/feishu.ico" alt="Feishu" />' +
|
|
907
|
+
'<span>' + (tenant.label || t('auth.feishu.button')) + '</span>';
|
|
908
|
+
btn.onclick = function() { startFeishuAuth(tenant.appId); };
|
|
909
|
+
container.appendChild(btn);
|
|
910
|
+
});
|
|
911
|
+
console.log('✅ 飞书登录按钮已生成,共 ' + tenants.length + ' 个租户');
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
function startFeishuAuth(appId) {
|
|
915
|
+
console.log('启动飞书认证...', appId ? 'appId=' + appId : '默认');
|
|
916
|
+
var body = appId ? JSON.stringify({ appId: appId }) : '{}';
|
|
917
|
+
fetch('/start-feishu-auth', {
|
|
918
|
+
method: 'POST',
|
|
919
|
+
headers: { 'Content-Type': 'application/json' },
|
|
920
|
+
body: body
|
|
921
|
+
})
|
|
922
|
+
.then(response => response.json())
|
|
923
|
+
.then(data => {
|
|
924
|
+
if (data.authUrl) {
|
|
925
|
+
window.location.replace(data.authUrl);
|
|
926
|
+
}
|
|
927
|
+
})
|
|
928
|
+
.catch(error => {
|
|
929
|
+
console.error('飞书认证启动失败:', error);
|
|
930
|
+
showMessage('error', t('auth.message.error.connection.title'), t('auth.message.error.feishu.content'), t('auth.message.error.connection.button'));
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
function startDeepvlabAuth() {
|
|
935
|
+
console.log('启动DeepVlab认证...');
|
|
936
|
+
// 这里会调用DeepVlab认证逻辑
|
|
937
|
+
fetch('/start-deepvlab-auth', { method: 'POST' })
|
|
938
|
+
.then(response => response.json())
|
|
939
|
+
.then(data => {
|
|
940
|
+
if (data.authUrl) {
|
|
941
|
+
// 修复方案:直接替换当前页面到认证URL,避免产生额外的空白页面
|
|
942
|
+
// 这样认证完成后只需要关闭一个页面,不会留下空白的中间页
|
|
943
|
+
window.location.replace(data.authUrl);
|
|
944
|
+
}
|
|
945
|
+
})
|
|
946
|
+
.catch(error => {
|
|
947
|
+
console.error('DeepVlab认证启动失败:', error);
|
|
948
|
+
showMessage('error', t('auth.message.error.connection.title'), t('auth.message.error.deepvlab.content'), t('auth.message.error.connection.button'));
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
function startCheetahAuth() {
|
|
953
|
+
console.log('显示猎豹OA登录表单...');
|
|
954
|
+
// 隐藏所有认证按钮
|
|
955
|
+
const buttons = document.querySelectorAll('.auth-button');
|
|
956
|
+
buttons.forEach(btn => btn.style.display = 'none');
|
|
957
|
+
|
|
958
|
+
// 显示猎豹OA表单
|
|
959
|
+
const form = document.getElementById('cheetah-form');
|
|
960
|
+
if (form) {
|
|
961
|
+
form.classList.remove('hidden');
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
function cancelCheetahAuth() {
|
|
966
|
+
console.log('取消猎豹OA登录...');
|
|
967
|
+
// 隐藏表单
|
|
968
|
+
const form = document.getElementById('cheetah-form');
|
|
969
|
+
if (form) {
|
|
970
|
+
form.classList.add('hidden');
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// 显示所有认证按钮
|
|
974
|
+
const buttons = document.querySelectorAll('.auth-button');
|
|
975
|
+
buttons.forEach(btn => btn.style.display = 'flex');
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
function submitCheetahAuth(event) {
|
|
979
|
+
event.preventDefault();
|
|
980
|
+
console.log('提交猎豹OA登录...');
|
|
981
|
+
|
|
982
|
+
const email = document.getElementById('cheetah-email').value;
|
|
983
|
+
const password = document.getElementById('cheetah-password').value;
|
|
984
|
+
|
|
985
|
+
if (!email || !password) {
|
|
986
|
+
showMessage('error', t('auth.message.error.input.title'), t('auth.message.error.input.content'), t('auth.message.error.input.button'));
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// 禁用提交按钮
|
|
991
|
+
const submitBtn = event.target.querySelector('button[type="submit"]');
|
|
992
|
+
if (submitBtn) {
|
|
993
|
+
submitBtn.disabled = true;
|
|
994
|
+
submitBtn.textContent = t('auth.cheetah.form.submitting');
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
fetch('/start-cheetah-auth', {
|
|
998
|
+
method: 'POST',
|
|
999
|
+
headers: {
|
|
1000
|
+
'Content-Type': 'application/json',
|
|
1001
|
+
},
|
|
1002
|
+
body: JSON.stringify({ email, password })
|
|
1003
|
+
})
|
|
1004
|
+
.then(response => response.json())
|
|
1005
|
+
.then(data => {
|
|
1006
|
+
if (data.success) {
|
|
1007
|
+
// 登录成功,显示成功消息(不允许关闭)
|
|
1008
|
+
showMessage('success', t('auth.message.success.title'), t('auth.message.success.content'), t('auth.message.success.button'), { closable: false });
|
|
1009
|
+
// 隐藏表单,显示按钮
|
|
1010
|
+
cancelCheetahAuth();
|
|
1011
|
+
} else {
|
|
1012
|
+
showMessage('error', t('auth.message.error.login.title'), data.message || t('auth.message.error.login.content'), t('auth.message.error.login.button'));
|
|
1013
|
+
}
|
|
1014
|
+
})
|
|
1015
|
+
.catch(error => {
|
|
1016
|
+
console.error('猎豹OA登录失败:', error);
|
|
1017
|
+
showMessage('error', t('auth.message.error.connection.title'), t('auth.message.error.connection.content'), t('auth.message.error.connection.button'));
|
|
1018
|
+
})
|
|
1019
|
+
.finally(() => {
|
|
1020
|
+
// 恢复提交按钮
|
|
1021
|
+
if (submitBtn) {
|
|
1022
|
+
submitBtn.disabled = false;
|
|
1023
|
+
submitBtn.textContent = t('auth.cheetah.form.submit');
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
function startVipCardAuth() {
|
|
1029
|
+
console.log('显示VIP卡登录表单...');
|
|
1030
|
+
// 隐藏所有认证按钮
|
|
1031
|
+
const buttons = document.querySelectorAll('.auth-button');
|
|
1032
|
+
buttons.forEach(btn => btn.style.display = 'none');
|
|
1033
|
+
|
|
1034
|
+
// 显示VIP卡表单
|
|
1035
|
+
const form = document.getElementById('vipcard-form');
|
|
1036
|
+
if (form) {
|
|
1037
|
+
form.classList.remove('hidden');
|
|
1038
|
+
// 聚焦到输入框
|
|
1039
|
+
const codeInput = document.getElementById('vipcard-code');
|
|
1040
|
+
if (codeInput) {
|
|
1041
|
+
codeInput.focus();
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
function cancelVipCardAuth() {
|
|
1047
|
+
console.log('取消VIP卡登录...');
|
|
1048
|
+
// 隐藏表单
|
|
1049
|
+
const form = document.getElementById('vipcard-form');
|
|
1050
|
+
if (form) {
|
|
1051
|
+
form.classList.add('hidden');
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// 清空输入
|
|
1055
|
+
const codeInput = document.getElementById('vipcard-code');
|
|
1056
|
+
if (codeInput) {
|
|
1057
|
+
codeInput.value = '';
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
// 显示所有认证按钮
|
|
1061
|
+
const buttons = document.querySelectorAll('.auth-button');
|
|
1062
|
+
buttons.forEach(btn => btn.style.display = 'flex');
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
function submitVipCardAuth(event) {
|
|
1066
|
+
event.preventDefault();
|
|
1067
|
+
console.log('提交VIP卡登录...');
|
|
1068
|
+
|
|
1069
|
+
const codeInput = document.getElementById('vipcard-code');
|
|
1070
|
+
const code = codeInput ? codeInput.value.trim().toUpperCase() : '';
|
|
1071
|
+
|
|
1072
|
+
if (!code) {
|
|
1073
|
+
showMessage('error', t('auth.message.error.input.title'), t('auth.vipcard.error.empty'), t('auth.message.error.input.button'));
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// 禁用提交按钮
|
|
1078
|
+
const submitBtn = event.target.querySelector('button[type="submit"]');
|
|
1079
|
+
const cancelBtn = event.target.querySelector('button[type="button"]');
|
|
1080
|
+
if (submitBtn) {
|
|
1081
|
+
submitBtn.disabled = true;
|
|
1082
|
+
submitBtn.textContent = t('auth.vipcard.form.submitting');
|
|
1083
|
+
}
|
|
1084
|
+
if (cancelBtn) {
|
|
1085
|
+
cancelBtn.disabled = true;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
fetch('/start-vipcard-auth', {
|
|
1089
|
+
method: 'POST',
|
|
1090
|
+
headers: {
|
|
1091
|
+
'Content-Type': 'application/json',
|
|
1092
|
+
},
|
|
1093
|
+
body: JSON.stringify({ code })
|
|
1094
|
+
})
|
|
1095
|
+
.then(response => response.json())
|
|
1096
|
+
.then(data => {
|
|
1097
|
+
if (data.success) {
|
|
1098
|
+
// 登录成功,显示成功消息(不允许关闭)
|
|
1099
|
+
showMessage('success', t('auth.vipcard.success.title'), t('auth.vipcard.success.content'), t('auth.message.success.button'), { closable: false });
|
|
1100
|
+
// 隐藏表单,显示按钮
|
|
1101
|
+
cancelVipCardAuth();
|
|
1102
|
+
} else {
|
|
1103
|
+
showMessage('error', t('auth.message.error.login.title'), data.message || t('auth.vipcard.error.invalid'), t('auth.message.error.login.button'));
|
|
1104
|
+
}
|
|
1105
|
+
})
|
|
1106
|
+
.catch(error => {
|
|
1107
|
+
console.error('VIP卡登录失败:', error);
|
|
1108
|
+
showMessage('error', t('auth.message.error.connection.title'), t('auth.message.error.connection.content'), t('auth.message.error.connection.button'));
|
|
1109
|
+
})
|
|
1110
|
+
.finally(() => {
|
|
1111
|
+
// 恢复提交按钮
|
|
1112
|
+
if (submitBtn) {
|
|
1113
|
+
submitBtn.disabled = false;
|
|
1114
|
+
submitBtn.textContent = t('auth.vipcard.form.submit');
|
|
1115
|
+
}
|
|
1116
|
+
if (cancelBtn) {
|
|
1117
|
+
cancelBtn.disabled = false;
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
</script>
|
|
1122
|
+
</body>
|
|
1123
|
+
</html>
|