diff --git a/web/src/hooks/storeHooks.ts b/web/src/hooks/storeHooks.ts new file mode 100644 index 000000000..3f69ce766 --- /dev/null +++ b/web/src/hooks/storeHooks.ts @@ -0,0 +1,11 @@ +import { getOneNamespaceEffectsLoading } from '@/utils/stroreUtil'; +import { useSelector } from 'umi'; + +// Get the loading status of given effects under a certain namespace +export const useOneNamespaceEffectsLoading = ( + namespace: string, + effectNames: Array, +) => { + const effects = useSelector((state: any) => state.loading.effects); + return getOneNamespaceEffectsLoading(namespace, effects, effectNames); +}; diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/components/createModal.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/components/createModal.tsx index 8e9e8c37f..c771ed356 100644 --- a/web/src/pages/add-knowledge/components/knowledge-chunk/components/createModal.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-chunk/components/createModal.tsx @@ -1,102 +1,116 @@ -import React, { useEffect, useState } from 'react' -import { connect, Dispatch } from 'umi'; -import i18n from 'i18next'; -import { useTranslation, Trans } from 'react-i18next' -import { Input, Modal, Form } from 'antd' -import styles from './index.less'; -import type { chunkModelState } from './model' -import EditTag from './editTag' +import { Form, Input, Modal } from 'antd'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useDispatch } from 'umi'; +import EditTag from './editTag'; type FieldType = { - content_ltks?: string; + content_ltks?: string; }; interface kFProps { - dispatch: Dispatch; - chunkModel: chunkModelState; - getChunkList: () => void; - isShowCreateModal: boolean; - doc_id: string; - chunk_id: string + getChunkList: () => void; + isShowCreateModal: boolean; + doc_id: string; + chunk_id: string; } -const Index: React.FC = ({ dispatch, getChunkList, doc_id, isShowCreateModal, chunk_id }) => { - // const { , chunkInfo } = chunkModel - const [important_kwd, setImportantKwd] = useState(['Unremovable', 'Tag 2', 'Tag 3']); - const { t } = useTranslation() - const handleCancel = () => { - dispatch({ - type: 'chunkModel/updateState', - payload: { - isShowCreateModal: false - } - }); - }; - useEffect(() => { - console.log(chunk_id, isShowCreateModal) - if (chunk_id && isShowCreateModal) { - dispatch({ - type: 'chunkModel/get_chunk', - payload: { - chunk_id - }, - callback(info: any) { - console.log(info) - const { content_ltks, important_kwd = [] } = info - form.setFieldsValue({ content_ltks }) - setImportantKwd(important_kwd) - } - }); - } - }, [chunk_id, isShowCreateModal]) - const [form] = Form.useForm() - const handleOk = async () => { - try { - const values = await form.validateFields(); - dispatch({ - type: 'chunkModel/create_hunk', - payload: { - content_ltks: values.content_ltks, - doc_id, - chunk_id, - important_kwd - }, - callback: () => { - dispatch({ - type: 'chunkModel/updateState', - payload: { - isShowCreateModal: false - } - }); - getChunkList && getChunkList() - } - }); - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }; +const Index: React.FC = ({ + getChunkList, + doc_id, + isShowCreateModal, + chunk_id, +}) => { + const dispatch = useDispatch(); + const [form] = Form.useForm(); - return ( - -
- - label="chunk 内容" - name="content_ltks" - rules={[{ required: true, message: 'Please input value!' }]} - > - - - - -
+ // const { , chunkInfo } = chunkModel + const [important_kwd, setImportantKwd] = useState([ + 'Unremovable', + 'Tag 2', + 'Tag 3', + ]); + const { t } = useTranslation(); + const handleCancel = () => { + dispatch({ + type: 'chunkModel/updateState', + payload: { + isShowCreateModal: false, + }, + }); + }; + const getChunk = useCallback(async () => { + if (chunk_id && isShowCreateModal) { + const data = await dispatch({ + type: 'chunkModel/get_chunk', + payload: { + chunk_id, + }, + }); - ); -} -export default connect(({ chunkModel, loading }) => ({ chunkModel, loading }))(Index); + if (data?.retcode === 0) { + const { content_ltks, important_kwd = [] } = data.data; + form.setFieldsValue({ content_ltks }); + setImportantKwd(important_kwd); + } + } + }, [chunk_id, isShowCreateModal]); + + useEffect(() => { + getChunk(); + }, [getChunk]); + + const handleOk = async () => { + try { + const values = await form.validateFields(); + dispatch({ + type: 'chunkModel/create_hunk', + payload: { + content_ltks: values.content_ltks, + doc_id, + chunk_id, + important_kwd, + }, + // callback: () => { + // dispatch({ + // type: 'chunkModel/updateState', + // payload: { + // isShowCreateModal: false, + // }, + // }); + // getChunkList && getChunkList(); + // }, + }); + } catch (errorInfo) { + console.log('Failed:', errorInfo); + } + }; + + return ( + +
+ + label="chunk 内容" + name="content_ltks" + rules={[{ required: true, message: 'Please input value!' }]} + > + + + + +
+ ); +}; +export default Index; diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/components/editTag.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/components/editTag.tsx index c5a0878d0..261b408da 100644 --- a/web/src/pages/add-knowledge/components/knowledge-chunk/components/editTag.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-chunk/components/editTag.tsx @@ -1,142 +1,141 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { PlusOutlined } from '@ant-design/icons'; import type { InputRef } from 'antd'; -import { Input, Space, Tag, theme, Tooltip } from 'antd'; -interface editTagsProps { - tags: any[], - setTags: (tags: any[]) => void +import { Input, Space, Tag, Tooltip, theme } from 'antd'; +import React, { useEffect, useRef, useState } from 'react'; +interface EditTagsProps { + tags: any[]; + setTags: (tags: any[]) => void; } -const App: React.FC = ({ tags, setTags }) => { - const { token } = theme.useToken(); +const EditTag: React.FC = ({ tags, setTags }) => { + const { token } = theme.useToken(); - const [inputVisible, setInputVisible] = useState(false); - const [inputValue, setInputValue] = useState(''); - const [editInputIndex, setEditInputIndex] = useState(-1); - const [editInputValue, setEditInputValue] = useState(''); - const inputRef = useRef(null); - const editInputRef = useRef(null); + const [inputVisible, setInputVisible] = useState(false); + const [inputValue, setInputValue] = useState(''); + const [editInputIndex, setEditInputIndex] = useState(-1); + const [editInputValue, setEditInputValue] = useState(''); + const inputRef = useRef(null); + const editInputRef = useRef(null); - useEffect(() => { - if (inputVisible) { - inputRef.current?.focus(); + useEffect(() => { + if (inputVisible) { + inputRef.current?.focus(); + } + }, [inputVisible]); + + useEffect(() => { + editInputRef.current?.focus(); + }, [editInputValue]); + + const handleClose = (removedTag: string) => { + const newTags = tags.filter((tag) => tag !== removedTag); + console.log(newTags); + setTags(newTags); + }; + + const showInput = () => { + setInputVisible(true); + }; + + const handleInputChange = (e: React.ChangeEvent) => { + setInputValue(e.target.value); + }; + + const handleInputConfirm = () => { + if (inputValue && !tags.includes(inputValue)) { + setTags([...tags, inputValue]); + } + setInputVisible(false); + setInputValue(''); + }; + + const handleEditInputChange = (e: React.ChangeEvent) => { + setEditInputValue(e.target.value); + }; + + const handleEditInputConfirm = () => { + const newTags = [...tags]; + newTags[editInputIndex] = editInputValue; + setTags(newTags); + setEditInputIndex(-1); + setEditInputValue(''); + }; + + const tagInputStyle: React.CSSProperties = { + width: 64, + height: 22, + marginInlineEnd: 8, + verticalAlign: 'top', + }; + + const tagPlusStyle: React.CSSProperties = { + height: 22, + background: token.colorBgContainer, + borderStyle: 'dashed', + }; + + return ( + + {tags.map((tag, index) => { + if (editInputIndex === index) { + return ( + + ); } - }, [inputVisible]); - - useEffect(() => { - editInputRef.current?.focus(); - }, [editInputValue]); - - const handleClose = (removedTag: string) => { - const newTags = tags.filter((tag) => tag !== removedTag); - console.log(newTags); - setTags(newTags); - }; - - const showInput = () => { - setInputVisible(true); - }; - - const handleInputChange = (e: React.ChangeEvent) => { - setInputValue(e.target.value); - }; - - const handleInputConfirm = () => { - if (inputValue && !tags.includes(inputValue)) { - setTags([...tags, inputValue]); - } - setInputVisible(false); - setInputValue(''); - }; - - const handleEditInputChange = (e: React.ChangeEvent) => { - setEditInputValue(e.target.value); - }; - - const handleEditInputConfirm = () => { - const newTags = [...tags]; - newTags[editInputIndex] = editInputValue; - setTags(newTags); - setEditInputIndex(-1); - setEditInputValue(''); - }; - - const tagInputStyle: React.CSSProperties = { - width: 64, - height: 22, - marginInlineEnd: 8, - verticalAlign: 'top', - }; - - const tagPlusStyle: React.CSSProperties = { - height: 22, - background: token.colorBgContainer, - borderStyle: 'dashed', - }; - - return ( - - {tags.map((tag, index) => { - if (editInputIndex === index) { - return ( - - ); + const isLongTag = tag.length > 20; + const tagElem = ( + handleClose(tag)} + > + { + if (index !== 0) { + setEditInputIndex(index); + setEditInputValue(tag); + e.preventDefault(); } - const isLongTag = tag.length > 20; - const tagElem = ( - handleClose(tag)} - > - { - if (index !== 0) { - setEditInputIndex(index); - setEditInputValue(tag); - e.preventDefault(); - } - }} - > - {isLongTag ? `${tag.slice(0, 20)}...` : tag} - - - ); - return isLongTag ? ( - - {tagElem} - - ) : ( - tagElem - ); - })} - {inputVisible ? ( - - ) : ( - - 添加关键词 - - )} - - ); + }} + > + {isLongTag ? `${tag.slice(0, 20)}...` : tag} + + + ); + return isLongTag ? ( + + {tagElem} + + ) : ( + tagElem + ); + })} + {inputVisible ? ( + + ) : ( + + 添加关键词 + + )} + + ); }; -export default App; \ No newline at end of file +export default EditTag; diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx index 6f80e7f14..291876fad 100644 --- a/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx @@ -1,225 +1,282 @@ -import React, { useEffect, useState, useCallback } from 'react'; -import { useNavigate, connect, Dispatch } from 'umi' -import { Card, Row, Col, Input, Select, Switch, Pagination, Spin, Button, Popconfirm } from 'antd'; -import { MinusSquareOutlined, DeleteOutlined, } from '@ant-design/icons'; +import { api_host } from '@/utils/api'; +import { getOneNamespaceEffectsLoading } from '@/utils/stroreUtil'; +import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons'; import type { PaginationProps } from 'antd'; -import { api_host } from '@/utils/api' -import CreateModal from './components/createModal' +import { + Button, + Card, + Col, + Input, + Pagination, + Popconfirm, + Row, + Select, + Spin, + Switch, +} from 'antd'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useDispatch, useNavigate, useSelector } from 'umi'; +import CreateModal from './components/createModal'; - -import styles from './index.less' import { debounce } from 'lodash'; -import type { chunkModelState } from './model' -interface chunkProps { - dispatch: Dispatch; - chunkModel: chunkModelState; - doc_id: string +import styles from './index.less'; + +interface PayloadType { + doc_id: string; + keywords?: string; + available_int?: number; } -const Index: React.FC = ({ chunkModel, dispatch, doc_id }) => { - const [keywords, SetKeywords] = useState('') - const [available_int, setAvailableInt] = useState(-1) - const navigate = useNavigate() - const [pagination, setPagination] = useState({ page: 1, size: 30 }) + +interface IProps { + doc_id: string; +} + +const Chunk = ({ doc_id }: IProps) => { + const dispatch = useDispatch(); + const chunkModel = useSelector((state: any) => state.chunkModel); + const [keywords, SetKeywords] = useState(''); + const [available_int, setAvailableInt] = useState(-1); + const navigate = useNavigate(); + const [pagination, setPagination] = useState({ page: 1, size: 30 }); // const [datas, setDatas] = useState(data) - const { data = [], total, loading, chunk_id, isShowCreateModal } = chunkModel - console.log(chunkModel) + const { data = [], total, chunk_id, isShowCreateModal } = chunkModel; + const effects = useSelector((state: any) => state.loading.effects); + const loading = getOneNamespaceEffectsLoading('chunkModel', effects, [ + 'create_hunk', + 'chunk_list', + 'switch_chunk', + ]); + const getChunkList = (value?: string) => { - dispatch({ - type: 'chunkModel/updateState', - payload: { - loading: true - } - }); - interface payloadType { - doc_id: string; - keywords?: string; - available_int?: number - } - const payload: payloadType = { + const payload: PayloadType = { doc_id, keywords: value || keywords, - available_int - } + available_int, + }; if (payload.available_int === -1) { - delete payload.available_int + delete payload.available_int; } dispatch({ type: 'chunkModel/chunk_list', payload: { ...payload, - ...pagination - } - }); - } - const confirm = (id: string) => { - console.log(id) - dispatch({ - type: 'chunkModel/rm_chunk', - payload: { - chunk_ids: [id] + ...pagination, }, - callback: getChunkList }); }; + const confirm = async (id: string) => { + const retcode = await dispatch({ + type: 'chunkModel/rm_chunk', + payload: { + chunk_ids: [id], + }, + }); + + retcode === 0 && getChunkList(); + }; + const handleEditchunk = (chunk_id?: string) => { dispatch({ type: 'chunkModel/updateState', payload: { isShowCreateModal: true, chunk_id, - doc_id + doc_id, }, - callback: getChunkList }); - } - const onShowSizeChange: PaginationProps['onShowSizeChange'] = (page, size) => { - setPagination({ page, size }) + getChunkList(); }; - const switchChunk = (id: string, available_int: boolean) => { - dispatch({ - type: 'chunkModel/updateState', - payload: { - loading: true - } - }); - dispatch({ + + const onShowSizeChange: PaginationProps['onShowSizeChange'] = ( + page, + size, + ) => { + setPagination({ page, size }); + }; + + const switchChunk = async (id: string, available_int: boolean) => { + const retcode = await dispatch({ type: 'chunkModel/switch_chunk', payload: { chunk_ids: [id], available_int: Number(available_int), - doc_id + doc_id, }, - callback: getChunkList }); - } + + retcode === 0 && getChunkList(); + }; useEffect(() => { - getChunkList() - }, [doc_id, available_int, pagination]) - const debounceChange = debounce(getChunkList, 300) - const debounceCallback = useCallback((value: string) => debounceChange(value), []) - const handleInputChange = (e: React.ChangeEvent) => { - const value = e.target.value - SetKeywords(value) - debounceCallback(value) - } + getChunkList(); + }, [doc_id, available_int, pagination]); + + const debounceChange = debounce(getChunkList, 300); + const debounceCallback = useCallback( + (value: string) => debounceChange(value), + [], + ); + + const handleInputChange = ( + e: React.ChangeEvent, + ) => { + const value = e.target.value; + SetKeywords(value); + debounceCallback(value); + }; const handleSelectChange = (value: number) => { - setAvailableInt(value) - } - console.log('loading', loading) - return (<> -
-
-
- - + - + const handleCancel = () => { + dispatch({ + type: 'kFModel/updateState', + payload: { + isShowCEFwModal: false, + }, + }); + }; + const handleOk = async () => { + try { + const values = await form.validateFields(); + const retcode = await dispatch({ + type: 'kFModel/document_create', + payload: { + name: values.name, + kb_id, + }, + }); + if (retcode === 0) { + getKfList && getKfList(); + } + } catch (errorInfo) { + console.log('Failed:', errorInfo); + } + }; - - - - - ); -} -export default connect(({ kFModel, loading }) => ({ kFModel, loading }))(Index); + return ( + +
+ + label="文件名" + name="name" + rules={[{ required: true, message: 'Please input value!' }]} + > + + + +
+ ); +}; +export default FileCreatingModal; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx index 866954f92..dfda40474 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx @@ -1,228 +1,273 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { connect, Dispatch, useNavigate } from 'umi' -import { Space, Table, Input, Button, Switch, Dropdown, } from 'antd'; +import { getOneNamespaceEffectsLoading } from '@/utils/stroreUtil'; +import { DownOutlined } from '@ant-design/icons'; import type { MenuProps } from 'antd'; -import { DownOutlined } from '@ant-design/icons' -import { debounce } from 'lodash'; +import { Button, Dropdown, Input, Space, Switch, Table } from 'antd'; import type { ColumnsType } from 'antd/es/table'; -import UploadFile from './upload' -import CreateEPModal from './createEFileModal' -import SegmentSetModal from './segmentSetModal' -import styles from './index.less' -import type { kFModelState } from './model' +import { debounce } from 'lodash'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { useDispatch, useNavigate, useSelector } from 'umi'; +import CreateEPModal from './createEFileModal'; +import styles from './index.less'; +import SegmentSetModal from './segmentSetModal'; +import UploadFile from './upload'; interface DataType { - name: string; - chunk_num: string; - token_num: number; - update_date: string; - size: string; - status: string; - id: string; - parser_id: string + name: string; + chunk_num: string; + token_num: number; + update_date: string; + size: string; + status: string; + id: string; + parser_id: string; } -interface kFProps { - dispatch: Dispatch; - kFModel: kFModelState; - kb_id: string +interface KFProps { + kb_id: string; } -const Index: React.FC = ({ kFModel, dispatch, kb_id }) => { - const { data, loading } = kFModel - const [inputValue, setInputValue] = useState('') - const [doc_id, setDocId] = useState('0') - const [parser_id, setParserId] = useState('0') - let navigate = useNavigate(); - const getKfList = (keywords?: string) => { - const payload = { - kb_id, - keywords - } - if (!keywords) { - delete payload.keywords - } - dispatch({ - type: 'kFModel/getKfList', - payload - }); - } - useEffect(() => { - if (kb_id) { - getKfList() - } - }, [kb_id]) - const debounceChange = debounce(getKfList, 300) - const debounceCallback = useCallback((value: string) => debounceChange(value), []) - const handleInputChange = (e: React.ChangeEvent) => { - const value = e.target.value - setInputValue(value) - debounceCallback(e.target.value) +const KnowledgeFile: React.FC = ({ kb_id }) => { + const dispatch = useDispatch(); + const kFModel = useSelector((state: any) => state.kFModel); + const effects = useSelector((state: any) => state.loading.effects); + const { data } = kFModel; + const loading = getOneNamespaceEffectsLoading('kFModel', effects, [ + 'getKfList', + 'updateDocumentStatus', + ]); + const [inputValue, setInputValue] = useState(''); + const [doc_id, setDocId] = useState('0'); + const [parser_id, setParserId] = useState('0'); + let navigate = useNavigate(); - } - const onChangeStatus = (e: boolean, doc_id: string) => { - dispatch({ - type: 'kFModel/updateDocumentStatus', - payload: { - doc_id, - status: Number(e) - }, - callback() { - getKfList() - } - }); - } - const onRmDocument = () => { - dispatch({ - type: 'kFModel/document_rm', - payload: { - doc_id - }, - callback() { - getKfList() - } - }); - - } - const showCEFModal = () => { - dispatch({ - type: 'kFModel/updateState', - payload: { - isShowCEFwModal: true - } - }); + const getKfList = (keywords?: string) => { + const payload = { + kb_id, + keywords, }; - - const showSegmentSetModal = () => { - dispatch({ - type: 'kFModel/updateState', - payload: { - isShowSegmentSetModal: true - } - }); - }; - const actionItems: MenuProps['items'] = useMemo(() => { - return [ - { - key: '1', - label: ( -
- -
- - ), - }, - { - key: '2', - label: ( -
- -
- ), - // disabled: true, - }, - ] - }, [kb_id]); - const chunkItems: MenuProps['items'] = [ - { - key: '1', - label: ( -
- - -
- - ), - }, - { - key: '2', - label: ( -
- -
- ), - // disabled: true, - }, - ] - const toChunk = (id: string) => { - console.log(id) - navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}&doc_id=${id}`); + if (!keywords) { + delete payload.keywords; } - const columns: ColumnsType = [ - { - title: '名称', - dataIndex: 'name', - key: 'name', - render: (text: any, { id }) =>
toChunk(id)}>{text}
, - className: `${styles.column}` - }, - { - title: '数据总量', - dataIndex: 'chunk_num', - key: 'chunk_num', - className: `${styles.column}` - }, - { - title: 'Tokens', - dataIndex: 'token_num', - key: 'token_num', - className: `${styles.column}` - }, - { - title: '文件大小', - dataIndex: 'size', - key: 'size', - className: `${styles.column}` - }, - { - title: '状态', - key: 'status', - dataIndex: 'status', - className: `${styles.column}`, - render: (_, { status: string, id }) => ( - <> - { - onChangeStatus(e, id) - }} /> - - ), - }, - { - title: 'Action', - key: 'action', - className: `${styles.column}`, - render: (_, record) => ( - - - { - setDocId(record.id) - setParserId(record.parser_id) - }}> - 分段设置 - - - - ), - }, + dispatch({ + type: 'kFModel/getKfList', + payload, + }); + }; + + useEffect(() => { + if (kb_id) { + getKfList(); + } + }, [kb_id]); + + const debounceChange = debounce(getKfList, 300); + const debounceCallback = useCallback( + (value: string) => debounceChange(value), + [], + ); + const handleInputChange = ( + e: React.ChangeEvent, + ) => { + const value = e.target.value; + setInputValue(value); + debounceCallback(e.target.value); + }; + const onChangeStatus = (e: boolean, doc_id: string) => { + dispatch({ + type: 'kFModel/updateDocumentStatus', + payload: { + doc_id, + status: Number(e), + kb_id, + }, + }); + }; + const onRmDocument = () => { + dispatch({ + type: 'kFModel/document_rm', + payload: { + doc_id, + kb_id, + }, + }); + }; + const showCEFModal = () => { + dispatch({ + type: 'kFModel/updateState', + payload: { + isShowCEFwModal: true, + }, + }); + }; + + const showSegmentSetModal = () => { + dispatch({ + type: 'kFModel/updateState', + payload: { + isShowSegmentSetModal: true, + }, + }); + }; + const actionItems: MenuProps['items'] = useMemo(() => { + return [ + { + key: '1', + label: ( +
+ +
+ ), + }, + { + key: '2', + label: ( +
+ +
+ ), + // disabled: true, + }, ]; - return <> -
-
- -
- + }, [kb_id]); + const chunkItems: MenuProps['items'] = [ + { + key: '1', + label: ( +
+
- - - + ), + }, + { + key: '2', + label: ( +
+ +
+ ), + // disabled: true, + }, + ]; + const toChunk = (id: string) => { + console.log(id); + navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}&doc_id=${id}`); + }; + const columns: ColumnsType = [ + { + title: '名称', + dataIndex: 'name', + key: 'name', + render: (text: any, { id }) => ( +
toChunk(id)}> + + {text} +
+ ), + className: `${styles.column}`, + }, + { + title: '数据总量', + dataIndex: 'chunk_num', + key: 'chunk_num', + className: `${styles.column}`, + }, + { + title: 'Tokens', + dataIndex: 'token_num', + key: 'token_num', + className: `${styles.column}`, + }, + { + title: '文件大小', + dataIndex: 'size', + key: 'size', + className: `${styles.column}`, + }, + { + title: '状态', + key: 'status', + dataIndex: 'status', + className: `${styles.column}`, + render: (_, { status: string, id }) => ( + <> + { + onChangeStatus(e, id); + }} + /> + + ), + }, + { + title: 'Action', + key: 'action', + className: `${styles.column}`, + render: (_, record) => ( + + + { + setDocId(record.id); + setParserId(record.parser_id); + }} + > + 分段设置 + + + + ), + }, + ]; + return ( + <> +
+
+ +
+ +
+
+ + + ); }; -export default connect(({ kFModel, loading }) => ({ kFModel, loading }))(Index); \ No newline at end of file +export default KnowledgeFile; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/model.ts b/web/src/pages/add-knowledge/components/knowledge-file/model.ts index 3923e651c..d193b1a62 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/model.ts +++ b/web/src/pages/add-knowledge/components/knowledge-file/model.ts @@ -1,57 +1,47 @@ import kbService from '@/services/kbService'; import { message } from 'antd'; -import { Effect, Reducer, Subscription } from 'umi'; +import pick from 'lodash/pick'; +import { DvaModel } from 'umi'; -export interface kFModelState { +export interface KFModelState { isShowCEFwModal: boolean; isShowTntModal: boolean; isShowSegmentSetModal: boolean; - loading: boolean; tenantIfo: any; data: any[]; } -export interface kFModelType { - namespace: 'kFModel'; - state: kFModelState; - effects: { - createKf: Effect; - updateKf: Effect; - getKfDetail: Effect; - getKfList: Effect; - updateDocumentStatus: Effect; - document_rm: Effect; - document_create: Effect; - document_change_parser: Effect; - }; - reducers: { - updateState: Reducer; - }; - subscriptions: { setup: Subscription }; -} -const Model: kFModelType = { + +const model: DvaModel = { namespace: 'kFModel', state: { isShowCEFwModal: false, isShowTntModal: false, isShowSegmentSetModal: false, - loading: false, tenantIfo: {}, data: [], }, + reducers: { + updateState(state, { payload }) { + return { + ...state, + ...payload, + }; + }, + }, subscriptions: { setup({ dispatch, history }) { history.listen((location) => {}); }, }, effects: { - *createKf({ payload = {}, callback }, { call, put }) { + *createKf({ payload = {} }, { call, put }) { const { data, response } = yield call(kbService.createKb, payload); const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('创建成功!'); } }, - *updateKf({ payload = {}, callback }, { call, put }) { + *updateKf({ payload = {} }, { call, put }) { const { data, response } = yield call(kbService.updateKb, payload); const { retcode, data: res, retmsg } = data; if (retcode === 0) { @@ -67,23 +57,12 @@ const Model: kFModelType = { } }, *getKfList({ payload = {} }, { call, put }) { - yield put({ - type: 'updateState', - payload: { - loading: true, - }, - }); const { data, response } = yield call( kbService.get_document_list, payload, ); const { retcode, data: res, retmsg } = data; - yield put({ - type: 'updateState', - payload: { - loading: false, - }, - }); + if (retcode === 0) { yield put({ type: 'updateState', @@ -93,64 +72,64 @@ const Model: kFModelType = { }); } }, - *updateDocumentStatus({ payload = {}, callback }, { call, put }) { - yield put({ - type: 'updateState', - payload: { - loading: true, - }, - }); + *updateDocumentStatus({ payload = {} }, { call, put }) { const { data, response } = yield call( kbService.document_change_status, - payload, + pick(payload, ['doc_id', 'status']), ); const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('修改成功!'); - yield put({ - type: 'updateState', - payload: { - loading: false, - }, + put({ + type: 'getKfList', + payload: { kb_id: payload.kb_id }, }); - callback && callback(); } }, - *document_rm({ payload = {}, callback }, { call, put }) { - const { data, response } = yield call(kbService.document_rm, payload); + *document_rm({ payload = {} }, { call, put }) { + const { data, response } = yield call(kbService.document_rm, { + doc_id: payload.doc_id, + }); const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('删除成功!'); - callback && callback(); + put({ + type: 'getKfList', + payload: { kb_id: payload.kb_id }, + }); } }, - *document_create({ payload = {}, callback }, { call, put }) { + *document_create({ payload = {} }, { call, put }) { const { data, response } = yield call(kbService.document_create, payload); const { retcode, data: res, retmsg } = data; if (retcode === 0) { + put({ + type: 'kFModel/updateState', + payload: { + isShowCEFwModal: false, + }, + }); message.success('创建成功!'); - callback && callback(); } + return retcode; }, - *document_change_parser({ payload = {}, callback }, { call, put }) { + *document_change_parser({ payload = {} }, { call, put }) { const { data, response } = yield call( kbService.document_change_parser, payload, ); const { retcode, data: res, retmsg } = data; if (retcode === 0) { + put({ + type: 'updateState', + payload: { + isShowSegmentSetModal: false, + }, + }); message.success('修改成功!'); - callback && callback(); } - }, - }, - reducers: { - updateState(state, { payload }) { - return { - ...state, - ...payload, - }; + return retcode; }, }, }; -export default Model; +export default model; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx b/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx index ae3881fbb..5da38b85b 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx @@ -1,91 +1,87 @@ -import React from 'react'; -import { connect, Dispatch } from 'umi'; -import i18n from 'i18next'; -import { useTranslation, } from 'react-i18next' -import { Modal, Tag, Space } from 'antd' -import { useEffect, useState } from 'react'; +import { Modal, Space, Tag } from 'antd'; +import React, { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useDispatch, useSelector } from 'umi'; import styles from './index.less'; -import type { kFModelState } from './model' -import type { settingModelState } from '@/pages/setting/model' const { CheckableTag } = Tag; interface kFProps { - dispatch: Dispatch; - kFModel: kFModelState; - settingModel: settingModelState; - getKfList: () => void; - parser_id: string; - doc_id: string; + getKfList: () => void; + parser_id: string; + doc_id: string; } -const Index: React.FC = ({ kFModel, settingModel, dispatch, getKfList, parser_id, doc_id }) => { - const [selectedTag, setSelectedTag] = useState('') - const { tenantIfo = {} } = settingModel - const { parser_ids = '' } = tenantIfo - useEffect(() => { - dispatch({ - type: 'settingModel/getTenantInfo', - payload: { - } - }); - setSelectedTag(parser_id) - }, [parser_id]) - const { isShowSegmentSetModal } = kFModel - const { t } = useTranslation() - const handleCancel = () => { - dispatch({ - type: 'kFModel/updateState', - payload: { - isShowSegmentSetModal: false - } - }); - }; - const handleOk = () => { - console.log(1111, selectedTag) - dispatch({ - type: 'kFModel/document_change_parser', - payload: { - parser_id: selectedTag, - doc_id - }, - callback: () => { - dispatch({ - type: 'kFModel/updateState', - payload: { - isShowSegmentSetModal: false - } - }); - getKfList && getKfList() - } - }); - }; +const SegmentSetModal: React.FC = ({ + getKfList, + parser_id, + doc_id, +}) => { + const dispatch = useDispatch(); + const kFModel = useSelector((state: any) => state.kFModel); + const settingModel = useSelector((state: any) => state.settingModel); + const [selectedTag, setSelectedTag] = useState(''); + const { tenantIfo = {} } = settingModel; + const { parser_ids = '' } = tenantIfo; + const { isShowSegmentSetModal } = kFModel; + const { t } = useTranslation(); - const handleChange = (tag: string, checked: boolean) => { - const nextSelectedTag = checked - ? tag - : selectedTag; - console.log('You are interested in: ', nextSelectedTag); - setSelectedTag(nextSelectedTag); - }; + useEffect(() => { + dispatch({ + type: 'settingModel/getTenantInfo', + payload: {}, + }); + setSelectedTag(parser_id); + }, [parser_id]); - return ( - - -
- { - parser_ids.split(',').map((tag: string) => { - return ( handleChange(tag, checked)} - > - {tag} - ) - }) - } -
-
-
+ const handleCancel = () => { + dispatch({ + type: 'kFModel/updateState', + payload: { + isShowSegmentSetModal: false, + }, + }); + }; + const handleOk = async () => { + console.log(1111, selectedTag); + const retcode = await dispatch({ + type: 'kFModel/document_change_parser', + payload: { + parser_id: selectedTag, + doc_id, + }, + }); - ); -} -export default connect(({ kFModel, settingModel, loading }) => ({ kFModel, settingModel, loading }))(Index); + retcode === 0 && getKfList && getKfList(); + }; + + const handleChange = (tag: string, checked: boolean) => { + const nextSelectedTag = checked ? tag : selectedTag; + console.log('You are interested in: ', nextSelectedTag); + setSelectedTag(nextSelectedTag); + }; + + return ( + + +
+ {parser_ids.split(',').map((tag: string) => { + return ( + handleChange(tag, checked)} + > + {tag} + + ); + })} +
+
+
+ ); +}; +export default SegmentSetModal; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/upload.tsx b/web/src/pages/add-knowledge/components/knowledge-file/upload.tsx index 60ae46e2b..656c8d736 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/upload.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/upload.tsx @@ -1,33 +1,39 @@ -import React from 'react'; -import { connect } from 'umi' +import uploadService from '@/services/uploadService'; import type { UploadProps } from 'antd'; import { Button, Upload } from 'antd'; -import uploadService from '@/services/uploadService' +import React from 'react'; interface PropsType { - kb_id: string; - getKfList: () => void + kb_id: string; + getKfList: () => void; } + type UploadRequestOption = Parameters< - NonNullable + NonNullable >[0]; -const Index: React.FC = ({ kb_id, getKfList }) => { - const createRequest: (props: UploadRequestOption) => void = async function ({ file, onSuccess, onError }) { - const { retcode, data } = await uploadService.uploadFile(file, kb_id); - if (retcode === 0) { - onSuccess && onSuccess(data, file); - } else { - onError && onError(data); - } - getKfList && getKfList() - }; - const uploadProps: UploadProps = { - customRequest: createRequest, - showUploadList: false, - }; - return ( - - ) -} +const FileUpload: React.FC = ({ kb_id, getKfList }) => { + const createRequest: (props: UploadRequestOption) => void = async function ({ + file, + onSuccess, + onError, + }) { + const { retcode, data } = await uploadService.uploadFile(file, kb_id); + if (retcode === 0) { + onSuccess && onSuccess(data, file); + } else { + onError && onError(data); + } + getKfList && getKfList(); + }; + const uploadProps: UploadProps = { + customRequest: createRequest, + showUploadList: false, + }; + return ( + + + + ); +}; -export default connect(({ kFModel, settingModel, loading }) => ({ kFModel, settingModel, loading }))(Index); \ No newline at end of file +export default FileUpload; diff --git a/web/src/pages/add-knowledge/components/knowledge-search/index.tsx b/web/src/pages/add-knowledge/components/knowledge-search/index.tsx index a50fb0c34..0635facb9 100644 --- a/web/src/pages/add-knowledge/components/knowledge-search/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-search/index.tsx @@ -1,247 +1,278 @@ -import React, { useEffect, useState, useCallback, } from 'react'; -import { useNavigate, connect, Dispatch } from 'umi' -import { Card, Row, Col, Input, Select, Switch, Pagination, Spin, Button, Popconfirm } from 'antd'; -import { MinusSquareOutlined, DeleteOutlined, } from '@ant-design/icons'; +import { api_host } from '@/utils/api'; +import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons'; import type { PaginationProps } from 'antd'; -import { api_host } from '@/utils/api' -import CreateModal from '../knowledge-chunk/components/createModal' +import { + Card, + Col, + Input, + Pagination, + Popconfirm, + Row, + Select, + Spin, + Switch, +} from 'antd'; +import React, { useCallback, useEffect } from 'react'; +import { useDispatch, useSelector } from 'umi'; +import CreateModal from '../knowledge-chunk/components/createModal'; - -import styles from './index.less' +import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; import { debounce } from 'lodash'; -import type { kSearchModelState } from './model' -import type { chunkModelState } from '../knowledge-chunk/model' +import styles from './index.less'; interface chunkProps { - dispatch: Dispatch; - kSearchModel: kSearchModelState; - chunkModel: chunkModelState; - kb_id: string + kb_id: string; } -const Index: React.FC = ({ kSearchModel, chunkModel, dispatch, kb_id }) => { - const { data = [], total, loading, d_list = [], question, doc_ids, pagination, } = kSearchModel - const { chunk_id, doc_id, isShowCreateModal } = chunkModel +const KnowledgeSearching: React.FC = ({ kb_id }) => { + const dispatch = useDispatch(); + const kSearchModel = useSelector((state: any) => state.kSearchModel); + const chunkModel = useSelector((state: any) => state.chunkModel); + const loading = useOneNamespaceEffectsLoading('kSearchModel', [ + 'chunk_list', + 'switch_chunk', + ]); + + const { + data = [], + total, + d_list = [], + question, + doc_ids, + pagination, + } = kSearchModel; + const { chunk_id, doc_id, isShowCreateModal } = chunkModel; + const getChunkList = () => { - dispatch({ - type: 'kSearchModel/updateState', - payload: { - loading: true - } - }); - interface payloadType { - kb_id: string; - question?: string; - doc_ids: any[]; - similarity_threshold?: number - } - const payload: payloadType = { - kb_id, - question, - doc_ids, - similarity_threshold: 0.1 - } dispatch({ type: 'kSearchModel/chunk_list', payload: { - ...payload, - ...pagination - } + kb_id, + }, }); - } + }; const confirm = (id: string) => { - console.log(id) dispatch({ type: 'kSearchModel/rm_chunk', payload: { - chunk_ids: [id] + chunk_ids: [id], + kb_id, }, - callback: getChunkList }); }; const handleEditchunk = (item: any) => { - const { chunk_id, doc_id } = item + const { chunk_id, doc_id } = item; dispatch({ type: 'chunkModel/updateState', payload: { isShowCreateModal: true, chunk_id, - doc_id + doc_id, }, - callback: getChunkList }); - } - const onShowSizeChange: PaginationProps['onShowSizeChange'] = (page, size) => { + getChunkList(); + }; + const onShowSizeChange: PaginationProps['onShowSizeChange'] = ( + page, + size, + ) => { dispatch({ type: 'kSearchModel/updateState', payload: { - pagination: { page, size } - } + pagination: { page, size }, + }, }); }; useEffect(() => { dispatch({ type: 'kSearchModel/updateState', payload: { - loading: false, doc_ids: [], - question: "" - } + question: '', + }, }); dispatch({ type: 'kSearchModel/getKfList', payload: { - kb_id - } - + kb_id, + }, }); - }, []) + }, []); const switchChunk = (item: any, available_int: boolean) => { - const { chunk_id, doc_id } = item - dispatch({ - type: 'kSearchModel/updateState', - payload: { - loading: true - } - }); + const { chunk_id, doc_id } = item; + dispatch({ type: 'kSearchModel/switch_chunk', payload: { chunk_ids: [chunk_id], doc_id, - available_int + available_int, + kb_id, }, - callback: getChunkList }); - } - + }; useEffect(() => { - getChunkList() - }, [doc_ids, pagination, question]) + getChunkList(); + }, [doc_ids, pagination, question]); const debounceChange = debounce((value) => { dispatch({ type: 'kSearchModel/updateState', payload: { - question: value - } + question: value, + }, }); - }, 300) - const debounceCallback = useCallback((value: string) => debounceChange(value), []) - const handleInputChange = (e: React.ChangeEvent) => { - const value = e.target.value - debounceCallback(value) - } - const handleSelectChange = (value: - any[]) => { + }, 300); + + const debounceCallback = useCallback( + (value: string) => debounceChange(value), + [], + ); + const handleInputChange = ( + e: React.ChangeEvent, + ) => { + const value = e.target.value; + debounceCallback(value); + }; + const handleSelectChange = (value: any[]) => { dispatch({ type: 'kSearchModel/updateState', payload: { - doc_ids: value - } + doc_ids: value, + }, }); - } - console.log('loading', loading) - return (<> -
-
- -
-
-
- - - { - data.map((item: any) => { - return (
- { handleEditchunk(item) }} - > - -
-
- - {item.content_ltks} - - - { - e.stopPropagation(); - e.nativeEvent.stopImmediatePropagation(); switchChunk(item, checked) - }} /> - -
-
- - {item.doc_num}文档 - - - {item.chunk_num}个 - - - {item.token_num}千字符 - - - { - e.stopPropagation(); - e.nativeEvent.stopImmediatePropagation() - console.log(confirm) - confirm(item.chunk_id) - - }} - okText="Yes" - cancelText="No" - > - { - e.stopPropagation(); - e.nativeEvent.stopImmediatePropagation() - }} /> - - - -
- -
-
- ) - }) - } - - - - -
-
+
+
+ + + {data.map((item: any) => { + return ( +
+ { + handleEditchunk(item); + }} + > + +
+
+ + {item.content_ltks} + + + { + e.stopPropagation(); + e.nativeEvent.stopImmediatePropagation(); + switchChunk(item, checked); + }} + /> + +
+
+ + + {item.doc_num}文档 + + + + {item.chunk_num}个 + + + + {item.token_num}千字符 + + + { + e.stopPropagation(); + e.nativeEvent.stopImmediatePropagation(); + console.log(confirm); + confirm(item.chunk_id); + }} + okText="Yes" + cancelText="No" + > + { + e.stopPropagation(); + e.nativeEvent.stopImmediatePropagation(); + }} + /> + + +
+
+
+ + ); + })} + + + +
+ +
+ - - - - - ) + + + ); }; -export default connect(({ kSearchModel, chunkModel, loading }) => ({ kSearchModel, chunkModel, loading }))(Index); \ No newline at end of file +export default KnowledgeSearching; diff --git a/web/src/pages/add-knowledge/components/knowledge-search/model.ts b/web/src/pages/add-knowledge/components/knowledge-search/model.ts index 247495e5b..da9a4acae 100644 --- a/web/src/pages/add-knowledge/components/knowledge-search/model.ts +++ b/web/src/pages/add-knowledge/components/knowledge-search/model.ts @@ -1,8 +1,8 @@ -import { Effect, Reducer, Subscription } from 'umi' -import { message } from 'antd'; import kbService from '@/services/kbService'; +import omit from 'lodash/omit'; +import { DvaModel } from 'umi'; -export interface kSearchModelState { +export interface KSearchModelState { loading: boolean; data: any[]; total: number; @@ -13,26 +13,10 @@ export interface kSearchModelState { question: string; doc_ids: any[]; pagination: any; - doc_id: string + doc_id: string; +} -} -export interface chunkgModelType { - namespace: 'kSearchModel'; - state: kSearchModelState; - effects: { - chunk_list: Effect; - get_chunk: Effect; - create_hunk: Effect; - switch_chunk: Effect; - rm_chunk: Effect; - getKfList: Effect; - }; - reducers: { - updateState: Reducer; - }; - subscriptions: { setup: Subscription }; -} -const Model: chunkgModelType = { +const model: DvaModel = { namespace: 'kSearchModel', state: { loading: false, @@ -45,114 +29,132 @@ const Model: chunkgModelType = { question: '', doc_ids: [], pagination: { page: 1, size: 30 }, - doc_id: '' + doc_id: '', + }, + reducers: { + updateState(state, { payload }) { + return { + ...state, + ...payload, + }; + }, }, subscriptions: { setup({ dispatch, history }) { - history.listen(location => { - console.log(location) + history.listen((location) => { + console.log(location); }); - } + }, }, effects: { *getKfList({ payload = {} }, { call, put }) { - const { data, response } = yield call(kbService.get_document_list, payload); + const { data, response } = yield call( + kbService.get_document_list, + payload, + ); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { yield put({ type: 'updateState', payload: { - d_list: res - } + d_list: res, + }, }); } }, - * chunk_list({ payload = {}, callback }, { call, put }) { - const { data, response } = yield call(kbService.retrieval_test, payload); - const { retcode, data: res, retmsg } = data + *chunk_list({ payload = {} }, { call, put, select }) { + const { question, doc_ids, pagination }: KSearchModelState = yield select( + (state: any) => state.kSearchModel, + ); + const { data } = yield call(kbService.retrieval_test, { + ...payload, + ...pagination, + question, + doc_ids, + similarity_threshold: 0.1, + }); + const { retcode, data: res, retmsg } = data; if (retcode === 0) { - console.log(res) yield put({ type: 'updateState', payload: { data: res.chunks, total: res.total, - loading: false - } + }, }); - callback && callback() - } }, - *switch_chunk({ payload = {}, callback }, { call, put }) { - const { data, response } = yield call(kbService.switch_chunk, payload); - const { retcode, data: res, retmsg } = data + *switch_chunk({ payload = {} }, { call, put }) { + const { data } = yield call( + kbService.switch_chunk, + omit(payload, ['kb_id']), + ); + const { retcode } = data; if (retcode === 0) { - callback && callback() - + yield put({ + type: 'chunk_list', + payload: { + kb_id: payload.kb_id, + }, + }); } }, - *rm_chunk({ payload = {}, callback }, { call, put }) { - console.log('shanchu') - const { data, response } = yield call(kbService.rm_chunk, payload); - const { retcode, data: res, retmsg } = data + *rm_chunk({ payload = {} }, { call, put }) { + const { data } = yield call(kbService.rm_chunk, { + chunk_ids: payload.chunk_ids, + }); + const { retcode, data: res, retmsg } = data; if (retcode === 0) { - callback && callback() - + // TODO: Can be extracted + yield put({ + type: 'chunk_list', + payload: { + kb_id: payload.kb_id, + }, + }); } }, - * get_chunk({ payload = {}, callback }, { call, put }) { + *get_chunk({ payload = {} }, { call, put }) { const { data, response } = yield call(kbService.get_chunk, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { - yield put({ type: 'updateState', payload: { - chunkInfo: res - } + chunkInfo: res, + }, }); - callback && callback(res) - } }, *create_hunk({ payload = {} }, { call, put }) { yield put({ type: 'updateState', payload: { - loading: true - } + loading: true, + }, }); - let service = kbService.create_chunk + let service = kbService.create_chunk; if (payload.chunk_id) { - service = kbService.set_chunk + service = kbService.set_chunk; } const { data, response } = yield call(service, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; yield put({ type: 'updateState', payload: { - loading: false - } + loading: false, + }, }); if (retcode === 0) { yield put({ type: 'updateState', payload: { - isShowCreateModal: false - } + isShowCreateModal: false, + }, }); } }, }, - reducers: { - updateState(state, { payload }) { - return { - ...state, - ...payload - }; - } - } }; -export default Model; +export default model; diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx b/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx index 67286f441..e7b5659c9 100644 --- a/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx @@ -1,170 +1,157 @@ -import React, { useEffect, useState } from 'react'; -import { useNavigate, connect, Dispatch } from 'umi' -import { Button, Form, Input, Radio, Select, Tag, Space, } from 'antd'; -import type { kSModelState } from './model' -import type { settingModelState } from '@/pages/setting/model' -import styles from './index.less' +import { Button, Form, Input, Radio, Select, Space, Tag } from 'antd'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useDispatch, useNavigate, useSelector } from 'umi'; +import styles from './index.less'; const { CheckableTag } = Tag; const layout = { - labelCol: { span: 8 }, - wrapperCol: { span: 16 }, - labelAlign: 'left' as const + labelCol: { span: 8 }, + wrapperCol: { span: 16 }, + labelAlign: 'left' as const, }; -const { Option } = Select +const { Option } = Select; /* eslint-disable no-template-curly-in-string */ interface kSProps { - dispatch: Dispatch; - kSModel: kSModelState; - settingModel: settingModelState; - kb_id: string + kb_id: string; } -const Index: React.FC = ({ settingModel, kSModel, dispatch, kb_id }) => { - let navigate = useNavigate(); - const { tenantIfo = {} } = settingModel - const { parser_ids = '', embd_id = '' } = tenantIfo - const [form] = Form.useForm(); +const KnowledgeSetting: React.FC = ({ kb_id }) => { + const dispatch = useDispatch(); + const settingModel = useSelector((state: any) => state.settingModel); + let navigate = useNavigate(); + const { tenantIfo = {} } = settingModel; + const { parser_ids = '', embd_id = '' } = tenantIfo; + const [form] = Form.useForm(); + const [selectedTag, setSelectedTag] = useState(''); + const values = Form.useWatch([], form); - useEffect(() => { + const getTenantInfo = useCallback(async () => { + dispatch({ + type: 'settingModel/getTenantInfo', + payload: {}, + }); + if (kb_id) { + const data = await dispatch({ + type: 'kSModel/getKbDetail', + payload: { + kb_id, + }, + }); + if (data.retcode === 0) { + const { description, name, permission, embd_id } = data.data; + form.setFieldsValue({ description, name, permission, embd_id }); + setSelectedTag(data.data.parser_id); + } + } + }, [kb_id]); + + const onFinish = async () => { + try { + await form.validateFields(); + + if (kb_id) { dispatch({ - type: 'settingModel/getTenantInfo', - payload: { - } + type: 'kSModel/updateKb', + payload: { + ...values, + parser_id: selectedTag, + kb_id, + embd_id: undefined, + }, }); - if (kb_id) { + } else { + const retcode = await dispatch({ + type: 'kSModel/createKb', + payload: { + ...values, + parser_id: selectedTag, + }, + }); + retcode === 0 && + navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}`); + } + } catch (error) { + console.warn(error); + } + }; - dispatch({ - type: 'kSModel/getKbDetail', - payload: { - kb_id - }, - callback(detail: any) { - console.log(detail) - const { description, name, permission, embd_id } = detail - form.setFieldsValue({ description, name, permission, embd_id }) - setSelectedTag(detail.parser_id) - } - }); - } + useEffect(() => { + getTenantInfo(); + }, [getTenantInfo]); - }, [kb_id]) - const [selectedTag, setSelectedTag] = useState('') - const values = Form.useWatch([], form); - console.log(values, '......变化') - const onFinish = () => { - form.validateFields().then( - () => { - if (kb_id) { - dispatch({ - type: 'kSModel/updateKb', - payload: { - ...values, - parser_id: selectedTag, - kb_id, - embd_id: undefined - } - }); - } else { - dispatch({ - type: 'kSModel/createKb', - payload: { - ...values, - parser_id: selectedTag - }, - callback(id: string) { - navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}`); - } - }); - } - }, - () => { + const handleChange = (tag: string, checked: boolean) => { + const nextSelectedTag = checked ? tag : selectedTag; + console.log('You are interested in: ', nextSelectedTag); + setSelectedTag(nextSelectedTag); + }; - }, - ); - - - - }; - - const handleChange = (tag: string, checked: boolean) => { - const nextSelectedTag = checked - ? tag - : selectedTag; - console.log('You are interested in: ', nextSelectedTag); - setSelectedTag(nextSelectedTag); - }; - - return
- - - - - - - - - 只有我 - 所有团队成员 - - - - - -
- 修改Embedding 模型,请去设置 + + + + + + + + + 只有我 + 所有团队成员 + + + + + +
+ 修改Embedding 模型,请去设置 +
+ +
+ {parser_ids.split(',').map((tag: string) => { + return ( + handleChange(tag, checked)} + > + {tag} + + ); + })}
- -
- { - parser_ids.split(',').map((tag: string) => { - return ( handleChange(tag, checked)} - > - {tag} - ) - }) - } -
-
- - - -
-
- xxxxx文章 -
-
- 预估份数 -
-
- - - - +
+ +
+
xxxxx文章
+
预估份数
+
+ + + + -} + ); +}; - - -export default connect(({ settingModel, kSModel, loading }) => ({ settingModel, kSModel, loading }))(Index); \ No newline at end of file +export default KnowledgeSetting; diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/model.ts b/web/src/pages/add-knowledge/components/knowledge-setting/model.ts index 42e33a5b3..188477130 100644 --- a/web/src/pages/add-knowledge/components/knowledge-setting/model.ts +++ b/web/src/pages/add-knowledge/components/knowledge-setting/model.ts @@ -1,72 +1,54 @@ -import { message } from 'antd'; -import { Effect, Reducer, Subscription } from 'umi' import kbService from '@/services/kbService'; +import { message } from 'antd'; +import { DvaModel } from 'umi'; -export interface kSModelState { +export interface KSModelState { isShowPSwModal: boolean; isShowTntModal: boolean; - loading: boolean; - tenantIfo: any + tenantIfo: any; } -export interface kSModelType { - namespace: 'kSModel'; - state: kSModelState; - effects: { - createKb: Effect; - updateKb: Effect; - getKbDetail: Effect; - }; - reducers: { - updateState: Reducer; - }; - subscriptions: { setup: Subscription }; -} -const Model: kSModelType = { + +const model: DvaModel = { namespace: 'kSModel', state: { isShowPSwModal: false, isShowTntModal: false, - loading: false, - tenantIfo: {} - }, - subscriptions: { - setup({ dispatch, history }) { - history.listen(location => { - }); - } - }, - effects: { - * createKb({ payload = {}, callback }, { call, put }) { - const { data, response } = yield call(kbService.createKb, payload); - const { retcode, data: res, retmsg } = data - if (retcode === 0) { - message.success('创建知识库成功!'); - callback && callback(res.kb_id) - } - }, - * updateKb({ payload = {}, callback }, { call, put }) { - const { data, response } = yield call(kbService.updateKb, payload); - const { retcode, data: res, retmsg } = data - if (retcode === 0) { - message.success('更新知识库成功!'); - } - }, - *getKbDetail({ payload = {}, callback }, { call, put }) { - const { data, response } = yield call(kbService.get_kb_detail, payload); - const { retcode, data: res, retmsg } = data - if (retcode === 0) { - // localStorage.setItem('userInfo',res.) - callback && callback(res) - } - }, + tenantIfo: {}, }, reducers: { updateState(state, { payload }) { return { ...state, - ...payload + ...payload, }; - } - } + }, + }, + subscriptions: { + setup({ dispatch, history }) { + history.listen((location) => {}); + }, + }, + effects: { + *createKb({ payload = {} }, { call, put }) { + const { data } = yield call(kbService.createKb, payload); + const { retcode } = data; + if (retcode === 0) { + message.success('创建知识库成功!'); + } + return retcode; + }, + *updateKb({ payload = {} }, { call, put }) { + const { data } = yield call(kbService.updateKb, payload); + const { retcode, data: res, retmsg } = data; + if (retcode === 0) { + message.success('更新知识库成功!'); + } + }, + *getKbDetail({ payload = {} }, { call, put }) { + const { data } = yield call(kbService.get_kb_detail, payload); + + return data; + }, + }, }; -export default Model; +export default model; diff --git a/web/src/pages/add-knowledge/index.tsx b/web/src/pages/add-knowledge/index.tsx index 073a0c836..d2386a771 100644 --- a/web/src/pages/add-knowledge/index.tsx +++ b/web/src/pages/add-knowledge/index.tsx @@ -1,123 +1,120 @@ -import { connect, useNavigate, useLocation, Dispatch } from 'umi' -import React, { useState, useEffect, useMemo } from 'react'; +import { getWidth } from '@/utils'; +import { BarsOutlined, SearchOutlined, ToolOutlined } from '@ant-design/icons'; import type { MenuProps } from 'antd'; import { Menu } from 'antd'; -import { - ToolOutlined, - BarsOutlined, - SearchOutlined -} from '@ant-design/icons'; -import File from './components/knowledge-file' -import Setting from './components/knowledge-setting' -import Search from './components/knowledge-search' -import Chunk from './components/knowledge-chunk' -import styles from './index.less' -import { getWidth } from '@/utils' -import { kAModelState } from './model' +import React, { useEffect, useMemo, useState } from 'react'; +import { useDispatch, useLocation, useNavigate, useSelector } from 'umi'; +import Chunk from './components/knowledge-chunk'; +import File from './components/knowledge-file'; +import Search from './components/knowledge-search'; +import Setting from './components/knowledge-setting'; +import styles from './index.less'; +const KnowledgeAdding = () => { + const dispatch = useDispatch(); + const kAModel = useSelector((state: any) => state.kAModel); + const { id, activeKey, doc_id } = kAModel; -interface kAProps { - dispatch: Dispatch; - kAModel: kAModelState; -} -const Index: React.FC = ({ kAModel, dispatch }) => { - const [collapsed, setCollapsed] = useState(false); - const { id, activeKey, doc_id } = kAModel - const [windowWidth, setWindowWidth] = useState(getWidth()); - let navigate = useNavigate(); - const location = useLocation(); - // 标记一下 - console.log(doc_id, '>>>>>>>>>>>>>doc_id') - useEffect(() => { - const widthSize = () => { - const width = getWidth() - console.log(width) + const [collapsed, setCollapsed] = useState(false); + const [windowWidth, setWindowWidth] = useState(getWidth()); + let navigate = useNavigate(); + const location = useLocation(); - setWindowWidth(width); - }; - window.addEventListener("resize", widthSize); - return () => { - window.removeEventListener("resize", widthSize); - }; - }, []); - useEffect(() => { - console.log(location) - const search = location.search.slice(1) - const map = search.split('&').reduce((obj, cur) => { - const [key, value] = cur.split('=') - obj[key] = value - return obj - }, {}) - dispatch({ - type: 'kAModel/updateState', - payload: { - doc_id: undefined, - ...map, + // 标记一下 + console.log(doc_id, '>>>>>>>>>>>>>doc_id'); + useEffect(() => { + const widthSize = () => { + const width = getWidth(); + console.log(width); + setWindowWidth(width); + }; + window.addEventListener('resize', widthSize); + return () => { + window.removeEventListener('resize', widthSize); + }; + }, []); + useEffect(() => { + const search: string = location.search.slice(1); + const map = search.split('&').reduce>((obj, cur) => { + const [key, value] = cur.split('='); + obj[key] = value; + return obj; + }, {}); + + dispatch({ + type: 'kAModel/updateState', + payload: { + doc_id: undefined, + ...map, + }, + }); + }, [location]); + + useEffect(() => { + if (windowWidth.width > 957) { + setCollapsed(false); + } else { + setCollapsed(true); + } + }, [windowWidth.width]); + + type MenuItem = Required['items'][number]; + + function getItem( + label: React.ReactNode, + key: React.Key, + icon?: React.ReactNode, + disabled?: boolean, + children?: MenuItem[], + type?: 'group', + ): MenuItem { + return { + key, + icon, + children, + label, + type, + disabled, + } as MenuItem; + } + const items: MenuItem[] = useMemo(() => { + const disabled = !id; + return [ + getItem('配置', 'setting', ), + getItem('知识库', 'file', , disabled), + getItem('搜索测试', 'search', , disabled), + ]; + }, [id]); + + const handleSelect: MenuProps['onSelect'] = (e) => { + navigate(`/knowledge/add/setting?activeKey=${e.key}&id=${id}`); + }; + + return ( + <> +
+
+ 957 ? styles.defaultWidth : styles.minWidth } - }); - }, [location]) - useEffect(() => { - if (windowWidth.width > 957) { - setCollapsed(false) - } else { - setCollapsed(true) - } - }, [windowWidth.width]) - type MenuItem = Required['items'][number]; - - function getItem( - label: React.ReactNode, - key: React.Key, - icon?: React.ReactNode, - disabled?: boolean, - children?: MenuItem[], - type?: 'group', - - ): MenuItem { - return { - key, - icon, - children, - label, - type, - disabled - } as MenuItem; - } - const items: MenuItem[] = useMemo(() => { - const disabled = !id - return [ - getItem('配置', 'setting', ), - getItem('知识库', 'file', , disabled), - getItem('搜索测试', 'search', , disabled), - ] - }, [id]); - const handleSelect: MenuProps['onSelect'] = (e) => { - navigate(`/knowledge/add/setting?activeKey=${e.key}&id=${id}`); - } - return ( - <> -
-
- 957 ? styles.defaultWidth : styles.minWidth} - inlineCollapsed={collapsed} - items={items} - onSelect={handleSelect} - /> -
-
- {activeKey === 'file' && !doc_id && } - {activeKey === 'setting' && } - {activeKey === 'search' && } - {activeKey === 'file' && !!doc_id && } - -
-
- - ); + inlineCollapsed={collapsed} + items={items} + onSelect={handleSelect} + /> +
+
+ {activeKey === 'file' && !doc_id && } + {activeKey === 'setting' && } + {activeKey === 'search' && } + {activeKey === 'file' && !!doc_id && } +
+
+ + ); }; -export default connect(({ kAModel, loading }) => ({ kAModel, loading }))(Index); \ No newline at end of file +export default KnowledgeAdding; diff --git a/web/src/pages/add-knowledge/model.ts b/web/src/pages/add-knowledge/model.ts index 6f1871bcf..32a75ef4d 100644 --- a/web/src/pages/add-knowledge/model.ts +++ b/web/src/pages/add-knowledge/model.ts @@ -1,6 +1,4 @@ -import { Effect, Reducer, Subscription } from 'umi' -import { message } from 'antd'; -import kbService from '@/services/kbService'; +import { DvaModel } from 'umi'; export interface kAModelState { isShowPSwModal: boolean; isShowTntModal: boolean; @@ -8,20 +6,10 @@ export interface kAModelState { tenantIfo: any; activeKey: string; id: string; - doc_id: string + doc_id: string; } -export interface kAModelType { - namespace: 'kAModel'; - state: kAModelState; - effects: { - }; - reducers: { - updateState: Reducer; - }; - subscriptions: { setup: Subscription }; -} -const Model: kAModelType = { +const model: DvaModel = { namespace: 'kAModel', state: { isShowPSwModal: false, @@ -30,25 +18,21 @@ const Model: kAModelType = { tenantIfo: {}, activeKey: 'setting', id: '', - doc_id: '' - - }, - subscriptions: { - setup({ dispatch, history }) { - history.listen(location => { - }); - } - }, - effects: { - + doc_id: '', }, reducers: { updateState(state, { payload }) { return { ...state, - ...payload + ...payload, }; - } - } + }, + }, + subscriptions: { + setup({ dispatch, history }) { + history.listen((location) => {}); + }, + }, + effects: {}, }; -export default Model; +export default model; diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx index 64445f6b4..f79132287 100644 --- a/web/src/pages/chat/index.tsx +++ b/web/src/pages/chat/index.tsx @@ -1,15 +1,8 @@ -import React from 'react'; -import { connect, Dispatch } from 'umi'; -import type { chatModelState } from './model' +import { useSelector } from 'umi'; -interface chatProps { - chatModel: chatModelState; - dispatch: Dispatch -} - -const View: React.FC = ({ chatModel, dispatch }) => { - const { name } = chatModel; - return
chat:{name}
; +const Chat = () => { + const { name } = useSelector((state: any) => state.chatModel); + return
chat:{name}
; }; -export default connect(({ chatModel, loading }) => ({ chatModel, loading }))(View); \ No newline at end of file +export default Chat; diff --git a/web/src/pages/chat/model.ts b/web/src/pages/chat/model.ts index 103c978c9..6efdc52e3 100644 --- a/web/src/pages/chat/model.ts +++ b/web/src/pages/chat/model.ts @@ -1,46 +1,32 @@ -import { Effect, Reducer, Subscription } from 'umi'; +import { DvaModel } from 'umi'; -export interface chatModelState { - name: string; +export interface ChatModelState { + name: string; } -export interface chatModelType { - namespace: 'chatModel'; - state: chatModelState; - effects: { - query: Effect; - }; - reducers: { - save: Reducer; - }; - subscriptions: { setup: Subscription }; -} - -const Model: chatModelType = { - namespace: 'chatModel', - state: { - name: 'kate', +const model: DvaModel = { + namespace: 'chatModel', + state: { + name: 'kate', + }, + reducers: { + save(state, action) { + return { + ...state, + ...action.payload, + }; }, - - effects: { - *query({ payload }, { call, put }) { }, - }, - reducers: { - save(state, action) { - return { - ...state, - ...action.payload, - }; - }, - }, - subscriptions: { - setup({ dispatch, history }) { - return history.listen((query) => { - console.log(query) - - }); - }, + }, + subscriptions: { + setup({ dispatch, history }) { + return history.listen((query) => { + console.log(query); + }); }, + }, + effects: { + *query({ payload }, { call, put }) {}, + }, }; -export default Model; \ No newline at end of file +export default model; diff --git a/web/src/pages/file/index.tsx b/web/src/pages/file/index.tsx index a9310e3d9..be7eada21 100644 --- a/web/src/pages/file/index.tsx +++ b/web/src/pages/file/index.tsx @@ -1,51 +1,50 @@ -import React, { useEffect, useState } from 'react'; import { UploadOutlined } from '@ant-design/icons'; import { Button, Upload } from 'antd'; -import type { UploadFile } from 'antd/es/upload/interface'; +import React, { useEffect, useState } from 'react'; - -const App: React.FC = () => { - const [fileList, setFileList] = useState([{ - uid: '0', - name: 'xxx.png', - status: 'uploading', - percent: 10, - }]) - const obj = { - uid: '-1', - name: 'yyy.png', - status: 'done', - url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', - thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', - } - useEffect(() => { - const timer = setInterval(() => { - setFileList((fileList: any) => { - const percent = fileList[0]?.percent - if (percent + 10 >= 100) { - clearInterval(timer) - return [obj] - } - const list = [{ ...fileList[0], percent: percent + 10 }] - console.log(list) - return list - - }) - }, 300) - }, []) - return ( - - <> - - - - - ) +const File: React.FC = () => { + const [fileList, setFileList] = useState([ + { + uid: '0', + name: 'xxx.png', + status: 'uploading', + percent: 10, + }, + ]); + const obj = { + uid: '-1', + name: 'yyy.png', + status: 'done', + url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', + thumbUrl: + 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', + }; + useEffect(() => { + const timer = setInterval(() => { + setFileList((fileList: any) => { + const percent = fileList[0]?.percent; + if (percent + 10 >= 100) { + clearInterval(timer); + return [obj]; + } + const list = [{ ...fileList[0], percent: percent + 10 }]; + console.log(list); + return list; + }); + }, 300); + }, []); + return ( + <> + + + + + ); }; -export default App; \ No newline at end of file +export default File; diff --git a/web/src/pages/knowledge/index.tsx b/web/src/pages/knowledge/index.tsx index cdf138b30..8af444f9c 100644 --- a/web/src/pages/knowledge/index.tsx +++ b/web/src/pages/knowledge/index.tsx @@ -5,21 +5,22 @@ import { PlusOutlined, } from '@ant-design/icons'; import { Card, Col, FloatButton, Popconfirm, Row } from 'antd'; -import React, { useEffect } from 'react'; -import { Dispatch, connect, useNavigate } from 'umi'; +import { useCallback, useEffect } from 'react'; +import { useDispatch, useNavigate, useSelector } from 'umi'; import styles from './index.less'; -import type { knowledgeModelState } from './model'; -interface KnowledgeProps { - dispatch: Dispatch; - knowledgeModel: knowledgeModelState; -} -const Index: React.FC = ({ knowledgeModel, dispatch }) => { - const navigate = useNavigate(); - // const [datas, setDatas] = useState(data) - const { data = [] } = knowledgeModel; - console.log(knowledgeModel); - // const x = useSelector((state) => state.knowledgeModel); +const Knowledge = () => { + const dispatch = useDispatch(); + const knowledgeModel = useSelector((state: any) => state.knowledgeModel); + const navigate = useNavigate(); + const { data = [] } = knowledgeModel; + + const fetchList = useCallback(() => { + dispatch({ + type: 'knowledgeModel/getList', + payload: {}, + }); + }, []); const confirm = (id: string) => { dispatch({ @@ -27,12 +28,6 @@ const Index: React.FC = ({ knowledgeModel, dispatch }) => { payload: { kb_id: id, }, - callback: () => { - dispatch({ - type: 'knowledgeModel/getList', - payload: {}, - }); - }, }); }; const handleAddKnowledge = () => { @@ -42,11 +37,8 @@ const Index: React.FC = ({ knowledgeModel, dispatch }) => { navigate(`add/setting?activeKey=file&id=${id}`); }; useEffect(() => { - dispatch({ - type: 'knowledgeModel/getList', - payload: {}, - }); - }, []); + fetchList(); + }, [fetchList]); return ( <>
@@ -125,7 +117,4 @@ const Index: React.FC = ({ knowledgeModel, dispatch }) => { ); }; -export default connect(({ knowledgeModel, loading }) => ({ - knowledgeModel, - loading, -}))(Index); +export default Knowledge; diff --git a/web/src/pages/knowledge/model.ts b/web/src/pages/knowledge/model.ts index 83e300081..0621f763a 100644 --- a/web/src/pages/knowledge/model.ts +++ b/web/src/pages/knowledge/model.ts @@ -1,58 +1,38 @@ import kbService from '@/services/kbService'; -import { Effect, Reducer } from 'umi'; +import { DvaModel } from 'umi'; -export interface knowledgeModelState { - loading: boolean; +export interface KnowledgeModelState { data: any[]; } -export interface knowledgegModelType { - namespace: 'knowledgeModel'; - state: knowledgeModelState; - effects: { - rmKb: Effect; - getList: Effect; - }; - reducers: { - updateState: Reducer; - }; - // subscriptions: { setup: Subscription }; -} -const Model: knowledgegModelType = { + +const model: DvaModel = { namespace: 'knowledgeModel', state: { - loading: false, data: [], }, - // subscriptions: { - // setup({ dispatch, history }) { - // history.listen((location) => { - // console.log(location); - // }); - // }, - // }, + reducers: { + updateState(state, { payload }) { + return { + ...state, + ...payload, + }; + }, + }, effects: { *rmKb({ payload = {}, callback }, { call, put }) { - const { data, response } = yield call(kbService.rmKb, payload); - const { retcode, data: res, retmsg } = data; + const { data } = yield call(kbService.rmKb, payload); + const { retcode } = data; if (retcode === 0) { - callback && callback(); + yield put({ + type: 'getList', + payload: {}, + }); } }, *getList({ payload = {} }, { call, put }) { - yield put({ - type: 'updateState', - payload: { - loading: true, - }, - }); - const { data, response } = yield call(kbService.getList, payload); + const { data } = yield call(kbService.getList, payload); const { retcode, data: res, retmsg } = data; - yield put({ - type: 'updateState', - payload: { - loading: false, - }, - }); + if (retcode === 0) { yield put({ type: 'updateState', @@ -63,13 +43,5 @@ const Model: knowledgegModelType = { } }, }, - reducers: { - updateState(state, { payload }) { - return { - ...state, - ...payload, - }; - }, - }, }; -export default Model; +export default model; diff --git a/web/src/pages/login/index.tsx b/web/src/pages/login/index.tsx index 29edc3968..a0696b361 100644 --- a/web/src/pages/login/index.tsx +++ b/web/src/pages/login/index.tsx @@ -1,15 +1,20 @@ import { rsaPsw } from '@/utils'; import { Button, Checkbox, Form, Input } from 'antd'; -import { FC, useEffect, useState } from 'react'; -import { Dispatch, Icon, connect, useNavigate } from 'umi'; +import { useEffect, useState } from 'react'; +import { Icon, useDispatch, useNavigate, useSelector } from 'umi'; import styles from './index.less'; -interface LoginProps { - dispatch: Dispatch; -} -const View: FC = ({ dispatch }) => { - let navigate = useNavigate(); +const Login = () => { const [title, setTitle] = useState('login'); + let navigate = useNavigate(); + const dispatch = useDispatch(); + const effectsLoading: any = useSelector( // TODO: Type needs to be improved + (state) => state.loading.effects, + ); + + const signLoading = + effectsLoading['loginModel/login'] || effectsLoading['loginModel/register']; + const changeTitle = () => { setTitle((title) => (title === 'login' ? 'register' : 'login')); }; @@ -26,27 +31,29 @@ const View: FC = ({ dispatch }) => { var rsaPassWord = rsaPsw(params.password); if (title === 'login') { - const ret = await dispatch({ + const retcode = await dispatch({ type: 'loginModel/login', payload: { email: params.email, password: rsaPassWord, }, }); - console.info(ret); - navigate('/knowledge'); + if (retcode === 0) { + navigate('/knowledge'); + } } else { - dispatch({ + // TODO: Type needs to be improved + const retcode = await dispatch({ type: 'loginModel/register', payload: { nickname: params.nickname, email: params.email, password: rsaPassWord, }, - callback() { - setTitle('login'); - }, }); + if (retcode === 0) { + setTitle('login'); + } } } catch (errorInfo) { console.log('Failed:', errorInfo); @@ -106,7 +113,7 @@ const View: FC = ({ dispatch }) => { label="Password" rules={[{ required: true, message: 'Please input value' }]} > - + {title === 'login' && ( @@ -132,7 +139,13 @@ const View: FC = ({ dispatch }) => {
)}
- {title === 'login' && ( @@ -175,6 +188,4 @@ const View: FC = ({ dispatch }) => { ); }; -export default connect(({ loginModel, loading }) => ({ loginModel, loading }))( - View, -); +export default Login; diff --git a/web/src/pages/login/model.ts b/web/src/pages/login/model.ts index 0ce6150c8..257879f6d 100644 --- a/web/src/pages/login/model.ts +++ b/web/src/pages/login/model.ts @@ -2,32 +2,29 @@ import { Authorization } from '@/constants/authorization'; import userService from '@/services/userService'; import authorizationUtil from '@/utils/authorizationUtil'; import { message } from 'antd'; -import { Effect, Reducer, Subscription } from 'umi'; +import { DvaModel } from 'umi'; -export interface loginModelState { +export interface LoginModelState { list: any[]; info: any; visible: boolean; } -export interface logingModelType { - namespace: 'loginModel'; - state: loginModelState; - effects: { - login: Effect; - register: Effect; - }; - reducers: { - updateState: Reducer; - }; - subscriptions: { setup: Subscription }; -} -const Model: logingModelType = { + +const model: DvaModel = { namespace: 'loginModel', state: { list: [], info: {}, visible: false, }, + reducers: { + updateState(state, { payload }) { + return { + ...state, + ...payload, + }; + }, + }, subscriptions: { setup({ dispatch, history }) { history.listen((location) => {}); @@ -53,29 +50,18 @@ const Model: logingModelType = { userInfo: JSON.stringify(userInfo), Token: token, }); - // setTimeout(() => { - // window.location.href = '/file'; - // }, 300); } - return data; + return retcode; }, - *register({ payload = {}, callback }, { call, put }) { + *register({ payload = {} }, { call, put }) { const { data, response } = yield call(userService.register, payload); console.log(); const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('注册成功!'); - callback && callback(); } - }, - }, - reducers: { - updateState(state, { payload }) { - return { - ...state, - ...payload, - }; + return retcode; }, }, }; -export default Model; +export default model; diff --git a/web/src/pages/setting/model.ts b/web/src/pages/setting/model.ts index 0971b31ef..604b87fda 100644 --- a/web/src/pages/setting/model.ts +++ b/web/src/pages/setting/model.ts @@ -1,9 +1,9 @@ import userService from '@/services/userService'; import authorizationUtil from '@/utils/authorizationUtil'; import { message } from 'antd'; -import { Effect, Reducer, Subscription } from 'umi'; +import { DvaModel } from 'umi'; -export interface settingModelState { +export interface SettingModelState { isShowPSwModal: boolean; isShowTntModal: boolean; isShowSAKModal: boolean; @@ -16,25 +16,7 @@ export interface settingModelState { factoriesList: any[]; } -export interface settingModelType { - namespace: 'settingModel'; - state: settingModelState; - effects: { - setting: Effect; - getUserInfo: Effect; - getTenantInfo: Effect; - set_tenant_info: Effect; - factories_list: Effect; - llm_list: Effect; - my_llm: Effect; - set_api_key: Effect; - }; - reducers: { - updateState: Reducer; - }; - subscriptions: { setup: Subscription }; -} -const Model: settingModelType = { +const model: DvaModel = { namespace: 'settingModel', state: { isShowPSwModal: false, @@ -48,6 +30,14 @@ const Model: settingModelType = { myLlm: [], factoriesList: [], }, + reducers: { + updateState(state, { payload }) { + return { + ...state, + ...payload, + }; + }, + }, subscriptions: { setup({ dispatch, history }) { history.listen((location) => {}); @@ -176,13 +166,5 @@ const Model: settingModelType = { } }, }, - reducers: { - updateState(state, { payload }) { - return { - ...state, - ...payload, - }; - }, - }, }; -export default Model; +export default model; diff --git a/web/src/services/kbService.ts b/web/src/services/kbService.ts index 2ea491798..0fa02544b 100644 --- a/web/src/services/kbService.ts +++ b/web/src/services/kbService.ts @@ -19,101 +19,83 @@ const { get_chunk, switch_chunk, rm_chunk, - retrieval_test } = api; -interface kbService { - createKb: () => void; - updateKb: () => void; - rmKb: () => void; - get_kb_detail: () => void; - getList: () => void; - get_document_list: () => void; - document_change_status: () => void; - document_rm: () => void; - document_create: () => void; - document_change_parser: () => void; - chunk_list: () => void; - create_chunk: () => void; - set_chunk: () => void; - get_chunk: () => void; - switch_chunk: () => void; - rm_chunk: () => void; - retrieval_test: () => void; -} -const kbService: kbService = registerServer( - { - // 知识库管理 - createKb: { - url: create_kb, - method: 'post' - }, - updateKb: { - url: update_kb, - method: 'post' - }, - rmKb: { - url: rm_kb, - method: 'post' - }, - get_kb_detail: { - url: get_kb_detail, - method: 'get' - }, - getList: { - url: kb_list, - method: 'get' - }, - // 文件管理 - get_document_list: { - url: get_document_list, - method: 'get' - }, - document_change_status: { - url: document_change_status, - method: 'post' - }, - document_rm: { - url: document_rm, - method: 'post' - }, - document_create: { - url: document_create, - method: 'post' - }, - document_change_parser: { - url: document_change_parser, - method: 'post' - }, - // chunk管理 - chunk_list: { - url: chunk_list, - method: 'post' - }, - create_chunk: { - url: create_chunk, - method: 'post' - }, - set_chunk: { - url: set_chunk, - method: 'post' - }, - get_chunk: { - url: get_chunk, - method: 'get' - }, - switch_chunk: { - url: switch_chunk, - method: 'post' - }, - rm_chunk: { - url: rm_chunk, - method: 'post' - }, - retrieval_test: { - url: retrieval_test, - method: 'post' - }, + retrieval_test, +} = api; + +const methods = { + // 知识库管理 + createKb: { + url: create_kb, + method: 'post', }, - request -); + updateKb: { + url: update_kb, + method: 'post', + }, + rmKb: { + url: rm_kb, + method: 'post', + }, + get_kb_detail: { + url: get_kb_detail, + method: 'get', + }, + getList: { + url: kb_list, + method: 'get', + }, + // 文件管理 + get_document_list: { + url: get_document_list, + method: 'get', + }, + document_change_status: { + url: document_change_status, + method: 'post', + }, + document_rm: { + url: document_rm, + method: 'post', + }, + document_create: { + url: document_create, + method: 'post', + }, + document_change_parser: { + url: document_change_parser, + method: 'post', + }, + // chunk管理 + chunk_list: { + url: chunk_list, + method: 'post', + }, + create_chunk: { + url: create_chunk, + method: 'post', + }, + set_chunk: { + url: set_chunk, + method: 'post', + }, + get_chunk: { + url: get_chunk, + method: 'get', + }, + switch_chunk: { + url: switch_chunk, + method: 'post', + }, + rm_chunk: { + url: rm_chunk, + method: 'post', + }, + retrieval_test: { + url: retrieval_test, + method: 'post', + }, +}; + +const kbService = registerServer(methods, request); export default kbService; diff --git a/web/src/services/userService.ts b/web/src/services/userService.ts index 37a7b3364..6e11f7344 100644 --- a/web/src/services/userService.ts +++ b/web/src/services/userService.ts @@ -3,55 +3,61 @@ import registerServer from '@/utils/registerServer'; import request from '@/utils/request'; const { - login, register, setting, user_info, tenant_info, factories_list, llm_list, my_llm, set_api_key, set_tenant_info } = api; -interface userServiceType { - login: (params: any) => void -} -const userService = registerServer( - { - login: { - url: login, - method: 'post', + login, + register, + setting, + user_info, + tenant_info, + factories_list, + llm_list, + my_llm, + set_api_key, + set_tenant_info, +} = api; - }, - register: { - url: register, - method: 'post' - }, - setting: { - url: setting, - method: 'post' - }, - user_info: { - url: user_info, - method: 'get' - }, - get_tenant_info: { - url: tenant_info, - method: 'get' - }, - set_tenant_info: { - url: set_tenant_info, - method: 'post' - }, - factories_list: { - url: factories_list, - method: 'get' - }, - llm_list: { - url: llm_list, - method: 'get' - }, - my_llm: { - url: my_llm, - method: 'get' - }, - set_api_key: { - url: set_api_key, - method: 'post' - }, +const methods = { + login: { + url: login, + method: 'post', }, - request -); + register: { + url: register, + method: 'post', + }, + setting: { + url: setting, + method: 'post', + }, + user_info: { + url: user_info, + method: 'get', + }, + get_tenant_info: { + url: tenant_info, + method: 'get', + }, + set_tenant_info: { + url: set_tenant_info, + method: 'post', + }, + factories_list: { + url: factories_list, + method: 'get', + }, + llm_list: { + url: llm_list, + method: 'get', + }, + my_llm: { + url: my_llm, + method: 'get', + }, + set_api_key: { + url: set_api_key, + method: 'post', + }, +} as const; + +const userService = registerServer(methods, request); export default userService; diff --git a/web/src/utils/registerServer.ts b/web/src/utils/registerServer.ts index 148ce0814..9404ce0d4 100644 --- a/web/src/utils/registerServer.ts +++ b/web/src/utils/registerServer.ts @@ -1,17 +1,24 @@ -const registerServer = (opt: any, request: any): any => { - let server = {}; +import { RequestMethod } from 'umi-request'; + +type Service = Record any>; + +const registerServer = ( + opt: Record, + request: RequestMethod, +) => { + const server: Service = {} as Service; for (let key in opt) { - server[key] = (params: any) => { + server[key] = (params) => { if (opt[key].method === 'post' || opt[key].method === 'POST') { return request(opt[key].url, { method: opt[key].method, - data: params + data: params, }); } if (opt[key].method === 'get' || opt[key].method === 'GET') { return request.get(opt[key].url, { - params + params, }); } }; diff --git a/web/src/utils/request.ts b/web/src/utils/request.ts index 60fae733b..536c6746e 100644 --- a/web/src/utils/request.ts +++ b/web/src/utils/request.ts @@ -1,5 +1,5 @@ import { message, notification } from 'antd'; -import { extend } from 'umi-request'; +import { RequestMethod, extend } from 'umi-request'; import { Authorization } from '@/constants/authorization'; import api from '@/utils/api'; @@ -9,7 +9,7 @@ const { login } = api; const ABORT_REQUEST_ERR_MESSAGE = 'The user aborted a request.'; // 手动中断请求。errorHandler 抛出的error message -const retcodeMessage = { +const RetcodeMessage = { 200: '服务器成功返回请求的数据。', 201: '新建或修改数据成功。', 202: '一个请求已经进入后台排队(异步任务)。', @@ -26,7 +26,7 @@ const retcodeMessage = { 503: '服务不可用,服务器暂时过载或维护。', 504: '网关超时。', }; -type retcode = +type ResultCode = | 200 | 201 | 202 @@ -45,7 +45,7 @@ type retcode = /** * 异常处理程序 */ -interface responseType { +interface ResponseType { retcode: number; data: any; retmsg: string; @@ -62,7 +62,7 @@ const errorHandler = (error: { } else { if (response && response.status) { const errorText = - retcodeMessage[response.status as retcode] || response.statusText; + RetcodeMessage[response.status as ResultCode] || response.statusText; const { status, url } = response; notification.error({ message: `请求错误 ${status}: ${url}`, @@ -81,7 +81,7 @@ const errorHandler = (error: { /** * 配置request请求时的默认参数 */ -const request = extend({ +const request: RequestMethod = extend({ errorHandler, // 默认错误处理 timeout: 3000000, getResponse: true, @@ -108,7 +108,7 @@ request.interceptors.request.use((url: string, options: any) => { request.interceptors.response.use(async (response: any, request) => { console.log(response, request); - const data: responseType = await response.clone().json(); + const data: ResponseType = await response.clone().json(); // response 拦截 if (data.retcode === 401 || data.retcode === 401) { diff --git a/web/src/utils/stroreUtil.ts b/web/src/utils/stroreUtil.ts new file mode 100644 index 000000000..4437d25fc --- /dev/null +++ b/web/src/utils/stroreUtil.ts @@ -0,0 +1,9 @@ +export const getOneNamespaceEffectsLoading = ( + namespace: string, + effects: Record, + effectNames: Array, +) => { + return effectNames.some( + (effectName) => effects[`${namespace}/${effectName}`], + ); +};