Skip to content

Commit 1c801e8

Browse files
authored
update
1 parent 73de1f0 commit 1c801e8

File tree

5 files changed

+122
-64
lines changed

5 files changed

+122
-64
lines changed

src/app/[variants]/(main)/settings/storage/Advanced.tsx

+50-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
'use client';
22

3-
import { Form, type ItemGroup } from '@lobehub/ui';
4-
import { App, Button } from 'antd';
3+
import { Form, Icon, type ItemGroup } from '@lobehub/ui';
4+
import { App, Button, Dropdown, Space } from 'antd';
55
import isEqual from 'fast-deep-equal';
6+
import { ChevronDown, HardDriveDownload, HardDriveUpload } from 'lucide-react';
67
import { useCallback } from 'react';
78
import { useTranslation } from 'react-i18next';
89

910
import { FORM_STYLE } from '@/const/layoutTokens';
11+
import DataImporter from '@/features/DataImporter';
12+
import { configService } from '@/services/config';
1013
import { useChatStore } from '@/store/chat';
1114
import { useFileStore } from '@/store/file';
1215
import { useSessionStore } from '@/store/session';
@@ -52,6 +55,51 @@ const AdvancedActions = () => {
5255

5356
const system: ItemGroup = {
5457
children: [
58+
{
59+
children: (
60+
<DataImporter>
61+
<Button icon={<Icon icon={HardDriveDownload} />}>
62+
{t('storage.actions.import.button')}
63+
</Button>
64+
</DataImporter>
65+
),
66+
label: t('storage.actions.import.title'),
67+
minWidth: undefined,
68+
},
69+
{
70+
children: (
71+
<Space.Compact>
72+
<Button icon={<Icon icon={HardDriveUpload} />} onClick={configService.exportAll}>
73+
{t('storage.actions.export.button')}
74+
</Button>
75+
<Dropdown
76+
menu={{
77+
items: [
78+
{
79+
key: 'allAgent',
80+
label: t('storage.actions.export.exportType.allAgent'),
81+
onClick: configService.exportAgents,
82+
},
83+
{
84+
key: 'allAgentWithMessage',
85+
label: t('storage.actions.export.exportType.allAgentWithMessage'),
86+
onClick: configService.exportSessions,
87+
},
88+
{
89+
key: 'globalSetting',
90+
label: t('storage.actions.export.exportType.globalSetting'),
91+
onClick: configService.exportSettings,
92+
},
93+
],
94+
}}
95+
>
96+
<Button icon={<Icon icon={ChevronDown} />} />
97+
</Dropdown>
98+
</Space.Compact>
99+
),
100+
label: t('storage.actions.export.title'),
101+
minWidth: undefined,
102+
},
55103
{
56104
children: (
57105
<Button danger onClick={handleClear} type="primary">

src/app/[variants]/(main)/settings/storage/IndexedDBStorage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const IndexedDBStorage = memo(() => {
2121

2222
const percent = (usage / quota) * 100;
2323

24-
return { percent: percent < 1 ? 2 : percent, total: quota, used: usage };
24+
return { percent: percent < 1 ? 1 : percent, total: quota, used: usage };
2525
});
2626

2727
return (

src/database/repositories/dataExporter/index.ts

+55-26
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,22 @@ export const DATA_EXPORT_CONFIG = {
4747
relationTables: [
4848
{
4949
relations: [
50-
{ sourceField: 'id', sourceTable: 'agents', field: 'agentId' },
50+
{ field: 'agentId', sourceField: 'id', sourceTable: 'agents' },
5151
{ sourceField: 'sessionId', sourceTable: 'sessions' },
5252
],
5353
table: 'agentsToSessions',
5454
},
55-
// {
56-
// relations: [
57-
// { sourceField: 'agentId', sourceTable: 'agents' },
58-
// { sourceField: 'fileId', sourceTable: 'files' },
59-
// ],
60-
// table: 'agentsFiles',
61-
// },
62-
// {
63-
// relations: [{ field: 'sessionId', sourceTable: 'sessions' }],
64-
// table: 'filesToSessions',
65-
// },
55+
{
56+
relations: [
57+
{ sourceField: 'agentId', sourceTable: 'agents' },
58+
{ sourceField: 'fileId', sourceTable: 'files' },
59+
],
60+
table: 'agentsFiles',
61+
},
62+
{
63+
relations: [{ field: 'sessionId', sourceTable: 'sessions' }],
64+
table: 'filesToSessions',
65+
},
6666
// {
6767
// relations: [{ field: 'id', sourceTable: 'chunks' }],
6868
// table: 'fileChunks',
@@ -115,10 +115,13 @@ export const DATA_EXPORT_CONFIG = {
115115
};
116116

117117
export class DataExporterRepos {
118-
constructor(
119-
private db: LobeChatDatabase,
120-
private userId: string,
121-
) {}
118+
private userId: string;
119+
private db: LobeChatDatabase;
120+
121+
constructor(db: LobeChatDatabase, userId: string) {
122+
this.db = db;
123+
this.userId = userId;
124+
}
122125

123126
private removeUserId(data: any[]) {
124127
return data.map((item) => {
@@ -134,17 +137,31 @@ export class DataExporterRepos {
134137
if (!tableObj) throw new Error(`Table ${table} not found`);
135138

136139
try {
137-
let where;
140+
const conditions = [];
138141

139-
const conditions = config.relations.map((relation) => {
142+
// 处理每个关联条件
143+
for (const relation of config.relations) {
140144
const sourceData = existingData[relation.sourceTable] || [];
141145

146+
// 如果源数据为空,这个表可能无法查询到任何数据
147+
if (sourceData.length === 0) {
148+
console.log(
149+
`Source table ${relation.sourceTable} has no data, skipping query for ${table}`,
150+
);
151+
return [];
152+
}
153+
142154
const sourceIds = sourceData.map((item) => item[relation.sourceField || 'id']);
143-
console.log(sourceIds);
144-
return inArray(tableObj[relation.field], sourceIds);
145-
});
155+
conditions.push(inArray(tableObj[relation.field], sourceIds));
156+
}
157+
158+
// 如果表有userId字段并且不是users表,添加用户过滤
159+
if ('userId' in tableObj && table !== 'users' && !config.relations) {
160+
conditions.push(eq(tableObj.userId, this.userId));
161+
}
146162

147-
where = conditions.length === 1 ? conditions[0] : and(...conditions);
163+
// 组合所有条件
164+
const where = conditions.length === 1 ? conditions[0] : and(...conditions);
148165

149166
// @ts-expect-error query
150167
const result = await this.db.query[table].findMany({ where });
@@ -204,10 +221,22 @@ export class DataExporterRepos {
204221
console.log('Querying relation tables...');
205222
const relationResults = await pMap(
206223
DATA_EXPORT_CONFIG.relationTables,
207-
async (config) => ({
208-
data: await this.queryTable(config, result),
209-
table: config.table,
210-
}),
224+
async (config) => {
225+
// 检查所有依赖的源表是否有数据
226+
const allSourcesHaveData = config.relations.every(
227+
(relation) => (result[relation.sourceTable] || []).length > 0,
228+
);
229+
230+
if (!allSourcesHaveData) {
231+
console.log(`Skipping table ${config.table} as some source tables have no data`);
232+
return { data: [], table: config.table };
233+
}
234+
235+
return {
236+
data: await this.queryTable(config, result),
237+
table: config.table,
238+
};
239+
},
211240
{ concurrency },
212241
);
213242

src/features/User/UserPanel/useMenu.tsx

-35
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
Feather,
1010
FileClockIcon,
1111
HardDriveDownload,
12-
HardDriveUpload,
1312
LifeBuoy,
1413
LogOut,
1514
Mail,
@@ -32,10 +31,8 @@ import {
3231
UTM_SOURCE,
3332
mailTo,
3433
} from '@/const/url';
35-
import { isServerMode } from '@/const/version';
3634
import DataImporter from '@/features/DataImporter';
3735
import { usePWAInstall } from '@/hooks/usePWAInstall';
38-
import { configService } from '@/services/config';
3936
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
4037
import { useUserStore } from '@/store/user';
4138
import { authSelectors } from '@/store/user/selectors';
@@ -121,38 +118,6 @@ export const useMenu = () => {
121118
key: 'import',
122119
label: <DataImporter>{t('import')}</DataImporter>,
123120
},
124-
isServerMode
125-
? null
126-
: {
127-
children: [
128-
{
129-
key: 'allAgent',
130-
label: t('exportType.allAgent'),
131-
onClick: configService.exportAgents,
132-
},
133-
{
134-
key: 'allAgentWithMessage',
135-
label: t('exportType.allAgentWithMessage'),
136-
onClick: configService.exportSessions,
137-
},
138-
{
139-
key: 'globalSetting',
140-
label: t('exportType.globalSetting'),
141-
onClick: configService.exportSettings,
142-
},
143-
{
144-
type: 'divider',
145-
},
146-
{
147-
key: 'all',
148-
label: t('exportType.all'),
149-
onClick: configService.exportAll,
150-
},
151-
],
152-
icon: <Icon icon={HardDriveUpload} />,
153-
key: 'export',
154-
label: t('export'),
155-
},
156121
{
157122
type: 'divider',
158123
},

src/locales/default/setting.ts

+16
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,22 @@ export default {
339339
},
340340
storage: {
341341
actions: {
342+
export: {
343+
button: '导出',
344+
exportType: {
345+
agent: '导出助手设定',
346+
agentWithMessage: '导出助手和消息',
347+
all: '导出全局设置和所有助手数据',
348+
allAgent: '导出所有助手设定',
349+
allAgentWithMessage: '导出所有助手和消息',
350+
globalSetting: '导出全局设置',
351+
},
352+
title: '导出数据',
353+
},
354+
import: {
355+
button: '导入',
356+
title: '导入数据',
357+
},
342358
title: '高级操作',
343359
},
344360
desc: '当前浏览器中的存储用量',

0 commit comments

Comments
 (0)