@lobehub/chat 1.77.0 → 1.77.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/locales/ar/common.json +1 -1
- package/locales/bg-BG/common.json +1 -1
- package/locales/de-DE/common.json +1 -1
- package/locales/en-US/common.json +1 -1
- package/locales/es-ES/common.json +1 -1
- package/locales/fa-IR/common.json +1 -1
- package/locales/fr-FR/common.json +1 -1
- package/locales/it-IT/common.json +1 -1
- package/locales/ja-JP/common.json +1 -1
- package/locales/ko-KR/common.json +1 -1
- package/locales/nl-NL/common.json +1 -1
- package/locales/pl-PL/common.json +1 -1
- package/locales/pt-BR/common.json +1 -1
- package/locales/ru-RU/common.json +1 -1
- package/locales/tr-TR/common.json +1 -1
- package/locales/vi-VN/common.json +1 -1
- package/locales/zh-CN/common.json +1 -1
- package/locales/zh-CN/models.json +1 -1
- package/locales/zh-TW/common.json +1 -1
- package/package.json +1 -1
- package/src/app/[variants]/(main)/(mobile)/me/data/features/Category.tsx +1 -1
- package/src/app/[variants]/(main)/settings/storage/Advanced.tsx +10 -35
- package/src/database/models/__tests__/session.test.ts +21 -0
- package/src/database/server/models/session.ts +85 -9
- package/src/features/DataImporter/ImportDetail.tsx +1 -1
- package/src/features/User/UserPanel/useMenu.tsx +1 -1
- package/src/locales/default/common.ts +2 -2
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.77.1](https://github.com/lobehub/lobe-chat/compare/v1.77.0...v1.77.1)
|
6
|
+
|
7
|
+
<sup>Released on **2025-03-29**</sup>
|
8
|
+
|
9
|
+
#### 🐛 Bug Fixes
|
10
|
+
|
11
|
+
- **misc**: Fix export button and clean orphan agent.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### What's fixed
|
19
|
+
|
20
|
+
- **misc**: Fix export button and clean orphan agent, closes [#7219](https://github.com/lobehub/lobe-chat/issues/7219) ([112282a](https://github.com/lobehub/lobe-chat/commit/112282a))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
## [Version 1.77.0](https://github.com/lobehub/lobe-chat/compare/v1.76.1...v1.77.0)
|
6
31
|
|
7
32
|
<sup>Released on **2025-03-29**</sup>
|
package/changelog/v1.json
CHANGED
package/locales/ar/common.json
CHANGED
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "وضع كامل الشاشة",
|
185
185
|
"historyRange": "نطاق التاريخ",
|
186
|
-
"
|
186
|
+
"importData": "استيراد البيانات",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "عذرًا، حدث استثناء أثناء عملية استيراد البيانات. يرجى المحاولة مرة أخرى، أو <1>تقديم مشكلتك</1>، وسنقوم بمساعدتك على الفور في تحديد المشكلة.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Цял екран",
|
185
185
|
"historyRange": "Диапазон на историята",
|
186
|
-
"
|
186
|
+
"importData": "Импорт на данни",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Съжаляваме, възникна грешка по време на процеса на импорт на данни. Моля, опитайте отново да ги импортирате или <1>подайте проблем</1>, за да можем да помогнем веднага с отстраняването на проблема.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Vollbildmodus",
|
185
185
|
"historyRange": "Verlaufsbereich",
|
186
|
-
"
|
186
|
+
"importData": "Daten importieren",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Es tut uns sehr leid, aber beim Importieren der Daten ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut oder <1>senden Sie uns eine Anfrage</1>, damit wir das Problem umgehend für Sie lösen können.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Full Screen Mode",
|
185
185
|
"historyRange": "History Range",
|
186
|
-
"
|
186
|
+
"importData": "Import Data",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Sorry, an error occurred during the data import process. Please try importing again, or <1>submit a request</1>, and we will help you troubleshoot the issue as soon as possible.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Pantalla completa",
|
185
185
|
"historyRange": "Rango de historial",
|
186
|
-
"
|
186
|
+
"importData": "Importar datos",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Lo sentimos mucho, se produjo un error durante el proceso de importación de datos. Inténtalo de nuevo o <1>envía un informe</1>, y te ayudaremos a solucionar el problema lo antes posible.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "حالت تمام صفحه",
|
185
185
|
"historyRange": "محدوده تاریخی",
|
186
|
-
"
|
186
|
+
"importData": "وارد کردن دادهها",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "متأسفانه در فرآیند وارد کردن دادهها خطایی رخ داده است. لطفاً دوباره تلاش کنید یا <1>مشکل را گزارش دهید</1> تا ما در اسرع وقت به شما کمک کنیم.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Mode plein écran",
|
185
185
|
"historyRange": "Plage d'historique",
|
186
|
-
"
|
186
|
+
"importData": "Importer des données",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Désolé, une erreur s'est produite lors de l'importation des données. Veuillez réessayer l'importation ou <1> soumettre un problème </1>, nous vous aiderons à résoudre le problème dès que possible.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Modalità a schermo intero",
|
185
185
|
"historyRange": "Intervallo cronologico",
|
186
|
-
"
|
186
|
+
"importData": "Importa dati",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Ci dispiace molto, si è verificato un errore durante il processo di importazione dei dati. Si prega di provare a importare nuovamente, o <1>invia un problema</1>, saremo pronti ad aiutarti a risolvere il problema al più presto.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Volledig scherm",
|
185
185
|
"historyRange": "Geschiedenisbereik",
|
186
|
-
"
|
186
|
+
"importData": "Gegevens importeren",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Sorry, er is een uitzondering opgetreden tijdens het importeren van gegevens. Probeer opnieuw te importeren of <1>diend een probleem in</1>, we zullen het probleem zo snel mogelijk voor je onderzoeken.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Tryb pełnoekranowy",
|
185
185
|
"historyRange": "Zakres historii",
|
186
|
-
"
|
186
|
+
"importData": "Importuj dane",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Przepraszamy, wystąpił błąd podczas importowania danych. Spróbuj ponownie zaimportować, lub <1>zgłoś problem</1>, a my postaramy się jak najszybciej rozwiązać problem.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Modo de Tela Cheia",
|
185
185
|
"historyRange": "Intervalo de histórico",
|
186
|
-
"
|
186
|
+
"importData": "Importar dados",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Desculpe, ocorreu um erro durante o processo de importação de dados. Por favor, tente importar novamente ou <1>envie um problema</1>, e nós iremos ajudá-lo a resolver o problema o mais rápido possível.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Полноэкранный режим",
|
185
185
|
"historyRange": "История",
|
186
|
-
"
|
186
|
+
"importData": "Импорт данных",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Извините, произошла ошибка в процессе импорта данных. Попробуйте импортировать заново или <1>сообщите о проблеме</1>, и мы постараемся помочь вам как можно скорее.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Tam Ekran Modu",
|
185
185
|
"historyRange": "Geçmiş Aralığı",
|
186
|
-
"
|
186
|
+
"importData": "Veri İçe Aktar",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Üzgünüz, veri aktarımı sırasında bir hata oluştu. Lütfen tekrar deneyin veya <1>bir sorun bildirin</1>, sorunu çözmek için elimizden geleni yapacağız.",
|
@@ -183,7 +183,7 @@
|
|
183
183
|
},
|
184
184
|
"fullscreen": "Chế độ toàn màn hình",
|
185
185
|
"historyRange": "Phạm vi lịch sử",
|
186
|
-
"
|
186
|
+
"importData": "Nhập dữ liệu",
|
187
187
|
"importModal": {
|
188
188
|
"error": {
|
189
189
|
"desc": "Xin lỗi vì quá trình nhập dữ liệu gặp sự cố. Vui lòng thử nhập lại hoặc <1>gửi vấn đề</1>, chúng tôi sẽ kiểm tra vấn đề ngay lập tức.",
|
@@ -1083,7 +1083,7 @@
|
|
1083
1083
|
"description": "GPT-4o-mini 实时版本,支持音频和文本实时输入输出"
|
1084
1084
|
},
|
1085
1085
|
"gpt-4o-mini-tts": {
|
1086
|
-
"description": "GPT-4o mini TTS
|
1086
|
+
"description": "GPT-4o mini TTS 是一个基于 GPT-4o mini 构建的文本转语音模型,这是一种快速且强大的语言模型。使用它可以将文本转换为自然听起来的语音文本。最大输入标记数为 2000。"
|
1087
1087
|
},
|
1088
1088
|
"gpt-4o-realtime-preview": {
|
1089
1089
|
"description": "GPT-4o 实时版本,支持音频和文本实时输入输出"
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.77.
|
3
|
+
"version": "1.77.1",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -1,9 +1,9 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
3
|
import { Form, Icon, type ItemGroup } from '@lobehub/ui';
|
4
|
-
import { App, Button
|
4
|
+
import { App, Button } from 'antd';
|
5
5
|
import isEqual from 'fast-deep-equal';
|
6
|
-
import {
|
6
|
+
import { HardDriveDownload, HardDriveUpload } from 'lucide-react';
|
7
7
|
import { useCallback } from 'react';
|
8
8
|
import { useTranslation } from 'react-i18next';
|
9
9
|
|
@@ -68,39 +68,14 @@ const AdvancedActions = () => {
|
|
68
68
|
},
|
69
69
|
{
|
70
70
|
children: (
|
71
|
-
<
|
72
|
-
<
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
</Button>
|
80
|
-
<Dropdown
|
81
|
-
menu={{
|
82
|
-
items: [
|
83
|
-
{
|
84
|
-
key: 'allAgent',
|
85
|
-
label: t('storage.actions.export.exportType.allAgent'),
|
86
|
-
onClick: configService.exportAgents,
|
87
|
-
},
|
88
|
-
{
|
89
|
-
key: 'allAgentWithMessage',
|
90
|
-
label: t('storage.actions.export.exportType.allAgentWithMessage'),
|
91
|
-
onClick: configService.exportSessions,
|
92
|
-
},
|
93
|
-
{
|
94
|
-
key: 'globalSetting',
|
95
|
-
label: t('storage.actions.export.exportType.globalSetting'),
|
96
|
-
onClick: configService.exportSettings,
|
97
|
-
},
|
98
|
-
],
|
99
|
-
}}
|
100
|
-
>
|
101
|
-
<Button icon={<Icon icon={ChevronDown} />} />
|
102
|
-
</Dropdown>
|
103
|
-
</Space.Compact>
|
71
|
+
<Button
|
72
|
+
icon={<Icon icon={HardDriveUpload} />}
|
73
|
+
onClick={() => {
|
74
|
+
configService.exportAll();
|
75
|
+
}}
|
76
|
+
>
|
77
|
+
{t('storage.actions.export.button')}
|
78
|
+
</Button>
|
104
79
|
),
|
105
80
|
label: t('storage.actions.export.title'),
|
106
81
|
minWidth: undefined,
|
@@ -489,6 +489,7 @@ describe('SessionModel', () => {
|
|
489
489
|
it('should delete a session and its associated topics and messages', async () => {
|
490
490
|
// Create a session
|
491
491
|
const sessionId = '1';
|
492
|
+
await serverDB.insert(users).values([{ id: '456' }]);
|
492
493
|
await serverDB.insert(sessions).values({ id: sessionId, userId });
|
493
494
|
|
494
495
|
// Create some topics and messages associated with the session
|
@@ -500,6 +501,11 @@ describe('SessionModel', () => {
|
|
500
501
|
{ id: '1', sessionId, userId, role: 'user' },
|
501
502
|
{ id: '2', sessionId, userId, role: 'assistant' },
|
502
503
|
]);
|
504
|
+
await serverDB.insert(agents).values([
|
505
|
+
{ id: 'a1', userId },
|
506
|
+
{ id: 'a2', userId: '456' },
|
507
|
+
]);
|
508
|
+
await serverDB.insert(agentsToSessions).values([{ agentId: 'a1', userId, sessionId: '1' }]);
|
503
509
|
|
504
510
|
// Delete the session
|
505
511
|
await sessionModel.delete(sessionId);
|
@@ -514,6 +520,7 @@ describe('SessionModel', () => {
|
|
514
520
|
expect(
|
515
521
|
await serverDB.select().from(messages).where(eq(messages.sessionId, sessionId)),
|
516
522
|
).toHaveLength(0);
|
523
|
+
expect(await serverDB.select().from(agents).where(eq(agents.userId, userId))).toHaveLength(0);
|
517
524
|
});
|
518
525
|
|
519
526
|
it('should not delete sessions belonging to other users', async () => {
|
@@ -576,6 +583,8 @@ describe('SessionModel', () => {
|
|
576
583
|
// Create some sessions
|
577
584
|
const sessionIds = ['1', '2', '3'];
|
578
585
|
await serverDB.insert(sessions).values(sessionIds.map((id) => ({ id, userId })));
|
586
|
+
await serverDB.insert(agents).values([{ id: '1', userId }]);
|
587
|
+
await serverDB.insert(agentsToSessions).values([{ sessionId: '1', agentId: '1', userId }]);
|
579
588
|
|
580
589
|
// Create some topics and messages associated with the sessions
|
581
590
|
await serverDB.insert(topics).values([
|
@@ -602,6 +611,7 @@ describe('SessionModel', () => {
|
|
602
611
|
expect(
|
603
612
|
await serverDB.select().from(messages).where(inArray(messages.sessionId, sessionIds)),
|
604
613
|
).toHaveLength(0);
|
614
|
+
expect(await serverDB.select().from(agents)).toHaveLength(0);
|
605
615
|
});
|
606
616
|
|
607
617
|
it('should not delete sessions belonging to other users', async () => {
|
@@ -710,6 +720,14 @@ describe('SessionModel', () => {
|
|
710
720
|
{ id: 'm1', sessionId: '1', userId, role: 'user' },
|
711
721
|
{ id: 'm2', sessionId: '2', userId, role: 'assistant' },
|
712
722
|
]);
|
723
|
+
await trx.insert(agents).values([
|
724
|
+
{ id: 'a1', userId },
|
725
|
+
{ id: 'a2', userId },
|
726
|
+
]);
|
727
|
+
await trx.insert(agentsToSessions).values([
|
728
|
+
{ agentId: 'a1', sessionId: '1', userId },
|
729
|
+
{ agentId: 'a2', sessionId: '2', userId },
|
730
|
+
]);
|
713
731
|
});
|
714
732
|
|
715
733
|
await sessionModel.deleteAll();
|
@@ -723,6 +741,9 @@ describe('SessionModel', () => {
|
|
723
741
|
.from(messages)
|
724
742
|
.where(eq(messages.userId, userId));
|
725
743
|
expect(remainingMessages).toHaveLength(0);
|
744
|
+
|
745
|
+
const agentsTopics = await serverDB.select().from(agents).where(eq(agents.userId, userId));
|
746
|
+
expect(agentsTopics).toHaveLength(0);
|
726
747
|
});
|
727
748
|
});
|
728
749
|
|
@@ -279,26 +279,102 @@ export class SessionModel {
|
|
279
279
|
// **************** Delete *************** //
|
280
280
|
|
281
281
|
/**
|
282
|
-
* Delete a session
|
282
|
+
* Delete a session and its associated agent data if no longer referenced.
|
283
283
|
*/
|
284
284
|
delete = async (id: string) => {
|
285
|
-
return this.db
|
286
|
-
|
287
|
-
|
285
|
+
return this.db.transaction(async (trx) => {
|
286
|
+
// First get the agent IDs associated with this session
|
287
|
+
const links = await trx
|
288
|
+
.select({ agentId: agentsToSessions.agentId })
|
289
|
+
.from(agentsToSessions)
|
290
|
+
.where(and(eq(agentsToSessions.sessionId, id), eq(agentsToSessions.userId, this.userId)));
|
291
|
+
|
292
|
+
const agentIds = links.map((link) => link.agentId);
|
293
|
+
|
294
|
+
// Delete links in agentsToSessions
|
295
|
+
await trx
|
296
|
+
.delete(agentsToSessions)
|
297
|
+
.where(and(eq(agentsToSessions.sessionId, id), eq(agentsToSessions.userId, this.userId)));
|
298
|
+
|
299
|
+
// Delete the session
|
300
|
+
const result = await trx
|
301
|
+
.delete(sessions)
|
302
|
+
.where(and(eq(sessions.id, id), eq(sessions.userId, this.userId)));
|
303
|
+
|
304
|
+
// Delete orphaned agents
|
305
|
+
await this.clearOrphanAgent(agentIds, trx);
|
306
|
+
|
307
|
+
return result;
|
308
|
+
});
|
288
309
|
};
|
289
310
|
|
290
311
|
/**
|
291
|
-
* Batch delete sessions
|
312
|
+
* Batch delete sessions and their associated agent data if no longer referenced.
|
292
313
|
*/
|
293
314
|
batchDelete = async (ids: string[]) => {
|
294
|
-
return
|
295
|
-
|
296
|
-
|
315
|
+
if (ids.length === 0) return { count: 0 };
|
316
|
+
|
317
|
+
return this.db.transaction(async (trx) => {
|
318
|
+
// Get agent IDs associated with these sessions
|
319
|
+
const links = await trx
|
320
|
+
.select({ agentId: agentsToSessions.agentId })
|
321
|
+
.from(agentsToSessions)
|
322
|
+
.where(
|
323
|
+
and(inArray(agentsToSessions.sessionId, ids), eq(agentsToSessions.userId, this.userId)),
|
324
|
+
);
|
325
|
+
|
326
|
+
const agentIds = [...new Set(links.map((link) => link.agentId))];
|
327
|
+
|
328
|
+
// Delete links in agentsToSessions
|
329
|
+
await trx
|
330
|
+
.delete(agentsToSessions)
|
331
|
+
.where(
|
332
|
+
and(inArray(agentsToSessions.sessionId, ids), eq(agentsToSessions.userId, this.userId)),
|
333
|
+
);
|
334
|
+
|
335
|
+
// Delete the sessions
|
336
|
+
const result = await trx
|
337
|
+
.delete(sessions)
|
338
|
+
.where(and(inArray(sessions.id, ids), eq(sessions.userId, this.userId)));
|
339
|
+
|
340
|
+
// Delete orphaned agents
|
341
|
+
await this.clearOrphanAgent(agentIds, trx);
|
342
|
+
|
343
|
+
return result;
|
344
|
+
});
|
297
345
|
};
|
298
346
|
|
347
|
+
/**
|
348
|
+
* Delete all sessions and their associated agent data for this user.
|
349
|
+
*/
|
299
350
|
deleteAll = async () => {
|
300
|
-
return this.db.
|
351
|
+
return this.db.transaction(async (trx) => {
|
352
|
+
// Delete all agentsToSessions for this user
|
353
|
+
await trx.delete(agentsToSessions).where(eq(agentsToSessions.userId, this.userId));
|
354
|
+
|
355
|
+
// Delete all agents that were only used by this user's sessions
|
356
|
+
await trx.delete(agents).where(eq(agents.userId, this.userId));
|
357
|
+
|
358
|
+
// Delete all sessions for this user
|
359
|
+
return trx.delete(sessions).where(eq(sessions.userId, this.userId));
|
360
|
+
});
|
361
|
+
};
|
362
|
+
|
363
|
+
clearOrphanAgent = async (agentIds: string[], trx: any) => {
|
364
|
+
// Delete orphaned agents (those not linked to any other sessions)
|
365
|
+
for (const agentId of agentIds) {
|
366
|
+
const remaining = await trx
|
367
|
+
.select()
|
368
|
+
.from(agentsToSessions)
|
369
|
+
.where(eq(agentsToSessions.agentId, agentId))
|
370
|
+
.limit(1);
|
371
|
+
|
372
|
+
if (remaining.length === 0) {
|
373
|
+
await trx.delete(agents).where(and(eq(agents.id, agentId), eq(agents.userId, this.userId)));
|
374
|
+
}
|
375
|
+
}
|
301
376
|
};
|
377
|
+
|
302
378
|
// **************** Update *************** //
|
303
379
|
|
304
380
|
update = async (id: string, data: Partial<SessionItem>) => {
|
@@ -186,7 +186,7 @@ export default {
|
|
186
186
|
},
|
187
187
|
fullscreen: '全屏模式',
|
188
188
|
historyRange: '历史范围',
|
189
|
-
|
189
|
+
importData: '导入数据',
|
190
190
|
importModal: {
|
191
191
|
error: {
|
192
192
|
desc: '非常抱歉,数据导入过程发生异常。请尝试重新导入,或 <1>提交问题</1>,我们将会第一时间帮你排查问题。',
|
@@ -225,7 +225,7 @@ export default {
|
|
225
225
|
name: '表名',
|
226
226
|
},
|
227
227
|
title: '导入数据预览',
|
228
|
-
totalRecords:
|
228
|
+
totalRecords: '总计将导入 {{count}} 条记录',
|
229
229
|
totalTables: '{{count}} 个表',
|
230
230
|
},
|
231
231
|
information: '社区与资讯',
|