diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e981dff..9ecd878 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,12 +8,14 @@ "name": "edatamate", "version": "0.0.0", "dependencies": { + "@reduxjs/toolkit": "^2.11.0", "@xyflow/react": "^12.8.3", "antd": "^5.27.0", "jssha": "^3.3.1", "lucide-react": "^0.539.0", "react": "^18.1.1", "react-dom": "^18.1.1", + "react-redux": "^9.2.0", "react-router": "^7.8.0", "recharts": "2.15.0" }, @@ -186,6 +188,7 @@ "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1370,6 +1373,32 @@ "react-dom": ">=16.9.0" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.0.tgz", + "integrity": "sha512-hBjYg0aaRL1O2Z0IqWhnTLytnjDIxekmRxm1snsHjHaKVmIF1HiImWqsq+PuEbn6zdMlkIj9WofK1vR8jjx+Xw==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.30", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.30.tgz", @@ -1657,6 +1686,18 @@ "win32" ] }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, "node_modules/@tailwindcss/node": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.12.tgz", @@ -2096,6 +2137,7 @@ "integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.10.0" } @@ -2113,6 +2155,7 @@ "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -2128,6 +2171,12 @@ "@types/react": "^18.0.0" } }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.39.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", @@ -2174,6 +2223,7 @@ "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.39.1", "@typescript-eslint/types": "8.39.1", @@ -2472,6 +2522,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2720,6 +2771,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001733", "electron-to-chromium": "^1.5.199", @@ -3116,6 +3168,7 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -3204,7 +3257,8 @@ "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/debug": { "version": "4.4.1", @@ -3431,6 +3485,7 @@ "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -4133,6 +4188,17 @@ "dev": true, "license": "ISC" }, + "node_modules/immer": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.0.1.tgz", + "integrity": "sha512-naDCyggtcBWANtIrjQEajhhBEuL9b0Zg4zmlWK2CzS6xCWSE39/vvf4LqnMjUAWHBhot4m9MHCM/Z+mfWhUkiA==", + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -5959,6 +6025,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -5971,6 +6038,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -5985,6 +6053,30 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", @@ -6093,6 +6185,28 @@ "decimal.js-light": "^2.4.1" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT", + "peer": true + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -6660,6 +6774,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -6763,6 +6878,7 @@ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6930,6 +7046,7 @@ "integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", @@ -7020,6 +7137,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, diff --git a/frontend/package.json b/frontend/package.json index 99161d0..5d44f3b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,12 +11,14 @@ "preview": "vite preview" }, "dependencies": { + "@reduxjs/toolkit": "^2.11.0", "@xyflow/react": "^12.8.3", "antd": "^5.27.0", "jssha": "^3.3.1", "lucide-react": "^0.539.0", "react": "^18.1.1", "react-dom": "^18.1.1", + "react-redux": "^9.2.0", "react-router": "^7.8.0", "recharts": "2.15.0" }, diff --git a/frontend/src/components/DatasetFileTransfer.tsx b/frontend/src/components/business/DatasetFileTransfer.tsx similarity index 95% rename from frontend/src/components/DatasetFileTransfer.tsx rename to frontend/src/components/business/DatasetFileTransfer.tsx index a92ed86..42bca6c 100644 --- a/frontend/src/components/DatasetFileTransfer.tsx +++ b/frontend/src/components/business/DatasetFileTransfer.tsx @@ -13,7 +13,6 @@ import { } from "@/pages/DataManagement/dataset.api"; import { formatBytes } from "@/utils/unit"; import { useDebouncedEffect } from "@/hooks/useDebouncedEffect"; -import { DatasetFileCols as fileCols } from "../pages/KnowledgeBase/knowledge-base.const"; interface DatasetFileTransferProps extends React.HTMLAttributes { @@ -22,6 +21,28 @@ interface DatasetFileTransferProps onSelectedFilesChange: (filesMap: { [key: string]: DatasetFile }) => void; } +const fileCols = [ + { + title: "所属数据集", + dataIndex: "datasetName", + key: "datasetName", + ellipsis: true, + }, + { + title: "文件名", + dataIndex: "fileName", + key: "fileName", + ellipsis: true, + }, + { + title: "大小", + dataIndex: "fileSize", + key: "fileSize", + ellipsis: true, + render: formatBytes, + }, +]; + // Customize Table Transfer const DatasetFileTransfer: React.FC = ({ open, diff --git a/frontend/src/components/TagManagement.tsx b/frontend/src/components/business/TagManagement.tsx similarity index 100% rename from frontend/src/components/TagManagement.tsx rename to frontend/src/components/business/TagManagement.tsx diff --git a/frontend/src/components/TaskPopover.tsx b/frontend/src/components/business/TaskPopover.tsx similarity index 100% rename from frontend/src/components/TaskPopover.tsx rename to frontend/src/components/business/TaskPopover.tsx diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 39407d8..4537c90 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -5,14 +5,18 @@ import router from "./routes/routes"; import { App as AntdApp, Spin } from "antd"; import "./index.css"; import TopLoadingBar from "./components/TopLoadingBar"; +import { store } from "./store"; +import { Provider } from "react-redux"; createRoot(document.getElementById("root")!).render( - - }> - - - - + + + }> + + + + + ); diff --git a/frontend/src/pages/DataManagement/Home/DataManagement.tsx b/frontend/src/pages/DataManagement/Home/DataManagement.tsx index f94b3b5..fa7b6d8 100644 --- a/frontend/src/pages/DataManagement/Home/DataManagement.tsx +++ b/frontend/src/pages/DataManagement/Home/DataManagement.tsx @@ -6,7 +6,7 @@ import { PlusOutlined, UploadOutlined, } from "@ant-design/icons"; -import TagManager from "@/components/TagManagement"; +import TagManager from "@/components/business/TagManagement"; import { Link, useNavigate } from "react-router"; import { useEffect, useMemo, useState } from "react"; import { SearchControls } from "@/components/SearchControls"; diff --git a/frontend/src/pages/KnowledgeBase/components/AddDataDialog.tsx b/frontend/src/pages/KnowledgeBase/components/AddDataDialog.tsx index d3696e0..9949d15 100644 --- a/frontend/src/pages/KnowledgeBase/components/AddDataDialog.tsx +++ b/frontend/src/pages/KnowledgeBase/components/AddDataDialog.tsx @@ -12,7 +12,7 @@ import { } from "antd"; import { PlusOutlined } from "@ant-design/icons"; import { addKnowledgeBaseFilesUsingPost } from "../knowledge-base.api"; -import DatasetFileTransfer from "../../../components/DatasetFileTransfer"; +import DatasetFileTransfer from "@/components/business/DatasetFileTransfer"; import { DescriptionsItemType } from "antd/es/descriptions"; import { DatasetFileCols } from "../knowledge-base.const"; @@ -128,7 +128,7 @@ export default function AddDataDialog({ knowledgeBase, onDataAdded }) { try { // 构造符合API要求的请求数据 const requestData = { - files: Object.values(selectedFilesMap), + files: Object.entries(selectedFilesMap), processType: newKB.processType, chunkSize: Number(newKB.chunkSize), // 确保是数字类型 overlapSize: Number(newKB.overlapSize), // 确保是数字类型 diff --git a/frontend/src/pages/KnowledgeBase/components/CreateKnowledgeBase.tsx b/frontend/src/pages/KnowledgeBase/components/CreateKnowledgeBase.tsx index d21387c..2ef7078 100644 --- a/frontend/src/pages/KnowledgeBase/components/CreateKnowledgeBase.tsx +++ b/frontend/src/pages/KnowledgeBase/components/CreateKnowledgeBase.tsx @@ -1,6 +1,7 @@ import { Button, Form, Input, message, Modal, Select } from "antd"; import { PlusOutlined } from "@ant-design/icons"; import { useEffect, useState } from "react"; +import { useDispatch } from "react-redux"; import { queryModelListUsingGet } from "@/pages/SettingsPage/settings.apis"; import { ModelI } from "@/pages/SettingsPage/ModelAccess"; import { @@ -8,6 +9,7 @@ import { updateKnowledgeBaseByIdUsingPut, } from "../knowledge-base.api"; import { KnowledgeBaseItem } from "../knowledge-base.model"; +import { showSettings } from "@/store/slices/settingsSlice"; export default function CreateKnowledgeBase({ isEdit, @@ -25,6 +27,7 @@ export default function CreateKnowledgeBase({ const [open, setOpen] = useState(false); const [form] = Form.useForm(); const [models, setModels] = useState([]); + const dispatch = useDispatch(); const embeddingModelOptions = models .filter((model) => model.type === "EMBEDDING") @@ -130,6 +133,19 @@ export default function CreateKnowledgeBase({ placeholder="请选择索引模型" options={embeddingModelOptions} disabled={isEdit} // 编辑模式下禁用索引模型修改 + popupRender={(menu) => ( + <> + {menu} + + + )} /> ); -} \ No newline at end of file +} diff --git a/frontend/src/pages/Layout/Sidebar.tsx b/frontend/src/pages/Layout/Sidebar.tsx index f1e706f..50af157 100644 --- a/frontend/src/pages/Layout/Sidebar.tsx +++ b/frontend/src/pages/Layout/Sidebar.tsx @@ -10,6 +10,8 @@ import { menuItems } from "@/pages/Layout/menu"; import { NavLink, useLocation, useNavigate } from "react-router"; import TaskUpload from "./TaskUpload"; import SettingsPage from "../SettingsPage/SettingsPage"; +import { useAppSelector, useAppDispatch } from "@/store/hooks"; +import { showSettings, hideSettings } from "@/store/slices/settingsSlice"; const AsiderAndHeaderLayout = () => { const { pathname } = useLocation(); @@ -17,7 +19,8 @@ const AsiderAndHeaderLayout = () => { const [activeItem, setActiveItem] = useState(""); const [sidebarOpen, setSidebarOpen] = useState(true); const [taskCenterVisible, setTaskCenterVisible] = useState(false); - const [settingVisible, setSettingVisible] = useState(false); + const settingVisible = useAppSelector((state) => state.settings.visible); + const dispatch = useAppDispatch(); // Initialize active item based on current pathname const initActiveItem = () => { @@ -140,7 +143,7 @@ const AsiderAndHeaderLayout = () => {