diff --git a/web/src/hooks/storeHooks.ts b/web/src/hooks/storeHooks.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3f69ce766eba7ae403e659396ff1dd2d5effc0e1
--- /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<string>,
+) => {
+  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 8e9e8c37fa37617a689f29495dacbf159e2df2e8..c771ed35674ebfbe397f22defc93fbe60d7abdc6 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<kFProps> = ({ 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<kFProps> = ({
+  getChunkList,
+  doc_id,
+  isShowCreateModal,
+  chunk_id,
+}) => {
+  const dispatch = useDispatch();
+  const [form] = Form.useForm();
 
-    return (
-        <Modal title="Basic Modal" open={isShowCreateModal} onOk={handleOk} onCancel={handleCancel}>
-            <Form
-                form={form}
-                name="validateOnly"
-                labelCol={{ span: 5 }}
-                wrapperCol={{ span: 19 }}
-                style={{ maxWidth: 600 }}
-                autoComplete="off"
-            >
-                <Form.Item<FieldType>
-                    label="chunk 内容"
-                    name="content_ltks"
-                    rules={[{ required: true, message: 'Please input value!' }]}
-                >
-                    <Input.TextArea />
-                </Form.Item>
-                <EditTag tags={important_kwd} setTags={setImportantKwd} />
-            </Form>
-        </Modal >
+  // 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<any>({
+        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 (
+    <Modal
+      title="Basic Modal"
+      open={isShowCreateModal}
+      onOk={handleOk}
+      onCancel={handleCancel}
+    >
+      <Form
+        form={form}
+        name="validateOnly"
+        labelCol={{ span: 5 }}
+        wrapperCol={{ span: 19 }}
+        style={{ maxWidth: 600 }}
+        autoComplete="off"
+      >
+        <Form.Item<FieldType>
+          label="chunk 内容"
+          name="content_ltks"
+          rules={[{ required: true, message: 'Please input value!' }]}
+        >
+          <Input.TextArea />
+        </Form.Item>
+        <EditTag tags={important_kwd} setTags={setImportantKwd} />
+      </Form>
+    </Modal>
+  );
+};
+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 c5a0878d06e2779e252206bbdebd320866a75845..261b408da4ca8f92e08212ba6894035747f02b6d 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<editTagsProps> = ({ tags, setTags }) => {
-    const { token } = theme.useToken();
+const EditTag: React.FC<EditTagsProps> = ({ 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<InputRef>(null);
-    const editInputRef = useRef<InputRef>(null);
+  const [inputVisible, setInputVisible] = useState(false);
+  const [inputValue, setInputValue] = useState('');
+  const [editInputIndex, setEditInputIndex] = useState(-1);
+  const [editInputValue, setEditInputValue] = useState('');
+  const inputRef = useRef<InputRef>(null);
+  const editInputRef = useRef<InputRef>(null);
 
-    useEffect(() => {
-        if (inputVisible) {
-            inputRef.current?.focus();
-        }
-    }, [inputVisible]);
+  useEffect(() => {
+    if (inputVisible) {
+      inputRef.current?.focus();
+    }
+  }, [inputVisible]);
 
-    useEffect(() => {
-        editInputRef.current?.focus();
-    }, [editInputValue]);
+  useEffect(() => {
+    editInputRef.current?.focus();
+  }, [editInputValue]);
 
-    const handleClose = (removedTag: string) => {
-        const newTags = tags.filter((tag) => tag !== removedTag);
-        console.log(newTags);
-        setTags(newTags);
-    };
+  const handleClose = (removedTag: string) => {
+    const newTags = tags.filter((tag) => tag !== removedTag);
+    console.log(newTags);
+    setTags(newTags);
+  };
 
-    const showInput = () => {
-        setInputVisible(true);
-    };
+  const showInput = () => {
+    setInputVisible(true);
+  };
 
-    const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        setInputValue(e.target.value);
-    };
+  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    setInputValue(e.target.value);
+  };
 
-    const handleInputConfirm = () => {
-        if (inputValue && !tags.includes(inputValue)) {
-            setTags([...tags, inputValue]);
-        }
-        setInputVisible(false);
-        setInputValue('');
-    };
+  const handleInputConfirm = () => {
+    if (inputValue && !tags.includes(inputValue)) {
+      setTags([...tags, inputValue]);
+    }
+    setInputVisible(false);
+    setInputValue('');
+  };
 
-    const handleEditInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        setEditInputValue(e.target.value);
-    };
+  const handleEditInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    setEditInputValue(e.target.value);
+  };
 
-    const handleEditInputConfirm = () => {
-        const newTags = [...tags];
-        newTags[editInputIndex] = editInputValue;
-        setTags(newTags);
-        setEditInputIndex(-1);
-        setEditInputValue('');
-    };
+  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 tagInputStyle: React.CSSProperties = {
+    width: 64,
+    height: 22,
+    marginInlineEnd: 8,
+    verticalAlign: 'top',
+  };
 
-    const tagPlusStyle: React.CSSProperties = {
-        height: 22,
-        background: token.colorBgContainer,
-        borderStyle: 'dashed',
-    };
+  const tagPlusStyle: React.CSSProperties = {
+    height: 22,
+    background: token.colorBgContainer,
+    borderStyle: 'dashed',
+  };
 
-    return (
-        <Space size={[0, 8]} wrap>
-            {tags.map((tag, index) => {
-                if (editInputIndex === index) {
-                    return (
-                        <Input
-                            ref={editInputRef}
-                            key={tag}
-                            size="small"
-                            style={tagInputStyle}
-                            value={editInputValue}
-                            onChange={handleEditInputChange}
-                            onBlur={handleEditInputConfirm}
-                            onPressEnter={handleEditInputConfirm}
-                        />
-                    );
+  return (
+    <Space size={[0, 8]} wrap>
+      {tags.map((tag, index) => {
+        if (editInputIndex === index) {
+          return (
+            <Input
+              ref={editInputRef}
+              key={tag}
+              size="small"
+              style={tagInputStyle}
+              value={editInputValue}
+              onChange={handleEditInputChange}
+              onBlur={handleEditInputConfirm}
+              onPressEnter={handleEditInputConfirm}
+            />
+          );
+        }
+        const isLongTag = tag.length > 20;
+        const tagElem = (
+          <Tag
+            key={tag}
+            closable={index !== 0}
+            style={{ userSelect: 'none' }}
+            onClose={() => handleClose(tag)}
+          >
+            <span
+              onDoubleClick={(e) => {
+                if (index !== 0) {
+                  setEditInputIndex(index);
+                  setEditInputValue(tag);
+                  e.preventDefault();
                 }
-                const isLongTag = tag.length > 20;
-                const tagElem = (
-                    <Tag
-                        key={tag}
-                        closable={index !== 0}
-                        style={{ userSelect: 'none' }}
-                        onClose={() => handleClose(tag)}
-                    >
-                        <span
-                            onDoubleClick={(e) => {
-                                if (index !== 0) {
-                                    setEditInputIndex(index);
-                                    setEditInputValue(tag);
-                                    e.preventDefault();
-                                }
-                            }}
-                        >
-                            {isLongTag ? `${tag.slice(0, 20)}...` : tag}
-                        </span>
-                    </Tag>
-                );
-                return isLongTag ? (
-                    <Tooltip title={tag} key={tag}>
-                        {tagElem}
-                    </Tooltip>
-                ) : (
-                    tagElem
-                );
-            })}
-            {inputVisible ? (
-                <Input
-                    ref={inputRef}
-                    type="text"
-                    size="small"
-                    style={tagInputStyle}
-                    value={inputValue}
-                    onChange={handleInputChange}
-                    onBlur={handleInputConfirm}
-                    onPressEnter={handleInputConfirm}
-                />
-            ) : (
-                <Tag style={tagPlusStyle} onClick={showInput}>
-                    添加关键词
-                </Tag>
-            )}
-        </Space>
-    );
+              }}
+            >
+              {isLongTag ? `${tag.slice(0, 20)}...` : tag}
+            </span>
+          </Tag>
+        );
+        return isLongTag ? (
+          <Tooltip title={tag} key={tag}>
+            {tagElem}
+          </Tooltip>
+        ) : (
+          tagElem
+        );
+      })}
+      {inputVisible ? (
+        <Input
+          ref={inputRef}
+          type="text"
+          size="small"
+          style={tagInputStyle}
+          value={inputValue}
+          onChange={handleInputChange}
+          onBlur={handleInputConfirm}
+          onPressEnter={handleInputConfirm}
+        />
+      ) : (
+        <Tag style={tagPlusStyle} onClick={showInput}>
+          添加关键词
+        </Tag>
+      )}
+    </Space>
+  );
 };
 
-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 6f80e7f144a403458629cfbfc7bbbe438c876798..291876fad6bfd5c3cfd17a5272b55379c3c6fee8 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;
+}
+
+interface IProps {
+  doc_id: string;
 }
-const Index: React.FC<chunkProps> = ({ 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 })
+
+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
-      }
+        ...pagination,
+      },
     });
-  }
-  const confirm = (id: string) => {
-    console.log(id)
-    dispatch({
+  };
+  const confirm = async (id: string) => {
+    const retcode = await dispatch<any>({
       type: 'chunkModel/rm_chunk',
       payload: {
-        chunk_ids: [id]
+        chunk_ids: [id],
       },
-      callback: getChunkList
     });
+
+    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<any>({
       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<HTMLInputElement | HTMLTextAreaElement>) => {
-    const value = e.target.value
-    SetKeywords(value)
-    debounceCallback(value)
-  }
-  const handleSelectChange = (value: number) => {
-    setAvailableInt(value)
-  }
-  console.log('loading', loading)
-  return (<>
-    <div className={styles.chunkPage}>
-      <div className={styles.filter}>
-        <div>
-          <Input placeholder="搜索" style={{ width: 220 }} value={keywords} allowClear onChange={handleInputChange} />
-          <Select
-            showSearch
-            placeholder="是否启用"
-            optionFilterProp="children"
-            value={available_int}
-            onChange={handleSelectChange}
-            style={{ width: 220 }}
-            options={[
-              {
-                value: -1,
-                label: '全部',
-              },
-              {
-                value: 1,
-                label: '启用',
-              },
-              {
-                value: 0,
-                label: '未启用',
-              },
-            ]}
-          />
+    getChunkList();
+  }, [doc_id, available_int, pagination]);
+
+  const debounceChange = debounce(getChunkList, 300);
+  const debounceCallback = useCallback(
+    (value: string) => debounceChange(value),
+    [],
+  );
 
+  const handleInputChange = (
+    e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
+  ) => {
+    const value = e.target.value;
+    SetKeywords(value);
+    debounceCallback(value);
+  };
+  const handleSelectChange = (value: number) => {
+    setAvailableInt(value);
+  };
+  return (
+    <>
+      <div className={styles.chunkPage}>
+        <div className={styles.filter}>
+          <div>
+            <Input
+              placeholder="搜索"
+              style={{ width: 220 }}
+              value={keywords}
+              allowClear
+              onChange={handleInputChange}
+            />
+            <Select
+              showSearch
+              placeholder="是否启用"
+              optionFilterProp="children"
+              value={available_int}
+              onChange={handleSelectChange}
+              style={{ width: 220 }}
+              options={[
+                {
+                  value: -1,
+                  label: '全部',
+                },
+                {
+                  value: 1,
+                  label: '启用',
+                },
+                {
+                  value: 0,
+                  label: '未启用',
+                },
+              ]}
+            />
+          </div>
+          <Button
+            onClick={() => {
+              handleEditchunk();
+            }}
+            type="link"
+          >
+            添加分段
+          </Button>
         </div>
-        <Button onClick={() => { handleEditchunk() }} type='link'>添加分段</Button>
-      </div>
-      <div className={styles.pageContent}>
-        <Spin spinning={loading} className={styles.spin} size='large'>
-          <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }} >
-            {
-              data.map((item: any) => {
-                return (<Col className="gutter-row" key={item.chunk_id} xs={24} sm={12} md={12} lg={8}>
-                  <Card className={styles.card}
-                    onClick={() => { handleEditchunk(item.chunk_id) }}
+        <div className={styles.pageContent}>
+          <Spin spinning={loading} className={styles.spin} size="large">
+            <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }}>
+              {data.map((item: any) => {
+                return (
+                  <Col
+                    className="gutter-row"
+                    key={item.chunk_id}
+                    xs={24}
+                    sm={12}
+                    md={12}
+                    lg={8}
                   >
-                    <img style={{ width: '50px' }} src={`${api_host}/document/image/${item.img_id}`} alt="" />
-                    <div className={styles.container}>
-                      <div className={styles.content}>
-                        <span className={styles.context}>
-                          {item.content_ltks}
-                        </span>
-                        <span className={styles.delete}>
-                          <Switch size="small" defaultValue={item.available_int == '1'} onChange={(checked: boolean, e: any) => {
-                            e.stopPropagation();
-                            e.nativeEvent.stopImmediatePropagation(); switchChunk(item.chunk_id, checked)
-                          }} />
-                        </span>
-                      </div>
-                      <div className={styles.footer}>
-                        <span className={styles.text}>
-                          <MinusSquareOutlined />{item.doc_num}文档
-                        </span>
-                        <span className={styles.text}>
-                          <MinusSquareOutlined />{item.chunk_num}个
-                        </span>
-                        <span className={styles.text}>
-                          <MinusSquareOutlined />{item.token_num}千字符
-                        </span>
-                        <span style={{ float: 'right' }}>
-                          <Popconfirm
-                            title="Delete the task"
-                            description="Are you sure to delete this task?"
-                            onConfirm={(e: any) => {
-                              e.stopPropagation();
-                              e.nativeEvent.stopImmediatePropagation()
-                              console.log(confirm)
-                              confirm(item.chunk_id)
-
-                            }}
-                            okText="Yes"
-                            cancelText="No"
-                          >
-                            <DeleteOutlined onClick={(e) => {
-                              e.stopPropagation();
-                              e.nativeEvent.stopImmediatePropagation()
-                            }} />
-                          </Popconfirm>
-
-                        </span>
+                    <Card
+                      className={styles.card}
+                      onClick={() => {
+                        handleEditchunk(item.chunk_id);
+                      }}
+                    >
+                      <img
+                        style={{ width: '50px' }}
+                        src={`${api_host}/document/image/${item.img_id}`}
+                        alt=""
+                      />
+                      <div className={styles.container}>
+                        <div className={styles.content}>
+                          <span className={styles.context}>
+                            {item.content_ltks}
+                          </span>
+                          <span className={styles.delete}>
+                            <Switch
+                              size="small"
+                              defaultValue={item.available_int == '1'}
+                              onChange={(checked: boolean, e: any) => {
+                                e.stopPropagation();
+                                e.nativeEvent.stopImmediatePropagation();
+                                switchChunk(item.chunk_id, checked);
+                              }}
+                            />
+                          </span>
+                        </div>
+                        <div className={styles.footer}>
+                          <span className={styles.text}>
+                            <MinusSquareOutlined />
+                            {item.doc_num}文档
+                          </span>
+                          <span className={styles.text}>
+                            <MinusSquareOutlined />
+                            {item.chunk_num}个
+                          </span>
+                          <span className={styles.text}>
+                            <MinusSquareOutlined />
+                            {item.token_num}千字符
+                          </span>
+                          <span style={{ float: 'right' }}>
+                            <Popconfirm
+                              title="Delete the task"
+                              description="Are you sure to delete this task?"
+                              onConfirm={(e: any) => {
+                                e.stopPropagation();
+                                e.nativeEvent.stopImmediatePropagation();
+                                console.log(confirm);
+                                confirm(item.chunk_id);
+                              }}
+                              okText="Yes"
+                              cancelText="No"
+                            >
+                              <DeleteOutlined
+                                onClick={(e) => {
+                                  e.stopPropagation();
+                                  e.nativeEvent.stopImmediatePropagation();
+                                }}
+                              />
+                            </Popconfirm>
+                          </span>
+                        </div>
                       </div>
-
-                    </div>
-                  </Card>
-                </Col>)
-              })
-            }
-          </Row>
-        </Spin>
-
-      </div>
-      <div className={styles.pageFooter}>
-        <Pagination
-          responsive
-          showLessItems
-          showQuickJumper
-          showSizeChanger
-          onChange={onShowSizeChange}
-          defaultPageSize={30}
-          pageSizeOptions={[30, 60, 90]}
-          defaultCurrent={pagination.page}
-          total={total}
-        />
+                    </Card>
+                  </Col>
+                );
+              })}
+            </Row>
+          </Spin>
+        </div>
+        <div className={styles.pageFooter}>
+          <Pagination
+            responsive
+            showLessItems
+            showQuickJumper
+            showSizeChanger
+            onChange={onShowSizeChange}
+            defaultPageSize={30}
+            pageSizeOptions={[30, 60, 90]}
+            defaultCurrent={pagination.page}
+            total={total}
+          />
+        </div>
       </div>
-
-    </div >
-    <CreateModal doc_id={doc_id} isShowCreateModal={isShowCreateModal} chunk_id={chunk_id} getChunkList={getChunkList} />
-  </>
-  )
+      <CreateModal
+        doc_id={doc_id}
+        isShowCreateModal={isShowCreateModal}
+        chunk_id={chunk_id}
+        getChunkList={getChunkList}
+      />
+    </>
+  );
 };
 
-export default connect(({ chunkModel, loading }) => ({ chunkModel, loading }))(Index);
\ No newline at end of file
+export default Chunk;
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts b/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
index 06ce4412ec6167d004a972681c306a06d7f1ca62..2ebba51716703d9234c9a11be1821c91a886cdae 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
@@ -1,8 +1,7 @@
 import kbService from '@/services/kbService';
-import { Effect, Reducer } from 'umi';
+import { DvaModel } from 'umi';
 
-export interface chunkModelState {
-  loading: boolean;
+export interface ChunkModelState {
   data: any[];
   total: number;
   isShowCreateModal: boolean;
@@ -10,25 +9,10 @@ export interface chunkModelState {
   doc_id: string;
   chunkInfo: any;
 }
-export interface chunkgModelType {
-  namespace: 'chunkModel';
-  state: chunkModelState;
-  effects: {
-    chunk_list: Effect;
-    get_chunk: Effect;
-    create_hunk: Effect;
-    switch_chunk: Effect;
-    rm_chunk: Effect;
-  };
-  reducers: {
-    updateState: Reducer<chunkModelState>;
-  };
-  // subscriptions: { setup: Subscription };
-}
-const Model: chunkgModelType = {
+
+const model: DvaModel<ChunkModelState> = {
   namespace: 'chunkModel',
   state: {
-    loading: false,
     data: [],
     total: 0,
     isShowCreateModal: false,
@@ -36,6 +20,14 @@ const Model: chunkgModelType = {
     doc_id: '',
     chunkInfo: {},
   },
+  reducers: {
+    updateState(state, { payload }) {
+      return {
+        ...state,
+        ...payload,
+      };
+    },
+  },
   // subscriptions: {
   //   setup({ dispatch, history }) {
   //     history.listen(location => {
@@ -44,7 +36,7 @@ const Model: chunkgModelType = {
   //   }
   // },
   effects: {
-    *chunk_list({ payload = {}, callback }, { call, put }) {
+    *chunk_list({ payload = {} }, { call, put }) {
       const { data, response } = yield call(kbService.chunk_list, payload);
 
       const { retcode, data: res, retmsg } = data;
@@ -55,28 +47,23 @@ const Model: chunkgModelType = {
           payload: {
             data: res.chunks,
             total: res.total,
-            loading: false,
           },
         });
-        callback && callback();
       }
     },
-    *switch_chunk({ payload = {}, callback }, { call, put }) {
+    *switch_chunk({ payload = {} }, { call, put }) {
       const { data, response } = yield call(kbService.switch_chunk, payload);
       const { retcode, data: res, retmsg } = data;
-      if (retcode === 0) {
-        callback && callback();
-      }
+      return retcode;
     },
-    *rm_chunk({ payload = {}, callback }, { call, put }) {
+    *rm_chunk({ payload = {} }, { call, put }) {
       console.log('shanchu');
       const { data, response } = yield call(kbService.rm_chunk, payload);
       const { retcode, data: res, retmsg } = data;
-      if (retcode === 0) {
-        callback && callback();
-      }
+
+      return retcode;
     },
-    *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;
       if (retcode === 0) {
@@ -86,28 +73,16 @@ const Model: chunkgModelType = {
             chunkInfo: res,
           },
         });
-        callback && callback(res);
       }
+      return data;
     },
     *create_hunk({ payload = {} }, { call, put }) {
-      yield put({
-        type: 'updateState',
-        payload: {
-          loading: true,
-        },
-      });
       let service = kbService.create_chunk;
       if (payload.chunk_id) {
         service = kbService.set_chunk;
       }
       const { data, response } = yield call(service, payload);
       const { retcode, data: res, retmsg } = data;
-      yield put({
-        type: 'updateState',
-        payload: {
-          loading: false,
-        },
-      });
       if (retcode === 0) {
         yield put({
           type: 'updateState',
@@ -118,13 +93,5 @@ const Model: chunkgModelType = {
       }
     },
   },
-  reducers: {
-    updateState(state, { payload }) {
-      return {
-        ...state,
-        ...payload,
-      };
-    },
-  },
 };
-export default Model;
+export default model;
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx b/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx
index fc9fcf92f7c0ddd1731805ee3b26c2a1d92737bf..b26269d635c9db7baa04be6ec0059c74d403dfc2 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx
@@ -1,79 +1,73 @@
-import React 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 { kFModelState } from './model'
+import { Form, Input, Modal } from 'antd';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useDispatch, useSelector } from 'umi';
 
 type FieldType = {
-    name?: string;
+  name?: string;
 };
 interface kFProps {
-    dispatch: Dispatch;
-    kFModel: kFModelState;
-    getKfList: () => void;
-    kb_id: string
+  getKfList: () => void;
+  kb_id: string;
 }
-const Index: React.FC<kFProps> = ({ kFModel, dispatch, getKfList, kb_id }) => {
-    const { isShowCEFwModal } = kFModel
-    const { t } = useTranslation()
-    const handleCancel = () => {
-        dispatch({
-            type: 'kFModel/updateState',
-            payload: {
-                isShowCEFwModal: false
-            }
-        });
-    };
-    const [form] = Form.useForm()
-    const handleOk = async () => {
-        try {
-            const values = await form.validateFields();
-            dispatch({
-                type: 'kFModel/document_create',
-                payload: {
-                    name: values.name,
-                    kb_id
-                },
-                callback: () => {
-                    dispatch({
-                        type: 'kFModel/updateState',
-                        payload: {
-                            isShowCEFwModal: false
-                        }
-                    });
-                    getKfList && getKfList()
-                }
-            });
 
-        } catch (errorInfo) {
-            console.log('Failed:', errorInfo);
-        }
-    };
+const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => {
+  const dispatch = useDispatch();
+  const kFModel = useSelector((state: any) => state.kFModel);
+  const { isShowCEFwModal } = kFModel;
+  const [form] = Form.useForm();
+  const { t } = useTranslation();
 
-    return (
-        <Modal title="Basic Modal" open={isShowCEFwModal} onOk={handleOk} onCancel={handleCancel}>
-            <Form
-                form={form}
-                name="validateOnly"
-                labelCol={{ span: 8 }}
-                wrapperCol={{ span: 16 }}
-                style={{ maxWidth: 600 }}
-                autoComplete="off"
-            >
-                <Form.Item<FieldType>
-                    label="文件名"
-                    name="name"
-                    rules={[{ required: true, message: 'Please input value!' }]}
-                >
-                    <Input />
-                </Form.Item>
+  const handleCancel = () => {
+    dispatch({
+      type: 'kFModel/updateState',
+      payload: {
+        isShowCEFwModal: false,
+      },
+    });
+  };
+  const handleOk = async () => {
+    try {
+      const values = await form.validateFields();
+      const retcode = await dispatch<any>({
+        type: 'kFModel/document_create',
+        payload: {
+          name: values.name,
+          kb_id,
+        },
+      });
+      if (retcode === 0) {
+        getKfList && getKfList();
+      }
+    } catch (errorInfo) {
+      console.log('Failed:', errorInfo);
+    }
+  };
 
-            </Form>
-        </Modal >
-
-
-    );
-}
-export default connect(({ kFModel, loading }) => ({ kFModel, loading }))(Index);
+  return (
+    <Modal
+      title="Basic Modal"
+      open={isShowCEFwModal}
+      onOk={handleOk}
+      onCancel={handleCancel}
+    >
+      <Form
+        form={form}
+        name="validateOnly"
+        labelCol={{ span: 8 }}
+        wrapperCol={{ span: 16 }}
+        style={{ maxWidth: 600 }}
+        autoComplete="off"
+      >
+        <Form.Item<FieldType>
+          label="文件名"
+          name="name"
+          rules={[{ required: true, message: 'Please input value!' }]}
+        >
+          <Input />
+        </Form.Item>
+      </Form>
+    </Modal>
+  );
+};
+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 866954f92b888c19bfd3cbcd3b8dbf88efc7b7ec..dfda404744cb2fb1307700e5371e796f2b1f2aaa 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<kFProps> = ({ 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<HTMLInputElement | HTMLTextAreaElement>) => {
-        const value = e.target.value
-        setInputValue(value)
-        debounceCallback(e.target.value)
+const KnowledgeFile: React.FC<KFProps> = ({ 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 getKfList = (keywords?: string) => {
+    const payload = {
+      kb_id,
+      keywords,
+    };
+    if (!keywords) {
+      delete payload.keywords;
     }
-    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()
-            }
-        });
+    dispatch({
+      type: 'kFModel/getKfList',
+      payload,
+    });
+  };
 
+  useEffect(() => {
+    if (kb_id) {
+      getKfList();
     }
-    const showCEFModal = () => {
-        dispatch({
-            type: 'kFModel/updateState',
-            payload: {
-                isShowCEFwModal: true
-            }
-        });
-    };
+  }, [kb_id]);
 
-    const showSegmentSetModal = () => {
-        dispatch({
-            type: 'kFModel/updateState',
-            payload: {
-                isShowSegmentSetModal: true
-            }
-        });
-    };
-    const actionItems: MenuProps['items'] = useMemo(() => {
-        return [
-            {
-                key: '1',
-                label: (
-                    <div>
-                        <UploadFile kb_id={kb_id} getKfList={getKfList} />
-                    </div>
+  const debounceChange = debounce(getKfList, 300);
+  const debounceCallback = useCallback(
+    (value: string) => debounceChange(value),
+    [],
+  );
+  const handleInputChange = (
+    e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
+  ) => {
+    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,
+      },
+    });
+  };
 
-                ),
-            },
-            {
-                key: '2',
-                label: (
-                    <div>
-                        <Button type="link" onClick={showCEFModal}> 导入虚拟文件</Button>
-                    </div>
-                ),
-                // disabled: true,
-            },
-        ]
-    }, [kb_id]);
-    const chunkItems: MenuProps['items'] = [
-        {
-            key: '1',
-            label: (
-                <div>
-
-                    <Button type="link" onClick={showSegmentSetModal}> 分段设置</Button>
-                </div>
-
-            ),
-        },
-        {
-            key: '2',
-            label: (
-                <div>
-                    <Button type="link" onClick={onRmDocument}> 删除</Button>
-                </div>
-            ),
-            // disabled: true,
-        },
-    ]
-    const toChunk = (id: string) => {
-        console.log(id)
-        navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}&doc_id=${id}`);
-    }
-    const columns: ColumnsType<DataType> = [
-        {
-            title: '名称',
-            dataIndex: 'name',
-            key: 'name',
-            render: (text: any, { id }) => <div className={styles.tochunks} onClick={() => toChunk(id)}><img className={styles.img} src='https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg' alt="" />{text}</div>,
-            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 }) => (
-                <>
-                    <Switch defaultChecked={status === '1'} onChange={(e) => {
-                        onChangeStatus(e, id)
-                    }} />
-                </>
-            ),
-        },
-        {
-            title: 'Action',
-            key: 'action',
-            className: `${styles.column}`,
-            render: (_, record) => (
-                <Space size="middle">
-                    <Dropdown menu={{ items: chunkItems }} trigger={['click']}>
-                        <a onClick={() => {
-                            setDocId(record.id)
-                            setParserId(record.parser_id)
-                        }}>
-                            分段设置 <DownOutlined />
-                        </a>
-                    </Dropdown>
-                </Space>
-            ),
-        },
+  const showSegmentSetModal = () => {
+    dispatch({
+      type: 'kFModel/updateState',
+      payload: {
+        isShowSegmentSetModal: true,
+      },
+    });
+  };
+  const actionItems: MenuProps['items'] = useMemo(() => {
+    return [
+      {
+        key: '1',
+        label: (
+          <div>
+            <UploadFile kb_id={kb_id} getKfList={getKfList} />
+          </div>
+        ),
+      },
+      {
+        key: '2',
+        label: (
+          <div>
+            <Button type="link" onClick={showCEFModal}>
+              {' '}
+              导入虚拟文件
+            </Button>
+          </div>
+        ),
+        // disabled: true,
+      },
     ];
-    return <>
-        <div className={styles.filter}>
-            <div className="search">
-                <Input placeholder="搜索" value={inputValue} style={{ width: 220 }} allowClear onChange={handleInputChange} />
-            </div>
-            <div className="operate">
-                <Dropdown menu={{ items: actionItems }} trigger={['click']} >
-                    <a>
-                        导入文件 <DownOutlined />
-                    </a>
-                </Dropdown>
-
-            </div>
+  }, [kb_id]);
+  const chunkItems: MenuProps['items'] = [
+    {
+      key: '1',
+      label: (
+        <div>
+          <Button type="link" onClick={showSegmentSetModal}>
+            {' '}
+            分段设置
+          </Button>
+        </div>
+      ),
+    },
+    {
+      key: '2',
+      label: (
+        <div>
+          <Button type="link" onClick={onRmDocument}>
+            {' '}
+            删除
+          </Button>
+        </div>
+      ),
+      // disabled: true,
+    },
+  ];
+  const toChunk = (id: string) => {
+    console.log(id);
+    navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}&doc_id=${id}`);
+  };
+  const columns: ColumnsType<DataType> = [
+    {
+      title: '名称',
+      dataIndex: 'name',
+      key: 'name',
+      render: (text: any, { id }) => (
+        <div className={styles.tochunks} onClick={() => toChunk(id)}>
+          <img
+            className={styles.img}
+            src="https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg"
+            alt=""
+          />
+          {text}
+        </div>
+      ),
+      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 }) => (
+        <>
+          <Switch
+            defaultChecked={status === '1'}
+            onChange={(e) => {
+              onChangeStatus(e, id);
+            }}
+          />
+        </>
+      ),
+    },
+    {
+      title: 'Action',
+      key: 'action',
+      className: `${styles.column}`,
+      render: (_, record) => (
+        <Space size="middle">
+          <Dropdown menu={{ items: chunkItems }} trigger={['click']}>
+            <a
+              onClick={() => {
+                setDocId(record.id);
+                setParserId(record.parser_id);
+              }}
+            >
+              分段设置 <DownOutlined />
+            </a>
+          </Dropdown>
+        </Space>
+      ),
+    },
+  ];
+  return (
+    <>
+      <div className={styles.filter}>
+        <div className="search">
+          <Input
+            placeholder="搜索"
+            value={inputValue}
+            style={{ width: 220 }}
+            allowClear
+            onChange={handleInputChange}
+          />
+        </div>
+        <div className="operate">
+          <Dropdown menu={{ items: actionItems }} trigger={['click']}>
+            <a>
+              导入文件 <DownOutlined />
+            </a>
+          </Dropdown>
         </div>
-        <Table rowKey='id' columns={columns} dataSource={data} loading={loading} pagination={false} scroll={{ scrollToFirstRowOnChange: true, x: true }} />
-        <CreateEPModal getKfList={getKfList} kb_id={kb_id} />
-        <SegmentSetModal getKfList={getKfList} parser_id={parser_id} doc_id={doc_id} />
+      </div>
+      <Table
+        rowKey="id"
+        columns={columns}
+        dataSource={data}
+        loading={loading}
+        pagination={false}
+        scroll={{ scrollToFirstRowOnChange: true, x: true }}
+      />
+      <CreateEPModal getKfList={getKfList} kb_id={kb_id} />
+      <SegmentSetModal
+        getKfList={getKfList}
+        parser_id={parser_id}
+        doc_id={doc_id}
+      />
     </>
+  );
 };
 
-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 3923e651c0a8285d8e642d07976641c6fbc48551..d193b1a6215496696c70989ba24e68de93f3c764 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<kFModelState>;
-  };
-  subscriptions: { setup: Subscription };
-}
-const Model: kFModelType = {
+
+const model: DvaModel<KFModelState> = {
   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 ae3881fbbe66031fef1ffabc37a18c4321f9d6a3..5da38b85b6a3ad5a1a7be2d26de48da23243c6f1 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<kFProps> = ({ 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<kFProps> = ({
+  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 (
-        <Modal title="Basic Modal" open={isShowSegmentSetModal} onOk={handleOk} onCancel={handleCancel}>
-            <Space size={[0, 8]} wrap>
-                <div className={styles.tags}>
-                    {
-                        parser_ids.split(',').map((tag: string) => {
-                            return (<CheckableTag
-                                key={tag}
-                                checked={selectedTag === tag}
-                                onChange={(checked) => handleChange(tag, checked)}
-                            >
-                                {tag}
-                            </CheckableTag>)
-                        })
-                    }
-                </div>
-            </Space>
-        </Modal >
+  const handleCancel = () => {
+    dispatch({
+      type: 'kFModel/updateState',
+      payload: {
+        isShowSegmentSetModal: false,
+      },
+    });
+  };
 
+  const handleOk = async () => {
+    console.log(1111, selectedTag);
+    const retcode = await dispatch<any>({
+      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 (
+    <Modal
+      title="Basic Modal"
+      open={isShowSegmentSetModal}
+      onOk={handleOk}
+      onCancel={handleCancel}
+    >
+      <Space size={[0, 8]} wrap>
+        <div className={styles.tags}>
+          {parser_ids.split(',').map((tag: string) => {
+            return (
+              <CheckableTag
+                key={tag}
+                checked={selectedTag === tag}
+                onChange={(checked) => handleChange(tag, checked)}
+              >
+                {tag}
+              </CheckableTag>
+            );
+          })}
+        </div>
+      </Space>
+    </Modal>
+  );
+};
+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 60ae46e2b6d30abb94a2ea43c1950d371bc7077f..656c8d7360443f1e9dfd8e0b204ae1f0c03d3c96 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<UploadProps["customRequest"]>
+  NonNullable<UploadProps['customRequest']>
 >[0];
-const Index: React.FC<PropsType> = ({ 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 (<Upload {...uploadProps} >
-        <Button type="link">导入文件</Button>
-    </Upload>)
-}
+const FileUpload: React.FC<PropsType> = ({ 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 (
+    <Upload {...uploadProps}>
+      <Button type="link">导入文件</Button>
+    </Upload>
+  );
+};
 
-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 a50fb0c3432780e60fe4b7516a99f487f5c10e8f..0635facb95461fa72929db9323fe97234659d04c 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<chunkProps> = ({ 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<chunkProps> = ({ 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<HTMLInputElement | HTMLTextAreaElement>) => {
-    const value = e.target.value
-    debounceCallback(value)
-  }
-  const handleSelectChange = (value:
-    any[]) => {
+  }, 300);
+
+  const debounceCallback = useCallback(
+    (value: string) => debounceChange(value),
+    [],
+  );
+  const handleInputChange = (
+    e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
+  ) => {
+    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 (<>
-    <div className={styles.chunkPage}>
-      <div className={styles.filter}>
-        <Select
-          showSearch
-          placeholder="文件列表"
-          optionFilterProp="children"
-          onChange={handleSelectChange}
-          style={{ width: 300, marginBottom: 20 }}
-          options={d_list}
-          fieldNames={{ label: 'name', value: 'id' }}
-          mode='multiple'
-        />
+  };
 
-        <Input.TextArea autoSize={{ minRows: 6, maxRows: 6 }} placeholder="搜索" style={{ width: 300 }} allowClear onChange={handleInputChange} />
+  return (
+    <>
+      <div className={styles.chunkPage}>
+        <div className={styles.filter}>
+          <Select
+            showSearch
+            placeholder="文件列表"
+            optionFilterProp="children"
+            onChange={handleSelectChange}
+            style={{ width: 300, marginBottom: 20 }}
+            options={d_list}
+            fieldNames={{ label: 'name', value: 'id' }}
+            mode="multiple"
+          />
 
-      </div>
-      <div className={styles.pageContainer}>
-        <div className={styles.pageContent}>
-          <Spin spinning={loading} className={styles.spin} size='large'>
-            <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }} >
-              {
-                data.map((item: any) => {
-                  return (<Col className="gutter-row" key={item.chunk_id} xs={24} sm={12} md={12} lg={8}>
-                    <Card className={styles.card}
-                      onClick={() => { handleEditchunk(item) }}
+          <Input.TextArea
+            autoSize={{ minRows: 6, maxRows: 6 }}
+            placeholder="搜索"
+            style={{ width: 300 }}
+            allowClear
+            onChange={handleInputChange}
+          />
+        </div>
+        <div className={styles.pageContainer}>
+          <div className={styles.pageContent}>
+            <Spin spinning={loading} className={styles.spin} size="large">
+              <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }}>
+                {data.map((item: any) => {
+                  return (
+                    <Col
+                      className="gutter-row"
+                      key={item.chunk_id}
+                      xs={24}
+                      sm={12}
+                      md={12}
+                      lg={8}
                     >
-                      <img style={{ width: '50px' }} src={`${api_host}/document/image/${item.img_id}`} alt="" />
-                      <div className={styles.container}>
-                        <div className={styles.content}>
-                          <span className={styles.context}>
-                            {item.content_ltks}
-                          </span>
-                          <span className={styles.delete}>
-                            <Switch size="small" defaultValue={item.doc_ids == '1'} onChange={(checked: boolean, e: any) => {
-                              e.stopPropagation();
-                              e.nativeEvent.stopImmediatePropagation(); switchChunk(item, checked)
-                            }} />
-                          </span>
+                      <Card
+                        className={styles.card}
+                        onClick={() => {
+                          handleEditchunk(item);
+                        }}
+                      >
+                        <img
+                          style={{ width: '50px' }}
+                          src={`${api_host}/document/image/${item.img_id}`}
+                          alt=""
+                        />
+                        <div className={styles.container}>
+                          <div className={styles.content}>
+                            <span className={styles.context}>
+                              {item.content_ltks}
+                            </span>
+                            <span className={styles.delete}>
+                              <Switch
+                                size="small"
+                                defaultValue={item.doc_ids == '1'}
+                                onChange={(checked: boolean, e: any) => {
+                                  e.stopPropagation();
+                                  e.nativeEvent.stopImmediatePropagation();
+                                  switchChunk(item, checked);
+                                }}
+                              />
+                            </span>
+                          </div>
+                          <div className={styles.footer}>
+                            <span className={styles.text}>
+                              <MinusSquareOutlined />
+                              {item.doc_num}文档
+                            </span>
+                            <span className={styles.text}>
+                              <MinusSquareOutlined />
+                              {item.chunk_num}个
+                            </span>
+                            <span className={styles.text}>
+                              <MinusSquareOutlined />
+                              {item.token_num}千字符
+                            </span>
+                            <span style={{ float: 'right' }}>
+                              <Popconfirm
+                                title="Delete the task"
+                                description="Are you sure to delete this task?"
+                                onConfirm={(e: any) => {
+                                  e.stopPropagation();
+                                  e.nativeEvent.stopImmediatePropagation();
+                                  console.log(confirm);
+                                  confirm(item.chunk_id);
+                                }}
+                                okText="Yes"
+                                cancelText="No"
+                              >
+                                <DeleteOutlined
+                                  onClick={(e) => {
+                                    e.stopPropagation();
+                                    e.nativeEvent.stopImmediatePropagation();
+                                  }}
+                                />
+                              </Popconfirm>
+                            </span>
+                          </div>
                         </div>
-                        <div className={styles.footer}>
-                          <span className={styles.text}>
-                            <MinusSquareOutlined />{item.doc_num}文档
-                          </span>
-                          <span className={styles.text}>
-                            <MinusSquareOutlined />{item.chunk_num}个
-                          </span>
-                          <span className={styles.text}>
-                            <MinusSquareOutlined />{item.token_num}千字符
-                          </span>
-                          <span style={{ float: 'right' }}>
-                            <Popconfirm
-                              title="Delete the task"
-                              description="Are you sure to delete this task?"
-                              onConfirm={(e: any) => {
-                                e.stopPropagation();
-                                e.nativeEvent.stopImmediatePropagation()
-                                console.log(confirm)
-                                confirm(item.chunk_id)
-
-                              }}
-                              okText="Yes"
-                              cancelText="No"
-                            >
-                              <DeleteOutlined onClick={(e) => {
-                                e.stopPropagation();
-                                e.nativeEvent.stopImmediatePropagation()
-                              }} />
-                            </Popconfirm>
-
-                          </span>
-                        </div>
-
-                      </div>
-                    </Card>
-                  </Col>)
-                })
-              }
-            </Row>
-          </Spin>
-
-        </div>
-        <div className={styles.pageFooter}>
-          <Pagination
-            responsive
-            showLessItems
-            showQuickJumper
-            showSizeChanger
-            onChange={onShowSizeChange}
-            defaultPageSize={30}
-            pageSizeOptions={[30, 60, 90]}
-            defaultCurrent={pagination.page}
-            total={total}
-          />
+                      </Card>
+                    </Col>
+                  );
+                })}
+              </Row>
+            </Spin>
+          </div>
+          <div className={styles.pageFooter}>
+            <Pagination
+              responsive
+              showLessItems
+              showQuickJumper
+              showSizeChanger
+              onChange={onShowSizeChange}
+              defaultPageSize={30}
+              pageSizeOptions={[30, 60, 90]}
+              defaultCurrent={pagination.page}
+              total={total}
+            />
+          </div>
         </div>
       </div>
-
-    </div >
-    <CreateModal getChunkList={getChunkList} isShowCreateModal={isShowCreateModal} chunk_id={chunk_id} doc_id={doc_id} />
-  </>
-  )
+      <CreateModal
+        getChunkList={getChunkList}
+        isShowCreateModal={isShowCreateModal}
+        chunk_id={chunk_id}
+        doc_id={doc_id}
+      />
+    </>
+  );
 };
 
-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 247495e5bb4e3fa1cfd273c65c466d6febde3dc2..da9a4acae82bd68467f2d1118df795a6a8a0c927 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
-
-}
-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<kSearchModelState>;
-  };
-  subscriptions: { setup: Subscription };
+  doc_id: string;
 }
-const Model: chunkgModelType = {
+
+const model: DvaModel<KSearchModelState> = {
   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 67286f441f413c83d187f85cdd19de5af3b3fcef..e7b5659c9ebceaa03d84729930aaaf1c398eb8f1 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<kSProps> = ({ 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<kSProps> = ({ 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(() => {
-        dispatch({
-            type: 'settingModel/getTenantInfo',
-            payload: {
-            }
-        });
-        if (kb_id) {
-
-            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)
-                }
-            });
-        }
-
-    }, [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 getTenantInfo = useCallback(async () => {
+    dispatch({
+      type: 'settingModel/getTenantInfo',
+      payload: {},
+    });
+    if (kb_id) {
+      const data = await dispatch<any>({
+        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: 'kSModel/updateKb',
+          payload: {
+            ...values,
+            parser_id: selectedTag,
+            kb_id,
+            embd_id: undefined,
+          },
+        });
+      } else {
+        const retcode = await dispatch<any>({
+          type: 'kSModel/createKb',
+          payload: {
+            ...values,
+            parser_id: selectedTag,
+          },
+        });
+        retcode === 0 &&
+          navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}`);
+      }
+    } catch (error) {
+      console.warn(error);
+    }
+  };
 
-    };
+  useEffect(() => {
+    getTenantInfo();
+  }, [getTenantInfo]);
 
-    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 <Form
-        {...layout}
-        form={form}
-        name="validateOnly"
-        style={{ maxWidth: 1000, padding: 14 }}
+  return (
+    <Form
+      {...layout}
+      form={form}
+      name="validateOnly"
+      style={{ maxWidth: 1000, padding: 14 }}
     >
-        <Form.Item name='name' label="知识库名称" rules={[{ required: true }]}>
-            <Input />
-        </Form.Item>
-        <Form.Item name='description' label="知识库描述">
-            <Input.TextArea />
-        </Form.Item>
-        <Form.Item name="permission" label="可见权限">
-            <Radio.Group>
-                <Radio value="me">只有我</Radio>
-                <Radio value="team">所有团队成员</Radio>
-            </Radio.Group>
-        </Form.Item>
-        <Form.Item
-            name="embd_id"
-            label="Embedding 模型"
-            hasFeedback
-            rules={[{ required: true, message: 'Please select your country!' }]}
-        >
-            <Select placeholder="Please select a country" >
-                {embd_id.split(',').map((item: string) => {
-                    return <Option value={item} key={item}>{item}</Option>
-                })}
-
-            </Select>
-        </Form.Item>
-        <div style={{ marginTop: '5px' }}>
-            修改Embedding 模型,请去<span style={{ color: '#1677ff' }}>设置</span>
-        </div>
-        <Space size={[0, 8]} wrap>
-            <div className={styles.tags}>
-                {
-                    parser_ids.split(',').map((tag: string) => {
-                        return (<CheckableTag
-                            key={tag}
-                            checked={selectedTag === tag}
-                            onChange={(checked) => handleChange(tag, checked)}
-                        >
-                            {tag}
-                        </CheckableTag>)
-                    })
-                }
-            </div>
-        </Space>
-        <Space size={[0, 8]} wrap>
-
-        </Space>
-        <div className={styles.preset}>
-            <div className={styles.left}>
-                xxxxx文章
-            </div>
-            <div className={styles.right}>
-                预估份数
-            </div>
+      <Form.Item name="name" label="知识库名称" rules={[{ required: true }]}>
+        <Input />
+      </Form.Item>
+      <Form.Item name="description" label="知识库描述">
+        <Input.TextArea />
+      </Form.Item>
+      <Form.Item name="permission" label="可见权限">
+        <Radio.Group>
+          <Radio value="me">只有我</Radio>
+          <Radio value="team">所有团队成员</Radio>
+        </Radio.Group>
+      </Form.Item>
+      <Form.Item
+        name="embd_id"
+        label="Embedding 模型"
+        hasFeedback
+        rules={[{ required: true, message: 'Please select your country!' }]}
+      >
+        <Select placeholder="Please select a country">
+          {embd_id.split(',').map((item: string) => {
+            return (
+              <Option value={item} key={item}>
+                {item}
+              </Option>
+            );
+          })}
+        </Select>
+      </Form.Item>
+      <div style={{ marginTop: '5px' }}>
+        修改Embedding 模型,请去<span style={{ color: '#1677ff' }}>设置</span>
+      </div>
+      <Space size={[0, 8]} wrap>
+        <div className={styles.tags}>
+          {parser_ids.split(',').map((tag: string) => {
+            return (
+              <CheckableTag
+                key={tag}
+                checked={selectedTag === tag}
+                onChange={(checked) => handleChange(tag, checked)}
+              >
+                {tag}
+              </CheckableTag>
+            );
+          })}
         </div>
-        <Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}>
-            <Button type="primary" onClick={onFinish}>
-                保存并处理
-            </Button>
-            <Button htmlType="button" style={{ marginLeft: '20px' }}>
-                取消
-            </Button>
-        </Form.Item>
+      </Space>
+      <Space size={[0, 8]} wrap></Space>
+      <div className={styles.preset}>
+        <div className={styles.left}>xxxxx文章</div>
+        <div className={styles.right}>预估份数</div>
+      </div>
+      <Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}>
+        <Button type="primary" onClick={onFinish}>
+          保存并处理
+        </Button>
+        <Button htmlType="button" style={{ marginLeft: '20px' }}>
+          取消
+        </Button>
+      </Form.Item>
     </Form>
-}
-
-
+  );
+};
 
-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 42e33a5b3e2c047e392f6765e6a224b2e3ffaa61..188477130671222a4fc235dc80b9f2f4fa42fc50 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
-}
-export interface kSModelType {
-  namespace: 'kSModel';
-  state: kSModelState;
-  effects: {
-    createKb: Effect;
-    updateKb: Effect;
-    getKbDetail: Effect;
-  };
-  reducers: {
-    updateState: Reducer<kSModelState>;
-  };
-  subscriptions: { setup: Subscription };
+  tenantIfo: any;
 }
-const Model: kSModelType = {
+
+const model: DvaModel<KSModelState> = {
   namespace: 'kSModel',
   state: {
     isShowPSwModal: false,
     isShowTntModal: false,
-    loading: false,
-    tenantIfo: {}
+    tenantIfo: {},
+  },
+  reducers: {
+    updateState(state, { payload }) {
+      return {
+        ...state,
+        ...payload,
+      };
+    },
   },
   subscriptions: {
     setup({ dispatch, history }) {
-      history.listen(location => {
-      });
-    }
+      history.listen((location) => {});
+    },
   },
   effects: {
-    * createKb({ payload = {}, callback }, { call, put }) {
-      const { data, response } = yield call(kbService.createKb, payload);
-      const { retcode, data: res, retmsg } = data
+    *createKb({ payload = {} }, { call, put }) {
+      const { data } = yield call(kbService.createKb, payload);
+      const { retcode } = data;
       if (retcode === 0) {
         message.success('创建知识库成功!');
-        callback && callback(res.kb_id)
       }
+      return retcode;
     },
-    * updateKb({ payload = {}, callback }, { call, put }) {
-      const { data, response } = yield call(kbService.updateKb, payload);
-      const { retcode, data: res, retmsg } = data
+    *updateKb({ payload = {} }, { call, put }) {
+      const { data } = 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)
-      }
+    *getKbDetail({ payload = {} }, { call, put }) {
+      const { data } = yield call(kbService.get_kb_detail, payload);
+
+      return data;
     },
   },
-  reducers: {
-    updateState(state, { payload }) {
-      return {
-        ...state,
-        ...payload
-      };
-    }
-  }
 };
-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 073a0c836043a0746ac54217487e68b6746d63ae..d2386a771c6aaebc07abbab21d24b4f57b34c4d1 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<kAProps> = ({ 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);
 
-            }
-        });
-    }, [location])
-    useEffect(() => {
-        if (windowWidth.width > 957) {
-            setCollapsed(false)
-        } else {
-            setCollapsed(true)
-        }
-    }, [windowWidth.width])
-    type MenuItem = Required<MenuProps>['items'][number];
+      setWindowWidth(width);
+    };
+    window.addEventListener('resize', widthSize);
+    return () => {
+      window.removeEventListener('resize', widthSize);
+    };
+  }, []);
+  useEffect(() => {
+    const search: string = location.search.slice(1);
+    const map = search.split('&').reduce<Record<string, string>>((obj, cur) => {
+      const [key, value] = cur.split('=');
+      obj[key] = value;
+      return obj;
+    }, {});
 
-    function getItem(
-        label: React.ReactNode,
-        key: React.Key,
-        icon?: React.ReactNode,
-        disabled?: boolean,
-        children?: MenuItem[],
-        type?: 'group',
+    dispatch({
+      type: 'kAModel/updateState',
+      payload: {
+        doc_id: undefined,
+        ...map,
+      },
+    });
+  }, [location]);
 
-    ): MenuItem {
-        return {
-            key,
-            icon,
-            children,
-            label,
-            type,
-            disabled
-        } as MenuItem;
-    }
-    const items: MenuItem[] = useMemo(() => {
-        const disabled = !id
-        return [
-            getItem('é…Ťç˝®', 'setting', <ToolOutlined />),
-            getItem('知识库', 'file', <BarsOutlined />, disabled),
-            getItem('搜索测试', 'search', <SearchOutlined />, disabled),
-        ]
-    }, [id]);
-    const handleSelect: MenuProps['onSelect'] = (e) => {
-        navigate(`/knowledge/add/setting?activeKey=${e.key}&id=${id}`);
+  useEffect(() => {
+    if (windowWidth.width > 957) {
+      setCollapsed(false);
+    } else {
+      setCollapsed(true);
     }
-    return (
-        <>
-            <div className={styles.container}>
-                <div className={styles.menu}>
-                    <Menu
-                        selectedKeys={[activeKey]}
-                        mode="inline"
-                        className={windowWidth.width > 957 ? styles.defaultWidth : styles.minWidth}
-                        inlineCollapsed={collapsed}
-                        items={items}
-                        onSelect={handleSelect}
-                    />
-                </div>
-                <div className={styles.content}>
-                    {activeKey === 'file' && !doc_id && <File kb_id={id} />}
-                    {activeKey === 'setting' && <Setting kb_id={id} />}
-                    {activeKey === 'search' && <Search kb_id={id} />}
-                    {activeKey === 'file' && !!doc_id && <Chunk doc_id={doc_id} />}
+  }, [windowWidth.width]);
+
+  type MenuItem = Required<MenuProps>['items'][number];
 
-                </div>
-            </div>
-        </>
-    );
+  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', <ToolOutlined />),
+      getItem('知识库', 'file', <BarsOutlined />, disabled),
+      getItem('搜索测试', 'search', <SearchOutlined />, disabled),
+    ];
+  }, [id]);
+
+  const handleSelect: MenuProps['onSelect'] = (e) => {
+    navigate(`/knowledge/add/setting?activeKey=${e.key}&id=${id}`);
+  };
+
+  return (
+    <>
+      <div className={styles.container}>
+        <div className={styles.menu}>
+          <Menu
+            selectedKeys={[activeKey]}
+            mode="inline"
+            className={
+              windowWidth.width > 957 ? styles.defaultWidth : styles.minWidth
+            }
+            inlineCollapsed={collapsed}
+            items={items}
+            onSelect={handleSelect}
+          />
+        </div>
+        <div className={styles.content}>
+          {activeKey === 'file' && !doc_id && <File kb_id={id} />}
+          {activeKey === 'setting' && <Setting kb_id={id} />}
+          {activeKey === 'search' && <Search kb_id={id} />}
+          {activeKey === 'file' && !!doc_id && <Chunk doc_id={doc_id} />}
+        </div>
+      </div>
+    </>
+  );
 };
 
-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 6f1871bcf0e55ef2c5ce65022c3cab6ea4145014..32a75ef4da0741e20937dd3da1edb974cba0bc20 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<kAModelState>;
-  };
-  subscriptions: { setup: Subscription };
-}
-const Model: kAModelType = {
+const model: DvaModel<kAModelState> = {
   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 64445f6b493cfa0625f402149adf7b04dac1b3c6..f791322875d6e185c89e8f1f9e72eb599305b47e 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<chatProps> = ({ chatModel, dispatch }) => {
-    const { name } = chatModel;
-    return <div>chat:{name} </div>;
+const Chat = () => {
+  const { name } = useSelector((state: any) => state.chatModel);
+  return <div>chat:{name} </div>;
 };
 
-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 103c978c9e0cd89d2a0ae5916c27e0986c686a48..6efdc52e38ff79d3821499e95277f5f0c0cf6c13 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<chatModelState>;
-    };
-    subscriptions: { setup: Subscription };
-}
-
-const Model: chatModelType = {
-    namespace: 'chatModel',
-    state: {
-        name: 'kate',
-    },
-
-    effects: {
-        *query({ payload }, { call, put }) { },
-    },
-    reducers: {
-        save(state, action) {
-            return {
-                ...state,
-                ...action.payload,
-            };
-        },
+const model: DvaModel<ChatModelState> = {
+  namespace: 'chatModel',
+  state: {
+    name: 'kate',
+  },
+  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 a9310e3d9a84afe8e80349e69f26d1ac55ac3951..be7eada21b32db334e3b5710f282cad5506bf9d7 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';
-
-
-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 (
+import React, { useEffect, useState } from 'react';
 
-        <>
-            <Upload
-                action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
-                listType="picture"
-                fileList={[...fileList]}
-                multiple
-            >
-                <Button icon={<UploadOutlined />}>Upload</Button>
-            </Upload>
-        </>
-    )
+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 (
+    <>
+      <Upload
+        action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
+        listType="picture"
+        fileList={[...fileList]}
+        multiple
+      >
+        <Button icon={<UploadOutlined />}>Upload</Button>
+      </Upload>
+    </>
+  );
 };
 
-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 cdf138b30bb9eebbe4529bb6299048201f549b20..8af444f9c086ae1a1976e2e5277faea20fd4a63e 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<KnowledgeProps> = ({ knowledgeModel, dispatch }) => {
+
+const Knowledge = () => {
+  const dispatch = useDispatch();
+  const knowledgeModel = useSelector((state: any) => state.knowledgeModel);
   const navigate = useNavigate();
-  // const [datas, setDatas] = useState(data)
   const { data = [] } = knowledgeModel;
-  console.log(knowledgeModel);
 
-  // const x = useSelector((state) => state.knowledgeModel);
+  const fetchList = useCallback(() => {
+    dispatch({
+      type: 'knowledgeModel/getList',
+      payload: {},
+    });
+  }, []);
 
   const confirm = (id: string) => {
     dispatch({
@@ -27,12 +28,6 @@ const Index: React.FC<KnowledgeProps> = ({ knowledgeModel, dispatch }) => {
       payload: {
         kb_id: id,
       },
-      callback: () => {
-        dispatch({
-          type: 'knowledgeModel/getList',
-          payload: {},
-        });
-      },
     });
   };
   const handleAddKnowledge = () => {
@@ -42,11 +37,8 @@ const Index: React.FC<KnowledgeProps> = ({ knowledgeModel, dispatch }) => {
     navigate(`add/setting?activeKey=file&id=${id}`);
   };
   useEffect(() => {
-    dispatch({
-      type: 'knowledgeModel/getList',
-      payload: {},
-    });
-  }, []);
+    fetchList();
+  }, [fetchList]);
   return (
     <>
       <div className={styles.knowledge}>
@@ -125,7 +117,4 @@ const Index: React.FC<KnowledgeProps> = ({ 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 83e30008196e5fa4fbb1d66996ce7e5371efe396..0621f763a38804df30158b558fb45cdb06b66bed 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<knowledgeModelState>;
-  };
-  // subscriptions: { setup: Subscription };
-}
-const Model: knowledgegModelType = {
+
+const model: DvaModel<KnowledgeModelState> = {
   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 29edc3968549bd7b949edec7b07e12f254aab2c4..a0696b361b38cd893873ee801a409ad327121283 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<LoginProps> = ({ dispatch }) => {
-  let navigate = useNavigate();
+const Login = () => {
   const [title, setTitle] = useState('login');
+  let navigate = useNavigate();
+  const dispatch = useDispatch();
+  const effectsLoading: any = useSelector<any>( // 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<LoginProps> = ({ dispatch }) => {
 
       var rsaPassWord = rsaPsw(params.password);
       if (title === 'login') {
-        const ret = await dispatch({
+        const retcode = await dispatch<any>({
           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<any>({
           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<LoginProps> = ({ dispatch }) => {
               label="Password"
               rules={[{ required: true, message: 'Please input value' }]}
             >
-              <Input size="large" placeholder="Please input value" />
+              <Input.Password size="large" placeholder="Please input value" />
             </Form.Item>
             {title === 'login' && (
               <Form.Item name="remember" valuePropName="checked">
@@ -132,7 +139,13 @@ const View: FC<LoginProps> = ({ dispatch }) => {
                 </div>
               )}
             </div>
-            <Button type="primary" block size="large" onClick={onCheck}>
+            <Button
+              type="primary"
+              block
+              size="large"
+              onClick={onCheck}
+              loading={signLoading}
+            >
               {title === 'login' ? 'Sign in' : 'Continue'}
             </Button>
             {title === 'login' && (
@@ -175,6 +188,4 @@ const View: FC<LoginProps> = ({ 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 0ce6150c8fd2286dd9b7e367c83c7cdb7b326e01..257879f6dea386b7ecc921bc9bb62e2c8845b5d5 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<loginModelState>;
-  };
-  subscriptions: { setup: Subscription };
-}
-const Model: logingModelType = {
+
+const model: DvaModel<LoginModelState> = {
   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 0971b31efc51d829cbe9f0a2a8df4f63f1b56c37..604b87fdacb7b25fc8483cf3b508915228ef525a 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<settingModelState>;
-  };
-  subscriptions: { setup: Subscription };
-}
-const Model: settingModelType = {
+const model: DvaModel<SettingModelState> = {
   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 2ea4917988c700beca7c76123078cf141dfffe53..0fa02544baa3a20a922ac2a513ec6fe4ce7d6feb 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'
-    },
-  },
-  request
-);
+  retrieval_test,
+} = api;
+
+const methods = {
+  // 知识库管理
+  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',
+  },
+};
+
+const kbService = registerServer<keyof typeof methods>(methods, request);
 
 export default kbService;
diff --git a/web/src/services/userService.ts b/web/src/services/userService.ts
index 37a7b3364610e66a7df24bf5eaf023043bf2fc76..6e11f7344d13b36cbb2df05b7120588a929bb428 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'
-    },
-  },
-  request
-);
+const methods = {
+  login: {
+    url: login,
+    method: 'post',
+  },
+  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<keyof typeof methods>(methods, request);
 
 export default userService;
diff --git a/web/src/utils/registerServer.ts b/web/src/utils/registerServer.ts
index 148ce0814a717961ab8c6f52cb8a942cca6f0748..9404ce0d4264abaf2ab5b6a85ba96de9f7f739b3 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<T extends string> = Record<T, (params: any) => any>;
+
+const registerServer = <T extends string>(
+  opt: Record<T, { url: string; method: string }>,
+  request: RequestMethod,
+) => {
+  const server: Service<T> = {} as Service<T>;
   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 60fae733b0bc4e081c0a177245d0f0ee66093743..536c6746ea1c7dacb5f35cc1f671d79f827864d2 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 0000000000000000000000000000000000000000..4437d25fcf03d65956a2b763eedb2282e9b438af
--- /dev/null
+++ b/web/src/utils/stroreUtil.ts
@@ -0,0 +1,9 @@
+export const getOneNamespaceEffectsLoading = (
+  namespace: string,
+  effects: Record<string, boolean>,
+  effectNames: Array<string>,
+) => {
+  return effectNames.some(
+    (effectName) => effects[`${namespace}/${effectName}`],
+  );
+};