From a346686944eef94a8e51f1519c4aa048d778ecc8 Mon Sep 17 00:00:00 2001 From: billchen Date: Fri, 26 Apr 2024 14:40:55 +0800 Subject: [PATCH 1/2] feat: translate FileManager --- web/.umirc.ts | 2 +- web/src/interfaces/common.ts | 2 +- web/src/layouts/components/header/index.tsx | 4 +- web/src/locales/en.ts | 20 +++++++++ web/src/locales/zh-traditional.ts | 21 +++++++++- web/src/locales/zh.ts | 26 ++++++++++-- .../pages/file-manager/action-cell/index.tsx | 2 +- .../connect-to-knowledge-modal/index.tsx | 8 +++- web/src/pages/file-manager/file-toolbar.tsx | 9 ++-- .../file-manager/file-upload-modal/index.tsx | 34 ++++++++------- .../folder-create-modal/index.tsx | 2 +- web/src/pages/file-manager/hooks.ts | 7 ++-- web/src/pages/file-manager/index.tsx | 41 +++++++++++++------ 13 files changed, 131 insertions(+), 47 deletions(-) diff --git a/web/.umirc.ts b/web/.umirc.ts index c4c622f15d3..5cbf1c0aa77 100644 --- a/web/.umirc.ts +++ b/web/.umirc.ts @@ -27,7 +27,7 @@ export default defineConfig({ devtool: 'source-map', proxy: { '/v1': { - target: 'http://192.168.200.233:9380/', + target: 'http://123.60.95.134:9380/', changeOrigin: true, // pathRewrite: { '^/v1': '/v1' }, }, diff --git a/web/src/interfaces/common.ts b/web/src/interfaces/common.ts index 180f20856c4..a26c610e0c3 100644 --- a/web/src/interfaces/common.ts +++ b/web/src/interfaces/common.ts @@ -14,5 +14,5 @@ export interface IModalProps { hideModal(): void; visible: boolean; loading?: boolean; - onOk?(payload?: T): Promise | void; + onOk?(payload?: T): Promise | void; } diff --git a/web/src/layouts/components/header/index.tsx b/web/src/layouts/components/header/index.tsx index 2819f426c03..6d73ccc23eb 100644 --- a/web/src/layouts/components/header/index.tsx +++ b/web/src/layouts/components/header/index.tsx @@ -1,5 +1,5 @@ import { ReactComponent as StarIon } from '@/assets/svg/chat-star.svg'; -// import { ReactComponent as FileIcon } from '@/assets/svg/file-management.svg'; +import { ReactComponent as FileIcon } from '@/assets/svg/file-management.svg'; import { ReactComponent as KnowledgeBaseIcon } from '@/assets/svg/knowledge-base.svg'; import { ReactComponent as Logo } from '@/assets/svg/logo.svg'; import { useTranslate } from '@/hooks/commonHooks'; @@ -25,7 +25,7 @@ const RagHeader = () => { () => [ { path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon }, { path: '/chat', name: t('chat'), icon: StarIon }, - // { path: '/file', name: 'File Management', icon: FileIcon }, + { path: '/file', name: t('fileManager'), icon: FileIcon }, ], [t], ); diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 2666319d61d..9e19302f84c 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -22,6 +22,7 @@ export default { languagePlaceholder: 'select your language', copy: 'Copy', copied: 'Copied', + comingSoon: 'Coming Soon', }, login: { login: 'Sign in', @@ -52,6 +53,7 @@ export default { home: 'Home', setting: '用户设置', logout: '登出', + fileManager: 'File Management', }, knowledgeList: { welcome: 'Welcome back', @@ -480,6 +482,24 @@ export default { networkAnomaly: 'network anomaly', hint: 'hint', }, + fileManager: { + name: 'Name', + uploadDate: 'Upload Date', + knowledgeBase: 'Knowledge Base', + size: 'Size', + action: 'Action', + addToKnowledge: 'Add to Knowledge Base', + pleaseSelect: 'Please select', + newFolder: 'New Folder', + file: 'File', + uploadFile: 'Upload File', + directory: 'Directory', + uploadTitle: 'Click or drag file to this area to upload', + uploadDescription: + 'Support for a single or bulk upload. Strictly prohibited from uploading company data or other banned files.', + local: 'Local uploads', + s3: 'S3 uploads', + }, footer: { profile: 'All rights reserved @ React', }, diff --git a/web/src/locales/zh-traditional.ts b/web/src/locales/zh-traditional.ts index c0b559cc0fa..bdaaa3cd482 100644 --- a/web/src/locales/zh-traditional.ts +++ b/web/src/locales/zh-traditional.ts @@ -22,6 +22,7 @@ export default { languagePlaceholder: '請選擇語言', copy: '複製', copied: '複製成功', + comingSoon: '即將推出', }, login: { login: '登入', @@ -52,6 +53,7 @@ export default { home: '首頁', setting: '用戶設置', logout: '登出', + fileManager: '文件管理', }, knowledgeList: { welcome: '歡迎回來', @@ -218,7 +220,7 @@ export default { 您只需與'ragflow'交談即可列出所有符合資格的候選人。

`, - table: `支持

excelcsv/txt格式文件。

以下是一些提示:

  • 对于Csv或Txt文件,列之间的分隔符为 tab
  • 第一行必须是列标题。
  • 列标题必须是有意义的术语,以便我们的法学硕士能够理解。列举一些同义词时最好使用斜杠'/'来分隔,甚至更好使用方括号枚举值,例如 “性別/性別(男性,女性)”.

    以下是标题的一些示例:

    1. 供应商/供货商'tab'顏色(黃色、紅色、棕色)'tab'性別(男、女)'tab'尺码(m、l、xl、xxl)
    2. 姓名/名字'tab'電話/手機/微信'tab'最高学历(高中,职高,硕士,本科,博士,初中,中技,中专,专科,专升本,mpa,mba,emba)

  • 表中的每一行都将被视为一个块。
`, + table: `支持

excelcsv/txt格式文件。

以下是一些提示:

  • 对于Csv或Txt文件,列之间的分隔符为 tab
  • 第一行必须是列标题。
  • 列标题必须是有意义的术语,以便我们的大語言模型能够理解。列举一些同义词时最好使用斜杠'/'来分隔,甚至更好使用方括号枚举值,例如 “性別/性別(男性,女性)”.

    以下是标题的一些示例:

    1. 供应商/供货商'tab'顏色(黃色、紅色、棕色)'tab'性別(男、女)'tab'尺码(m、l、xl、xxl)
    2. 姓名/名字'tab'電話/手機/微信'tab'最高学历(高中,职高,硕士,本科,博士,初中,中技,中专,专科,专升本,mpa,mba,emba)

  • 表中的每一行都将被视为一个块。
`, picture: `

支持圖像文件。視頻即將推出。

如果圖片中有文字,則應用 OCR 提取文字作為其文字描述。 @@ -444,6 +446,23 @@ export default { networkAnomaly: '網絡異常', hint: '提示', }, + fileManager: { + name: '名稱', + uploadDate: '上傳日期', + knowledgeBase: '知識庫', + size: '大小', + action: '操作', + addToKnowledge: '添加到知識庫', + pleaseSelect: '請選擇', + newFolder: '新建文件夾', + uploadFile: '上傳文件', + uploadTitle: '點擊或拖拽文件至此區域即可上傳', + uploadDescription: '支持單次或批量上傳。嚴禁上傳公司數據或其他違禁文件。', + file: '文件', + directory: '文件夾', + local: '本地上傳', + s3: 'S3 上傳', + }, footer: { profile: '“保留所有權利 @ react”', }, diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index 36748060673..4b853134310 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -22,6 +22,7 @@ export default { languagePlaceholder: '请选择语言', copy: '复制', copied: '复制成功', + comingSoon: '即将推出', }, login: { login: '登录', @@ -52,6 +53,7 @@ export default { home: '首页', setting: '用户设置', logout: '登出', + fileManager: '文件管理', }, knowledgeList: { welcome: '欢迎回来', @@ -225,7 +227,7 @@ export default {

  • 对于 csv 或 txt 文件,列之间的分隔符为 TAB
  • 第一行必须是列标题。
  • -
  • 列标题必须是有意义的术语,以便我们的法学硕士能够理解。 +
  • 列标题必须是有意义的术语,以便我们的大语言模型能够理解。 列举一些同义词时最好使用斜杠'/'来分隔,甚至更好 使用方括号枚举值,例如 'gender/sex(male,female)'.

    以下是标题的一些示例:

      @@ -298,7 +300,7 @@ export default { systemTip: '当LLM回答问题时,你需要LLM遵循的说明,比如角色设计、答案长度和答案语言等。', topN: 'Top N', - topNTip: `并非所有相似度得分高于“相似度阈值”的块都会被提供给法学硕士。 LLM 只能看到这些“Top N”块。`, + topNTip: `并非所有相似度得分高于“相似度阈值”的块都会被提供给大语言模型。 LLM 只能看到这些“Top N”块。`, variable: '变量', variableTip: `如果您使用对话 API,变量可能会帮助您使用不同的策略与客户聊天。 这些变量用于填写提示中的“系统”部分,以便给LLM一个提示。 @@ -315,7 +317,7 @@ export default { improvise: '即兴创作', precise: '精确', balance: '平衡', - freedomTip: `“精确”意味着法学硕士会保守并谨慎地回答你的问题。 “即兴发挥”意味着你希望法学硕士能够自由地畅所欲言。 “平衡”是谨慎与自由之间的平衡。`, + freedomTip: `“精确”意味着大语言模型会保守并谨慎地回答你的问题。 “即兴发挥”意味着你希望大语言模型能够自由地畅所欲言。 “平衡”是谨慎与自由之间的平衡。`, temperature: '温度', temperatureMessage: '温度是必填项', temperatureTip: @@ -461,6 +463,24 @@ export default { networkAnomaly: '网络异常', hint: '提示', }, + fileManager: { + name: '名称', + uploadDate: '上传日期', + knowledgeBase: '知识库', + size: '大小', + action: '操作', + addToKnowledge: '添加到知识库', + pleaseSelect: '请选择', + newFolder: '新建文件夹', + uploadFile: '上传文件', + uploadTitle: '点击或拖拽文件至此区域即可上传', + uploadDescription: + '支持单次或批量上传。 严禁上传公司数据或其他违禁文件。', + file: '文件', + directory: '文件夹', + local: '本地上传', + s3: 'S3 上传', + }, footer: { profile: 'All rights reserved @ React', }, diff --git a/web/src/pages/file-manager/action-cell/index.tsx b/web/src/pages/file-manager/action-cell/index.tsx index 3107e611eac..1c8aeae0d2e 100644 --- a/web/src/pages/file-manager/action-cell/index.tsx +++ b/web/src/pages/file-manager/action-cell/index.tsx @@ -38,7 +38,7 @@ const ActionCell = ({ const onDownloadDocument = () => { downloadFile({ - url: `${api_host}/document/get/${documentId}`, + url: `${api_host}/file/get/${documentId}`, filename: record.name, }); }; diff --git a/web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx b/web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx index 0dbfdf7238d..9ed27e721c3 100644 --- a/web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx +++ b/web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx @@ -1,3 +1,4 @@ +import { useTranslate } from '@/hooks/commonHooks'; import { useFetchKnowledgeList } from '@/hooks/knowledgeHook'; import { IModalProps } from '@/interfaces/common'; import { Form, Modal, Select, SelectProps } from 'antd'; @@ -8,9 +9,11 @@ const ConnectToKnowledgeModal = ({ hideModal, onOk, initialValue, + loading, }: IModalProps & { initialValue: string[] }) => { const [form] = Form.useForm(); const { list, fetchList } = useFetchKnowledgeList(); + const { t } = useTranslate('fileManager'); const options: SelectProps['options'] = list?.map((item) => ({ label: item.name, @@ -32,10 +35,11 @@ const ConnectToKnowledgeModal = ({ return (
      @@ -43,7 +47,7 @@ const ConnectToKnowledgeModal = ({ mode="multiple" allowClear style={{ width: '100%' }} - placeholder="Please select" + placeholder={t('pleaseSelect')} options={options} /> diff --git a/web/src/pages/file-manager/file-toolbar.tsx b/web/src/pages/file-manager/file-toolbar.tsx index 0acf0a0666b..e2fcf82be63 100644 --- a/web/src/pages/file-manager/file-toolbar.tsx +++ b/web/src/pages/file-manager/file-toolbar.tsx @@ -70,7 +70,7 @@ const FileToolbar = ({ @@ -83,12 +83,13 @@ const FileToolbar = ({ label: (
      ), - // disabled: true, }, ]; }, [t, showFolderCreateModal, showFileUploadModal]); diff --git a/web/src/pages/file-manager/file-upload-modal/index.tsx b/web/src/pages/file-manager/file-upload-modal/index.tsx index b88fa4b3d7f..da035ff673c 100644 --- a/web/src/pages/file-manager/file-upload-modal/index.tsx +++ b/web/src/pages/file-manager/file-upload-modal/index.tsx @@ -1,3 +1,4 @@ +import { useTranslate } from '@/hooks/commonHooks'; import { IModalProps } from '@/interfaces/common'; import { InboxOutlined } from '@ant-design/icons'; import { @@ -23,6 +24,7 @@ const FileUpload = ({ fileList: UploadFile[]; setFileList: Dispatch>; }) => { + const { t } = useTranslate('fileManager'); const props: UploadProps = { multiple: true, onRemove: (file) => { @@ -47,13 +49,8 @@ const FileUpload = ({

      -

      - Click or drag file to this area to upload -

      -

      - Support for a single or bulk upload. Strictly prohibited from uploading - company data or other banned files. -

      +

      {t('uploadTitle')}

      +

      {t('uploadDescription')}

      ); }; @@ -64,18 +61,25 @@ const FileUploadModal = ({ loading, onOk: onFileUploadOk, }: IModalProps) => { + const { t } = useTranslate('fileManager'); const [value, setValue] = useState('local'); const [fileList, setFileList] = useState([]); const [directoryFileList, setDirectoryFileList] = useState([]); - const onOk = () => { - return onFileUploadOk?.([...fileList, ...directoryFileList]); + const onOk = async () => { + const ret = await onFileUploadOk?.([...fileList, ...directoryFileList]); + console.info(ret); + if (ret !== undefined && ret === 0) { + setFileList([]); + setDirectoryFileList([]); + } + return ret; }; const items: TabsProps['items'] = [ { key: '1', - label: 'File', + label: t('file'), children: ( ) : ( - 'coming soon' + t('comingSoon', { keyPrefix: 'common' }) )} diff --git a/web/src/pages/file-manager/folder-create-modal/index.tsx b/web/src/pages/file-manager/folder-create-modal/index.tsx index e16511f3e77..7ab58ed08b0 100644 --- a/web/src/pages/file-manager/folder-create-modal/index.tsx +++ b/web/src/pages/file-manager/folder-create-modal/index.tsx @@ -35,7 +35,7 @@ const FolderCreateModal = ({ visible, hideModal, loading, onOk }: IProps) => { return ( { const id = useGetFolderId(); const onFileUploadOk = useCallback( - async (fileList: UploadFile[]) => { - console.info('fileList', fileList); + async (fileList: UploadFile[]): Promise => { if (fileList.length > 0) { - const ret = await uploadFile(fileList, id); + const ret: number = await uploadFile(fileList, id); console.info(ret); if (ret === 0) { hideFileUploadModal(); } + return ret; } }, [uploadFile, hideFileUploadModal, id], @@ -295,6 +295,7 @@ export const useHandleConnectToKnowledge = () => { if (ret === 0) { hideConnectToKnowledgeModal(); } + return ret; }, [connectToKnowledge, hideConnectToKnowledgeModal, id, record.id], ); diff --git a/web/src/pages/file-manager/index.tsx b/web/src/pages/file-manager/index.tsx index c2a7042a05c..9b45fe9d626 100644 --- a/web/src/pages/file-manager/index.tsx +++ b/web/src/pages/file-manager/index.tsx @@ -1,7 +1,7 @@ import { useSelectFileList } from '@/hooks/fileManagerHooks'; import { IFile } from '@/interfaces/database/file-manager'; import { formatDate } from '@/utils/date'; -import { Button, Flex, Table } from 'antd'; +import { Button, Flex, Space, Table, Tag } from 'antd'; import { ColumnsType } from 'antd/es/table'; import ActionCell from './action-cell'; import FileToolbar from './file-toolbar'; @@ -18,6 +18,7 @@ import { import RenameModal from '@/components/rename-modal'; import SvgIcon from '@/components/svg-icon'; +import { useTranslate } from '@/hooks/commonHooks'; import { getExtension } from '@/utils/documentUtils'; import ConnectToKnowledgeModal from './connect-to-knowledge-modal'; import FileUploadModal from './file-upload-modal'; @@ -25,6 +26,7 @@ import FolderCreateModal from './folder-create-modal'; import styles from './index.less'; const FileManager = () => { + const { t } = useTranslate('fileManager'); const fileList = useSelectFileList(); const { rowSelection, setSelectedRowKeys } = useGetRowSelection(); const loading = useSelectFileListLoading(); @@ -57,12 +59,13 @@ const FileManager = () => { showConnectToKnowledgeModal, onConnectToKnowledgeOk, initialValue, + connectToKnowledgeLoading, } = useHandleConnectToKnowledge(); const { pagination } = useGetFilesPagination(); const columns: ColumnsType = [ { - title: 'Name', + title: t('name'), dataIndex: 'name', key: 'name', render(value, record) { @@ -88,7 +91,7 @@ const FileManager = () => { }, }, { - title: 'Upload Date', + title: t('uploadDate'), dataIndex: 'create_date', key: 'create_date', render(text) { @@ -96,22 +99,33 @@ const FileManager = () => { }, }, { - title: 'Knowledge Base', - dataIndex: 'kbs_info', - key: 'kbs_info', + title: t('size'), + dataIndex: 'size', + key: 'size', render(value) { - return Array.isArray(value) - ? value?.map((x) => x.kb_name).join(',') - : ''; + return (value / 1024).toFixed(2) + ' KB'; }, }, { - title: 'Location', - dataIndex: 'location', - key: 'location', + title: t('knowledgeBase'), + dataIndex: 'kbs_info', + key: 'kbs_info', + render(value) { + return Array.isArray(value) ? ( + + {value?.map((x) => ( + + {x.kb_name} + + ))} + + ) : ( + '' + ); + }, }, { - title: 'Action', + title: t('action'), dataIndex: 'action', key: 'action', render: (text, record) => ( @@ -168,6 +182,7 @@ const FileManager = () => { visible={connectToKnowledgeVisible} hideModal={hideConnectToKnowledgeModal} onOk={onConnectToKnowledgeOk} + loading={connectToKnowledgeLoading} > ); From f0ba315e36c7fc61bb7267cebd3d96e0e1b7e23a Mon Sep 17 00:00:00 2001 From: billchen Date: Fri, 26 Apr 2024 16:54:51 +0800 Subject: [PATCH 2/2] feat: batch delete files from the file table in the knowledge base --- web/src/hooks/documentHooks.ts | 4 +-- web/src/locales/en.ts | 1 + web/src/locales/zh-traditional.ts | 1 + web/src/locales/zh.ts | 1 + .../knowledge-file/document-toolbar.tsx | 4 +-- .../parsing-action-cell/index.tsx | 2 +- web/src/pages/file-manager/file-toolbar.tsx | 36 +++++++++++-------- .../file-manager/file-upload-modal/index.less | 8 +++++ .../file-manager/file-upload-modal/index.tsx | 4 ++- web/src/pages/file-manager/hooks.ts | 17 +++++++++ web/src/pages/file-manager/index.less | 7 ++++ web/src/pages/file-manager/index.tsx | 5 ++- web/src/pages/file-manager/model.ts | 9 +++++ web/src/utils/commonUtil.ts | 6 ++++ 14 files changed, 82 insertions(+), 23 deletions(-) create mode 100644 web/src/pages/file-manager/file-upload-modal/index.less diff --git a/web/src/hooks/documentHooks.ts b/web/src/hooks/documentHooks.ts index 0f6b82828f8..0d753ded1c4 100644 --- a/web/src/hooks/documentHooks.ts +++ b/web/src/hooks/documentHooks.ts @@ -160,12 +160,12 @@ export const useRemoveDocument = () => { const { knowledgeId } = useGetKnowledgeSearchParams(); const removeDocument = useCallback( - (documentId: string) => { + (documentIds: string[]) => { try { return dispatch({ type: 'kFModel/document_rm', payload: { - doc_id: documentId, + doc_id: documentIds, kb_id: knowledgeId, }, }); diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 9e19302f84c..94e7fcff1c9 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -461,6 +461,7 @@ export default { renamed: 'Renamed', operated: 'Operated', updated: 'Updated', + uploaded: 'Uploaded', 200: 'The server successfully returns the requested data.', 201: 'Create or modify data successfully.', 202: 'A request has been queued in the background (asynchronous task).', diff --git a/web/src/locales/zh-traditional.ts b/web/src/locales/zh-traditional.ts index bdaaa3cd482..b0391f89bb7 100644 --- a/web/src/locales/zh-traditional.ts +++ b/web/src/locales/zh-traditional.ts @@ -426,6 +426,7 @@ export default { renamed: '重命名成功', operated: '操作成功', updated: '更新成功', + uploaded: '上傳成功', 200: '服務器成功返回請求的數據。', 201: '新建或修改數據成功。', 202: '一個請求已經進入後台排隊(異步任務)。', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index 4b853134310..36b85de1c58 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -443,6 +443,7 @@ export default { renamed: '重命名成功', operated: '操作成功', updated: '更新成功', + uploaded: '上传成功', 200: '服务器成功返回请求的数据。', 201: '新建或修改数据成功。', 202: '一个请求已经进入后台排队(异步任务)。', diff --git a/web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx b/web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx index b5f594069e5..e0564c2c090 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx @@ -80,9 +80,7 @@ const DocumentToolbar = ({ selectedRowKeys, showCreateModal }: IProps) => { const handleDelete = useCallback(() => { showDeleteConfirm({ onOk: () => { - selectedRowKeys.forEach((id) => { - removeDocument(id); - }); + removeDocument(selectedRowKeys); }, }); }, [removeDocument, showDeleteConfirm, selectedRowKeys]); diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx index 8ac1be98151..c50a6931b0d 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx @@ -35,7 +35,7 @@ const ParsingActionCell = ({ const onRmDocument = () => { if (!isRunning) { - showDeleteConfirm({ onOk: () => removeDocument(documentId) }); + showDeleteConfirm({ onOk: () => removeDocument([documentId]) }); } }; diff --git a/web/src/pages/file-manager/file-toolbar.tsx b/web/src/pages/file-manager/file-toolbar.tsx index e2fcf82be63..b8485b1c3ff 100644 --- a/web/src/pages/file-manager/file-toolbar.tsx +++ b/web/src/pages/file-manager/file-toolbar.tsx @@ -20,12 +20,12 @@ import { import { useMemo } from 'react'; import { useFetchDocumentListOnMount, + useHandleBreadcrumbClick, useHandleDeleteFile, useHandleSearchChange, useSelectBreadcrumbItems, } from './hooks'; -import { Link } from 'umi'; import styles from './index.less'; interface IProps { @@ -35,20 +35,6 @@ interface IProps { setSelectedRowKeys: (keys: string[]) => void; } -const itemRender: BreadcrumbProps['itemRender'] = ( - currentRoute, - params, - items, -) => { - const isLast = currentRoute?.path === items[items.length - 1]?.path; - - return isLast ? ( - {currentRoute.title} - ) : ( - {currentRoute.title} - ); -}; - const FileToolbar = ({ selectedRowKeys, showFolderCreateModal, @@ -59,6 +45,26 @@ const FileToolbar = ({ useFetchDocumentListOnMount(); const { handleInputChange, searchString } = useHandleSearchChange(); const breadcrumbItems = useSelectBreadcrumbItems(); + const { handleBreadcrumbClick } = useHandleBreadcrumbClick(); + + const itemRender: BreadcrumbProps['itemRender'] = ( + currentRoute, + params, + items, + ) => { + const isLast = currentRoute?.path === items[items.length - 1]?.path; + + return isLast ? ( + {currentRoute.title} + ) : ( + handleBreadcrumbClick(currentRoute.path)} + > + {currentRoute.title} + + ); + }; const actionItems: MenuProps['items'] = useMemo(() => { return [ diff --git a/web/src/pages/file-manager/file-upload-modal/index.less b/web/src/pages/file-manager/file-upload-modal/index.less new file mode 100644 index 00000000000..a840e8aed0e --- /dev/null +++ b/web/src/pages/file-manager/file-upload-modal/index.less @@ -0,0 +1,8 @@ +.uploader { + :global { + .ant-upload-list { + max-height: 40vh; + overflow-y: auto; + } + } +} diff --git a/web/src/pages/file-manager/file-upload-modal/index.tsx b/web/src/pages/file-manager/file-upload-modal/index.tsx index da035ff673c..49684c52791 100644 --- a/web/src/pages/file-manager/file-upload-modal/index.tsx +++ b/web/src/pages/file-manager/file-upload-modal/index.tsx @@ -13,6 +13,8 @@ import { } from 'antd'; import { Dispatch, SetStateAction, useState } from 'react'; +import styles from './index.less'; + const { Dragger } = Upload; const FileUpload = ({ @@ -45,7 +47,7 @@ const FileUpload = ({ }; return ( - +

      diff --git a/web/src/pages/file-manager/hooks.ts b/web/src/pages/file-manager/hooks.ts index 437460dd48f..dc95043276c 100644 --- a/web/src/pages/file-manager/hooks.ts +++ b/web/src/pages/file-manager/hooks.ts @@ -321,3 +321,20 @@ export const useHandleConnectToKnowledge = () => { showConnectToKnowledgeModal: handleShowConnectToKnowledgeModal, }; }; + +export const useHandleBreadcrumbClick = () => { + const navigate = useNavigate(); + const setPagination = useSetPagination('fileManager'); + + const handleBreadcrumbClick = useCallback( + (path?: string) => { + if (path) { + setPagination(); + navigate(path); + } + }, + [setPagination, navigate], + ); + + return { handleBreadcrumbClick }; +}; diff --git a/web/src/pages/file-manager/index.less b/web/src/pages/file-manager/index.less index 6d354bcc6fe..7737c80cf43 100644 --- a/web/src/pages/file-manager/index.less +++ b/web/src/pages/file-manager/index.less @@ -20,3 +20,10 @@ .linkButton { padding: 0; } + +.breadcrumbItemButton { + cursor: pointer; + color: #1677ff; + padding: 0; + height: auto; +} diff --git a/web/src/pages/file-manager/index.tsx b/web/src/pages/file-manager/index.tsx index 9b45fe9d626..ebeff54817d 100644 --- a/web/src/pages/file-manager/index.tsx +++ b/web/src/pages/file-manager/index.tsx @@ -19,6 +19,7 @@ import { import RenameModal from '@/components/rename-modal'; import SvgIcon from '@/components/svg-icon'; import { useTranslate } from '@/hooks/commonHooks'; +import { formatNumberWithThousandsSeparator } from '@/utils/commonUtil'; import { getExtension } from '@/utils/documentUtils'; import ConnectToKnowledgeModal from './connect-to-knowledge-modal'; import FileUploadModal from './file-upload-modal'; @@ -103,7 +104,9 @@ const FileManager = () => { dataIndex: 'size', key: 'size', render(value) { - return (value / 1024).toFixed(2) + ' KB'; + return ( + formatNumberWithThousandsSeparator((value / 1024).toFixed(2)) + ' KB' + ); }, }, { diff --git a/web/src/pages/file-manager/model.ts b/web/src/pages/file-manager/model.ts index 3fbdebf0da0..ce08dbdb735 100644 --- a/web/src/pages/file-manager/model.ts +++ b/web/src/pages/file-manager/model.ts @@ -1,7 +1,9 @@ import { paginationModel } from '@/base'; import { BaseState } from '@/interfaces/common'; import { IFile, IFolder } from '@/interfaces/database/file-manager'; +import i18n from '@/locales/config'; import fileManagerService from '@/services/fileManagerService'; +import { message } from 'antd'; import omit from 'lodash/omit'; import { DvaModel } from 'umi'; @@ -33,6 +35,7 @@ const model: DvaModel = { }); const { retcode } = data; if (retcode === 0) { + message.success(i18n.t('message.deleted')); yield put({ type: 'listFile', payload: { parentId: payload.parentId }, @@ -69,6 +72,7 @@ const model: DvaModel = { omit(payload, ['parentId']), ); if (data.retcode === 0) { + message.success(i18n.t('message.renamed')); yield put({ type: 'listFile', payload: { parentId: payload.parentId }, @@ -89,6 +93,8 @@ const model: DvaModel = { }); const { data } = yield call(fileManagerService.uploadFile, formData); if (data.retcode === 0) { + message.success(i18n.t('message.uploaded')); + yield put({ type: 'listFile', payload: { parentId: payload.parentId }, @@ -99,6 +105,8 @@ const model: DvaModel = { *createFolder({ payload = {} }, { call, put }) { const { data } = yield call(fileManagerService.createFolder, payload); if (data.retcode === 0) { + message.success(i18n.t('message.created')); + yield put({ type: 'listFile', payload: { parentId: payload.parentId }, @@ -125,6 +133,7 @@ const model: DvaModel = { omit(payload, 'parentId'), ); if (data.retcode === 0) { + message.success(i18n.t('message.operated')); yield put({ type: 'listFile', payload: { parentId: payload.parentId }, diff --git a/web/src/utils/commonUtil.ts b/web/src/utils/commonUtil.ts index cd6c0d5c74b..8753a62b8dd 100644 --- a/web/src/utils/commonUtil.ts +++ b/web/src/utils/commonUtil.ts @@ -27,3 +27,9 @@ export const getSearchValue = (key: string) => { const params = new URL(document.location as any).searchParams; return params.get(key); }; + +// Formatize numbers, add thousands of separators +export const formatNumberWithThousandsSeparator = (numberStr: string) => { + const formattedNumber = numberStr.replace(/\B(?=(\d{3})+(?!\d))/g, ','); + return formattedNumber; +};