diff --git a/web/.umirc.ts b/web/.umirc.ts index c23ebb28..46f10065 100644 --- a/web/.umirc.ts +++ b/web/.umirc.ts @@ -1,22 +1,20 @@ -import { defineConfig } from "umi"; -import routes from './routes' +import { defineConfig } from 'umi'; +import routes from './src/routes'; export default defineConfig({ outputPath: 'dist', // alias: { '@': './src' }, - routes, npmClient: 'npm', base: '/', + routes, publicPath: '/web/dist/', esbuildMinifyIIFE: true, - icons: { - - }, + icons: {}, hash: true, history: { type: 'browser', }, - plugins: ['@react-dev-inspector/umi4-plugin','@umijs/plugins/dist/dva',], + plugins: ['@react-dev-inspector/umi4-plugin', '@umijs/plugins/dist/dva'], dva: {}, // proxy: { // '/v1': { @@ -26,4 +24,3 @@ export default defineConfig({ // }, // }, }); - diff --git a/web/routes.js b/web/routes.js deleted file mode 100644 index c924fe3b..00000000 --- a/web/routes.js +++ /dev/null @@ -1,89 +0,0 @@ - - -const routes = [ - { - path: '/login', - component: '@/pages/login', - layout: false - }, - { - path: '/', - component: '@/layouts', // 默认页面 - redirect: '/knowledge', - // wrappers: [ - // '@/wrappers/auth', - // ] - }, - - { - id: 2, - name: '知识库', - icon: 'home', - auth: [3, 4, 100], - path: '/knowledge', - component: '@/pages/knowledge', - pathname: 'knowledge' - }, - { - id: 2, - name: '知识库', - icon: 'home', - auth: [3, 4, 100], - path: '/knowledge/add/*', - component: '@/pages/add-knowledge', - pathname: 'knowledge', - // routes: [{ - // id: 3, - // name: '设置', - // icon: 'home', - // auth: [3, 4, 100], - // path: '/knowledge/add/setting', - // component: '@/pages/setting', - // pathname: "setting" - // }, { - // id: 1, - // name: '文件', - // icon: 'file', - // auth: [3, 4, 100], - // path: '/knowledge/add/file', - // component: '@/pages/file', - // pathname: 'file' - // },] - }, - { - id: 3, - name: '聊天', - icon: 'home', - auth: [3, 4, 100], - path: '/chat', - component: '@/pages/chat', - pathname: "chat" - }, - { - id: 3, - name: '设置', - icon: 'home', - auth: [3, 4, 100], - path: '/setting', - component: '@/pages/setting', - pathname: "setting" - }, - { - id: 1, - name: '文件', - icon: 'file', - auth: [3, 4, 100], - path: '/file', - component: '@/pages/file', - pathname: 'file' - }, - { - path: '/*', - component: '@/pages/404', - layout: false - } - -]; - - -module.exports = routes; \ No newline at end of file diff --git a/web/src/constants/authorization.ts b/web/src/constants/authorization.ts new file mode 100644 index 00000000..85b0930b --- /dev/null +++ b/web/src/constants/authorization.ts @@ -0,0 +1,3 @@ +export const Authorization = 'Authorization'; +export const Token = 'token'; +export const UserInfo = 'userInfo'; diff --git a/web/src/constants/common.ts b/web/src/constants/common.ts new file mode 100644 index 00000000..e69de29b diff --git a/web/src/hooks/authHook.ts b/web/src/hooks/authHook.ts new file mode 100644 index 00000000..e65f097c --- /dev/null +++ b/web/src/hooks/authHook.ts @@ -0,0 +1,10 @@ +import authorizationUtil from '@/utils/authorizationUtil'; +import { useState } from 'react'; + +export const useAuth = () => { + const [isLogin, setIsLogin] = useState( + () => !!authorizationUtil.getAuthorization(), + ); + + return { isLogin }; +}; diff --git a/web/src/layouts/components/user/index.tsx b/web/src/layouts/components/user/index.tsx index 0cc86aa2..51d20eb9 100644 --- a/web/src/layouts/components/user/index.tsx +++ b/web/src/layouts/components/user/index.tsx @@ -1,38 +1,53 @@ -import React, { useMemo } from 'react'; +import authorizationUtil from '@/utils/authorizationUtil'; import type { MenuProps } from 'antd'; -import { Button, Dropdown, } from 'antd'; -import { history } from 'umi' -import { useTranslation, Trans } from 'react-i18next' +import { Button, Dropdown } from 'antd'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { history } from 'umi'; const App: React.FC = () => { - const { t } = useTranslation() - const logout = () => { history.push('/login') } - const toSetting = () => { history.push('/setting') } - const items: MenuProps['items'] = useMemo(() => { - return [ - { - key: '1', - label: ( - - ), - }, - { - key: '2', - label: ( - - ), - }, - ] - }, []); + const { t } = useTranslation(); - return (<> - - - - ) -} + const logout = () => { + authorizationUtil.removeAll(); + history.push('/login'); + }; -export default App; \ No newline at end of file + const toSetting = () => { + history.push('/setting'); + }; + + const items: MenuProps['items'] = useMemo(() => { + return [ + { + key: '1', + label: ( + + ), + }, + { + key: '2', + label: ( + + ), + }, + ]; + }, []); + + return ( + <> + + + + + ); +}; + +export default App; diff --git a/web/src/layouts/index.tsx b/web/src/layouts/index.tsx index 6d4cfe08..3c809f14 100644 --- a/web/src/layouts/index.tsx +++ b/web/src/layouts/index.tsx @@ -1,22 +1,18 @@ +import logo from '@/assets/logo.png'; +import { Layout, Space, theme } from 'antd'; +import classnames from 'classnames'; import React, { useEffect, useState } from 'react'; -import { history, Outlet, useLocation, useNavigate } from 'umi'; -import { useTranslation, Trans } from 'react-i18next' -import classnames from 'classnames' +import { useTranslation } from 'react-i18next'; +import { Outlet, useLocation, useNavigate } from 'umi'; import '../locales/config'; -import logo from '@/assets/logo.png' -import { - RedditOutlined -} from '@ant-design/icons'; -import { Layout, Button, theme, Space, } from 'antd'; -import styles from './index.less' -import User from './components/user' -import { head } from 'lodash'; +import User from './components/user'; +import styles from './index.less'; const { Header, Content } = Layout; const App: React.FC = (props) => { - const { t } = useTranslation() - const navigate = useNavigate() + const { t } = useTranslation(); + const navigate = useNavigate(); const { token: { colorBgContainer, borderRadiusLG }, } = theme.useToken(); @@ -25,34 +21,49 @@ const App: React.FC = (props) => { const location = useLocation(); useEffect(() => { if (location.pathname !== '/') { - const path = location.pathname.split('/') - setCurrent(path[1]); + const path = location.pathname.split('/'); + // setCurrent(path[1]); } - console.log(location.pathname.split('/')) - }, [location.pathname]) + console.log(location.pathname.split('/')); + }, [location.pathname]); const handleChange = (path: string) => { - setCurrent(path) + // setCurrent(path) navigate(path); }; - const tagsData = [{ path: '/knowledge', name: 'knowledge' }, { path: '/chat', name: 'chat' }, { path: '/file', name: 'file' }]; + const tagsData = [ + { path: '/knowledge', name: 'knowledge' }, + { path: '/chat', name: 'chat' }, + { path: '/file', name: 'file' }, + ]; return ( - + -
- +
- {tagsData.map((item) => - ( handleChange(item.path)}> - {item.name} - ) - )} + {tagsData.map((item) => ( + handleChange(item.path)} + > + {item.name} + + ))} - +
{ minHeight: 280, background: colorBgContainer, borderRadius: borderRadiusLG, - overflow: 'auto' + overflow: 'auto', }} > - + ); }; -export default App; \ No newline at end of file +export default App; 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 9091c70d..06ce4412 100644 --- a/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts +++ b/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts @@ -1,6 +1,5 @@ -import { Effect, Reducer, Subscription } from 'umi' -import { message } from 'antd'; import kbService from '@/services/kbService'; +import { Effect, Reducer } from 'umi'; export interface chunkModelState { loading: boolean; @@ -9,7 +8,7 @@ export interface chunkModelState { isShowCreateModal: boolean; chunk_id: string; doc_id: string; - chunkInfo: any + chunkInfo: any; } export interface chunkgModelType { namespace: 'chunkModel'; @@ -24,7 +23,7 @@ export interface chunkgModelType { reducers: { updateState: Reducer; }; - subscriptions: { setup: Subscription }; + // subscriptions: { setup: Subscription }; } const Model: chunkgModelType = { namespace: 'chunkModel', @@ -35,91 +34,86 @@ const Model: chunkgModelType = { isShowCreateModal: false, chunk_id: '', doc_id: '', - chunkInfo: {} - }, - subscriptions: { - setup({ dispatch, history }) { - history.listen(location => { - console.log(location) - }); - } + chunkInfo: {}, }, + // subscriptions: { + // setup({ dispatch, history }) { + // history.listen(location => { + // console.log(location) + // }); + // } + // }, effects: { - * chunk_list({ payload = {}, callback }, { call, put }) { + *chunk_list({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(kbService.chunk_list, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { - console.log(res) + console.log(res); yield put({ type: 'updateState', payload: { data: res.chunks, total: res.total, - loading: false - } + loading: false, + }, }); - callback && callback() - + callback && callback(); } }, *switch_chunk({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(kbService.switch_chunk, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { - callback && callback() - + callback && callback(); } }, *rm_chunk({ payload = {}, callback }, { call, put }) { - console.log('shanchu') + console.log('shanchu'); const { data, response } = yield call(kbService.rm_chunk, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { - callback && callback() - + callback && callback(); } }, - * get_chunk({ payload = {}, callback }, { call, put }) { + *get_chunk({ payload = {}, callback }, { 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) - + 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, + }, }); } }, @@ -128,9 +122,9 @@ const Model: chunkgModelType = { updateState(state, { payload }) { return { ...state, - ...payload + ...payload, }; - } - } + }, + }, }; export default Model; 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 a1146865..3923e651 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/model.ts +++ b/web/src/pages/add-knowledge/components/knowledge-file/model.ts @@ -1,6 +1,6 @@ -import { message } from 'antd'; -import { Effect, Reducer, Subscription } from 'umi' import kbService from '@/services/kbService'; +import { message } from 'antd'; +import { Effect, Reducer, Subscription } from 'umi'; export interface kFModelState { isShowCEFwModal: boolean; @@ -8,7 +8,7 @@ export interface kFModelState { isShowSegmentSetModal: boolean; loading: boolean; tenantIfo: any; - data: any[] + data: any[]; } export interface kFModelType { namespace: 'kFModel'; @@ -36,60 +36,60 @@ const Model: kFModelType = { isShowSegmentSetModal: false, loading: false, tenantIfo: {}, - data: [] + data: [], }, subscriptions: { setup({ dispatch, history }) { - history.listen(location => { - }); - } + history.listen((location) => {}); + }, }, effects: { - * createKf({ payload = {}, callback }, { call, put }) { + *createKf({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(kbService.createKb, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { - message.success('创建成功!'); } }, - * updateKf({ payload = {}, callback }, { call, put }) { + *updateKf({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(kbService.updateKb, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('修改成功!'); - } }, *getKfDetail({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(kbService.get_kb_detail, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { // localStorage.setItem('userInfo',res.) - callback && callback(res) + callback && callback(res); } }, *getKfList({ payload = {} }, { call, put }) { yield put({ type: 'updateState', payload: { - loading: true - } + loading: true, + }, }); - const { data, response } = yield call(kbService.get_document_list, payload); - const { retcode, data: res, retmsg } = data + const { data, response } = yield call( + kbService.get_document_list, + payload, + ); + const { retcode, data: res, retmsg } = data; yield put({ type: 'updateState', payload: { - loading: false - } + loading: false, + }, }); if (retcode === 0) { yield put({ type: 'updateState', payload: { - data: res - } + data: res, + }, }); } }, @@ -97,58 +97,60 @@ const Model: kFModelType = { yield put({ type: 'updateState', payload: { - loading: true - } + loading: true, + }, }); - const { data, response } = yield call(kbService.document_change_status, payload); - const { retcode, data: res, retmsg } = data + const { data, response } = yield call( + kbService.document_change_status, + payload, + ); + const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('修改成功!'); yield put({ type: 'updateState', payload: { - loading: false - } + loading: false, + }, }); - callback && callback() + callback && callback(); } - }, *document_rm({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(kbService.document_rm, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('删除成功!'); - callback && callback() + callback && callback(); } - }, *document_create({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(kbService.document_create, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('创建成功!'); - callback && callback() + callback && callback(); } - }, *document_change_parser({ payload = {}, callback }, { call, put }) { - const { data, response } = yield call(kbService.document_change_parser, payload); - const { retcode, data: res, retmsg } = data + const { data, response } = yield call( + kbService.document_change_parser, + payload, + ); + const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('修改成功!'); - callback && callback() + callback && callback(); } - }, }, reducers: { updateState(state, { payload }) { return { ...state, - ...payload + ...payload, }; - } - } + }, + }, }; export default Model; diff --git a/web/src/pages/knowledge/index.tsx b/web/src/pages/knowledge/index.tsx index dfb3c280..cdf138b3 100644 --- a/web/src/pages/knowledge/index.tsx +++ b/web/src/pages/knowledge/index.tsx @@ -1,109 +1,131 @@ -import React, { useEffect, useState, } from 'react'; -import { useNavigate, connect, Dispatch } from 'umi' -import { Card, List, Popconfirm, message, FloatButton, Row, Col } from 'antd'; -import { MinusSquareOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons'; -import styles from './index.less' -import { formatDate } from '@/utils/date' -import type { knowledgeModelState } from './model' +import { formatDate } from '@/utils/date'; +import { + DeleteOutlined, + MinusSquareOutlined, + 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 styles from './index.less'; +import type { knowledgeModelState } from './model'; interface KnowledgeProps { dispatch: Dispatch; - knowledgeModel: knowledgeModelState + knowledgeModel: knowledgeModelState; } const Index: React.FC = ({ knowledgeModel, dispatch }) => { - const navigate = useNavigate() + const navigate = useNavigate(); // const [datas, setDatas] = useState(data) - const { data = [] } = knowledgeModel - console.log(knowledgeModel) + const { data = [] } = knowledgeModel; + console.log(knowledgeModel); + + // const x = useSelector((state) => state.knowledgeModel); + const confirm = (id: string) => { dispatch({ type: 'knowledgeModel/rmKb', payload: { - kb_id: id + kb_id: id, }, callback: () => { dispatch({ type: 'knowledgeModel/getList', - payload: { - - } + payload: {}, }); - } + }, }); }; const handleAddKnowledge = () => { navigate(`add/setting?activeKey=setting`); - } + }; const handleEditKnowledge = (id: string) => { navigate(`add/setting?activeKey=file&id=${id}`); - } + }; useEffect(() => { dispatch({ type: 'knowledgeModel/getList', - payload: { - - } + payload: {}, }); - }, []) - return (<> -
- } type="primary" style={{ right: 24, top: 100 }} /> - - { - data.map((item: any) => { - return ( - { handleEditKnowledge(item.id) }} + }, []); + return ( + <> +
+ } + type="primary" + style={{ right: 24, top: 100 }} + /> + + {data.map((item: any) => { + return ( + -
-
- - {item.name} - - - { - e.stopPropagation(); - e.nativeEvent.stopImmediatePropagation() - confirm(item.id) - - }} - okText="Yes" - cancelText="No" - > - { - e.stopPropagation(); - e.nativeEvent.stopImmediatePropagation() - }} /> - - - + { + handleEditKnowledge(item.id); + }} + > +
+
+ {item.name} + + { + e.stopPropagation(); + e.nativeEvent.stopImmediatePropagation(); + confirm(item.id); + }} + okText="Yes" + cancelText="No" + > + { + e.stopPropagation(); + e.nativeEvent.stopImmediatePropagation(); + }} + /> + + +
+
+ + + {item.doc_num}文档 + + + + {item.chunk_num}个 + + + + {item.token_num}千字符 + + + {formatDate(item.update_date)} + +
-
- - {item.doc_num}文档 - - - {item.chunk_num}个 - - - {item.token_num}千字符 - - - {formatDate(item.update_date)} - -
- -
- - ) - }) - } - -
- - ) + + + ); + })} +
+
+ + ); }; -export default connect(({ knowledgeModel, loading }) => ({ knowledgeModel, loading }))(Index); \ No newline at end of file +export default connect(({ knowledgeModel, loading }) => ({ + knowledgeModel, + loading, +}))(Index); diff --git a/web/src/pages/knowledge/model.ts b/web/src/pages/knowledge/model.ts index 938548e2..83e30008 100644 --- a/web/src/pages/knowledge/model.ts +++ b/web/src/pages/knowledge/model.ts @@ -1,5 +1,5 @@ import kbService from '@/services/kbService'; -import { Effect, Reducer, Subscription } from 'umi'; +import { Effect, Reducer } from 'umi'; export interface knowledgeModelState { loading: boolean; @@ -15,7 +15,7 @@ export interface knowledgegModelType { reducers: { updateState: Reducer; }; - subscriptions: { setup: Subscription }; + // subscriptions: { setup: Subscription }; } const Model: knowledgegModelType = { namespace: 'knowledgeModel', @@ -23,13 +23,13 @@ const Model: knowledgegModelType = { loading: false, data: [], }, - subscriptions: { - setup({ dispatch, history }) { - history.listen((location) => { - console.log(location); - }); - }, - }, + // subscriptions: { + // setup({ dispatch, history }) { + // history.listen((location) => { + // console.log(location); + // }); + // }, + // }, effects: { *rmKb({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(kbService.rmKb, payload); diff --git a/web/src/pages/login/index.tsx b/web/src/pages/login/index.tsx index bb5aad3f..29edc396 100644 --- a/web/src/pages/login/index.tsx +++ b/web/src/pages/login/index.tsx @@ -1,19 +1,18 @@ -import { connect, Icon, Dispatch } from 'umi'; -import { Input, Form, Button, Checkbox } from 'antd'; +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 styles from './index.less'; -import { rsaPsw } from '@/utils' -import { useState, useEffect, FC } from 'react'; interface LoginProps { dispatch: Dispatch; } -const View: FC = ({ - dispatch, -}) => { - const [title, setTitle] = useState('login') +const View: FC = ({ dispatch }) => { + let navigate = useNavigate(); + const [title, setTitle] = useState('login'); const changeTitle = () => { - setTitle((title) => title === 'login' ? 'register' : 'login') - } + setTitle((title) => (title === 'login' ? 'register' : 'login')); + }; const [form] = Form.useForm(); const [checkNick, setCheckNick] = useState(false); @@ -25,15 +24,17 @@ const View: FC = ({ try { const params = await form.validateFields(); - var rsaPassWord = rsaPsw(params.password) + var rsaPassWord = rsaPsw(params.password); if (title === 'login') { - dispatch({ + const ret = await dispatch({ type: 'loginModel/login', payload: { email: params.email, - password: rsaPassWord - } + password: rsaPassWord, + }, }); + console.info(ret); + navigate('/knowledge'); } else { dispatch({ type: 'loginModel/register', @@ -43,8 +44,8 @@ const View: FC = ({ password: rsaPassWord, }, callback() { - setTitle('login') - } + setTitle('login'); + }, }); } } catch (errorInfo) { @@ -56,103 +57,124 @@ const View: FC = ({ // wrapperCol: { span: 8 }, }; - const toGoogle = () => { - window.location.href = "https://github.com/login/oauth/authorize?scope=user:email&client_id=302129228f0d96055bee" - } + window.location.href = + 'https://github.com/login/oauth/authorize?scope=user:email&client_id=302129228f0d96055bee'; + }; return (
-
-
- {title === 'login' ? 'Sign in' : 'Create an account'} -
- - {title === 'login' ? 'We’re so excited to see you again!' : 'Glad to have you on board!'} +
{title === 'login' ? 'Sign in' : 'Create an account'}
+ + {title === 'login' + ? 'We’re so excited to see you again!' + : 'Glad to have you on board!'}
-
+ - + - { - title === 'register' && - + - } + )} - + - { - title === 'login' && + {title === 'login' && ( + Remember me - } -
{ - title === 'login' && (
- Don’t have an account? - -
) - } - { - title === 'register' && (
+ )} +
+ {' '} + {title === 'login' && ( +
+ Don’t have an account? + +
+ )} + {title === 'register' && ( +
Already have an account? -
) - } +
+ )}
- - { - title === 'login' && (<> - + ) - } - + + + )}
-
- -
+
); }; -export default connect(({ loginModel, loading }) => ({ loginModel, loading }))(View); +export default connect(({ loginModel, loading }) => ({ loginModel, loading }))( + View, +); diff --git a/web/src/pages/login/model.ts b/web/src/pages/login/model.ts index d95187e9..0ce6150c 100644 --- a/web/src/pages/login/model.ts +++ b/web/src/pages/login/model.ts @@ -1,6 +1,8 @@ -import { Effect, Reducer, Subscription } from 'umi' -import { message } from 'antd'; +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'; export interface loginModelState { list: any[]; @@ -28,49 +30,52 @@ const Model: logingModelType = { }, subscriptions: { setup({ dispatch, history }) { - history.listen(location => { }); - } + history.listen((location) => {}); + }, }, effects: { *login({ payload = {} }, { call, put }) { - console.log(111, payload) + console.log(111, payload); const { data, response } = yield call(userService.login, payload); - const { retcode, data: res, retmsg } = data - console.log() - const Authorization = response.headers.get('Authorization') + const { retcode, data: res, retmsg } = data; + console.log(); + const authorization = response.headers.get(Authorization); if (retcode === 0) { message.success('登录成功!'); const token = res.access_token; const userInfo = { avatar: res.avatar, name: res.nickname, - email: res.email + email: res.email, }; - localStorage.setItem('token', token) - localStorage.setItem('userInfo', JSON.stringify(userInfo)) - localStorage.setItem('Authorization', Authorization) - setTimeout(() => { - window.location.href = '/file'; - }, 300); + authorizationUtil.setItems({ + Authorization: authorization, + userInfo: JSON.stringify(userInfo), + Token: token, + }); + // setTimeout(() => { + // window.location.href = '/file'; + // }, 300); } + return data; }, *register({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(userService.register, payload); - console.log() - const { retcode, data: res, retmsg } = data + console.log(); + const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('注册成功!'); - callback && callback() + callback && callback(); } - } + }, }, reducers: { updateState(state, { payload }) { return { ...state, - ...payload + ...payload, }; - } - } + }, + }, }; export default Model; diff --git a/web/src/pages/setting/index.tsx b/web/src/pages/setting/index.tsx index fdf15429..98855294 100644 --- a/web/src/pages/setting/index.tsx +++ b/web/src/pages/setting/index.tsx @@ -1,90 +1,105 @@ -import { connect, Dispatch } from 'umi'; +import { Button, FloatButton } from 'antd'; import i18n from 'i18next'; -import { useTranslation, Trans } from 'react-i18next' -import { Button, FloatButton } from 'antd' - +import { useTranslation } from 'react-i18next'; +import { Dispatch, connect } from 'umi'; +import authorizationUtil from '@/utils/authorizationUtil'; +import { FC, useEffect } from 'react'; +import CPwModal from './CPwModal'; +import List from './List'; +import SAKModal from './SAKModal'; +import SSModal from './SSModal'; +import TntModal from './TntModal'; import styles from './index.less'; -import CPwModal from './CPwModal' -import SAKModal from './SAKModal' -import TntModal from './TntModal' -import SSModal from './SSModal' -import List from './List' -import { useEffect, useState, FC } from 'react'; interface CPwModalProps { - dispatch: Dispatch; - settingModel: any + dispatch: Dispatch; + settingModel: any; } const Index: FC = ({ settingModel, dispatch }) => { - // const [llm_factory, set_llm_factory] = useState('') - const { t } = useTranslation() - const userInfo = JSON.parse(localStorage.getItem('userInfo') || '') - const changeLang = (val: string) => { // 改变状态里的 语言 进行切换 - i18n.changeLanguage(val); - } - useEffect(() => { - dispatch({ - type: 'settingModel/getTenantInfo', - payload: { - } - }); - }, []) - const showCPwModal = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowPSwModal: true - } - }); - }; - const showTntModal = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowTntModal: true - } - }); - }; - const showSSModal = () => { - dispatch({ - type: 'settingModel/updateState', - payload: { - isShowSSModal: true - } - }); - // dispatch({ - // type: 'settingModel/getTenantInfo', - // payload: { - // } - // }); - }; - return ( -
-
- -
-
账号:{userInfo.name}
-
密码:******
- -
-
-
- - - -
- - - - - i18n.changeLanguage(i18n.language == 'en' ? 'zh' : 'en')} type="default" style={{ right: 94, fontSize: 14 }} /> -
- - - ); -} -export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index); + // const [llm_factory, set_llm_factory] = useState('') + const { t } = useTranslation(); + const userInfo = authorizationUtil.getUserInfoObject(); + const changeLang = (val: string) => { + // 改变状态里的 语言 进行切换 + i18n.changeLanguage(val); + }; + useEffect(() => { + dispatch({ + type: 'settingModel/getTenantInfo', + payload: {}, + }); + }, []); + const showCPwModal = () => { + dispatch({ + type: 'settingModel/updateState', + payload: { + isShowPSwModal: true, + }, + }); + }; + const showTntModal = () => { + dispatch({ + type: 'settingModel/updateState', + payload: { + isShowTntModal: true, + }, + }); + }; + const showSSModal = () => { + dispatch({ + type: 'settingModel/updateState', + payload: { + isShowSSModal: true, + }, + }); + // dispatch({ + // type: 'settingModel/getTenantInfo', + // payload: { + // } + // }); + }; + return ( +
+
+ +
+
账号:{userInfo.name}
+
+ 密码:****** + +
+
+
+
+ + + +
+ + + + + i18n.changeLanguage(i18n.language == 'en' ? 'zh' : 'en')} + type="default" + style={{ right: 94, fontSize: 14 }} + /> +
+ ); +}; +export default connect(({ settingModel, loading }) => ({ + settingModel, + loading, +}))(Index); diff --git a/web/src/pages/setting/model.ts b/web/src/pages/setting/model.ts index 4800ff1a..0971b31e 100644 --- a/web/src/pages/setting/model.ts +++ b/web/src/pages/setting/model.ts @@ -1,6 +1,7 @@ -import { Effect, Reducer, Subscription } from 'umi'; -import { message } from 'antd'; import userService from '@/services/userService'; +import authorizationUtil from '@/utils/authorizationUtil'; +import { message } from 'antd'; +import { Effect, Reducer, Subscription } from 'umi'; export interface settingModelState { isShowPSwModal: boolean; @@ -9,10 +10,10 @@ export interface settingModelState { isShowSSModal: boolean; llm_factory: string; loading: boolean; - tenantIfo: any, - llmInfo: any, - myLlm: any[], - factoriesList: any[] + tenantIfo: any; + llmInfo: any; + myLlm: any[]; + factoriesList: any[]; } export interface settingModelType { @@ -45,32 +46,31 @@ const Model: settingModelType = { tenantIfo: {}, llmInfo: {}, myLlm: [], - factoriesList: [] + factoriesList: [], }, subscriptions: { setup({ dispatch, history }) { - history.listen(location => { - }); - } + history.listen((location) => {}); + }, }, effects: { *setting({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(userService.setting, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('密码修改成功!'); - callback && callback() + callback && callback(); } }, *getUserInfo({ payload = {} }, { call, put }) { const { data, response } = yield call(userService.user_info, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; const userInfo = { avatar: res.avatar, name: res.nickname, - email: res.email + email: res.email, }; - localStorage.setItem('userInfo', JSON.stringify(userInfo)) + authorizationUtil.setUserInfo(userInfo); if (retcode === 0) { // localStorage.setItem('userInfo',res.) } @@ -79,91 +79,100 @@ const Model: settingModelType = { yield put({ type: 'updateState', payload: { - loading: true - } + loading: true, + }, }); - const { data, response } = yield call(userService.get_tenant_info, payload); - const { retcode, data: res, retmsg } = data + const { data, response } = yield call( + userService.get_tenant_info, + payload, + ); + const { retcode, data: res, retmsg } = data; // llm_id 对应chat_id // asr_id 对应speech2txt yield put({ type: 'updateState', payload: { - loading: false - } + loading: false, + }, }); if (retcode === 0) { - res.chat_id = res.llm_id - res.speech2text_id = res.asr_id + res.chat_id = res.llm_id; + res.speech2text_id = res.asr_id; yield put({ type: 'updateState', payload: { - tenantIfo: res - } + tenantIfo: res, + }, }); } }, *set_tenant_info({ payload = {} }, { call, put }) { - const { data, response } = yield call(userService.set_tenant_info, payload); - const { retcode, data: res, retmsg } = data + const { data, response } = yield call( + userService.set_tenant_info, + payload, + ); + const { retcode, data: res, retmsg } = data; // llm_id 对应chat_id // asr_id 对应speech2txt if (retcode === 0) { yield put({ type: 'updateState', payload: { - isShowSSModal: false - } + isShowSSModal: false, + }, }); yield put({ - type: 'getTenantInfo' - }) + type: 'getTenantInfo', + }); } }, *factories_list({ payload = {} }, { call, put }) { - const { data, response } = yield call(userService.factories_list, payload); - const { retcode, data: res, retmsg } = data + const { data, response } = yield call( + userService.factories_list, + payload, + ); + const { retcode, data: res, retmsg } = data; if (retcode === 0) { yield put({ type: 'updateState', payload: { - factoriesList: res - } + factoriesList: res, + }, }); } }, *llm_list({ payload = {} }, { call, put }) { const { data, response } = yield call(userService.llm_list, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { yield put({ type: 'updateState', payload: { - llmInfo: res - } + llmInfo: res, + }, }); } }, *my_llm({ payload = {} }, { call, put }) { const { data, response } = yield call(userService.my_llm, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { yield put({ type: 'updateState', payload: { - myLlm: res - } + myLlm: res, + }, }); } }, *set_api_key({ payload = {}, callback }, { call, put }) { const { data, response } = yield call(userService.set_api_key, payload); - const { retcode, data: res, retmsg } = data + const { retcode, data: res, retmsg } = data; if (retcode === 0) { message.success('设置API KEY成功!'); - callback && callback() + callback && callback(); } }, }, @@ -171,9 +180,9 @@ const Model: settingModelType = { updateState(state, { payload }) { return { ...state, - ...payload + ...payload, }; - } - } + }, + }, }; export default Model; diff --git a/web/src/routes.ts b/web/src/routes.ts new file mode 100644 index 00000000..547404bd --- /dev/null +++ b/web/src/routes.ts @@ -0,0 +1,43 @@ +const routes = [ + { + path: '/login', + component: '@/pages/login', + layout: false, + }, + { + path: '/', + component: '@/layouts', + layout: false, + wrappers: ['@/wrappers/auth'], + routes: [ + { path: '/', redirect: '/knowledge' }, + { + path: '/knowledge', + component: '@/pages/knowledge', + }, + { + path: '/knowledge/add/*', + component: '@/pages/add-knowledge', + }, + { + path: '/chat', + component: '@/pages/chat', + }, + { + path: '/setting', + component: '@/pages/setting', + }, + { + path: '/file', + component: '@/pages/file', + }, + ], + }, + { + path: '/*', + component: '@/pages/404', + layout: false, + }, +]; + +export default routes; diff --git a/web/src/utils/authorizationUtil.ts b/web/src/utils/authorizationUtil.ts new file mode 100644 index 00000000..a2b3d069 --- /dev/null +++ b/web/src/utils/authorizationUtil.ts @@ -0,0 +1,43 @@ +import { Authorization, Token, UserInfo } from '@/constants/authorization'; + +const KeySet = [Authorization, Token, UserInfo]; + +const storage = { + getAuthorization: () => { + return localStorage.getItem(Authorization); + }, + getToken: () => { + return localStorage.getItem(Token); + }, + getUserInfo: () => { + return localStorage.getItem(UserInfo); + }, + getUserInfoObject: () => { + return JSON.parse(localStorage.getItem('userInfo') || ''); + }, + setAuthorization: (value: string) => { + localStorage.setItem(Authorization, value); + }, + setToken: (value: string) => { + localStorage.setItem(Token, value); + }, + setUserInfo: (value: string | Object) => { + let valueStr = typeof value !== 'string' ? JSON.stringify(value) : value; + localStorage.setItem(UserInfo, valueStr); + }, + setItems: (pairs: Record) => { + Object.entries(pairs).forEach(([key, value]) => { + localStorage.setItem(key, value); + }); + }, + removeAuthorization: () => { + localStorage.removeItem(Authorization); + }, + removeAll: () => { + KeySet.forEach((x) => { + localStorage.removeItem(x); + }); + }, +}; + +export default storage; diff --git a/web/src/utils/history.ts b/web/src/utils/history.ts new file mode 100644 index 00000000..f529e5d6 --- /dev/null +++ b/web/src/utils/history.ts @@ -0,0 +1,3 @@ +import { createBrowserHistory } from 'history'; + +export const history = createBrowserHistory(); diff --git a/web/src/utils/request.ts b/web/src/utils/request.ts index 781ea67f..60fae733 100644 --- a/web/src/utils/request.ts +++ b/web/src/utils/request.ts @@ -1,14 +1,14 @@ - +import { message, notification } from 'antd'; import { extend } from 'umi-request'; -import { notification, message } from 'antd'; +import { Authorization } from '@/constants/authorization'; import api from '@/utils/api'; +import authorizationUtil from '@/utils/authorizationUtil'; + const { login } = api; const ABORT_REQUEST_ERR_MESSAGE = 'The user aborted a request.'; // 手动中断请求。errorHandler 抛出的error message - - const retcodeMessage = { 200: '服务器成功返回请求的数据。', 201: '新建或修改数据成功。', @@ -24,7 +24,7 @@ const retcodeMessage = { 500: '服务器发生错误,请检查服务器。', 502: '网关错误。', 503: '服务不可用,服务器暂时过载或维护。', - 504: '网关超时。' + 504: '网关超时。', }; type retcode = | 200 @@ -49,16 +49,20 @@ interface responseType { retcode: number; data: any; retmsg: string; - status: number + status: number; } -const errorHandler = (error: { response: Response, message: string }): Response => { +const errorHandler = (error: { + response: Response; + message: string; +}): Response => { const { response } = error; // 手动中断请求 abort if (error.message === ABORT_REQUEST_ERR_MESSAGE) { console.log('user abort request'); } else { if (response && response.status) { - const errorText = retcodeMessage[response.status as retcode] || response.statusText; + const errorText = + retcodeMessage[response.status as retcode] || response.statusText; const { status, url } = response; notification.error({ message: `请求错误 ${status}: ${url}`, @@ -80,21 +84,21 @@ const errorHandler = (error: { response: Response, message: string }): Response const request = extend({ errorHandler, // 默认错误处理 timeout: 3000000, - getResponse: true + getResponse: true, }); request.interceptors.request.use((url: string, options: any) => { - const Authorization = localStorage.getItem('Authorization') + const authorization = authorizationUtil.getAuthorization(); return { url, options: { ...options, headers: { - ...(options.skipToken ? undefined : { Authorization }), - ...options.headers + ...(options.skipToken ? undefined : { [Authorization]: authorization }), + ...options.headers, }, - interceptors: true - } + interceptors: true, + }, }; }); @@ -103,7 +107,7 @@ request.interceptors.request.use((url: string, options: any) => { * */ request.interceptors.response.use(async (response: any, request) => { - console.log(response, request) + console.log(response, request); const data: responseType = await response.clone().json(); // response 拦截 @@ -113,6 +117,8 @@ request.interceptors.response.use(async (response: any, request) => { description: data.retmsg, duration: 3, }); + authorizationUtil.removeAll(); + // history.push('/login'); // Will not jump to the login page } else if (data.retcode !== 0) { if (data.retcode === 100) { message.error(data.retmsg); @@ -126,7 +132,6 @@ request.interceptors.response.use(async (response: any, request) => { return response; } else { - return response; } }); diff --git a/web/src/wrappers/auth.tsx b/web/src/wrappers/auth.tsx index 5ad888ca..2f0b8037 100644 --- a/web/src/wrappers/auth.tsx +++ b/web/src/wrappers/auth.tsx @@ -1,12 +1,11 @@ -import { Navigate, Outlet } from 'umi' +import { useAuth } from '@/hooks/authHook'; +import { Navigate, Outlet } from 'umi'; -export default (props) => { - // const { isLogin } = useAuth(); - console.log(props) - const isLogin = false - if (isLogin) { - return ; - } else { - return ; - } -} \ No newline at end of file +export default () => { + const { isLogin } = useAuth(); + if (isLogin) { + return ; + } else { + return ; + } +};