lejianwen 1 год назад
Родитель
Сommit
7cf1a14950

+ 3 - 3
src/router/index.js

@@ -191,9 +191,9 @@ export const asyncRoutes = [
191 191
         component: () => import('@/views/share_record/index.vue'),
192 192
       },
193 193
       {
194
-        path: '/rustdesk',
195
-        name: 'RustDesk',
196
-        meta: { title: 'RustDesk', icon: 'Setting' /*keepAlive: true*/ },
194
+        path: '/serverCmd',
195
+        name: 'ServerCmd',
196
+        meta: { title: 'ServerCmd', icon: 'Tools' /*keepAlive: true*/ },
197 197
         component: () => import('@/views/rustdesk/control.vue'),
198 198
       },
199 199
     ],

+ 36 - 0
src/utils/i18n/en.json

@@ -468,5 +468,41 @@
468 468
   },
469 469
   "Captcha": {
470 470
     "One": "Captcha"
471
+  },
472
+  "ServerCmd": {
473
+    "One": "Server Cmd"
474
+  },
475
+  "Simple": {
476
+    "One": "Simple"
477
+  },
478
+  "Advanced": {
479
+    "One": "Advanced"
480
+  },
481
+  "Available": {
482
+    "One": "Available"
483
+  },
484
+  "NotAvailable": {
485
+    "One": "Not Available"
486
+  },
487
+  "ServerCmdTips": {
488
+    "One": "This feature is experimental. Please ensure that the API and hbbs are on the same loopback address. For more information, please refer to the {wiki}"
489
+  },
490
+  "Refresh": {
491
+    "One": "Refresh"
492
+  },
493
+  "Save": {
494
+    "One": "Save"
495
+  },
496
+  "SendCustom": {
497
+    "One": "Send Custom"
498
+  },
499
+  "Send": {
500
+    "One": "Send"
501
+  },
502
+  "SendCmd": {
503
+    "One": "Send Cmd"
504
+  },
505
+  "Result": {
506
+    "One": "Result"
471 507
   }
472 508
 }

+ 36 - 0
src/utils/i18n/es.json

@@ -471,5 +471,41 @@
471 471
   },
472 472
   "Captcha": {
473 473
     "One": "Captcha"
474
+  },
475
+  "ServerCmd": {
476
+    "One": "Comando del servidor"
477
+  },
478
+  "Simple": {
479
+    "One": "Simple"
480
+  },
481
+  "Advanced": {
482
+    "One": "Avanzado"
483
+  },
484
+  "Available": {
485
+    "One": "Disponible"
486
+  },
487
+  "NotAvailable": {
488
+    "One": "No disponible"
489
+  },
490
+  "ServerCmdTips": {
491
+    "One": "Esta función es experimental, asegúrese de que la API y hbbs estén en la misma dirección de bucle, para más detalles consulte el {wiki}"
492
+  },
493
+  "Refresh": {
494
+    "One": "Actualizar"
495
+  },
496
+  "Save": {
497
+    "One": "Guardar"
498
+  },
499
+  "SendCustom": {
500
+    "One": "Enviar personalizado"
501
+  },
502
+  "Send": {
503
+    "One": "Enviar"
504
+  },
505
+  "SendCmd": {
506
+    "One": "Enviar comando"
507
+  },
508
+  "Result": {
509
+    "One": "Resultado"
474 510
   }
475 511
 }

+ 214 - 178
src/utils/i18n/fr.json

@@ -1,192 +1,192 @@
1 1
 {
2 2
   "Login": {
3
-  "One": "Connexion"
3
+    "One": "Connexion"
4 4
   },
5 5
   "Logout": {
6
-  "One": "Déconnexion"
6
+    "One": "Déconnexion"
7 7
   },
8 8
   "Register": {
9
-  "One": "S'inscrire"
9
+    "One": "S'inscrire"
10 10
   },
11 11
   "Confirm": {
12
-  "One": "Confirmer"
12
+    "One": "Confirmer"
13 13
   },
14 14
   "Username": {
15
-  "One": "Nom d'utilisateur"
15
+    "One": "Nom d'utilisateur"
16 16
   },
17 17
   "Password": {
18
-  "One": "Mot de passe"
18
+    "One": "Mot de passe"
19 19
   },
20 20
   "LoginSuccess": {
21
-  "One": "Connexion réussie"
21
+    "One": "Connexion réussie"
22 22
   },
23 23
   "ForgotPassword": {
24
-  "One": "Mot de passe oublié"
24
+    "One": "Mot de passe oublié"
25 25
   },
26 26
   "ResetPassword": {
27
-  "One": "Réinitialiser le mot de passe"
27
+    "One": "Réinitialiser le mot de passe"
28 28
   },
29 29
   "ChangePassword": {
30
-  "One": "Modifier le mot de passe"
30
+    "One": "Modifier le mot de passe"
31 31
   },
32 32
   "Userinfo": {
33
-  "One": "Informations utilisateur"
33
+    "One": "Informations utilisateur"
34 34
   },
35 35
   "ParamRequired": {
36
-  "One": "{param} est obligatoire"
36
+    "One": "{param} est obligatoire"
37 37
   },
38 38
   "HasBind": {
39
-  "One": "A une liaison"
39
+    "One": "A une liaison"
40 40
   },
41 41
   "NoBind": {
42
-  "One": "Aucune liaison"
42
+    "One": "Aucune liaison"
43 43
   },
44 44
   "UnBind": {
45
-  "One": "Délier"
45
+    "One": "Délier"
46 46
   },
47 47
   "ToBind": {
48
-  "One": "Lier"
48
+    "One": "Lier"
49 49
   },
50 50
   "Confirm?": {
51
-  "One": "{param} Confirmer?"
51
+    "One": "{param} Confirmer?"
52 52
   },
53 53
   "Cancel": {
54
-  "One": "Annuler"
54
+    "One": "Annuler"
55 55
   },
56 56
   "Platform": {
57
-  "One": "Plateforme"
57
+    "One": "Plateforme"
58 58
   },
59 59
   "Status": {
60
-  "One": "État"
60
+    "One": "État"
61 61
   },
62 62
   "Actions": {
63
-  "One": "Actions"
63
+    "One": "Actions"
64 64
   },
65 65
   "Filter": {
66
-  "One": "Filtre"
66
+    "One": "Filtre"
67 67
   },
68 68
   "Add": {
69
-  "One": "Ajouter"
69
+    "One": "Ajouter"
70 70
   },
71 71
   "Hostname": {
72
-  "One": "Nom d'hôte"
72
+    "One": "Nom d'hôte"
73 73
   },
74 74
   "Alias": {
75
-  "One": "Alias"
75
+    "One": "Alias"
76 76
   },
77 77
   "Hash": {
78
-  "One": "Hachage"
78
+    "One": "Hachage"
79 79
   },
80 80
   "Tags": {
81
-  "One": "Etiquettes"
81
+    "One": "Etiquettes"
82 82
   },
83 83
   "Edit": {
84
-  "One": "Modifier"
84
+    "One": "Modifier"
85 85
   },
86 86
   "Delete": {
87
-  "One": "Supprimer"
87
+    "One": "Supprimer"
88 88
   },
89 89
   "Create": {
90
-  "One": "Créer"
90
+    "One": "Créer"
91 91
   },
92
-  "Update" : {
93
-  "One" : "Mise à jour"
92
+  "Update": {
93
+    "One": "Mise à jour"
94 94
   },
95
-  "LoginName" : {
96
-  "One" : "Nom de connexion"
95
+  "LoginName": {
96
+    "One": "Nom de connexion"
97 97
   },
98
-  "Submit" : {
99
-  "One" : "Envoyer"
98
+  "Submit": {
99
+    "One": "Envoyer"
100 100
   },
101
-  "OperationSuccess" : {
102
-  "One" : "Opération réussie"
101
+  "OperationSuccess": {
102
+    "One": "Opération réussie"
103 103
   },
104
-  "Owner" : {
105
-  "One" : "Propriétaire"
104
+  "Owner": {
105
+    "One": "Propriétaire"
106 106
   },
107
-  "Name" : {
108
-  "One" : "Nom"
107
+  "Name": {
108
+    "One": "Nom"
109 109
   },
110
-  "Color" : {
111
-  "One" : "Couleur"
110
+  "Color": {
111
+    "One": "Couleur"
112 112
   },
113
-  "CreatedAt" : {
114
-  "One" : "Créé le"
113
+  "CreatedAt": {
114
+    "One": "Créé le"
115 115
   },
116
-  "UpdatedAt" : {
117
-  "One" : "Mis à jour le"
116
+  "UpdatedAt": {
117
+    "One": "Mis à jour le"
118 118
   },
119
-  "Memory" : {
120
-  "One" : "Mémoire"
119
+  "Memory": {
120
+    "One": "Mémoire"
121 121
   },
122
-  "Os" : {
123
-  "One" : "Os"
122
+  "Os": {
123
+    "One": "Os"
124 124
   },
125
-  "Uuid" : {
126
-  "One" : "Uuid"
125
+  "Uuid": {
126
+    "One": "Uuid"
127 127
   },
128
-  "Version" : {
129
-  "One": "Version"
128
+  "Version": {
129
+    "One": "Version"
130 130
   },
131 131
   "Type": {
132
-  "One": "Type"
132
+    "One": "Type"
133 133
   },
134 134
   "Group": {
135
-  "One": "Groupe"
135
+    "One": "Groupe"
136 136
   },
137 137
   "CommonGroup": {
138
-  "One": "Groupe commun"
138
+    "One": "Groupe commun"
139 139
   },
140 140
   "CommonGroupNote": {
141
-  "One": "Seuls les administrateurs peuvent voir les membres du groupe et leurs appareils"
141
+    "One": "Seuls les administrateurs peuvent voir les membres du groupe et leurs appareils"
142 142
   },
143 143
   "SharedGroup": {
144
-  "One": "Groupe partagé"
144
+    "One": "Groupe partagé"
145 145
   },
146 146
   "SharedGroupNote": {
147
-  "One": "Tous les utilisateurs peuvent voir les membres du groupe et leurs appareils"
147
+    "One": "Tous les utilisateurs peuvent voir les membres du groupe et leurs appareils"
148 148
   },
149 149
   "Nickname": {
150
-  "One": "Pseudonyme"
150
+    "One": "Pseudonyme"
151 151
   },
152 152
   "UserTags": {
153
-  "One": "Etiquettes utilisateur"
153
+    "One": "Etiquettes utilisateur"
154 154
   },
155 155
   "UserAddressBook": {
156
-  "One": "Carnet d'adresses utilisateur"
156
+    "One": "Carnet d'adresses utilisateur"
157 157
   },
158 158
   "IsAdmin": {
159
-  "One": "Est administrateur"
159
+    "One": "Est administrateur"
160 160
   },
161 161
   "PleaseInputNewPassword": {
162
-  "One": "Veuillez saisir nouveau mot de passe"
162
+    "One": "Veuillez saisir nouveau mot de passe"
163 163
   },
164 164
   "AutoRegister": {
165
-  "One": "Enregistrement automatique"
165
+    "One": "Enregistrement automatique"
166 166
   },
167 167
   "AutoRegisterNote": {
168
-  "One": "Si activé, un compte sera automatiquement enregistré lorsqu'un utilisateur se connectera avec OAuth sans lier un compte existant"
168
+    "One": "Si activé, un compte sera automatiquement enregistré lorsqu'un utilisateur se connectera avec OAuth sans lier un compte existant"
169 169
   },
170 170
   "ThirdName": {
171
-  "One": "Troisième nom"
171
+    "One": "Troisième nom"
172 172
   },
173 173
   "Close": {
174
-  "One": "Fermer"
174
+    "One": "Fermer"
175 175
   },
176 176
   "OauthBinding": {
177
-  "One": "Vous autorisez la liaison"
177
+    "One": "Vous autorisez la liaison"
178 178
   },
179 179
   "OauthLogining": {
180
-  "One": "Vous autorisez la connexion"
180
+    "One": "Vous autorisez la connexion"
181 181
   },
182 182
   "OauthCloseNote": {
183
-  "One": "Si vous ne l'autorisez pas, veuillez fermer la page directement"
183
+    "One": "Si vous ne l'autorisez pas, veuillez fermer la page directement"
184 184
   },
185 185
   "OperationSuccessAndCloseAfter3Seconds": {
186
-  "One": "Opération réussie, fermer après 3 secondes"
186
+    "One": "Opération réussie, fermer après 3 secondes"
187 187
   },
188 188
   "ConfirmOauth": {
189
-  "One": "Confirmer Oauth"
189
+    "One": "Confirmer Oauth"
190 190
   },
191 191
   "View": {
192 192
     "One": "Informations"
@@ -195,261 +195,261 @@
195 195
     "One": "Appareil"
196 196
   },
197 197
   "ChangeLang": {
198
-  "One": "Changer la langue"
198
+    "One": "Changer la langue"
199 199
   },
200 200
   "My": {
201
-  "One": "Moi"
201
+    "One": "Moi"
202 202
   },
203 203
   "Info": {
204
-  "One": "Info"
204
+    "One": "Info"
205 205
   },
206 206
   "AddressBooks": {
207
-  "One": "Carnets d'adresses"
207
+    "One": "Carnets d'adresses"
208 208
   },
209 209
   "System": {
210
-  "One": "Système"
210
+    "One": "Système"
211 211
   },
212 212
   "PeerManage": {
213
-  "One": "Appareils"
213
+    "One": "Appareils"
214 214
   },
215 215
   "AddressBookManage": {
216
-  "One": "Carnets d'adresses"
216
+    "One": "Carnets d'adresses"
217 217
   },
218 218
   "GroupManage": {
219
-  "One": "Groupes"
219
+    "One": "Groupes"
220 220
   },
221 221
   "UserManage": {
222
-  "One": "Utilisateurs"
222
+    "One": "Utilisateurs"
223 223
   },
224 224
   "UserAdd": {
225
-  "One": "Ajout d'utilisateur"
225
+    "One": "Ajout d'utilisateur"
226 226
   },
227 227
   "UserEdit": {
228
-  "One": "Utilisateur Modifier"
228
+    "One": "Utilisateur Modifier"
229 229
   },
230 230
   "TagsManage": {
231
-  "One": "Etiquettes"
231
+    "One": "Etiquettes"
232 232
   },
233 233
   "OauthManage": {
234
-  "One": "Oauth"
234
+    "One": "Oauth"
235 235
   },
236 236
   "LoginLog": {
237
-  "One": "Journal de connexion"
237
+    "One": "Journal de connexion"
238 238
   },
239 239
   "LastOnlineTime": {
240
-  "One": "Dernière heure de connexion"
240
+    "One": "Dernière heure de connexion"
241 241
   },
242 242
   "JustNow": {
243
-  "One": "Juste maintenant"
243
+    "One": "Juste maintenant"
244 244
   },
245 245
   "MinutesAgo": {
246
-  "One": "Il y a {param} minute",
247
-  "Other": "Il y a {param} minutes"
246
+    "One": "Il y a {param} minute",
247
+    "Other": "Il y a {param} minutes"
248 248
   },
249 249
   "HoursAgo": {
250
-  "One": "Il y a {param} heure",
251
-  "Other": "Il y a {param} heures"
250
+    "One": "Il y a {param} heure",
251
+    "Other": "Il y a {param} heures"
252 252
   },
253 253
   "DaysAgo": {
254
-  "One": "Il y a {param} jour",
255
-  "Other": "Il y a {param} jours"
254
+    "One": "Il y a {param} jour",
255
+    "Other": "Il y a {param} jours"
256 256
   },
257 257
   "MonthsAgo": {
258
-  "One": " Il y a {param} mois",
259
-  "Autre": "Il y a {param} mois"
258
+    "One": " Il y a {param} mois",
259
+    "Autre": "Il y a {param} mois"
260 260
   },
261 261
   "YearsAgo": {
262
-  "One": "Il y a {param} an",
263
-  "Autre": "Il y a {param} ans"
262
+    "One": "Il y a {param} an",
263
+    "Autre": "Il y a {param} ans"
264 264
   },
265 265
   "MinutesLess": {
266
-  "One": "Moins de {param} minute",
267
-  "Autre": "Moins de {param} minutes"
266
+    "One": "Moins de {param} minute",
267
+    "Autre": "Moins de {param} minutes"
268 268
   },
269 269
   "HoursLess": {
270
-  "One": "Moins de {param} heure",
271
-  "Autre": "Moins de {param} heures"
270
+    "One": "Moins de {param} heure",
271
+    "Autre": "Moins de {param} heures"
272 272
   },
273 273
   "DaysLess": {
274
-  "One": "Moins de {param} jour",
275
-  "Autre": "Moins de {param} jours"
274
+    "One": "Moins de {param} jour",
275
+    "Autre": "Moins de {param} jours"
276 276
   },
277 277
   "Export": {
278
-  "One": "Exporter"
278
+    "One": "Exporter"
279 279
   },
280 280
   "AddToAddressBook": {
281
-  "One": "Ajouter au carnet d'adresses"
281
+    "One": "Ajouter au carnet d'adresses"
282 282
   },
283 283
   "BatchDelete": {
284
-  "One": "Suppression par lot"
284
+    "One": "Suppression par lot"
285 285
   },
286 286
   "PleaseSelectData": {
287
-  "One": "Veuillez sélectionner des données"
287
+    "One": "Veuillez sélectionner des données"
288 288
   },
289 289
   "PasswordType": {
290
-  "One": "Type de mot de passe"
290
+    "One": "Type de mot de passe"
291 291
   },
292 292
   "OncePassword": {
293
-  "One": "Mot de passe à usage unique"
293
+    "One": "Mot de passe à usage unique"
294 294
   },
295 295
   "FixedPassword": {
296
-  "One": "Mot de passe fixe"
296
+    "One": "Mot de passe fixe"
297 297
   },
298 298
   "FixedPasswordWarning": {
299
-  "One": "Les mots de passe fixes peuvent être divulgués, veuillez donc les utiliser avec prudence et l'utilisation de mots de passe à usage unique est recommandée"
299
+    "One": "Les mots de passe fixes peuvent être divulgués, veuillez donc les utiliser avec prudence et l'utilisation de mots de passe à usage unique est recommandée"
300 300
   },
301 301
   "ExpireTime": {
302
-  "One": "Heure d'expiration"
302
+    "One": "Heure d'expiration"
303 303
   },
304 304
   "Minutes": {
305
-  "One": "{param} Minute",
306
-  "Other": "{param} Minutes"
305
+    "One": "{param} Minute",
306
+    "Other": "{param} Minutes"
307 307
   },
308 308
   "Hours": {
309
-  "One": "{param} Heure",
310
-  "Other": "{param} Heures"
309
+    "One": "{param} Heure",
310
+    "Other": "{param} Heures"
311 311
   },
312 312
   "Days": {
313
-  "One": "{param} Jour",
314
-  "Other": "{param} Jours"
313
+    "One": "{param} Jour",
314
+    "Other": "{param} Jours"
315 315
   },
316 316
   "Weeks": {
317
-  "One": "{param} Semaine",
318
-  "Other": "{param} Semaines"
317
+    "One": "{param} Semaine",
318
+    "Other": "{param} Semaines"
319 319
   },
320 320
   "Months": {
321
-  "One": "{param} Mois",
322
-  "Other": "{param} Mois"
321
+    "One": "{param} Mois",
322
+    "Other": "{param} Mois"
323 323
   },
324 324
   "Forever": {
325
-  "One": "Forever"
325
+    "One": "Forever"
326 326
   },
327 327
   "Error": {
328
-  "One": "Erreur"
328
+    "One": "Erreur"
329 329
   },
330 330
   "IDNotExist": {
331
-  "One": "L'ID n'existe pas"
331
+    "One": "L'ID n'existe pas"
332 332
   },
333 333
   "RemoteDesktopOffline": {
334
-  "One": "Le bureau à distance est hors ligne"
334
+    "One": "Le bureau à distance est hors ligne"
335 335
   },
336 336
   "KeyMismatch": {
337
-  "One": "Non-correspondance de clé"
337
+    "One": "Non-correspondance de clé"
338 338
   },
339 339
   "KeyOveruse": {
340
-  "One": "Surutilisation de clé"
340
+    "One": "Surutilisation de clé"
341 341
   },
342 342
   "Link": {
343
-  "One": "Lien"
343
+    "One": "Lien"
344 344
   },
345 345
   "CopySuccess": {
346
-  "One": "Copie réussie"
346
+    "One": "Copie réussie"
347 347
   },
348 348
   "CopyFailed": {
349
-  "One": "Copie échouée"
349
+    "One": "Copie échouée"
350 350
   },
351 351
   "Timeout": {
352
-  "One": "Expiration du délai"
352
+    "One": "Expiration du délai"
353 353
   },
354 354
   "AuditConnLog": {
355
-  "One": "Journal de connexion"
355
+    "One": "Journal de connexion"
356 356
   },
357 357
   "Peer": {
358
-  "One": "Appareil",
359
-  "Other": "Appareils distants"
358
+    "One": "Appareil",
359
+    "Other": "Appareils distants"
360 360
   },
361 361
   "FromPeer": {
362
-  "One": "Par Appareil distant"
362
+    "One": "Par Appareil distant"
363 363
   },
364 364
   "FromName": {
365
-  "One": "Par nom"
365
+    "One": "Par nom"
366 366
   },
367 367
   "CloseTime": {
368
-  "One": "Heure de clôture"
368
+    "One": "Heure de clôture"
369 369
   },
370 370
   "AuditFileLog": {
371
-  "One": "Fichier Journal"
371
+    "One": "Fichier Journal"
372 372
   },
373 373
   "Common": {
374
-  "One": "Commun"
374
+    "One": "Commun"
375 375
   },
376 376
   "File": {
377
-  "One": "Fichier"
377
+    "One": "Fichier"
378 378
   },
379 379
   "Num": {
380
-  "One": "Num"
380
+    "One": "Num"
381 381
   },
382 382
   "Ip": {
383
-  "One": "Ip"
383
+    "One": "Ip"
384 384
   },
385 385
   "FileName": {
386
-  "One": "Nom du fichier"
386
+    "One": "Nom du fichier"
387 387
   },
388 388
   "FileInfo": {
389
-  "One": "Informations sur le fichier"
389
+    "One": "Informations sur le fichier"
390 390
   },
391 391
   "Path": {
392
-  "One": "Chemin"
392
+    "One": "Chemin"
393 393
   },
394 394
   "IndexNum": {
395
-  "One": "Num. index"
395
+    "One": "Num. index"
396 396
   },
397 397
   "ToRemote": {
398
-  "One": "Vers distant"
398
+    "One": "Vers distant"
399 399
   },
400 400
   "ToLocal": {
401
-  "One": "Vers local"
401
+    "One": "Vers local"
402 402
   },
403 403
   "AddressBookName": {
404
-  "One": "Nom du carnet d'adresses"
404
+    "One": "Nom du carnet d'adresses"
405 405
   },
406 406
   "AddRule": {
407
-  "One": "Ajouter une règle"
407
+    "One": "Ajouter une règle"
408 408
   },
409 409
   "ShareRules": {
410
-  "One": "Partager des règles"
410
+    "One": "Partager des règles"
411 411
   },
412 412
   "Rule": {
413
-  "One": "Règle"
413
+    "One": "Règle"
414 414
   },
415 415
   "Read": {
416
-  "One": "Lecture"
416
+    "One": "Lecture"
417 417
   },
418 418
   "ReadWrite": {
419
-  "One": "Lecture et écriture"
419
+    "One": "Lecture et écriture"
420 420
   },
421 421
   "FullControl": {
422
-  "One": "Contrôle total"
422
+    "One": "Contrôle total"
423 423
   },
424 424
   "ShareTo": {
425
-  "One": "Partager avec"
425
+    "One": "Partager avec"
426 426
   },
427 427
   "MyAddressBook": {
428
-  "One": "Mon carnet d'adresses"
428
+    "One": "Mon carnet d'adresses"
429 429
   },
430 430
   "AddressBook": {
431
-  "One": "Carnet d'adresses"
431
+    "One": "Carnet d'adresses"
432 432
   },
433 433
   "AddressBookNameManage": {
434
-  "One": "Noms du carnet d'adresses"
434
+    "One": "Noms du carnet d'adresses"
435 435
   },
436 436
   "MyAddressBookTips": {
437
-  "One": "\"Mon carnet d'adresses\" est la valeur par défaut du système, ne peut pas être modifié ou supprimé"
437
+    "One": "\"Mon carnet d'adresses\" est la valeur par défaut du système, ne peut pas être modifié ou supprimé"
438 438
   },
439 439
   "LastOnlineIp": {
440
-  "One": "Dernière adresse IP en ligne"
440
+    "One": "Dernière adresse IP en ligne"
441 441
   },
442 442
   "ConfirmPassword": {
443
-  "One": "Confirmer le mot de passe"
443
+    "One": "Confirmer le mot de passe"
444 444
   },
445 445
   "PasswordNotMatchConfirmPassword": {
446
-  "One": "Les mots de passe ne correspondent pas"
446
+    "One": "Les mots de passe ne correspondent pas"
447 447
   },
448 448
   "ToLogin": {
449
-  "One": "Pour se connecter"
449
+    "One": "Pour se connecter"
450 450
   },
451 451
   "UserToken": {
452
-  "One": "Jeton Utilisateur"
452
+    "One": "Jeton Utilisateur"
453 453
   },
454 454
   "Token": {
455 455
     "One": "Jeton"
@@ -458,21 +458,57 @@
458 458
     "One": "Mon appareil"
459 459
   },
460 460
   "BatchAddToAB": {
461
-  "One": "Ajout par lots au carnet d'adresses"
461
+    "One": "Ajout par lots au carnet d'adresses"
462 462
   },
463 463
   "BatchEditTags": {
464
-  "One": "Modification par lots des étiquettes"
464
+    "One": "Modification par lots des étiquettes"
465 465
   },
466 466
   "User": {
467
-  "One": "Utilisateur"
467
+    "One": "Utilisateur"
468 468
   },
469 469
   "ShareRecord": {
470
-  "One": "Enregistrement des partages"
470
+    "One": "Enregistrement des partages"
471 471
   },
472 472
   "Second": {
473
-  "One": "Seconde"
473
+    "One": "Seconde"
474 474
   },
475 475
   "Captcha": {
476
-  "One": "Captcha"
476
+    "One": "Captcha"
477
+  },
478
+  "ServerCmd": {
479
+    "One": "Commande serveur"
480
+  },
481
+  "Simple": {
482
+    "One": "Simple"
483
+  },
484
+  "Advanced": {
485
+    "One": "Avancé"
486
+  },
487
+  "Available": {
488
+    "One": "Disponible"
489
+  },
490
+  "NotAvailable": {
491
+    "One": "Non disponible"
492
+  },
493
+  "ServerCmdTips": {
494
+    "One": "Cette fonctionnalité est expérimentale, veuillez vous assurer que l'API et hbbs sont sur la même adresse de boucle, pour plus de détails veuillez consulter le {wiki}"
495
+  },
496
+  "Refresh": {
497
+    "One": "Actualiser"
498
+  },
499
+  "Save": {
500
+    "One": "Enregistrer"
501
+  },
502
+  "SendCustom": {
503
+    "One": "Envoyer personnalisé"
504
+  },
505
+  "Send": {
506
+    "One": "Envoyer"
507
+  },
508
+  "SendCmd": {
509
+    "One": "Envoyer Cmd"
510
+  },
511
+  "Result": {
512
+    "One": "Résultat"
477 513
   }
478
-}
514
+}

+ 36 - 0
src/utils/i18n/ko.json

@@ -457,5 +457,41 @@
457 457
   },
458 458
   "Captcha": {
459 459
     "One": "Captcha"
460
+  },
461
+  "ServerCmd": {
462
+    "One": "서버 명령"
463
+  },
464
+  "Simple": {
465
+    "One": "간단"
466
+  },
467
+  "Advanced": {
468
+    "One": "고급"
469
+  },
470
+  "Available": {
471
+    "One": "사용 가능"
472
+  },
473
+  "NotAvailable": {
474
+    "One": "사용 불가"
475
+  },
476
+  "ServerCmdTips": {
477
+    "One": "이 기능은 실험적이므로, api와 hbbs가 동일한 루프백 주소에 있는지 확인하십시오. 자세한 내용은 {wiki}를 참조하십시오."
478
+  },
479
+  "Refresh": {
480
+    "One": "새로 고침"
481
+  },
482
+  "Save": {
483
+    "One": "저장"
484
+  },
485
+  "SendCustom": {
486
+    "One": "사용자 정의 전송"
487
+  },
488
+  "Send": {
489
+    "One": "보내기"
490
+  },
491
+  "SendCmd": {
492
+    "One": "명령 보내기"
493
+  },
494
+  "Result": {
495
+    "One": "결과"
460 496
   }
461 497
 }

+ 36 - 0
src/utils/i18n/ru.json

@@ -471,6 +471,42 @@
471 471
   },
472 472
   "Captcha": {
473 473
     "One": "Captcha"
474
+  },
475
+  "ServerCmd": {
476
+    "One": "Команда сервера"
477
+  },
478
+  "Simple": {
479
+    "One": "Простой"
480
+  },
481
+  "Advanced": {
482
+    "One": "Расширенный"
483
+  },
484
+  "Available": {
485
+    "One": "Доступно"
486
+  },
487
+  "NotAvailable": {
488
+    "One": "Недоступно"
489
+  },
490
+  "ServerCmdTips": {
491
+    "One": "Эта функция является экспериментальной, убедитесь, что api и hbbs находятся на одном и том же адресе обратной связи, для получения дополнительной информации см. {wiki}"
492
+  },
493
+  "Refresh": {
494
+    "One": "Обновить"
495
+  },
496
+  "Save": {
497
+    "One": "Сохранить"
498
+  },
499
+  "SendCustom": {
500
+    "One": "Отправить настраиваемое"
501
+  },
502
+  "Send": {
503
+    "One": "Отправить"
504
+  },
505
+  "SendCmd": {
506
+    "One": "Отправить команду"
507
+  },
508
+  "Result": {
509
+    "One": "Результат"
474 510
   }
475 511
 }
476 512
 

+ 36 - 0
src/utils/i18n/zh_CN.json

@@ -487,5 +487,41 @@
487 487
   },
488 488
   "Captcha": {
489 489
     "One": "验证码"
490
+  },
491
+  "ServerCmd": {
492
+    "One": "服务端命令"
493
+  },
494
+  "Simple": {
495
+    "One": "简单"
496
+  },
497
+  "Advanced": {
498
+    "One": "高级"
499
+  },
500
+  "Available": {
501
+    "One": "可用"
502
+  },
503
+  "NotAvailable": {
504
+    "One": "不可用"
505
+  },
506
+  "ServerCmdTips": {
507
+    "One": "此处功能为实验性质,请确保api和hbbs处于同一回环地址下,更多说明请参考 {wiki}"
508
+  },
509
+  "Refresh": {
510
+    "One": "刷新"
511
+  },
512
+  "Save": {
513
+    "One": "保存"
514
+  },
515
+  "SendCustom": {
516
+    "One": "发送自定义"
517
+  },
518
+  "Send": {
519
+    "One": "发送"
520
+  },
521
+  "SendCmd": {
522
+    "One": "发送命令"
523
+  },
524
+  "Result": {
525
+    "One": "结果"
490 526
   }
491 527
 }

+ 184 - 63
src/views/rustdesk/control.vue

@@ -1,68 +1,124 @@
1 1
 <template>
2 2
   <div>
3
-    <h2>此处功能为实验性质,更多说明请参考 <a target="_blank" href="https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command">WIKI</a></h2>
4
-    <el-card class="list-query" shadow="hover">
5
-      <el-form inline label-width="80px">
6
-        <el-form-item>
7
-          <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
8
-          <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
9
-        </el-form-item>
10
-      </el-form>
11
-    </el-card>
12
-    <el-card class="list-body" shadow="hover">
13
-
14
-      <el-table :data="listRes.list" v-loading="listRes.loading" border>
15
-        <el-table-column prop="cmd" label="cmd" align="center"></el-table-column>
16
-        <el-table-column prop="alias" label="alias" align="center"></el-table-column>
17
-        <el-table-column prop="option" label="option" align="center"></el-table-column>
18
-        <el-table-column prop="explain" label="explain" align="center"></el-table-column>
19
-        <el-table-column label="actions" align="center">
20
-          <template #default="{row}">
21
-            <el-button type="success" @click="showCmd(row)">执行</el-button>
22
-            <el-button v-if="row.id" type="primary" @click="toUpdate(row)">编辑</el-button>
23
-            <el-button v-if="row.id" type="danger" @click="del(row)">删除</el-button>
24
-          </template>
25
-        </el-table-column>
26
-      </el-table>
27
-
28
-      <el-dialog v-model="formVisible">
29
-        <el-form label-width="150">
30
-          <el-form-item label="cmd">
31
-            <el-input v-model="formData.cmd"></el-input>
32
-          </el-form-item>
33
-          <el-form-item label="alias">
34
-            <el-input v-model="formData.alias"></el-input>
35
-          </el-form-item>
36
-          <el-form-item label="option">
37
-            <el-input v-model="formData.option"></el-input>
38
-          </el-form-item>
39
-          <el-form-item label="explain">
40
-            <el-input v-model="formData.explain"></el-input>
41
-          </el-form-item>
42
-          <el-form-item>
43
-            <el-button type="primary" @click="submit">提交</el-button>
44
-            <el-button @click="cancel">取消</el-button>
45
-          </el-form-item>
46
-        </el-form>
47
-      </el-dialog>
48
-
49
-      <el-dialog title="发送指令" v-model="showCmdForm">
50
-        <el-form label-width="300">
51
-          <el-form-item label="cmd">
52
-            <el-input v-model="customCmd.cmd"></el-input>
53
-          </el-form-item>
54
-          <el-form-item label="option">
55
-            <el-input type="textarea" v-model="customCmd.option"></el-input>
56
-          </el-form-item>
57
-          <el-form-item>
58
-            <el-button type="primary" @click="submitCmd">发送</el-button>
59
-          </el-form-item>
60
-          <el-form-item label="执行结果">
61
-            <el-input type="textarea" readonly disabled v-model="customCmd.res" rows="20"></el-input>
62
-          </el-form-item>
63
-        </el-form>
64
-      </el-dialog>
65
-    </el-card>
3
+    <h4 v-html="T('ServerCmdTips', {wiki: '<a target=\'_blank\' href=\'https://github.com/lejianwen/rustdesk-api/wiki/Rustdesk-Command\'>WIKI</a>'})"></h4>
4
+    <h5>
5
+      <span>{{ T('Status') }}: </span>
6
+      <el-tag v-if="canSendCmd" type="success">{{ T('Available') }}</el-tag>
7
+      <el-tag v-else type="danger">{{ T('NotAvailable') }}</el-tag>
8
+      <el-button size="small" type="text" @click="refreshCanSendCmd">{{ T('Refresh') }}</el-button>
9
+    </h5>
10
+    <el-tabs
11
+        v-model="activeName"
12
+        type="card"
13
+    >
14
+      <el-tab-pane :label="T('Simple')" name="Simple">
15
+        <el-space>
16
+          <el-card shadow="hover" style="width: 300px" v-loading="rsForm.loading">
17
+            <template #header>
18
+              <div class="card-header">
19
+                <span>RELAY_SERVERS</span>
20
+              </div>
21
+            </template>
22
+            <el-form :disabled="!canSendCmd">
23
+              <el-form-item>
24
+                <el-input v-model="rsForm.option"></el-input>
25
+              </el-form-item>
26
+              <el-form-item>
27
+                <el-button @click="getRS">{{ T('Refresh') }}</el-button>
28
+                <el-button @click="saveRS" type="primary">{{ T('Save') }}</el-button>
29
+              </el-form-item>
30
+            </el-form>
31
+          </el-card>
32
+          <el-card shadow="hover" style="width: 300px">
33
+            <template #header>
34
+              <div class="card-header">
35
+                <span>ALWAYS_USE_RELAY</span>
36
+              </div>
37
+            </template>
38
+            <el-form :disabled="!canSendCmd">
39
+              <el-form-item>
40
+                <el-switch v-model="aurForm.option" active-value="Y" inactive-value="N"></el-switch>
41
+              </el-form-item>
42
+              <el-form-item>
43
+                <el-button @click="getAUR">{{ T('Refresh') }}</el-button>
44
+                <el-button @click="saveAUR" type="primary">{{ T('Save') }}</el-button>
45
+              </el-form-item>
46
+            </el-form>
47
+          </el-card>
48
+        </el-space>
49
+
50
+
51
+      </el-tab-pane>
52
+      <el-tab-pane :label="T('Advanced')" name="Advanced">
53
+        <el-card class="list-query" shadow="hover">
54
+          <el-form inline label-width="80px">
55
+            <el-form-item>
56
+              <el-button type="primary" @click="handlerQuery">{{ T('Filter') }}</el-button>
57
+              <el-button type="danger" @click="toAdd">{{ T('Add') }}</el-button>
58
+              <el-button type="success" :disabled="!canSendCmd" @click="showCmd({cmd:'',option:''})">{{ T('Send') }}</el-button>
59
+            </el-form-item>
60
+          </el-form>
61
+        </el-card>
62
+        <el-card class="list-body" shadow="hover">
63
+
64
+          <el-table :data="listRes.list" v-loading="listRes.loading" border>
65
+            <el-table-column prop="cmd" label="cmd" align="center"></el-table-column>
66
+            <el-table-column prop="alias" label="alias" align="center"></el-table-column>
67
+            <el-table-column prop="option" label="option" align="center"></el-table-column>
68
+            <el-table-column prop="explain" label="explain" align="center"></el-table-column>
69
+            <el-table-column label="actions" align="center">
70
+              <template #default="{row}">
71
+                <el-button type="success" :disabled="!canSendCmd" @click="showCmd(row)">{{ T('SendCustom') }}</el-button>
72
+                <el-button v-if="row.id" type="primary" @click="toUpdate(row)">{{ T('Edit') }}</el-button>
73
+                <el-button v-if="row.id" type="danger" @click="del(row)">{{ T('Delete') }}</el-button>
74
+              </template>
75
+            </el-table-column>
76
+          </el-table>
77
+
78
+          <el-dialog v-model="formVisible">
79
+            <el-form label-width="150">
80
+              <el-form-item label="cmd">
81
+                <el-input v-model="formData.cmd"></el-input>
82
+              </el-form-item>
83
+              <el-form-item label="alias">
84
+                <el-input v-model="formData.alias"></el-input>
85
+              </el-form-item>
86
+              <el-form-item label="option">
87
+                <el-input v-model="formData.option"></el-input>
88
+              </el-form-item>
89
+              <el-form-item label="explain">
90
+                <el-input v-model="formData.explain"></el-input>
91
+              </el-form-item>
92
+              <el-form-item>
93
+                <el-button type="primary" @click="submit">{{ T('Submit') }}</el-button>
94
+                <el-button @click="cancel">{{ T('Cancel') }}</el-button>
95
+              </el-form-item>
96
+            </el-form>
97
+          </el-dialog>
98
+
99
+          <el-dialog :title="T('SendCmd')" v-model="showCmdForm">
100
+            <el-form label-width="150" :disabled="!canSendCmd">
101
+              <el-form-item label="cmd">
102
+                <el-input v-model="customCmd.cmd"></el-input>
103
+              </el-form-item>
104
+              <el-form-item label="option">
105
+                <el-input v-model="customCmd.option"></el-input>
106
+                <el-text v-if="customCmd.example.trim()" style="margin-top: 5px">Example:
107
+                  <el-text type="primary">{{ customCmd.example }}</el-text>
108
+                </el-text>
109
+              </el-form-item>
110
+              <el-form-item>
111
+                <el-button type="primary" @click="submitCmd">{{ T('Send') }}</el-button>
112
+              </el-form-item>
113
+              <el-form-item :label="T('Result')">
114
+                <el-input type="textarea" readonly disabled v-model="customCmd.res" rows="15"></el-input>
115
+              </el-form-item>
116
+            </el-form>
117
+          </el-dialog>
118
+        </el-card>
119
+      </el-tab-pane>
120
+    </el-tabs>
121
+
66 122
   </div>
67 123
 </template>
68 124
 
@@ -73,6 +129,69 @@
73 129
   import { T } from '@/utils/i18n'
74 130
   import { ElMessage, ElMessageBox } from 'element-plus'
75 131
 
132
+  const activeName = ref('Simple')
133
+
134
+  const canSendCmd = ref(false)
135
+  const checkCanSendCmd = async () => {
136
+    const res = await sendCmd({ cmd: 'h' }).catch(_ => false)
137
+    canSendCmd.value = !!res.data
138
+  }
139
+  const refreshCanSendCmd = () => {
140
+    checkCanSendCmd().then(_ => {
141
+      if (canSendCmd.value) {
142
+        getAUR()
143
+        getRS()
144
+      }
145
+    })
146
+  }
147
+  onMounted(refreshCanSendCmd)
148
+
149
+  const rsForm = reactive({
150
+    cmd: 'rs',
151
+    option: '',
152
+    loading: false,
153
+  })
154
+  const getRS = async () => {
155
+    rsForm.loading = true
156
+    const res = await sendCmd({ cmd: 'rs' }).catch(_ => false)
157
+    rsForm.loading = false
158
+    if (res) {
159
+      const data = res.data.split('\n').filter(i => i)
160
+      rsForm.option = data.join(',')
161
+    }
162
+  }
163
+  const saveRS = async () => {
164
+    const res = await sendCmd(rsForm).catch(_ => false)
165
+    if (res) {
166
+      ElMessage.success(T('OperationSuccess'))
167
+    }
168
+  }
169
+
170
+  const aurForm = reactive({
171
+    cmd: 'aur',
172
+    option: '',
173
+    value: 0,
174
+    loading: false,
175
+  })
176
+  const getAUR = async () => {
177
+    aurForm.loading = true
178
+    const res = await sendCmd({ cmd: 'aur' }).catch(_ => false)
179
+    aurForm.loading = false
180
+    if (res) {
181
+      if (res.data === 'ALWAYS_USE_RELAY: true' || res.data === 'ALWAYS_USE_RELAY: true\n') {
182
+        aurForm.option = 'Y'
183
+      } else {
184
+        aurForm.option = 'N'
185
+      }
186
+    }
187
+  }
188
+  const saveAUR = async () => {
189
+    const res = await sendCmd(aurForm).catch(_ => false)
190
+    if (res) {
191
+      ElMessage.success(T('OperationSuccess'))
192
+    }
193
+  }
194
+
76 195
   const listRes = reactive({
77 196
     list: [], total: 0, loading: false,
78 197
   })
@@ -157,12 +276,14 @@
157 276
     cmd: '',
158 277
     option: '',
159 278
     res: '',
279
+    example: '',
160 280
   })
161 281
   const showCmd = (row) => {
162 282
     showCmdForm.value = true
163 283
     customCmd.cmd = row.cmd
164 284
     customCmd.option = ''
165 285
     customCmd.res = ''
286
+    customCmd.example = `${row.cmd} ${row.option}`
166 287
   }
167 288
   const submitCmd = async () => {
168 289
     sendCmd(customCmd).then(res => {