From 20b3db0c0122addccab3a9ebd5e9f32b5667b822 Mon Sep 17 00:00:00 2001 From: Teo Date: Sat, 14 Jun 2025 15:48:47 +0800 Subject: [PATCH] Revert "refactor(FileItem, FileList, FilesPage, i18n): enhance file management UI and localization" This reverts commit edeb9f84f917d4613b714184c102123451142ce1. --- src/renderer/src/i18n/locales/en-us.json | 2 +- src/renderer/src/i18n/locales/ja-jp.json | 2 +- src/renderer/src/i18n/locales/ru-ru.json | 2 +- src/renderer/src/i18n/locales/zh-cn.json | 2 +- src/renderer/src/i18n/locales/zh-tw.json | 2 +- src/renderer/src/pages/files/FileItem.tsx | 70 ++---- src/renderer/src/pages/files/FileList.tsx | 200 ++++++++--------- src/renderer/src/pages/files/FilesPage.tsx | 209 +++--------------- .../src/pages/knowledge/KnowledgeContent.tsx | 14 +- .../components/KnowledgeFileItem.tsx | 124 ----------- 10 files changed, 169 insertions(+), 458 deletions(-) delete mode 100644 src/renderer/src/pages/knowledge/components/KnowledgeFileItem.tsx diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 0f4cc70d3d..71c0a6339f 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -470,7 +470,7 @@ "count": "files", "created_at": "Created At", "delete": "Delete", - "delete.content": "Deleting a file will delete its reference from all messages. Are you sure you want to delete {{count}} files?", + "delete.content": "Deleting a file will delete its reference from all messages. Are you sure you want to delete this file?", "delete.paintings.warning": "Image contains this file, deletion is not possible", "delete.title": "Delete File", "document": "Document", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index ebeecfa285..65b84150c4 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -470,7 +470,7 @@ "count": "ファイル", "created_at": "作成日", "delete": "削除", - "delete.content": "ファイルを削除すると、ファイルがすべてのメッセージで参照されることを削除します。この{{count}}ファイルを削除してもよろしいですか?", + "delete.content": "ファイルを削除すると、ファイルがすべてのメッセージで参照されることを削除します。このファイルを削除してもよろしいですか?", "delete.paintings.warning": "画像に含まれているため、削除できません", "delete.title": "ファイルを削除", "document": "ドキュメント", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 223e6b04a3..e54ae2cb1f 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -470,7 +470,7 @@ "count": "файлов", "created_at": "Дата создания", "delete": "Удалить", - "delete.content": "Удаление файла удалит его из всех сообщений, вы уверены, что хотите удалить этот {{count}} файл", + "delete.content": "Удаление файла удалит его из всех сообщений, вы уверены, что хотите удалить этот файл?", "delete.paintings.warning": "В изображениях содержится этот файл, удаление невозможно", "delete.title": "Удалить файл", "document": "Документ", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 2ec0ae5e56..17a37b6af3 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -470,7 +470,7 @@ "count": "个文件", "created_at": "创建时间", "delete": "删除", - "delete.content": "删除文件会删除文件在所有消息中的引用,确定要删除这{{count}}个文件吗?", + "delete.content": "删除文件会删除文件在所有消息中的引用,确定要删除此文件吗?", "delete.paintings.warning": "绘图中包含该图片,暂时无法删除", "delete.title": "删除文件", "document": "文档", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index c2d7ae0ca6..4e4265c3d3 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -470,7 +470,7 @@ "count": "個檔案", "created_at": "建立時間", "delete": "刪除", - "delete.content": "刪除檔案會刪除檔案在所有訊息中的引用,確定要刪除這{{count}}個檔案嗎?", + "delete.content": "刪除檔案會刪除檔案在所有訊息中的引用,確定要刪除此檔案嗎?", "delete.paintings.warning": "繪圖中包含該圖片,暫時無法刪除", "delete.title": "刪除檔案", "document": "文件", diff --git a/src/renderer/src/pages/files/FileItem.tsx b/src/renderer/src/pages/files/FileItem.tsx index 08724033e8..ce611ce983 100644 --- a/src/renderer/src/pages/files/FileItem.tsx +++ b/src/renderer/src/pages/files/FileItem.tsx @@ -12,7 +12,7 @@ import { GlobalOutlined, LinkOutlined } from '@ant-design/icons' -import { t } from 'i18next' +import { Flex } from 'antd' import React, { memo } from 'react' import styled from 'styled-components' @@ -21,14 +21,10 @@ interface FileItemProps { icon?: React.ReactNode name: React.ReactNode | string ext: string - size: string - created_at: string - count?: number - checkbox?: React.ReactNode + extra?: React.ReactNode | string actions: React.ReactNode } style?: React.CSSProperties - gridTemplate?: string } const getFileIcon = (type?: string) => { @@ -79,30 +75,19 @@ const getFileIcon = (type?: string) => { return } -const FileItem: React.FC = ({ fileInfo, style, gridTemplate = '' }) => { - const { name, ext, size, created_at, count, actions, icon, checkbox } = fileInfo +const FileItem: React.FC = ({ fileInfo, style }) => { + const { name, ext, extra, actions, icon } = fileInfo return ( - - {checkbox && {checkbox}} - - {icon || getFileIcon(ext)} - - - - {name} - {count && ( - - {count} {t('files.count')} - - )} - - - {size} - {created_at} - {actions} - + + {icon || getFileIcon(ext)} + + {name} + {extra && {extra}} + + {actions} + ) } @@ -126,36 +111,20 @@ const FileItemCard = styled.div` } ` -const FileGrid = styled.div` - display: grid; - gap: 8px; +const CardContent = styled.div` padding: 8px 8px 8px 16px; - align-items: center; -` - -const FileCell = styled.div` display: flex; - align-items: center; - min-width: 0; + align-items: stretch; + gap: 16px; ` const FileIcon = styled.div` max-height: 44px; - width: 100%; color: var(--color-text-3); font-size: 32px; display: flex; align-items: center; justify-content: center; - flex-shrink: 0; -` - -const FileNameColumn = styled.div` - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; - width: 100%; ` const FileName = styled.div` @@ -173,9 +142,16 @@ const FileName = styled.div` } ` -const FileCount = styled.div` +const FileInfo = styled.div` font-size: 13px; color: var(--color-text-2); ` +const FileActions = styled.div` + max-height: 44px; + display: flex; + align-items: center; + justify-content: center; +` + export default memo(FileItem) diff --git a/src/renderer/src/pages/files/FileList.tsx b/src/renderer/src/pages/files/FileList.tsx index 39fb61dfa9..cdb0421439 100644 --- a/src/renderer/src/pages/files/FileList.tsx +++ b/src/renderer/src/pages/files/FileList.tsx @@ -1,6 +1,11 @@ +import FileManager from '@renderer/services/FileManager' import { FileType, FileTypes } from '@renderer/types' +import { formatFileSize } from '@renderer/utils' +import { Col, Image, Row, Spin } from 'antd' +import { t } from 'i18next' import VirtualList from 'rc-virtual-list' import React, { memo } from 'react' +import styled from 'styled-components' import FileItem from './FileItem' @@ -14,47 +19,43 @@ interface FileItemProps { size: string ext: string created_at: string - checkbox?: React.ReactNode actions: React.ReactNode }[] files?: FileType[] - selectedFileIds?: string[] - onFileSelect?: (fileId: string, checked: boolean) => void - columnWidths?: string } -const FileList: React.FC = ({ list, columnWidths }) => { - // if (id === FileTypes.IMAGE && files?.length && files?.length > 0) { - // return ( - //
- // - // - // {files?.map((file) => ( - // - // - // - // - // - // { - // const img = e.target as HTMLImageElement - // img.parentElement?.classList.add('loaded') - // }} - // /> - // - //
{formatFileSize(file.size)}
- //
- //
- // - // ))} - //
- //
- //
- // ) - // } +const FileList: React.FC = ({ id, list, files }) => { + if (id === FileTypes.IMAGE && files?.length && files?.length > 0) { + return ( +
+ + + {files?.map((file) => ( + + + + + + { + const img = e.target as HTMLImageElement + img.parentElement?.classList.add('loaded') + }} + /> + +
{formatFileSize(file.size)}
+
+
+ + ))} +
+
+
+ ) + } return ( = ({ list, columnWidths }) => { height={window.innerHeight - 100} itemHeight={75} itemKey="key" - style={{ padding: '0 0 16px 0' }} + style={{ padding: '0 16px 16px 16px' }} styles={{ verticalScrollBar: { width: 6 @@ -75,21 +76,16 @@ const FileList: React.FC = ({ list, columnWidths }) => {
)} @@ -97,70 +93,70 @@ const FileList: React.FC = ({ list, columnWidths }) => { ) } -// const ImageWrapper = styled.div` -// position: relative; -// aspect-ratio: 1; -// overflow: hidden; -// border-radius: 8px; -// background-color: var(--color-background-soft); -// display: flex; -// align-items: center; -// justify-content: center; -// border: 0.5px solid var(--color-border); +const ImageWrapper = styled.div` + position: relative; + aspect-ratio: 1; + overflow: hidden; + border-radius: 8px; + background-color: var(--color-background-soft); + display: flex; + align-items: center; + justify-content: center; + border: 0.5px solid var(--color-border); -// .ant-image { -// height: 100%; -// width: 100%; -// opacity: 0; -// transition: -// opacity 0.3s ease, -// transform 0.3s ease; + .ant-image { + height: 100%; + width: 100%; + opacity: 0; + transition: + opacity 0.3s ease, + transform 0.3s ease; -// &.loaded { -// opacity: 1; -// } -// } + &.loaded { + opacity: 1; + } + } -// &:hover { -// .ant-image.loaded { -// transform: scale(1.05); -// } + &:hover { + .ant-image.loaded { + transform: scale(1.05); + } -// div:last-child { -// opacity: 1; -// } -// } -// ` + div:last-child { + opacity: 1; + } + } +` -// const LoadingWrapper = styled.div` -// position: absolute; -// top: 0; -// left: 0; -// right: 0; -// bottom: 0; -// display: flex; -// align-items: center; -// justify-content: center; -// background-color: var(--color-background-soft); -// ` +const LoadingWrapper = styled.div` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background-color: var(--color-background-soft); +` -// const ImageInfo = styled.div` -// position: absolute; -// bottom: 0; -// left: 0; -// right: 0; -// background: rgba(0, 0, 0, 0.6); -// color: white; -// padding: 5px 8px; -// opacity: 0; -// transition: opacity 0.3s ease; -// font-size: 12px; +const ImageInfo = styled.div` + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: rgba(0, 0, 0, 0.6); + color: white; + padding: 5px 8px; + opacity: 0; + transition: opacity 0.3s ease; + font-size: 12px; -// > div:first-child { -// white-space: nowrap; -// overflow: hidden; -// text-overflow: ellipsis; -// } -// ` + > div:first-child { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +` export default memo(FileList) diff --git a/src/renderer/src/pages/files/FilesPage.tsx b/src/renderer/src/pages/files/FilesPage.tsx index 64b21839cf..fa4b220e42 100644 --- a/src/renderer/src/pages/files/FilesPage.tsx +++ b/src/renderer/src/pages/files/FilesPage.tsx @@ -15,7 +15,7 @@ import store from '@renderer/store' import { FileType, FileTypes } from '@renderer/types' import { Message } from '@renderer/types/newMessage' import { formatFileSize } from '@renderer/utils' -import { Button, Checkbox, Empty, Flex, Popconfirm } from 'antd' +import { Button, Empty, Flex, Popconfirm } from 'antd' import dayjs from 'dayjs' import { useLiveQuery } from 'dexie-react-hooks' import { File as FileIcon, FileImage, FileText, FileType as FileTypeIcon } from 'lucide-react' @@ -25,8 +25,6 @@ import styled from 'styled-components' import FileList from './FileList' -const GRID_TEMPLATE = 'auto 60px 1fr 120px 140px 100px' - type SortField = 'created_at' | 'size' | 'name' type SortOrder = 'asc' | 'desc' @@ -35,7 +33,6 @@ const FilesPage: FC = () => { const [fileType, setFileType] = useState('document') const [sortField, setSortField] = useState('created_at') const [sortOrder, setSortOrder] = useState('desc') - const [selectedFileIds, setSelectedFileIds] = useState([]) const tempFilesSort = (files: FileType[]) => { return files.sort((a, b) => { @@ -173,38 +170,6 @@ const FilesPage: FC = () => { } } - // 全选/取消全选 - const handleSelectAll = (checked: boolean) => { - if (checked) { - setSelectedFileIds(sortedFiles.map((file) => file.id)) - } else { - setSelectedFileIds([]) - } - } - - // 单个文件选择 - const handleFileSelect = (fileId: string, checked: boolean) => { - if (checked) { - setSelectedFileIds((prev) => [...prev, fileId]) - } else { - setSelectedFileIds((prev) => prev.filter((id) => id !== fileId)) - } - } - - // 批量删除 - const handleBatchDelete = async () => { - if (selectedFileIds.length === 0) return - - try { - for (const fileId of selectedFileIds) { - await handleDelete(fileId) - } - setSelectedFileIds([]) - } catch (error) { - Logger.error('Batch delete error:', error) - } - } - const dataSource = sortedFiles?.map((file) => { return { key: file.id, @@ -216,18 +181,12 @@ const FilesPage: FC = () => { ext: file.ext, created_at: dayjs(file.created_at).format('MM-DD HH:mm'), created_at_unix: dayjs(file.created_at).unix(), - checkbox: ( - handleFileSelect(file.id, e.target.checked)} - /> - ), actions: (