feat: Add knowledge base file management functionality

- Implemented `useKnowledgeFiles` hook for managing knowledge base files
- Added localization support for knowledge base file management in multiple languages
- Created UI option to remove all knowledge base files in DataSettings
- Updated file size formatting utility function
- Modified ContentView and FilesPage to use file size correctly
This commit is contained in:
kangfenmao 2025-03-03 23:20:31 +08:00
parent 37cf7427f9
commit 886a7ec1e9
10 changed files with 95 additions and 6 deletions

View File

@ -0,0 +1,43 @@
import FileManager from '@renderer/services/FileManager'
import { FileType } from '@renderer/types'
import { isEmpty } from 'lodash'
import { useEffect, useState } from 'react'
import { useKnowledgeBases } from './useKnowledge'
export const useKnowledgeFiles = () => {
const [knowledgeFiles, setKnowledgeFiles] = useState<FileType[]>([])
const { bases, updateKnowledgeBases } = useKnowledgeBases()
useEffect(() => {
const items = bases.map((kb) => kb.items).flat()
const fileItems = items.filter((item) => item.type === 'file')
const files = fileItems.map((item) => item.content as FileType)
!isEmpty(files) && setKnowledgeFiles(files)
}, [bases])
const removeAllFiles = async () => {
console.debug('removeAllFiles', knowledgeFiles)
await FileManager.deleteFiles(knowledgeFiles)
const newBases = bases.map((kb) => ({
...kb,
items: kb.items.map((item) =>
item.type === 'file'
? {
...item,
content: {
...(item.content as FileType),
size: 0
}
}
: item
)
}))
updateKnowledgeBases(newBases)
}
const size = knowledgeFiles.reduce((acc, file) => acc + file.size, 0)
return { knowledgeFiles, size, removeAllFiles }
}

View File

@ -595,6 +595,10 @@
"data": { "data": {
"app_data": "App Data", "app_data": "App Data",
"app_logs": "App Logs", "app_logs": "App Logs",
"app_knowledge": "Knowledge Base Files",
"app_knowledge.remove_all": "Remove Files",
"app_knowledge.remove_all_confirm": "Removing knowledge base files will not delete the knowledge base itself, which will reduce the storage space occupied. Continue?",
"app_knowledge.remove_all_success": "Files removed successfully",
"clear_cache": { "clear_cache": {
"button": "Clear Cache", "button": "Clear Cache",
"confirm": "Clearing the cache will delete application cache data, including minapp data. This action is irreversible, continue?", "confirm": "Clearing the cache will delete application cache data, including minapp data. This action is irreversible, continue?",

View File

@ -595,6 +595,10 @@
"data": { "data": {
"app_data": "アプリデータ", "app_data": "アプリデータ",
"app_logs": "アプリログ", "app_logs": "アプリログ",
"app_knowledge": "ナレッジベースファイル",
"app_knowledge.remove_all": "ファイルを削除",
"app_knowledge.remove_all_confirm": "ナレッジベースファイルを削除してもナレッジベース自体は削除されません。これにより、ストレージ容量を節約できます。続行しますか?",
"app_knowledge.remove_all_success": "ファイル削除成功",
"clear_cache": { "clear_cache": {
"button": "キャッシュをクリア", "button": "キャッシュをクリア",
"confirm": "キャッシュをクリアすると、アプリのキャッシュデータ(ミニアプリデータを含む)が削除されます。この操作は元に戻せません。続行しますか?", "confirm": "キャッシュをクリアすると、アプリのキャッシュデータ(ミニアプリデータを含む)が削除されます。この操作は元に戻せません。続行しますか?",

View File

@ -595,6 +595,10 @@
"data": { "data": {
"app_data": "Данные приложения", "app_data": "Данные приложения",
"app_logs": "Логи приложения", "app_logs": "Логи приложения",
"app_knowledge": "База знаний",
"app_knowledge.remove_all": "Удалить файлы",
"app_knowledge.remove_all_confirm": "Удаление файлов базы знаний не удалит саму базу знаний, что позволит уменьшить занимаемый объем памяти, продолжить?",
"app_knowledge.remove_all_success": "Файлы удалены успешно",
"clear_cache": { "clear_cache": {
"button": "Очистка кэша", "button": "Очистка кэша",
"confirm": "Очистка кэша удалит данные приложения. Это действие необратимо, продолжить?", "confirm": "Очистка кэша удалит данные приложения. Это действие необратимо, продолжить?",

View File

@ -595,6 +595,10 @@
"data": { "data": {
"app_data": "应用数据", "app_data": "应用数据",
"app_logs": "应用日志", "app_logs": "应用日志",
"app_knowledge": "知识库文件",
"app_knowledge.remove_all": "删除文件",
"app_knowledge.remove_all_confirm": "删除知识库文件不会删除知识库本身,可以减少存储空间占用,删除之后文件无法再打开,是否继续?",
"app_knowledge.remove_all_success": "文件删除成功",
"clear_cache": { "clear_cache": {
"button": "清除缓存", "button": "清除缓存",
"confirm": "清除缓存将删除应用缓存的数据,包括小程序数据。此操作不可恢复,是否继续?", "confirm": "清除缓存将删除应用缓存的数据,包括小程序数据。此操作不可恢复,是否继续?",

View File

@ -595,6 +595,10 @@
"data": { "data": {
"app_data": "應用數據", "app_data": "應用數據",
"app_logs": "應用日誌", "app_logs": "應用日誌",
"app_knowledge": "知識庫文件",
"app_knowledge.remove_all": "刪除文件",
"app_knowledge.remove_all_confirm": "刪除知識庫文件不會刪除知識庫本身,可以減少存儲空間占用,刪除之後文件無法再打開,是否繼續?",
"app_knowledge.remove_all_success": "文件刪除成功",
"clear_cache": { "clear_cache": {
"button": "清除緩存", "button": "清除緩存",
"confirm": "清除緩存將刪除應用緩存數據,包括小程序數據。此操作不可恢復,是否繼續?", "confirm": "清除緩存將刪除應用緩存數據,包括小程序數據。此操作不可恢復,是否繼續?",

View File

@ -35,7 +35,7 @@ const ContentView: React.FC<ContentViewProps> = ({ id, files, dataSource, column
}} }}
/> />
<ImageInfo> <ImageInfo>
<div>{formatFileSize(file)}</div> <div>{formatFileSize(file.size)}</div>
</ImageInfo> </ImageInfo>
</ImageWrapper> </ImageWrapper>
</Col> </Col>

View File

@ -111,7 +111,7 @@ const FilesPage: FC = () => {
{file.origin_name} {file.origin_name}
</FileNameText> </FileNameText>
), ),
size: formatFileSize(file), size: formatFileSize(file.size),
size_bytes: file.size, size_bytes: file.size,
count: file.count, count: file.count,
created_at: dayjs(file.created_at).format('MM-DD HH:mm'), created_at: dayjs(file.created_at).format('MM-DD HH:mm'),

View File

@ -5,6 +5,7 @@ import MinApp from '@renderer/components/MinApp'
import BackupPopup from '@renderer/components/Popups/BackupPopup' import BackupPopup from '@renderer/components/Popups/BackupPopup'
import RestorePopup from '@renderer/components/Popups/RestorePopup' import RestorePopup from '@renderer/components/Popups/RestorePopup'
import { useTheme } from '@renderer/context/ThemeProvider' import { useTheme } from '@renderer/context/ThemeProvider'
import { useKnowledgeFiles } from '@renderer/hooks/useKnowledgeFiles'
import { reset } from '@renderer/services/BackupService' import { reset } from '@renderer/services/BackupService'
import { RootState, useAppDispatch } from '@renderer/store' import { RootState, useAppDispatch } from '@renderer/store'
import { import {
@ -18,6 +19,7 @@ import {
setYuqueUrl setYuqueUrl
} from '@renderer/store/settings' } from '@renderer/store/settings'
import { AppInfo } from '@renderer/types' import { AppInfo } from '@renderer/types'
import { formatFileSize } from '@renderer/utils'
import { Button, InputNumber, Modal, Switch, Tooltip, Typography } from 'antd' import { Button, InputNumber, Modal, Switch, Tooltip, Typography } from 'antd'
import Input from 'antd/es/input/Input' import Input from 'antd/es/input/Input'
import { FC, useEffect, useState } from 'react' import { FC, useEffect, useState } from 'react'
@ -298,6 +300,7 @@ const YuqueSettings: FC = () => {
const DataSettings: FC = () => { const DataSettings: FC = () => {
const { t } = useTranslation() const { t } = useTranslation()
const [appInfo, setAppInfo] = useState<AppInfo>() const [appInfo, setAppInfo] = useState<AppInfo>()
const { size, removeAllFiles } = useKnowledgeFiles()
const { theme } = useTheme() const { theme } = useTheme()
useEffect(() => { useEffect(() => {
@ -334,6 +337,22 @@ const DataSettings: FC = () => {
}) })
} }
const handleRemoveAllFiles = () => {
Modal.confirm({
centered: true,
title: t('settings.data.app_knowledge.remove_all') + ` (${formatFileSize(size)}) `,
content: t('settings.data.app_knowledge.remove_all_confirm'),
onOk: async () => {
await removeAllFiles()
window.message.success(t('settings.data.app_knowledge.remove_all_success'))
},
okText: t('common.delete'),
okButtonProps: {
danger: true
}
})
}
return ( return (
<SettingContainer theme={theme}> <SettingContainer theme={theme}>
<SettingGroup theme={theme}> <SettingGroup theme={theme}>
@ -384,6 +403,15 @@ const DataSettings: FC = () => {
</HStack> </HStack>
</SettingRow> </SettingRow>
<SettingDivider /> <SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.data.app_knowledge')}</SettingRowTitle>
<HStack alignItems="center" gap="5px">
<Button onClick={handleRemoveAllFiles} danger>
{t('settings.data.app_knowledge.remove_all')}
</Button>
</HStack>
</SettingRow>
<SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitle>{t('settings.data.clear_cache.title')}</SettingRowTitle> <SettingRowTitle>{t('settings.data.clear_cache.title')}</SettingRowTitle>
<HStack gap="5px"> <HStack gap="5px">

View File

@ -1,4 +1,4 @@
import { FileType, Model } from '@renderer/types' import { Model } from '@renderer/types'
import { ModalFuncProps } from 'antd/es/modal/interface' import { ModalFuncProps } from 'antd/es/modal/interface'
import imageCompression from 'browser-image-compression' import imageCompression from 'browser-image-compression'
import html2canvas from 'html2canvas' import html2canvas from 'html2canvas'
@ -394,9 +394,7 @@ export function hasPath(url: string): boolean {
} }
} }
export function formatFileSize(file: FileType) { export function formatFileSize(size: number) {
const size = file.size
if (size > 1024 * 1024) { if (size > 1024 * 1024) {
return (size / 1024 / 1024).toFixed(1) + ' MB' return (size / 1024 / 1024).toFixed(1) + ' MB'
} }