balibabu
commited on
Commit
·
04aba1b
1
Parent(s):
e1bc1d4
feat: prevent the user from entering the knowledge base if he is not logged in (#45)
Browse files- web/.umirc.ts +5 -8
- web/routes.js +0 -89
- web/src/constants/authorization.ts +3 -0
- web/src/constants/common.ts +0 -0
- web/src/hooks/authHook.ts +10 -0
- web/src/layouts/components/user/index.tsx +48 -33
- web/src/layouts/index.tsx +44 -33
- web/src/pages/add-knowledge/components/knowledge-chunk/model.ts +39 -45
- web/src/pages/add-knowledge/components/knowledge-file/model.ts +46 -44
- web/src/pages/knowledge/index.tsx +103 -81
- web/src/pages/knowledge/model.ts +9 -9
- web/src/pages/login/index.tsx +92 -70
- web/src/pages/login/model.ts +27 -22
- web/src/pages/setting/index.tsx +99 -84
- web/src/pages/setting/model.ts +55 -46
- web/src/routes.ts +43 -0
- web/src/utils/authorizationUtil.ts +43 -0
- web/src/utils/history.ts +3 -0
- web/src/utils/request.ts +21 -16
- web/src/wrappers/auth.tsx +10 -11
web/.umirc.ts
CHANGED
|
@@ -1,22 +1,20 @@
|
|
| 1 |
-
import { defineConfig } from
|
| 2 |
-
import routes from './routes'
|
| 3 |
|
| 4 |
export default defineConfig({
|
| 5 |
outputPath: 'dist',
|
| 6 |
// alias: { '@': './src' },
|
| 7 |
-
routes,
|
| 8 |
npmClient: 'npm',
|
| 9 |
base: '/',
|
|
|
|
| 10 |
publicPath: '/web/dist/',
|
| 11 |
esbuildMinifyIIFE: true,
|
| 12 |
-
icons: {
|
| 13 |
-
|
| 14 |
-
},
|
| 15 |
hash: true,
|
| 16 |
history: {
|
| 17 |
type: 'browser',
|
| 18 |
},
|
| 19 |
-
plugins: ['@react-dev-inspector/umi4-plugin','@umijs/plugins/dist/dva'
|
| 20 |
dva: {},
|
| 21 |
// proxy: {
|
| 22 |
// '/v1': {
|
|
@@ -26,4 +24,3 @@ export default defineConfig({
|
|
| 26 |
// },
|
| 27 |
// },
|
| 28 |
});
|
| 29 |
-
|
|
|
|
| 1 |
+
import { defineConfig } from 'umi';
|
| 2 |
+
import routes from './src/routes';
|
| 3 |
|
| 4 |
export default defineConfig({
|
| 5 |
outputPath: 'dist',
|
| 6 |
// alias: { '@': './src' },
|
|
|
|
| 7 |
npmClient: 'npm',
|
| 8 |
base: '/',
|
| 9 |
+
routes,
|
| 10 |
publicPath: '/web/dist/',
|
| 11 |
esbuildMinifyIIFE: true,
|
| 12 |
+
icons: {},
|
|
|
|
|
|
|
| 13 |
hash: true,
|
| 14 |
history: {
|
| 15 |
type: 'browser',
|
| 16 |
},
|
| 17 |
+
plugins: ['@react-dev-inspector/umi4-plugin', '@umijs/plugins/dist/dva'],
|
| 18 |
dva: {},
|
| 19 |
// proxy: {
|
| 20 |
// '/v1': {
|
|
|
|
| 24 |
// },
|
| 25 |
// },
|
| 26 |
});
|
|
|
web/routes.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
const routes = [
|
| 4 |
-
{
|
| 5 |
-
path: '/login',
|
| 6 |
-
component: '@/pages/login',
|
| 7 |
-
layout: false
|
| 8 |
-
},
|
| 9 |
-
{
|
| 10 |
-
path: '/',
|
| 11 |
-
component: '@/layouts', // 默认页面
|
| 12 |
-
redirect: '/knowledge',
|
| 13 |
-
// wrappers: [
|
| 14 |
-
// '@/wrappers/auth',
|
| 15 |
-
// ]
|
| 16 |
-
},
|
| 17 |
-
|
| 18 |
-
{
|
| 19 |
-
id: 2,
|
| 20 |
-
name: '知识库',
|
| 21 |
-
icon: 'home',
|
| 22 |
-
auth: [3, 4, 100],
|
| 23 |
-
path: '/knowledge',
|
| 24 |
-
component: '@/pages/knowledge',
|
| 25 |
-
pathname: 'knowledge'
|
| 26 |
-
},
|
| 27 |
-
{
|
| 28 |
-
id: 2,
|
| 29 |
-
name: '知识库',
|
| 30 |
-
icon: 'home',
|
| 31 |
-
auth: [3, 4, 100],
|
| 32 |
-
path: '/knowledge/add/*',
|
| 33 |
-
component: '@/pages/add-knowledge',
|
| 34 |
-
pathname: 'knowledge',
|
| 35 |
-
// routes: [{
|
| 36 |
-
// id: 3,
|
| 37 |
-
// name: '设置',
|
| 38 |
-
// icon: 'home',
|
| 39 |
-
// auth: [3, 4, 100],
|
| 40 |
-
// path: '/knowledge/add/setting',
|
| 41 |
-
// component: '@/pages/setting',
|
| 42 |
-
// pathname: "setting"
|
| 43 |
-
// }, {
|
| 44 |
-
// id: 1,
|
| 45 |
-
// name: '文件',
|
| 46 |
-
// icon: 'file',
|
| 47 |
-
// auth: [3, 4, 100],
|
| 48 |
-
// path: '/knowledge/add/file',
|
| 49 |
-
// component: '@/pages/file',
|
| 50 |
-
// pathname: 'file'
|
| 51 |
-
// },]
|
| 52 |
-
},
|
| 53 |
-
{
|
| 54 |
-
id: 3,
|
| 55 |
-
name: '聊天',
|
| 56 |
-
icon: 'home',
|
| 57 |
-
auth: [3, 4, 100],
|
| 58 |
-
path: '/chat',
|
| 59 |
-
component: '@/pages/chat',
|
| 60 |
-
pathname: "chat"
|
| 61 |
-
},
|
| 62 |
-
{
|
| 63 |
-
id: 3,
|
| 64 |
-
name: '设置',
|
| 65 |
-
icon: 'home',
|
| 66 |
-
auth: [3, 4, 100],
|
| 67 |
-
path: '/setting',
|
| 68 |
-
component: '@/pages/setting',
|
| 69 |
-
pathname: "setting"
|
| 70 |
-
},
|
| 71 |
-
{
|
| 72 |
-
id: 1,
|
| 73 |
-
name: '文件',
|
| 74 |
-
icon: 'file',
|
| 75 |
-
auth: [3, 4, 100],
|
| 76 |
-
path: '/file',
|
| 77 |
-
component: '@/pages/file',
|
| 78 |
-
pathname: 'file'
|
| 79 |
-
},
|
| 80 |
-
{
|
| 81 |
-
path: '/*',
|
| 82 |
-
component: '@/pages/404',
|
| 83 |
-
layout: false
|
| 84 |
-
}
|
| 85 |
-
|
| 86 |
-
];
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
module.exports = routes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web/src/constants/authorization.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const Authorization = 'Authorization';
|
| 2 |
+
export const Token = 'token';
|
| 3 |
+
export const UserInfo = 'userInfo';
|
web/src/constants/common.ts
ADDED
|
File without changes
|
web/src/hooks/authHook.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import authorizationUtil from '@/utils/authorizationUtil';
|
| 2 |
+
import { useState } from 'react';
|
| 3 |
+
|
| 4 |
+
export const useAuth = () => {
|
| 5 |
+
const [isLogin, setIsLogin] = useState(
|
| 6 |
+
() => !!authorizationUtil.getAuthorization(),
|
| 7 |
+
);
|
| 8 |
+
|
| 9 |
+
return { isLogin };
|
| 10 |
+
};
|
web/src/layouts/components/user/index.tsx
CHANGED
|
@@ -1,38 +1,53 @@
|
|
| 1 |
-
import
|
| 2 |
import type { MenuProps } from 'antd';
|
| 3 |
-
import { Button, Dropdown
|
| 4 |
-
import {
|
| 5 |
-
import { useTranslation
|
|
|
|
| 6 |
|
| 7 |
const App: React.FC = () => {
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
|
|
|
|
|
|
| 37 |
|
| 38 |
-
export default App;
|
|
|
|
| 1 |
+
import authorizationUtil from '@/utils/authorizationUtil';
|
| 2 |
import type { MenuProps } from 'antd';
|
| 3 |
+
import { Button, Dropdown } from 'antd';
|
| 4 |
+
import React, { useMemo } from 'react';
|
| 5 |
+
import { useTranslation } from 'react-i18next';
|
| 6 |
+
import { history } from 'umi';
|
| 7 |
|
| 8 |
const App: React.FC = () => {
|
| 9 |
+
const { t } = useTranslation();
|
| 10 |
+
|
| 11 |
+
const logout = () => {
|
| 12 |
+
authorizationUtil.removeAll();
|
| 13 |
+
history.push('/login');
|
| 14 |
+
};
|
| 15 |
+
|
| 16 |
+
const toSetting = () => {
|
| 17 |
+
history.push('/setting');
|
| 18 |
+
};
|
| 19 |
+
|
| 20 |
+
const items: MenuProps['items'] = useMemo(() => {
|
| 21 |
+
return [
|
| 22 |
+
{
|
| 23 |
+
key: '1',
|
| 24 |
+
label: (
|
| 25 |
+
<Button type="text" onClick={logout}>
|
| 26 |
+
{t('header.logout')}
|
| 27 |
+
</Button>
|
| 28 |
+
),
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
key: '2',
|
| 32 |
+
label: (
|
| 33 |
+
<Button type="text" onClick={toSetting}>
|
| 34 |
+
{t('header.setting')}
|
| 35 |
+
</Button>
|
| 36 |
+
),
|
| 37 |
+
},
|
| 38 |
+
];
|
| 39 |
+
}, []);
|
| 40 |
|
| 41 |
+
return (
|
| 42 |
+
<>
|
| 43 |
+
<Dropdown menu={{ items }} placement="bottomLeft" arrow>
|
| 44 |
+
<img
|
| 45 |
+
style={{ width: '50px', height: '50px', borderRadius: '25px' }}
|
| 46 |
+
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
|
| 47 |
+
/>
|
| 48 |
+
</Dropdown>
|
| 49 |
+
</>
|
| 50 |
+
);
|
| 51 |
+
};
|
| 52 |
|
| 53 |
+
export default App;
|
web/src/layouts/index.tsx
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import React, { useEffect, useState } from 'react';
|
| 2 |
-
import {
|
| 3 |
-
import {
|
| 4 |
-
import classnames from 'classnames'
|
| 5 |
import '../locales/config';
|
| 6 |
-
import
|
| 7 |
-
import
|
| 8 |
-
RedditOutlined
|
| 9 |
-
} from '@ant-design/icons';
|
| 10 |
-
import { Layout, Button, theme, Space, } from 'antd';
|
| 11 |
-
import styles from './index.less'
|
| 12 |
-
import User from './components/user'
|
| 13 |
-
import { head } from 'lodash';
|
| 14 |
|
| 15 |
const { Header, Content } = Layout;
|
| 16 |
|
| 17 |
const App: React.FC = (props) => {
|
| 18 |
-
const { t } = useTranslation()
|
| 19 |
-
const navigate = useNavigate()
|
| 20 |
const {
|
| 21 |
token: { colorBgContainer, borderRadiusLG },
|
| 22 |
} = theme.useToken();
|
|
@@ -25,34 +21,49 @@ const App: React.FC = (props) => {
|
|
| 25 |
const location = useLocation();
|
| 26 |
useEffect(() => {
|
| 27 |
if (location.pathname !== '/') {
|
| 28 |
-
const path = location.pathname.split('/')
|
| 29 |
-
setCurrent(path[1]);
|
| 30 |
}
|
| 31 |
-
console.log(location.pathname.split('/'))
|
| 32 |
-
}, [location.pathname])
|
| 33 |
|
| 34 |
const handleChange = (path: string) => {
|
| 35 |
-
setCurrent(path)
|
| 36 |
navigate(path);
|
| 37 |
};
|
| 38 |
-
const tagsData = [
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
return (
|
| 41 |
-
<Layout className={styles.layout}
|
| 42 |
<Layout>
|
| 43 |
-
<Header
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
<img src={logo} alt="" style={{ height: 30, width: 30 }} />
|
| 46 |
<Space size={[0, 8]} wrap>
|
| 47 |
-
{tagsData.map((item) =>
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
</Space>
|
| 55 |
-
<User
|
| 56 |
</Header>
|
| 57 |
<Content
|
| 58 |
style={{
|
|
@@ -61,14 +72,14 @@ const App: React.FC = (props) => {
|
|
| 61 |
minHeight: 280,
|
| 62 |
background: colorBgContainer,
|
| 63 |
borderRadius: borderRadiusLG,
|
| 64 |
-
overflow: 'auto'
|
| 65 |
}}
|
| 66 |
>
|
| 67 |
<Outlet />
|
| 68 |
</Content>
|
| 69 |
</Layout>
|
| 70 |
-
</Layout
|
| 71 |
);
|
| 72 |
};
|
| 73 |
|
| 74 |
-
export default App;
|
|
|
|
| 1 |
+
import logo from '@/assets/logo.png';
|
| 2 |
+
import { Layout, Space, theme } from 'antd';
|
| 3 |
+
import classnames from 'classnames';
|
| 4 |
import React, { useEffect, useState } from 'react';
|
| 5 |
+
import { useTranslation } from 'react-i18next';
|
| 6 |
+
import { Outlet, useLocation, useNavigate } from 'umi';
|
|
|
|
| 7 |
import '../locales/config';
|
| 8 |
+
import User from './components/user';
|
| 9 |
+
import styles from './index.less';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
const { Header, Content } = Layout;
|
| 12 |
|
| 13 |
const App: React.FC = (props) => {
|
| 14 |
+
const { t } = useTranslation();
|
| 15 |
+
const navigate = useNavigate();
|
| 16 |
const {
|
| 17 |
token: { colorBgContainer, borderRadiusLG },
|
| 18 |
} = theme.useToken();
|
|
|
|
| 21 |
const location = useLocation();
|
| 22 |
useEffect(() => {
|
| 23 |
if (location.pathname !== '/') {
|
| 24 |
+
const path = location.pathname.split('/');
|
| 25 |
+
// setCurrent(path[1]);
|
| 26 |
}
|
| 27 |
+
console.log(location.pathname.split('/'));
|
| 28 |
+
}, [location.pathname]);
|
| 29 |
|
| 30 |
const handleChange = (path: string) => {
|
| 31 |
+
// setCurrent(path)
|
| 32 |
navigate(path);
|
| 33 |
};
|
| 34 |
+
const tagsData = [
|
| 35 |
+
{ path: '/knowledge', name: 'knowledge' },
|
| 36 |
+
{ path: '/chat', name: 'chat' },
|
| 37 |
+
{ path: '/file', name: 'file' },
|
| 38 |
+
];
|
| 39 |
|
| 40 |
return (
|
| 41 |
+
<Layout className={styles.layout}>
|
| 42 |
<Layout>
|
| 43 |
+
<Header
|
| 44 |
+
style={{
|
| 45 |
+
padding: '0 8px',
|
| 46 |
+
background: colorBgContainer,
|
| 47 |
+
display: 'flex',
|
| 48 |
+
justifyContent: 'space-between',
|
| 49 |
+
alignItems: 'center',
|
| 50 |
+
}}
|
| 51 |
+
>
|
| 52 |
<img src={logo} alt="" style={{ height: 30, width: 30 }} />
|
| 53 |
<Space size={[0, 8]} wrap>
|
| 54 |
+
{tagsData.map((item) => (
|
| 55 |
+
<span
|
| 56 |
+
key={item.name}
|
| 57 |
+
className={classnames(styles['tag'], {
|
| 58 |
+
[styles['checked']]: current === item.name,
|
| 59 |
+
})}
|
| 60 |
+
onClick={() => handleChange(item.path)}
|
| 61 |
+
>
|
| 62 |
+
{item.name}
|
| 63 |
+
</span>
|
| 64 |
+
))}
|
| 65 |
</Space>
|
| 66 |
+
<User></User>
|
| 67 |
</Header>
|
| 68 |
<Content
|
| 69 |
style={{
|
|
|
|
| 72 |
minHeight: 280,
|
| 73 |
background: colorBgContainer,
|
| 74 |
borderRadius: borderRadiusLG,
|
| 75 |
+
overflow: 'auto',
|
| 76 |
}}
|
| 77 |
>
|
| 78 |
<Outlet />
|
| 79 |
</Content>
|
| 80 |
</Layout>
|
| 81 |
+
</Layout>
|
| 82 |
);
|
| 83 |
};
|
| 84 |
|
| 85 |
+
export default App;
|
web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
-
import { Effect, Reducer, Subscription } from 'umi'
|
| 2 |
-
import { message } from 'antd';
|
| 3 |
import kbService from '@/services/kbService';
|
|
|
|
| 4 |
|
| 5 |
export interface chunkModelState {
|
| 6 |
loading: boolean;
|
|
@@ -9,7 +8,7 @@ export interface chunkModelState {
|
|
| 9 |
isShowCreateModal: boolean;
|
| 10 |
chunk_id: string;
|
| 11 |
doc_id: string;
|
| 12 |
-
chunkInfo: any
|
| 13 |
}
|
| 14 |
export interface chunkgModelType {
|
| 15 |
namespace: 'chunkModel';
|
|
@@ -24,7 +23,7 @@ export interface chunkgModelType {
|
|
| 24 |
reducers: {
|
| 25 |
updateState: Reducer<chunkModelState>;
|
| 26 |
};
|
| 27 |
-
subscriptions: { setup: Subscription };
|
| 28 |
}
|
| 29 |
const Model: chunkgModelType = {
|
| 30 |
namespace: 'chunkModel',
|
|
@@ -35,91 +34,86 @@ const Model: chunkgModelType = {
|
|
| 35 |
isShowCreateModal: false,
|
| 36 |
chunk_id: '',
|
| 37 |
doc_id: '',
|
| 38 |
-
chunkInfo: {}
|
| 39 |
-
},
|
| 40 |
-
subscriptions: {
|
| 41 |
-
setup({ dispatch, history }) {
|
| 42 |
-
history.listen(location => {
|
| 43 |
-
console.log(location)
|
| 44 |
-
});
|
| 45 |
-
}
|
| 46 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
effects: {
|
| 48 |
-
*
|
| 49 |
const { data, response } = yield call(kbService.chunk_list, payload);
|
| 50 |
|
| 51 |
-
const { retcode, data: res, retmsg } = data
|
| 52 |
if (retcode === 0) {
|
| 53 |
-
console.log(res)
|
| 54 |
yield put({
|
| 55 |
type: 'updateState',
|
| 56 |
payload: {
|
| 57 |
data: res.chunks,
|
| 58 |
total: res.total,
|
| 59 |
-
loading: false
|
| 60 |
-
}
|
| 61 |
});
|
| 62 |
-
callback && callback()
|
| 63 |
-
|
| 64 |
}
|
| 65 |
},
|
| 66 |
*switch_chunk({ payload = {}, callback }, { call, put }) {
|
| 67 |
const { data, response } = yield call(kbService.switch_chunk, payload);
|
| 68 |
-
const { retcode, data: res, retmsg } = data
|
| 69 |
if (retcode === 0) {
|
| 70 |
-
callback && callback()
|
| 71 |
-
|
| 72 |
}
|
| 73 |
},
|
| 74 |
*rm_chunk({ payload = {}, callback }, { call, put }) {
|
| 75 |
-
console.log('shanchu')
|
| 76 |
const { data, response } = yield call(kbService.rm_chunk, payload);
|
| 77 |
-
const { retcode, data: res, retmsg } = data
|
| 78 |
if (retcode === 0) {
|
| 79 |
-
callback && callback()
|
| 80 |
-
|
| 81 |
}
|
| 82 |
},
|
| 83 |
-
*
|
| 84 |
const { data, response } = yield call(kbService.get_chunk, payload);
|
| 85 |
-
const { retcode, data: res, retmsg } = data
|
| 86 |
if (retcode === 0) {
|
| 87 |
-
|
| 88 |
yield put({
|
| 89 |
type: 'updateState',
|
| 90 |
payload: {
|
| 91 |
-
chunkInfo: res
|
| 92 |
-
}
|
| 93 |
});
|
| 94 |
-
callback && callback(res)
|
| 95 |
-
|
| 96 |
}
|
| 97 |
},
|
| 98 |
*create_hunk({ payload = {} }, { call, put }) {
|
| 99 |
yield put({
|
| 100 |
type: 'updateState',
|
| 101 |
payload: {
|
| 102 |
-
loading: true
|
| 103 |
-
}
|
| 104 |
});
|
| 105 |
-
let service = kbService.create_chunk
|
| 106 |
if (payload.chunk_id) {
|
| 107 |
-
service = kbService.set_chunk
|
| 108 |
}
|
| 109 |
const { data, response } = yield call(service, payload);
|
| 110 |
-
const { retcode, data: res, retmsg } = data
|
| 111 |
yield put({
|
| 112 |
type: 'updateState',
|
| 113 |
payload: {
|
| 114 |
-
loading: false
|
| 115 |
-
}
|
| 116 |
});
|
| 117 |
if (retcode === 0) {
|
| 118 |
yield put({
|
| 119 |
type: 'updateState',
|
| 120 |
payload: {
|
| 121 |
-
isShowCreateModal: false
|
| 122 |
-
}
|
| 123 |
});
|
| 124 |
}
|
| 125 |
},
|
|
@@ -128,9 +122,9 @@ const Model: chunkgModelType = {
|
|
| 128 |
updateState(state, { payload }) {
|
| 129 |
return {
|
| 130 |
...state,
|
| 131 |
-
...payload
|
| 132 |
};
|
| 133 |
-
}
|
| 134 |
-
}
|
| 135 |
};
|
| 136 |
export default Model;
|
|
|
|
|
|
|
|
|
|
| 1 |
import kbService from '@/services/kbService';
|
| 2 |
+
import { Effect, Reducer } from 'umi';
|
| 3 |
|
| 4 |
export interface chunkModelState {
|
| 5 |
loading: boolean;
|
|
|
|
| 8 |
isShowCreateModal: boolean;
|
| 9 |
chunk_id: string;
|
| 10 |
doc_id: string;
|
| 11 |
+
chunkInfo: any;
|
| 12 |
}
|
| 13 |
export interface chunkgModelType {
|
| 14 |
namespace: 'chunkModel';
|
|
|
|
| 23 |
reducers: {
|
| 24 |
updateState: Reducer<chunkModelState>;
|
| 25 |
};
|
| 26 |
+
// subscriptions: { setup: Subscription };
|
| 27 |
}
|
| 28 |
const Model: chunkgModelType = {
|
| 29 |
namespace: 'chunkModel',
|
|
|
|
| 34 |
isShowCreateModal: false,
|
| 35 |
chunk_id: '',
|
| 36 |
doc_id: '',
|
| 37 |
+
chunkInfo: {},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
},
|
| 39 |
+
// subscriptions: {
|
| 40 |
+
// setup({ dispatch, history }) {
|
| 41 |
+
// history.listen(location => {
|
| 42 |
+
// console.log(location)
|
| 43 |
+
// });
|
| 44 |
+
// }
|
| 45 |
+
// },
|
| 46 |
effects: {
|
| 47 |
+
*chunk_list({ payload = {}, callback }, { call, put }) {
|
| 48 |
const { data, response } = yield call(kbService.chunk_list, payload);
|
| 49 |
|
| 50 |
+
const { retcode, data: res, retmsg } = data;
|
| 51 |
if (retcode === 0) {
|
| 52 |
+
console.log(res);
|
| 53 |
yield put({
|
| 54 |
type: 'updateState',
|
| 55 |
payload: {
|
| 56 |
data: res.chunks,
|
| 57 |
total: res.total,
|
| 58 |
+
loading: false,
|
| 59 |
+
},
|
| 60 |
});
|
| 61 |
+
callback && callback();
|
|
|
|
| 62 |
}
|
| 63 |
},
|
| 64 |
*switch_chunk({ payload = {}, callback }, { call, put }) {
|
| 65 |
const { data, response } = yield call(kbService.switch_chunk, payload);
|
| 66 |
+
const { retcode, data: res, retmsg } = data;
|
| 67 |
if (retcode === 0) {
|
| 68 |
+
callback && callback();
|
|
|
|
| 69 |
}
|
| 70 |
},
|
| 71 |
*rm_chunk({ payload = {}, callback }, { call, put }) {
|
| 72 |
+
console.log('shanchu');
|
| 73 |
const { data, response } = yield call(kbService.rm_chunk, payload);
|
| 74 |
+
const { retcode, data: res, retmsg } = data;
|
| 75 |
if (retcode === 0) {
|
| 76 |
+
callback && callback();
|
|
|
|
| 77 |
}
|
| 78 |
},
|
| 79 |
+
*get_chunk({ payload = {}, callback }, { call, put }) {
|
| 80 |
const { data, response } = yield call(kbService.get_chunk, payload);
|
| 81 |
+
const { retcode, data: res, retmsg } = data;
|
| 82 |
if (retcode === 0) {
|
|
|
|
| 83 |
yield put({
|
| 84 |
type: 'updateState',
|
| 85 |
payload: {
|
| 86 |
+
chunkInfo: res,
|
| 87 |
+
},
|
| 88 |
});
|
| 89 |
+
callback && callback(res);
|
|
|
|
| 90 |
}
|
| 91 |
},
|
| 92 |
*create_hunk({ payload = {} }, { call, put }) {
|
| 93 |
yield put({
|
| 94 |
type: 'updateState',
|
| 95 |
payload: {
|
| 96 |
+
loading: true,
|
| 97 |
+
},
|
| 98 |
});
|
| 99 |
+
let service = kbService.create_chunk;
|
| 100 |
if (payload.chunk_id) {
|
| 101 |
+
service = kbService.set_chunk;
|
| 102 |
}
|
| 103 |
const { data, response } = yield call(service, payload);
|
| 104 |
+
const { retcode, data: res, retmsg } = data;
|
| 105 |
yield put({
|
| 106 |
type: 'updateState',
|
| 107 |
payload: {
|
| 108 |
+
loading: false,
|
| 109 |
+
},
|
| 110 |
});
|
| 111 |
if (retcode === 0) {
|
| 112 |
yield put({
|
| 113 |
type: 'updateState',
|
| 114 |
payload: {
|
| 115 |
+
isShowCreateModal: false,
|
| 116 |
+
},
|
| 117 |
});
|
| 118 |
}
|
| 119 |
},
|
|
|
|
| 122 |
updateState(state, { payload }) {
|
| 123 |
return {
|
| 124 |
...state,
|
| 125 |
+
...payload,
|
| 126 |
};
|
| 127 |
+
},
|
| 128 |
+
},
|
| 129 |
};
|
| 130 |
export default Model;
|
web/src/pages/add-knowledge/components/knowledge-file/model.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
-
import { message } from 'antd';
|
| 2 |
-
import { Effect, Reducer, Subscription } from 'umi'
|
| 3 |
import kbService from '@/services/kbService';
|
|
|
|
|
|
|
| 4 |
|
| 5 |
export interface kFModelState {
|
| 6 |
isShowCEFwModal: boolean;
|
|
@@ -8,7 +8,7 @@ export interface kFModelState {
|
|
| 8 |
isShowSegmentSetModal: boolean;
|
| 9 |
loading: boolean;
|
| 10 |
tenantIfo: any;
|
| 11 |
-
data: any[]
|
| 12 |
}
|
| 13 |
export interface kFModelType {
|
| 14 |
namespace: 'kFModel';
|
|
@@ -36,60 +36,60 @@ const Model: kFModelType = {
|
|
| 36 |
isShowSegmentSetModal: false,
|
| 37 |
loading: false,
|
| 38 |
tenantIfo: {},
|
| 39 |
-
data: []
|
| 40 |
},
|
| 41 |
subscriptions: {
|
| 42 |
setup({ dispatch, history }) {
|
| 43 |
-
history.listen(location => {
|
| 44 |
-
|
| 45 |
-
}
|
| 46 |
},
|
| 47 |
effects: {
|
| 48 |
-
*
|
| 49 |
const { data, response } = yield call(kbService.createKb, payload);
|
| 50 |
-
const { retcode, data: res, retmsg } = data
|
| 51 |
if (retcode === 0) {
|
| 52 |
-
|
| 53 |
message.success('创建成功!');
|
| 54 |
}
|
| 55 |
},
|
| 56 |
-
*
|
| 57 |
const { data, response } = yield call(kbService.updateKb, payload);
|
| 58 |
-
const { retcode, data: res, retmsg } = data
|
| 59 |
if (retcode === 0) {
|
| 60 |
message.success('修改成功!');
|
| 61 |
-
|
| 62 |
}
|
| 63 |
},
|
| 64 |
*getKfDetail({ payload = {}, callback }, { call, put }) {
|
| 65 |
const { data, response } = yield call(kbService.get_kb_detail, payload);
|
| 66 |
-
const { retcode, data: res, retmsg } = data
|
| 67 |
if (retcode === 0) {
|
| 68 |
// localStorage.setItem('userInfo',res.)
|
| 69 |
-
callback && callback(res)
|
| 70 |
}
|
| 71 |
},
|
| 72 |
*getKfList({ payload = {} }, { call, put }) {
|
| 73 |
yield put({
|
| 74 |
type: 'updateState',
|
| 75 |
payload: {
|
| 76 |
-
loading: true
|
| 77 |
-
}
|
| 78 |
});
|
| 79 |
-
const { data, response } = yield call(
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
| 81 |
yield put({
|
| 82 |
type: 'updateState',
|
| 83 |
payload: {
|
| 84 |
-
loading: false
|
| 85 |
-
}
|
| 86 |
});
|
| 87 |
if (retcode === 0) {
|
| 88 |
yield put({
|
| 89 |
type: 'updateState',
|
| 90 |
payload: {
|
| 91 |
-
data: res
|
| 92 |
-
}
|
| 93 |
});
|
| 94 |
}
|
| 95 |
},
|
|
@@ -97,58 +97,60 @@ const Model: kFModelType = {
|
|
| 97 |
yield put({
|
| 98 |
type: 'updateState',
|
| 99 |
payload: {
|
| 100 |
-
loading: true
|
| 101 |
-
}
|
| 102 |
});
|
| 103 |
-
const { data, response } = yield call(
|
| 104 |
-
|
|
|
|
|
|
|
|
|
|
| 105 |
if (retcode === 0) {
|
| 106 |
message.success('修改成功!');
|
| 107 |
yield put({
|
| 108 |
type: 'updateState',
|
| 109 |
payload: {
|
| 110 |
-
loading: false
|
| 111 |
-
}
|
| 112 |
});
|
| 113 |
-
callback && callback()
|
| 114 |
}
|
| 115 |
-
|
| 116 |
},
|
| 117 |
*document_rm({ payload = {}, callback }, { call, put }) {
|
| 118 |
const { data, response } = yield call(kbService.document_rm, payload);
|
| 119 |
-
const { retcode, data: res, retmsg } = data
|
| 120 |
if (retcode === 0) {
|
| 121 |
message.success('删除成功!');
|
| 122 |
-
callback && callback()
|
| 123 |
}
|
| 124 |
-
|
| 125 |
},
|
| 126 |
*document_create({ payload = {}, callback }, { call, put }) {
|
| 127 |
const { data, response } = yield call(kbService.document_create, payload);
|
| 128 |
-
const { retcode, data: res, retmsg } = data
|
| 129 |
if (retcode === 0) {
|
| 130 |
message.success('创建成功!');
|
| 131 |
-
callback && callback()
|
| 132 |
}
|
| 133 |
-
|
| 134 |
},
|
| 135 |
*document_change_parser({ payload = {}, callback }, { call, put }) {
|
| 136 |
-
const { data, response } = yield call(
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
| 138 |
if (retcode === 0) {
|
| 139 |
message.success('修改成功!');
|
| 140 |
-
callback && callback()
|
| 141 |
}
|
| 142 |
-
|
| 143 |
},
|
| 144 |
},
|
| 145 |
reducers: {
|
| 146 |
updateState(state, { payload }) {
|
| 147 |
return {
|
| 148 |
...state,
|
| 149 |
-
...payload
|
| 150 |
};
|
| 151 |
-
}
|
| 152 |
-
}
|
| 153 |
};
|
| 154 |
export default Model;
|
|
|
|
|
|
|
|
|
|
| 1 |
import kbService from '@/services/kbService';
|
| 2 |
+
import { message } from 'antd';
|
| 3 |
+
import { Effect, Reducer, Subscription } from 'umi';
|
| 4 |
|
| 5 |
export interface kFModelState {
|
| 6 |
isShowCEFwModal: boolean;
|
|
|
|
| 8 |
isShowSegmentSetModal: boolean;
|
| 9 |
loading: boolean;
|
| 10 |
tenantIfo: any;
|
| 11 |
+
data: any[];
|
| 12 |
}
|
| 13 |
export interface kFModelType {
|
| 14 |
namespace: 'kFModel';
|
|
|
|
| 36 |
isShowSegmentSetModal: false,
|
| 37 |
loading: false,
|
| 38 |
tenantIfo: {},
|
| 39 |
+
data: [],
|
| 40 |
},
|
| 41 |
subscriptions: {
|
| 42 |
setup({ dispatch, history }) {
|
| 43 |
+
history.listen((location) => {});
|
| 44 |
+
},
|
|
|
|
| 45 |
},
|
| 46 |
effects: {
|
| 47 |
+
*createKf({ payload = {}, callback }, { call, put }) {
|
| 48 |
const { data, response } = yield call(kbService.createKb, payload);
|
| 49 |
+
const { retcode, data: res, retmsg } = data;
|
| 50 |
if (retcode === 0) {
|
|
|
|
| 51 |
message.success('创建成功!');
|
| 52 |
}
|
| 53 |
},
|
| 54 |
+
*updateKf({ payload = {}, callback }, { call, put }) {
|
| 55 |
const { data, response } = yield call(kbService.updateKb, payload);
|
| 56 |
+
const { retcode, data: res, retmsg } = data;
|
| 57 |
if (retcode === 0) {
|
| 58 |
message.success('修改成功!');
|
|
|
|
| 59 |
}
|
| 60 |
},
|
| 61 |
*getKfDetail({ payload = {}, callback }, { call, put }) {
|
| 62 |
const { data, response } = yield call(kbService.get_kb_detail, payload);
|
| 63 |
+
const { retcode, data: res, retmsg } = data;
|
| 64 |
if (retcode === 0) {
|
| 65 |
// localStorage.setItem('userInfo',res.)
|
| 66 |
+
callback && callback(res);
|
| 67 |
}
|
| 68 |
},
|
| 69 |
*getKfList({ payload = {} }, { call, put }) {
|
| 70 |
yield put({
|
| 71 |
type: 'updateState',
|
| 72 |
payload: {
|
| 73 |
+
loading: true,
|
| 74 |
+
},
|
| 75 |
});
|
| 76 |
+
const { data, response } = yield call(
|
| 77 |
+
kbService.get_document_list,
|
| 78 |
+
payload,
|
| 79 |
+
);
|
| 80 |
+
const { retcode, data: res, retmsg } = data;
|
| 81 |
yield put({
|
| 82 |
type: 'updateState',
|
| 83 |
payload: {
|
| 84 |
+
loading: false,
|
| 85 |
+
},
|
| 86 |
});
|
| 87 |
if (retcode === 0) {
|
| 88 |
yield put({
|
| 89 |
type: 'updateState',
|
| 90 |
payload: {
|
| 91 |
+
data: res,
|
| 92 |
+
},
|
| 93 |
});
|
| 94 |
}
|
| 95 |
},
|
|
|
|
| 97 |
yield put({
|
| 98 |
type: 'updateState',
|
| 99 |
payload: {
|
| 100 |
+
loading: true,
|
| 101 |
+
},
|
| 102 |
});
|
| 103 |
+
const { data, response } = yield call(
|
| 104 |
+
kbService.document_change_status,
|
| 105 |
+
payload,
|
| 106 |
+
);
|
| 107 |
+
const { retcode, data: res, retmsg } = data;
|
| 108 |
if (retcode === 0) {
|
| 109 |
message.success('修改成功!');
|
| 110 |
yield put({
|
| 111 |
type: 'updateState',
|
| 112 |
payload: {
|
| 113 |
+
loading: false,
|
| 114 |
+
},
|
| 115 |
});
|
| 116 |
+
callback && callback();
|
| 117 |
}
|
|
|
|
| 118 |
},
|
| 119 |
*document_rm({ payload = {}, callback }, { call, put }) {
|
| 120 |
const { data, response } = yield call(kbService.document_rm, payload);
|
| 121 |
+
const { retcode, data: res, retmsg } = data;
|
| 122 |
if (retcode === 0) {
|
| 123 |
message.success('删除成功!');
|
| 124 |
+
callback && callback();
|
| 125 |
}
|
|
|
|
| 126 |
},
|
| 127 |
*document_create({ payload = {}, callback }, { call, put }) {
|
| 128 |
const { data, response } = yield call(kbService.document_create, payload);
|
| 129 |
+
const { retcode, data: res, retmsg } = data;
|
| 130 |
if (retcode === 0) {
|
| 131 |
message.success('创建成功!');
|
| 132 |
+
callback && callback();
|
| 133 |
}
|
|
|
|
| 134 |
},
|
| 135 |
*document_change_parser({ payload = {}, callback }, { call, put }) {
|
| 136 |
+
const { data, response } = yield call(
|
| 137 |
+
kbService.document_change_parser,
|
| 138 |
+
payload,
|
| 139 |
+
);
|
| 140 |
+
const { retcode, data: res, retmsg } = data;
|
| 141 |
if (retcode === 0) {
|
| 142 |
message.success('修改成功!');
|
| 143 |
+
callback && callback();
|
| 144 |
}
|
|
|
|
| 145 |
},
|
| 146 |
},
|
| 147 |
reducers: {
|
| 148 |
updateState(state, { payload }) {
|
| 149 |
return {
|
| 150 |
...state,
|
| 151 |
+
...payload,
|
| 152 |
};
|
| 153 |
+
},
|
| 154 |
+
},
|
| 155 |
};
|
| 156 |
export default Model;
|
web/src/pages/knowledge/index.tsx
CHANGED
|
@@ -1,109 +1,131 @@
|
|
| 1 |
-
import
|
| 2 |
-
import {
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
interface KnowledgeProps {
|
| 9 |
dispatch: Dispatch;
|
| 10 |
-
knowledgeModel: knowledgeModelState
|
| 11 |
}
|
| 12 |
const Index: React.FC<KnowledgeProps> = ({ knowledgeModel, dispatch }) => {
|
| 13 |
-
const navigate = useNavigate()
|
| 14 |
// const [datas, setDatas] = useState(data)
|
| 15 |
-
const { data = [] } = knowledgeModel
|
| 16 |
-
console.log(knowledgeModel)
|
|
|
|
|
|
|
|
|
|
| 17 |
const confirm = (id: string) => {
|
| 18 |
dispatch({
|
| 19 |
type: 'knowledgeModel/rmKb',
|
| 20 |
payload: {
|
| 21 |
-
kb_id: id
|
| 22 |
},
|
| 23 |
callback: () => {
|
| 24 |
dispatch({
|
| 25 |
type: 'knowledgeModel/getList',
|
| 26 |
-
payload: {
|
| 27 |
-
|
| 28 |
-
}
|
| 29 |
});
|
| 30 |
-
}
|
| 31 |
});
|
| 32 |
};
|
| 33 |
const handleAddKnowledge = () => {
|
| 34 |
navigate(`add/setting?activeKey=setting`);
|
| 35 |
-
}
|
| 36 |
const handleEditKnowledge = (id: string) => {
|
| 37 |
navigate(`add/setting?activeKey=file&id=${id}`);
|
| 38 |
-
}
|
| 39 |
useEffect(() => {
|
| 40 |
dispatch({
|
| 41 |
type: 'knowledgeModel/getList',
|
| 42 |
-
payload: {
|
| 43 |
-
|
| 44 |
-
}
|
| 45 |
});
|
| 46 |
-
}, [])
|
| 47 |
-
return (
|
| 48 |
-
|
| 49 |
-
<
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
>
|
| 57 |
-
<
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
</
|
| 87 |
-
<
|
| 88 |
-
<
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
</div>
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
</>
|
| 106 |
-
)
|
| 107 |
};
|
| 108 |
|
| 109 |
-
export default connect(({ knowledgeModel, loading }) => ({
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { formatDate } from '@/utils/date';
|
| 2 |
+
import {
|
| 3 |
+
DeleteOutlined,
|
| 4 |
+
MinusSquareOutlined,
|
| 5 |
+
PlusOutlined,
|
| 6 |
+
} from '@ant-design/icons';
|
| 7 |
+
import { Card, Col, FloatButton, Popconfirm, Row } from 'antd';
|
| 8 |
+
import React, { useEffect } from 'react';
|
| 9 |
+
import { Dispatch, connect, useNavigate } from 'umi';
|
| 10 |
+
import styles from './index.less';
|
| 11 |
+
import type { knowledgeModelState } from './model';
|
| 12 |
interface KnowledgeProps {
|
| 13 |
dispatch: Dispatch;
|
| 14 |
+
knowledgeModel: knowledgeModelState;
|
| 15 |
}
|
| 16 |
const Index: React.FC<KnowledgeProps> = ({ knowledgeModel, dispatch }) => {
|
| 17 |
+
const navigate = useNavigate();
|
| 18 |
// const [datas, setDatas] = useState(data)
|
| 19 |
+
const { data = [] } = knowledgeModel;
|
| 20 |
+
console.log(knowledgeModel);
|
| 21 |
+
|
| 22 |
+
// const x = useSelector((state) => state.knowledgeModel);
|
| 23 |
+
|
| 24 |
const confirm = (id: string) => {
|
| 25 |
dispatch({
|
| 26 |
type: 'knowledgeModel/rmKb',
|
| 27 |
payload: {
|
| 28 |
+
kb_id: id,
|
| 29 |
},
|
| 30 |
callback: () => {
|
| 31 |
dispatch({
|
| 32 |
type: 'knowledgeModel/getList',
|
| 33 |
+
payload: {},
|
|
|
|
|
|
|
| 34 |
});
|
| 35 |
+
},
|
| 36 |
});
|
| 37 |
};
|
| 38 |
const handleAddKnowledge = () => {
|
| 39 |
navigate(`add/setting?activeKey=setting`);
|
| 40 |
+
};
|
| 41 |
const handleEditKnowledge = (id: string) => {
|
| 42 |
navigate(`add/setting?activeKey=file&id=${id}`);
|
| 43 |
+
};
|
| 44 |
useEffect(() => {
|
| 45 |
dispatch({
|
| 46 |
type: 'knowledgeModel/getList',
|
| 47 |
+
payload: {},
|
|
|
|
|
|
|
| 48 |
});
|
| 49 |
+
}, []);
|
| 50 |
+
return (
|
| 51 |
+
<>
|
| 52 |
+
<div className={styles.knowledge}>
|
| 53 |
+
<FloatButton
|
| 54 |
+
onClick={handleAddKnowledge}
|
| 55 |
+
icon={<PlusOutlined />}
|
| 56 |
+
type="primary"
|
| 57 |
+
style={{ right: 24, top: 100 }}
|
| 58 |
+
/>
|
| 59 |
+
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
|
| 60 |
+
{data.map((item: any) => {
|
| 61 |
+
return (
|
| 62 |
+
<Col
|
| 63 |
+
className="gutter-row"
|
| 64 |
+
key={item.name}
|
| 65 |
+
xs={24}
|
| 66 |
+
sm={12}
|
| 67 |
+
md={8}
|
| 68 |
+
lg={6}
|
| 69 |
>
|
| 70 |
+
<Card
|
| 71 |
+
className={styles.card}
|
| 72 |
+
onClick={() => {
|
| 73 |
+
handleEditKnowledge(item.id);
|
| 74 |
+
}}
|
| 75 |
+
>
|
| 76 |
+
<div className={styles.container}>
|
| 77 |
+
<div className={styles.content}>
|
| 78 |
+
<span className={styles.context}>{item.name}</span>
|
| 79 |
+
<span className={styles.delete}>
|
| 80 |
+
<Popconfirm
|
| 81 |
+
title="Delete the task"
|
| 82 |
+
description="Are you sure to delete this task?"
|
| 83 |
+
onConfirm={(e: any) => {
|
| 84 |
+
e.stopPropagation();
|
| 85 |
+
e.nativeEvent.stopImmediatePropagation();
|
| 86 |
+
confirm(item.id);
|
| 87 |
+
}}
|
| 88 |
+
okText="Yes"
|
| 89 |
+
cancelText="No"
|
| 90 |
+
>
|
| 91 |
+
<DeleteOutlined
|
| 92 |
+
onClick={(e) => {
|
| 93 |
+
e.stopPropagation();
|
| 94 |
+
e.nativeEvent.stopImmediatePropagation();
|
| 95 |
+
}}
|
| 96 |
+
/>
|
| 97 |
+
</Popconfirm>
|
| 98 |
+
</span>
|
| 99 |
+
</div>
|
| 100 |
+
<div className={styles.footer}>
|
| 101 |
+
<span className={styles.text}>
|
| 102 |
+
<MinusSquareOutlined />
|
| 103 |
+
{item.doc_num}文档
|
| 104 |
+
</span>
|
| 105 |
+
<span className={styles.text}>
|
| 106 |
+
<MinusSquareOutlined />
|
| 107 |
+
{item.chunk_num}个
|
| 108 |
+
</span>
|
| 109 |
+
<span className={styles.text}>
|
| 110 |
+
<MinusSquareOutlined />
|
| 111 |
+
{item.token_num}千字符
|
| 112 |
+
</span>
|
| 113 |
+
<span style={{ float: 'right' }}>
|
| 114 |
+
{formatDate(item.update_date)}
|
| 115 |
+
</span>
|
| 116 |
+
</div>
|
| 117 |
</div>
|
| 118 |
+
</Card>
|
| 119 |
+
</Col>
|
| 120 |
+
);
|
| 121 |
+
})}
|
| 122 |
+
</Row>
|
| 123 |
+
</div>
|
| 124 |
+
</>
|
| 125 |
+
);
|
|
|
|
|
|
|
| 126 |
};
|
| 127 |
|
| 128 |
+
export default connect(({ knowledgeModel, loading }) => ({
|
| 129 |
+
knowledgeModel,
|
| 130 |
+
loading,
|
| 131 |
+
}))(Index);
|
web/src/pages/knowledge/model.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
import kbService from '@/services/kbService';
|
| 2 |
-
import { Effect, Reducer
|
| 3 |
|
| 4 |
export interface knowledgeModelState {
|
| 5 |
loading: boolean;
|
|
@@ -15,7 +15,7 @@ export interface knowledgegModelType {
|
|
| 15 |
reducers: {
|
| 16 |
updateState: Reducer<knowledgeModelState>;
|
| 17 |
};
|
| 18 |
-
subscriptions: { setup: Subscription };
|
| 19 |
}
|
| 20 |
const Model: knowledgegModelType = {
|
| 21 |
namespace: 'knowledgeModel',
|
|
@@ -23,13 +23,13 @@ const Model: knowledgegModelType = {
|
|
| 23 |
loading: false,
|
| 24 |
data: [],
|
| 25 |
},
|
| 26 |
-
subscriptions: {
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
},
|
| 33 |
effects: {
|
| 34 |
*rmKb({ payload = {}, callback }, { call, put }) {
|
| 35 |
const { data, response } = yield call(kbService.rmKb, payload);
|
|
|
|
| 1 |
import kbService from '@/services/kbService';
|
| 2 |
+
import { Effect, Reducer } from 'umi';
|
| 3 |
|
| 4 |
export interface knowledgeModelState {
|
| 5 |
loading: boolean;
|
|
|
|
| 15 |
reducers: {
|
| 16 |
updateState: Reducer<knowledgeModelState>;
|
| 17 |
};
|
| 18 |
+
// subscriptions: { setup: Subscription };
|
| 19 |
}
|
| 20 |
const Model: knowledgegModelType = {
|
| 21 |
namespace: 'knowledgeModel',
|
|
|
|
| 23 |
loading: false,
|
| 24 |
data: [],
|
| 25 |
},
|
| 26 |
+
// subscriptions: {
|
| 27 |
+
// setup({ dispatch, history }) {
|
| 28 |
+
// history.listen((location) => {
|
| 29 |
+
// console.log(location);
|
| 30 |
+
// });
|
| 31 |
+
// },
|
| 32 |
+
// },
|
| 33 |
effects: {
|
| 34 |
*rmKb({ payload = {}, callback }, { call, put }) {
|
| 35 |
const { data, response } = yield call(kbService.rmKb, payload);
|
web/src/pages/login/index.tsx
CHANGED
|
@@ -1,19 +1,18 @@
|
|
| 1 |
-
import {
|
| 2 |
-
import {
|
|
|
|
|
|
|
| 3 |
import styles from './index.less';
|
| 4 |
-
import { rsaPsw } from '@/utils'
|
| 5 |
-
import { useState, useEffect, FC } from 'react';
|
| 6 |
|
| 7 |
interface LoginProps {
|
| 8 |
dispatch: Dispatch;
|
| 9 |
}
|
| 10 |
-
const View: FC<LoginProps> = ({
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
const [title, setTitle] = useState('login')
|
| 14 |
const changeTitle = () => {
|
| 15 |
-
setTitle((title) => title === 'login' ? 'register' : 'login')
|
| 16 |
-
}
|
| 17 |
const [form] = Form.useForm();
|
| 18 |
const [checkNick, setCheckNick] = useState(false);
|
| 19 |
|
|
@@ -25,15 +24,17 @@ const View: FC<LoginProps> = ({
|
|
| 25 |
try {
|
| 26 |
const params = await form.validateFields();
|
| 27 |
|
| 28 |
-
var rsaPassWord = rsaPsw(params.password)
|
| 29 |
if (title === 'login') {
|
| 30 |
-
dispatch({
|
| 31 |
type: 'loginModel/login',
|
| 32 |
payload: {
|
| 33 |
email: params.email,
|
| 34 |
-
password: rsaPassWord
|
| 35 |
-
}
|
| 36 |
});
|
|
|
|
|
|
|
| 37 |
} else {
|
| 38 |
dispatch({
|
| 39 |
type: 'loginModel/register',
|
|
@@ -43,8 +44,8 @@ const View: FC<LoginProps> = ({
|
|
| 43 |
password: rsaPassWord,
|
| 44 |
},
|
| 45 |
callback() {
|
| 46 |
-
setTitle('login')
|
| 47 |
-
}
|
| 48 |
});
|
| 49 |
}
|
| 50 |
} catch (errorInfo) {
|
|
@@ -56,103 +57,124 @@ const View: FC<LoginProps> = ({
|
|
| 56 |
// wrapperCol: { span: 8 },
|
| 57 |
};
|
| 58 |
|
| 59 |
-
|
| 60 |
const toGoogle = () => {
|
| 61 |
-
window.location.href =
|
| 62 |
-
|
|
|
|
| 63 |
return (
|
| 64 |
<div className={styles.loginPage}>
|
| 65 |
-
|
| 66 |
<div className={styles.loginLeft}>
|
| 67 |
<div className={styles.modal}>
|
| 68 |
<div className={styles.loginTitle}>
|
| 69 |
-
<div>
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
</span>
|
| 75 |
</div>
|
| 76 |
|
| 77 |
-
<Form
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
<Form.Item
|
| 79 |
{...formItemLayout}
|
| 80 |
name="email"
|
| 81 |
label="Email"
|
| 82 |
rules={[{ required: true, message: 'Please input value' }]}
|
| 83 |
>
|
| 84 |
-
<Input size=
|
| 85 |
</Form.Item>
|
| 86 |
-
{
|
| 87 |
-
|
| 88 |
{...formItemLayout}
|
| 89 |
name="nickname"
|
| 90 |
label="Nickname"
|
| 91 |
-
rules={[
|
|
|
|
|
|
|
| 92 |
>
|
| 93 |
-
<Input size=
|
| 94 |
</Form.Item>
|
| 95 |
-
}
|
| 96 |
<Form.Item
|
| 97 |
{...formItemLayout}
|
| 98 |
name="password"
|
| 99 |
label="Password"
|
| 100 |
rules={[{ required: true, message: 'Please input value' }]}
|
| 101 |
>
|
| 102 |
-
<Input size=
|
| 103 |
</Form.Item>
|
| 104 |
-
{
|
| 105 |
-
|
| 106 |
-
name="remember"
|
| 107 |
-
valuePropName="checked"
|
| 108 |
-
|
| 109 |
-
>
|
| 110 |
<Checkbox> Remember me</Checkbox>
|
| 111 |
</Form.Item>
|
| 112 |
-
}
|
| 113 |
-
<div>
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
<
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
|
|
|
|
|
|
| 123 |
Already have an account?
|
| 124 |
<Button type="link" onClick={changeTitle}>
|
| 125 |
Sign in
|
| 126 |
</Button>
|
| 127 |
-
</div>
|
| 128 |
-
}
|
| 129 |
</div>
|
| 130 |
-
<Button type="primary" block size=
|
| 131 |
{title === 'login' ? 'Sign in' : 'Continue'}
|
| 132 |
</Button>
|
| 133 |
-
{
|
| 134 |
-
|
| 135 |
-
<
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
<div
|
| 142 |
-
<Icon
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
Sign in with Github
|
| 144 |
</div>
|
| 145 |
-
</Button
|
| 146 |
-
|
| 147 |
-
|
| 148 |
</Form>
|
| 149 |
</div>
|
| 150 |
</div>
|
| 151 |
-
<div className={styles.loginRight}>
|
| 152 |
-
|
| 153 |
-
</div>
|
| 154 |
</div>
|
| 155 |
);
|
| 156 |
};
|
| 157 |
|
| 158 |
-
export default connect(({ loginModel, loading }) => ({ loginModel, loading }))(
|
|
|
|
|
|
|
|
|
| 1 |
+
import { rsaPsw } from '@/utils';
|
| 2 |
+
import { Button, Checkbox, Form, Input } from 'antd';
|
| 3 |
+
import { FC, useEffect, useState } from 'react';
|
| 4 |
+
import { Dispatch, Icon, connect, useNavigate } from 'umi';
|
| 5 |
import styles from './index.less';
|
|
|
|
|
|
|
| 6 |
|
| 7 |
interface LoginProps {
|
| 8 |
dispatch: Dispatch;
|
| 9 |
}
|
| 10 |
+
const View: FC<LoginProps> = ({ dispatch }) => {
|
| 11 |
+
let navigate = useNavigate();
|
| 12 |
+
const [title, setTitle] = useState('login');
|
|
|
|
| 13 |
const changeTitle = () => {
|
| 14 |
+
setTitle((title) => (title === 'login' ? 'register' : 'login'));
|
| 15 |
+
};
|
| 16 |
const [form] = Form.useForm();
|
| 17 |
const [checkNick, setCheckNick] = useState(false);
|
| 18 |
|
|
|
|
| 24 |
try {
|
| 25 |
const params = await form.validateFields();
|
| 26 |
|
| 27 |
+
var rsaPassWord = rsaPsw(params.password);
|
| 28 |
if (title === 'login') {
|
| 29 |
+
const ret = await dispatch({
|
| 30 |
type: 'loginModel/login',
|
| 31 |
payload: {
|
| 32 |
email: params.email,
|
| 33 |
+
password: rsaPassWord,
|
| 34 |
+
},
|
| 35 |
});
|
| 36 |
+
console.info(ret);
|
| 37 |
+
navigate('/knowledge');
|
| 38 |
} else {
|
| 39 |
dispatch({
|
| 40 |
type: 'loginModel/register',
|
|
|
|
| 44 |
password: rsaPassWord,
|
| 45 |
},
|
| 46 |
callback() {
|
| 47 |
+
setTitle('login');
|
| 48 |
+
},
|
| 49 |
});
|
| 50 |
}
|
| 51 |
} catch (errorInfo) {
|
|
|
|
| 57 |
// wrapperCol: { span: 8 },
|
| 58 |
};
|
| 59 |
|
|
|
|
| 60 |
const toGoogle = () => {
|
| 61 |
+
window.location.href =
|
| 62 |
+
'https://github.com/login/oauth/authorize?scope=user:email&client_id=302129228f0d96055bee';
|
| 63 |
+
};
|
| 64 |
return (
|
| 65 |
<div className={styles.loginPage}>
|
|
|
|
| 66 |
<div className={styles.loginLeft}>
|
| 67 |
<div className={styles.modal}>
|
| 68 |
<div className={styles.loginTitle}>
|
| 69 |
+
<div>{title === 'login' ? 'Sign in' : 'Create an account'}</div>
|
| 70 |
+
<span>
|
| 71 |
+
{title === 'login'
|
| 72 |
+
? 'We’re so excited to see you again!'
|
| 73 |
+
: 'Glad to have you on board!'}
|
| 74 |
</span>
|
| 75 |
</div>
|
| 76 |
|
| 77 |
+
<Form
|
| 78 |
+
form={form}
|
| 79 |
+
layout="vertical"
|
| 80 |
+
name="dynamic_rule"
|
| 81 |
+
style={{ maxWidth: 600 }}
|
| 82 |
+
>
|
| 83 |
<Form.Item
|
| 84 |
{...formItemLayout}
|
| 85 |
name="email"
|
| 86 |
label="Email"
|
| 87 |
rules={[{ required: true, message: 'Please input value' }]}
|
| 88 |
>
|
| 89 |
+
<Input size="large" placeholder="Please input value" />
|
| 90 |
</Form.Item>
|
| 91 |
+
{title === 'register' && (
|
| 92 |
+
<Form.Item
|
| 93 |
{...formItemLayout}
|
| 94 |
name="nickname"
|
| 95 |
label="Nickname"
|
| 96 |
+
rules={[
|
| 97 |
+
{ required: true, message: 'Please input your nickname' },
|
| 98 |
+
]}
|
| 99 |
>
|
| 100 |
+
<Input size="large" placeholder="Please input your nickname" />
|
| 101 |
</Form.Item>
|
| 102 |
+
)}
|
| 103 |
<Form.Item
|
| 104 |
{...formItemLayout}
|
| 105 |
name="password"
|
| 106 |
label="Password"
|
| 107 |
rules={[{ required: true, message: 'Please input value' }]}
|
| 108 |
>
|
| 109 |
+
<Input size="large" placeholder="Please input value" />
|
| 110 |
</Form.Item>
|
| 111 |
+
{title === 'login' && (
|
| 112 |
+
<Form.Item name="remember" valuePropName="checked">
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
<Checkbox> Remember me</Checkbox>
|
| 114 |
</Form.Item>
|
| 115 |
+
)}
|
| 116 |
+
<div>
|
| 117 |
+
{' '}
|
| 118 |
+
{title === 'login' && (
|
| 119 |
+
<div>
|
| 120 |
+
Don’t have an account?
|
| 121 |
+
<Button type="link" onClick={changeTitle}>
|
| 122 |
+
Sign up
|
| 123 |
+
</Button>
|
| 124 |
+
</div>
|
| 125 |
+
)}
|
| 126 |
+
{title === 'register' && (
|
| 127 |
+
<div>
|
| 128 |
Already have an account?
|
| 129 |
<Button type="link" onClick={changeTitle}>
|
| 130 |
Sign in
|
| 131 |
</Button>
|
| 132 |
+
</div>
|
| 133 |
+
)}
|
| 134 |
</div>
|
| 135 |
+
<Button type="primary" block size="large" onClick={onCheck}>
|
| 136 |
{title === 'login' ? 'Sign in' : 'Continue'}
|
| 137 |
</Button>
|
| 138 |
+
{title === 'login' && (
|
| 139 |
+
<>
|
| 140 |
+
<Button
|
| 141 |
+
block
|
| 142 |
+
size="large"
|
| 143 |
+
onClick={toGoogle}
|
| 144 |
+
style={{ marginTop: 15 }}
|
| 145 |
+
>
|
| 146 |
+
<div>
|
| 147 |
+
<Icon
|
| 148 |
+
icon="local:google"
|
| 149 |
+
style={{ verticalAlign: 'middle', marginRight: 5 }}
|
| 150 |
+
/>
|
| 151 |
+
Sign in with Google
|
| 152 |
+
</div>
|
| 153 |
+
</Button>
|
| 154 |
+
<Button
|
| 155 |
+
block
|
| 156 |
+
size="large"
|
| 157 |
+
onClick={toGoogle}
|
| 158 |
+
style={{ marginTop: 15 }}
|
| 159 |
+
>
|
| 160 |
+
<div>
|
| 161 |
+
<Icon
|
| 162 |
+
icon="local:github"
|
| 163 |
+
style={{ verticalAlign: 'middle', marginRight: 5 }}
|
| 164 |
+
/>
|
| 165 |
Sign in with Github
|
| 166 |
</div>
|
| 167 |
+
</Button>
|
| 168 |
+
</>
|
| 169 |
+
)}
|
| 170 |
</Form>
|
| 171 |
</div>
|
| 172 |
</div>
|
| 173 |
+
<div className={styles.loginRight}></div>
|
|
|
|
|
|
|
| 174 |
</div>
|
| 175 |
);
|
| 176 |
};
|
| 177 |
|
| 178 |
+
export default connect(({ loginModel, loading }) => ({ loginModel, loading }))(
|
| 179 |
+
View,
|
| 180 |
+
);
|
web/src/pages/login/model.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
| 1 |
-
import {
|
| 2 |
-
import { message } from 'antd';
|
| 3 |
import userService from '@/services/userService';
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
export interface loginModelState {
|
| 6 |
list: any[];
|
|
@@ -28,49 +30,52 @@ const Model: logingModelType = {
|
|
| 28 |
},
|
| 29 |
subscriptions: {
|
| 30 |
setup({ dispatch, history }) {
|
| 31 |
-
history.listen(location => {
|
| 32 |
-
}
|
| 33 |
},
|
| 34 |
effects: {
|
| 35 |
*login({ payload = {} }, { call, put }) {
|
| 36 |
-
console.log(111, payload)
|
| 37 |
const { data, response } = yield call(userService.login, payload);
|
| 38 |
-
const { retcode, data: res, retmsg } = data
|
| 39 |
-
console.log()
|
| 40 |
-
const
|
| 41 |
if (retcode === 0) {
|
| 42 |
message.success('登录成功!');
|
| 43 |
const token = res.access_token;
|
| 44 |
const userInfo = {
|
| 45 |
avatar: res.avatar,
|
| 46 |
name: res.nickname,
|
| 47 |
-
email: res.email
|
| 48 |
};
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
| 55 |
}
|
|
|
|
| 56 |
},
|
| 57 |
*register({ payload = {}, callback }, { call, put }) {
|
| 58 |
const { data, response } = yield call(userService.register, payload);
|
| 59 |
-
console.log()
|
| 60 |
-
const { retcode, data: res, retmsg } = data
|
| 61 |
if (retcode === 0) {
|
| 62 |
message.success('注册成功!');
|
| 63 |
-
callback && callback()
|
| 64 |
}
|
| 65 |
-
}
|
| 66 |
},
|
| 67 |
reducers: {
|
| 68 |
updateState(state, { payload }) {
|
| 69 |
return {
|
| 70 |
...state,
|
| 71 |
-
...payload
|
| 72 |
};
|
| 73 |
-
}
|
| 74 |
-
}
|
| 75 |
};
|
| 76 |
export default Model;
|
|
|
|
| 1 |
+
import { Authorization } from '@/constants/authorization';
|
|
|
|
| 2 |
import userService from '@/services/userService';
|
| 3 |
+
import authorizationUtil from '@/utils/authorizationUtil';
|
| 4 |
+
import { message } from 'antd';
|
| 5 |
+
import { Effect, Reducer, Subscription } from 'umi';
|
| 6 |
|
| 7 |
export interface loginModelState {
|
| 8 |
list: any[];
|
|
|
|
| 30 |
},
|
| 31 |
subscriptions: {
|
| 32 |
setup({ dispatch, history }) {
|
| 33 |
+
history.listen((location) => {});
|
| 34 |
+
},
|
| 35 |
},
|
| 36 |
effects: {
|
| 37 |
*login({ payload = {} }, { call, put }) {
|
| 38 |
+
console.log(111, payload);
|
| 39 |
const { data, response } = yield call(userService.login, payload);
|
| 40 |
+
const { retcode, data: res, retmsg } = data;
|
| 41 |
+
console.log();
|
| 42 |
+
const authorization = response.headers.get(Authorization);
|
| 43 |
if (retcode === 0) {
|
| 44 |
message.success('登录成功!');
|
| 45 |
const token = res.access_token;
|
| 46 |
const userInfo = {
|
| 47 |
avatar: res.avatar,
|
| 48 |
name: res.nickname,
|
| 49 |
+
email: res.email,
|
| 50 |
};
|
| 51 |
+
authorizationUtil.setItems({
|
| 52 |
+
Authorization: authorization,
|
| 53 |
+
userInfo: JSON.stringify(userInfo),
|
| 54 |
+
Token: token,
|
| 55 |
+
});
|
| 56 |
+
// setTimeout(() => {
|
| 57 |
+
// window.location.href = '/file';
|
| 58 |
+
// }, 300);
|
| 59 |
}
|
| 60 |
+
return data;
|
| 61 |
},
|
| 62 |
*register({ payload = {}, callback }, { call, put }) {
|
| 63 |
const { data, response } = yield call(userService.register, payload);
|
| 64 |
+
console.log();
|
| 65 |
+
const { retcode, data: res, retmsg } = data;
|
| 66 |
if (retcode === 0) {
|
| 67 |
message.success('注册成功!');
|
| 68 |
+
callback && callback();
|
| 69 |
}
|
| 70 |
+
},
|
| 71 |
},
|
| 72 |
reducers: {
|
| 73 |
updateState(state, { payload }) {
|
| 74 |
return {
|
| 75 |
...state,
|
| 76 |
+
...payload,
|
| 77 |
};
|
| 78 |
+
},
|
| 79 |
+
},
|
| 80 |
};
|
| 81 |
export default Model;
|
web/src/pages/setting/index.tsx
CHANGED
|
@@ -1,90 +1,105 @@
|
|
| 1 |
-
import {
|
| 2 |
import i18n from 'i18next';
|
| 3 |
-
import { useTranslation
|
| 4 |
-
import {
|
| 5 |
-
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
import styles from './index.less';
|
| 8 |
-
import CPwModal from './CPwModal'
|
| 9 |
-
import SAKModal from './SAKModal'
|
| 10 |
-
import TntModal from './TntModal'
|
| 11 |
-
import SSModal from './SSModal'
|
| 12 |
-
import List from './List'
|
| 13 |
-
import { useEffect, useState, FC } from 'react';
|
| 14 |
interface CPwModalProps {
|
| 15 |
-
|
| 16 |
-
|
| 17 |
}
|
| 18 |
const Index: FC<CPwModalProps> = ({ settingModel, dispatch }) => {
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
</
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Button, FloatButton } from 'antd';
|
| 2 |
import i18n from 'i18next';
|
| 3 |
+
import { useTranslation } from 'react-i18next';
|
| 4 |
+
import { Dispatch, connect } from 'umi';
|
|
|
|
| 5 |
|
| 6 |
+
import authorizationUtil from '@/utils/authorizationUtil';
|
| 7 |
+
import { FC, useEffect } from 'react';
|
| 8 |
+
import CPwModal from './CPwModal';
|
| 9 |
+
import List from './List';
|
| 10 |
+
import SAKModal from './SAKModal';
|
| 11 |
+
import SSModal from './SSModal';
|
| 12 |
+
import TntModal from './TntModal';
|
| 13 |
import styles from './index.less';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
interface CPwModalProps {
|
| 15 |
+
dispatch: Dispatch;
|
| 16 |
+
settingModel: any;
|
| 17 |
}
|
| 18 |
const Index: FC<CPwModalProps> = ({ settingModel, dispatch }) => {
|
| 19 |
+
// const [llm_factory, set_llm_factory] = useState('')
|
| 20 |
+
const { t } = useTranslation();
|
| 21 |
+
const userInfo = authorizationUtil.getUserInfoObject();
|
| 22 |
+
const changeLang = (val: string) => {
|
| 23 |
+
// 改变状态里的 语言 进行切换
|
| 24 |
+
i18n.changeLanguage(val);
|
| 25 |
+
};
|
| 26 |
+
useEffect(() => {
|
| 27 |
+
dispatch({
|
| 28 |
+
type: 'settingModel/getTenantInfo',
|
| 29 |
+
payload: {},
|
| 30 |
+
});
|
| 31 |
+
}, []);
|
| 32 |
+
const showCPwModal = () => {
|
| 33 |
+
dispatch({
|
| 34 |
+
type: 'settingModel/updateState',
|
| 35 |
+
payload: {
|
| 36 |
+
isShowPSwModal: true,
|
| 37 |
+
},
|
| 38 |
+
});
|
| 39 |
+
};
|
| 40 |
+
const showTntModal = () => {
|
| 41 |
+
dispatch({
|
| 42 |
+
type: 'settingModel/updateState',
|
| 43 |
+
payload: {
|
| 44 |
+
isShowTntModal: true,
|
| 45 |
+
},
|
| 46 |
+
});
|
| 47 |
+
};
|
| 48 |
+
const showSSModal = () => {
|
| 49 |
+
dispatch({
|
| 50 |
+
type: 'settingModel/updateState',
|
| 51 |
+
payload: {
|
| 52 |
+
isShowSSModal: true,
|
| 53 |
+
},
|
| 54 |
+
});
|
| 55 |
+
// dispatch({
|
| 56 |
+
// type: 'settingModel/getTenantInfo',
|
| 57 |
+
// payload: {
|
| 58 |
+
// }
|
| 59 |
+
// });
|
| 60 |
+
};
|
| 61 |
+
return (
|
| 62 |
+
<div className={styles.settingPage}>
|
| 63 |
+
<div className={styles.avatar}>
|
| 64 |
+
<img
|
| 65 |
+
style={{ width: 50, marginRight: 5 }}
|
| 66 |
+
src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png"
|
| 67 |
+
alt=""
|
| 68 |
+
/>
|
| 69 |
+
<div>
|
| 70 |
+
<div>账号:{userInfo.name}</div>
|
| 71 |
+
<div>
|
| 72 |
+
<span>密码:******</span>
|
| 73 |
+
<Button type="link" onClick={showCPwModal}>
|
| 74 |
+
修改密码
|
| 75 |
+
</Button>
|
| 76 |
+
</div>
|
| 77 |
+
</div>
|
| 78 |
+
</div>
|
| 79 |
+
<div>
|
| 80 |
+
<Button type="link" onClick={showTntModal}>
|
| 81 |
+
租户
|
| 82 |
+
</Button>
|
| 83 |
+
<Button type="link" onClick={showSSModal}>
|
| 84 |
+
系统模型设置
|
| 85 |
+
</Button>
|
| 86 |
+
<List />
|
| 87 |
+
</div>
|
| 88 |
+
<CPwModal />
|
| 89 |
+
<SAKModal />
|
| 90 |
+
<SSModal />
|
| 91 |
+
<TntModal />
|
| 92 |
+
<FloatButton
|
| 93 |
+
shape="square"
|
| 94 |
+
description={t('setting.btn')}
|
| 95 |
+
onClick={() => i18n.changeLanguage(i18n.language == 'en' ? 'zh' : 'en')}
|
| 96 |
+
type="default"
|
| 97 |
+
style={{ right: 94, fontSize: 14 }}
|
| 98 |
+
/>
|
| 99 |
+
</div>
|
| 100 |
+
);
|
| 101 |
+
};
|
| 102 |
+
export default connect(({ settingModel, loading }) => ({
|
| 103 |
+
settingModel,
|
| 104 |
+
loading,
|
| 105 |
+
}))(Index);
|
web/src/pages/setting/model.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
-
import { Effect, Reducer, Subscription } from 'umi';
|
| 2 |
-
import { message } from 'antd';
|
| 3 |
import userService from '@/services/userService';
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
export interface settingModelState {
|
| 6 |
isShowPSwModal: boolean;
|
|
@@ -9,10 +10,10 @@ export interface settingModelState {
|
|
| 9 |
isShowSSModal: boolean;
|
| 10 |
llm_factory: string;
|
| 11 |
loading: boolean;
|
| 12 |
-
tenantIfo: any
|
| 13 |
-
llmInfo: any
|
| 14 |
-
myLlm: any[]
|
| 15 |
-
factoriesList: any[]
|
| 16 |
}
|
| 17 |
|
| 18 |
export interface settingModelType {
|
|
@@ -45,32 +46,31 @@ const Model: settingModelType = {
|
|
| 45 |
tenantIfo: {},
|
| 46 |
llmInfo: {},
|
| 47 |
myLlm: [],
|
| 48 |
-
factoriesList: []
|
| 49 |
},
|
| 50 |
subscriptions: {
|
| 51 |
setup({ dispatch, history }) {
|
| 52 |
-
history.listen(location => {
|
| 53 |
-
|
| 54 |
-
}
|
| 55 |
},
|
| 56 |
effects: {
|
| 57 |
*setting({ payload = {}, callback }, { call, put }) {
|
| 58 |
const { data, response } = yield call(userService.setting, payload);
|
| 59 |
-
const { retcode, data: res, retmsg } = data
|
| 60 |
if (retcode === 0) {
|
| 61 |
message.success('密码修改成功!');
|
| 62 |
-
callback && callback()
|
| 63 |
}
|
| 64 |
},
|
| 65 |
*getUserInfo({ payload = {} }, { call, put }) {
|
| 66 |
const { data, response } = yield call(userService.user_info, payload);
|
| 67 |
-
const { retcode, data: res, retmsg } = data
|
| 68 |
const userInfo = {
|
| 69 |
avatar: res.avatar,
|
| 70 |
name: res.nickname,
|
| 71 |
-
email: res.email
|
| 72 |
};
|
| 73 |
-
|
| 74 |
if (retcode === 0) {
|
| 75 |
// localStorage.setItem('userInfo',res.)
|
| 76 |
}
|
|
@@ -79,91 +79,100 @@ const Model: settingModelType = {
|
|
| 79 |
yield put({
|
| 80 |
type: 'updateState',
|
| 81 |
payload: {
|
| 82 |
-
loading: true
|
| 83 |
-
}
|
| 84 |
});
|
| 85 |
-
const { data, response } = yield call(
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
| 87 |
// llm_id 对应chat_id
|
| 88 |
// asr_id 对应speech2txt
|
| 89 |
|
| 90 |
yield put({
|
| 91 |
type: 'updateState',
|
| 92 |
payload: {
|
| 93 |
-
loading: false
|
| 94 |
-
}
|
| 95 |
});
|
| 96 |
if (retcode === 0) {
|
| 97 |
-
res.chat_id = res.llm_id
|
| 98 |
-
res.speech2text_id = res.asr_id
|
| 99 |
yield put({
|
| 100 |
type: 'updateState',
|
| 101 |
payload: {
|
| 102 |
-
tenantIfo: res
|
| 103 |
-
}
|
| 104 |
});
|
| 105 |
}
|
| 106 |
},
|
| 107 |
*set_tenant_info({ payload = {} }, { call, put }) {
|
| 108 |
-
const { data, response } = yield call(
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
| 110 |
// llm_id 对应chat_id
|
| 111 |
// asr_id 对应speech2txt
|
| 112 |
if (retcode === 0) {
|
| 113 |
yield put({
|
| 114 |
type: 'updateState',
|
| 115 |
payload: {
|
| 116 |
-
isShowSSModal: false
|
| 117 |
-
}
|
| 118 |
});
|
| 119 |
yield put({
|
| 120 |
-
type: 'getTenantInfo'
|
| 121 |
-
})
|
| 122 |
}
|
| 123 |
},
|
| 124 |
|
| 125 |
*factories_list({ payload = {} }, { call, put }) {
|
| 126 |
-
const { data, response } = yield call(
|
| 127 |
-
|
|
|
|
|
|
|
|
|
|
| 128 |
if (retcode === 0) {
|
| 129 |
yield put({
|
| 130 |
type: 'updateState',
|
| 131 |
payload: {
|
| 132 |
-
factoriesList: res
|
| 133 |
-
}
|
| 134 |
});
|
| 135 |
}
|
| 136 |
},
|
| 137 |
*llm_list({ payload = {} }, { call, put }) {
|
| 138 |
const { data, response } = yield call(userService.llm_list, payload);
|
| 139 |
-
const { retcode, data: res, retmsg } = data
|
| 140 |
if (retcode === 0) {
|
| 141 |
yield put({
|
| 142 |
type: 'updateState',
|
| 143 |
payload: {
|
| 144 |
-
llmInfo: res
|
| 145 |
-
}
|
| 146 |
});
|
| 147 |
}
|
| 148 |
},
|
| 149 |
*my_llm({ payload = {} }, { call, put }) {
|
| 150 |
const { data, response } = yield call(userService.my_llm, payload);
|
| 151 |
-
const { retcode, data: res, retmsg } = data
|
| 152 |
if (retcode === 0) {
|
| 153 |
yield put({
|
| 154 |
type: 'updateState',
|
| 155 |
payload: {
|
| 156 |
-
myLlm: res
|
| 157 |
-
}
|
| 158 |
});
|
| 159 |
}
|
| 160 |
},
|
| 161 |
*set_api_key({ payload = {}, callback }, { call, put }) {
|
| 162 |
const { data, response } = yield call(userService.set_api_key, payload);
|
| 163 |
-
const { retcode, data: res, retmsg } = data
|
| 164 |
if (retcode === 0) {
|
| 165 |
message.success('设置API KEY成功!');
|
| 166 |
-
callback && callback()
|
| 167 |
}
|
| 168 |
},
|
| 169 |
},
|
|
@@ -171,9 +180,9 @@ const Model: settingModelType = {
|
|
| 171 |
updateState(state, { payload }) {
|
| 172 |
return {
|
| 173 |
...state,
|
| 174 |
-
...payload
|
| 175 |
};
|
| 176 |
-
}
|
| 177 |
-
}
|
| 178 |
};
|
| 179 |
export default Model;
|
|
|
|
|
|
|
|
|
|
| 1 |
import userService from '@/services/userService';
|
| 2 |
+
import authorizationUtil from '@/utils/authorizationUtil';
|
| 3 |
+
import { message } from 'antd';
|
| 4 |
+
import { Effect, Reducer, Subscription } from 'umi';
|
| 5 |
|
| 6 |
export interface settingModelState {
|
| 7 |
isShowPSwModal: boolean;
|
|
|
|
| 10 |
isShowSSModal: boolean;
|
| 11 |
llm_factory: string;
|
| 12 |
loading: boolean;
|
| 13 |
+
tenantIfo: any;
|
| 14 |
+
llmInfo: any;
|
| 15 |
+
myLlm: any[];
|
| 16 |
+
factoriesList: any[];
|
| 17 |
}
|
| 18 |
|
| 19 |
export interface settingModelType {
|
|
|
|
| 46 |
tenantIfo: {},
|
| 47 |
llmInfo: {},
|
| 48 |
myLlm: [],
|
| 49 |
+
factoriesList: [],
|
| 50 |
},
|
| 51 |
subscriptions: {
|
| 52 |
setup({ dispatch, history }) {
|
| 53 |
+
history.listen((location) => {});
|
| 54 |
+
},
|
|
|
|
| 55 |
},
|
| 56 |
effects: {
|
| 57 |
*setting({ payload = {}, callback }, { call, put }) {
|
| 58 |
const { data, response } = yield call(userService.setting, payload);
|
| 59 |
+
const { retcode, data: res, retmsg } = data;
|
| 60 |
if (retcode === 0) {
|
| 61 |
message.success('密码修改成功!');
|
| 62 |
+
callback && callback();
|
| 63 |
}
|
| 64 |
},
|
| 65 |
*getUserInfo({ payload = {} }, { call, put }) {
|
| 66 |
const { data, response } = yield call(userService.user_info, payload);
|
| 67 |
+
const { retcode, data: res, retmsg } = data;
|
| 68 |
const userInfo = {
|
| 69 |
avatar: res.avatar,
|
| 70 |
name: res.nickname,
|
| 71 |
+
email: res.email,
|
| 72 |
};
|
| 73 |
+
authorizationUtil.setUserInfo(userInfo);
|
| 74 |
if (retcode === 0) {
|
| 75 |
// localStorage.setItem('userInfo',res.)
|
| 76 |
}
|
|
|
|
| 79 |
yield put({
|
| 80 |
type: 'updateState',
|
| 81 |
payload: {
|
| 82 |
+
loading: true,
|
| 83 |
+
},
|
| 84 |
});
|
| 85 |
+
const { data, response } = yield call(
|
| 86 |
+
userService.get_tenant_info,
|
| 87 |
+
payload,
|
| 88 |
+
);
|
| 89 |
+
const { retcode, data: res, retmsg } = data;
|
| 90 |
// llm_id 对应chat_id
|
| 91 |
// asr_id 对应speech2txt
|
| 92 |
|
| 93 |
yield put({
|
| 94 |
type: 'updateState',
|
| 95 |
payload: {
|
| 96 |
+
loading: false,
|
| 97 |
+
},
|
| 98 |
});
|
| 99 |
if (retcode === 0) {
|
| 100 |
+
res.chat_id = res.llm_id;
|
| 101 |
+
res.speech2text_id = res.asr_id;
|
| 102 |
yield put({
|
| 103 |
type: 'updateState',
|
| 104 |
payload: {
|
| 105 |
+
tenantIfo: res,
|
| 106 |
+
},
|
| 107 |
});
|
| 108 |
}
|
| 109 |
},
|
| 110 |
*set_tenant_info({ payload = {} }, { call, put }) {
|
| 111 |
+
const { data, response } = yield call(
|
| 112 |
+
userService.set_tenant_info,
|
| 113 |
+
payload,
|
| 114 |
+
);
|
| 115 |
+
const { retcode, data: res, retmsg } = data;
|
| 116 |
// llm_id 对应chat_id
|
| 117 |
// asr_id 对应speech2txt
|
| 118 |
if (retcode === 0) {
|
| 119 |
yield put({
|
| 120 |
type: 'updateState',
|
| 121 |
payload: {
|
| 122 |
+
isShowSSModal: false,
|
| 123 |
+
},
|
| 124 |
});
|
| 125 |
yield put({
|
| 126 |
+
type: 'getTenantInfo',
|
| 127 |
+
});
|
| 128 |
}
|
| 129 |
},
|
| 130 |
|
| 131 |
*factories_list({ payload = {} }, { call, put }) {
|
| 132 |
+
const { data, response } = yield call(
|
| 133 |
+
userService.factories_list,
|
| 134 |
+
payload,
|
| 135 |
+
);
|
| 136 |
+
const { retcode, data: res, retmsg } = data;
|
| 137 |
if (retcode === 0) {
|
| 138 |
yield put({
|
| 139 |
type: 'updateState',
|
| 140 |
payload: {
|
| 141 |
+
factoriesList: res,
|
| 142 |
+
},
|
| 143 |
});
|
| 144 |
}
|
| 145 |
},
|
| 146 |
*llm_list({ payload = {} }, { call, put }) {
|
| 147 |
const { data, response } = yield call(userService.llm_list, payload);
|
| 148 |
+
const { retcode, data: res, retmsg } = data;
|
| 149 |
if (retcode === 0) {
|
| 150 |
yield put({
|
| 151 |
type: 'updateState',
|
| 152 |
payload: {
|
| 153 |
+
llmInfo: res,
|
| 154 |
+
},
|
| 155 |
});
|
| 156 |
}
|
| 157 |
},
|
| 158 |
*my_llm({ payload = {} }, { call, put }) {
|
| 159 |
const { data, response } = yield call(userService.my_llm, payload);
|
| 160 |
+
const { retcode, data: res, retmsg } = data;
|
| 161 |
if (retcode === 0) {
|
| 162 |
yield put({
|
| 163 |
type: 'updateState',
|
| 164 |
payload: {
|
| 165 |
+
myLlm: res,
|
| 166 |
+
},
|
| 167 |
});
|
| 168 |
}
|
| 169 |
},
|
| 170 |
*set_api_key({ payload = {}, callback }, { call, put }) {
|
| 171 |
const { data, response } = yield call(userService.set_api_key, payload);
|
| 172 |
+
const { retcode, data: res, retmsg } = data;
|
| 173 |
if (retcode === 0) {
|
| 174 |
message.success('设置API KEY成功!');
|
| 175 |
+
callback && callback();
|
| 176 |
}
|
| 177 |
},
|
| 178 |
},
|
|
|
|
| 180 |
updateState(state, { payload }) {
|
| 181 |
return {
|
| 182 |
...state,
|
| 183 |
+
...payload,
|
| 184 |
};
|
| 185 |
+
},
|
| 186 |
+
},
|
| 187 |
};
|
| 188 |
export default Model;
|
web/src/routes.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const routes = [
|
| 2 |
+
{
|
| 3 |
+
path: '/login',
|
| 4 |
+
component: '@/pages/login',
|
| 5 |
+
layout: false,
|
| 6 |
+
},
|
| 7 |
+
{
|
| 8 |
+
path: '/',
|
| 9 |
+
component: '@/layouts',
|
| 10 |
+
layout: false,
|
| 11 |
+
wrappers: ['@/wrappers/auth'],
|
| 12 |
+
routes: [
|
| 13 |
+
{ path: '/', redirect: '/knowledge' },
|
| 14 |
+
{
|
| 15 |
+
path: '/knowledge',
|
| 16 |
+
component: '@/pages/knowledge',
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
path: '/knowledge/add/*',
|
| 20 |
+
component: '@/pages/add-knowledge',
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
path: '/chat',
|
| 24 |
+
component: '@/pages/chat',
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
path: '/setting',
|
| 28 |
+
component: '@/pages/setting',
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
path: '/file',
|
| 32 |
+
component: '@/pages/file',
|
| 33 |
+
},
|
| 34 |
+
],
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
path: '/*',
|
| 38 |
+
component: '@/pages/404',
|
| 39 |
+
layout: false,
|
| 40 |
+
},
|
| 41 |
+
];
|
| 42 |
+
|
| 43 |
+
export default routes;
|
web/src/utils/authorizationUtil.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Authorization, Token, UserInfo } from '@/constants/authorization';
|
| 2 |
+
|
| 3 |
+
const KeySet = [Authorization, Token, UserInfo];
|
| 4 |
+
|
| 5 |
+
const storage = {
|
| 6 |
+
getAuthorization: () => {
|
| 7 |
+
return localStorage.getItem(Authorization);
|
| 8 |
+
},
|
| 9 |
+
getToken: () => {
|
| 10 |
+
return localStorage.getItem(Token);
|
| 11 |
+
},
|
| 12 |
+
getUserInfo: () => {
|
| 13 |
+
return localStorage.getItem(UserInfo);
|
| 14 |
+
},
|
| 15 |
+
getUserInfoObject: () => {
|
| 16 |
+
return JSON.parse(localStorage.getItem('userInfo') || '');
|
| 17 |
+
},
|
| 18 |
+
setAuthorization: (value: string) => {
|
| 19 |
+
localStorage.setItem(Authorization, value);
|
| 20 |
+
},
|
| 21 |
+
setToken: (value: string) => {
|
| 22 |
+
localStorage.setItem(Token, value);
|
| 23 |
+
},
|
| 24 |
+
setUserInfo: (value: string | Object) => {
|
| 25 |
+
let valueStr = typeof value !== 'string' ? JSON.stringify(value) : value;
|
| 26 |
+
localStorage.setItem(UserInfo, valueStr);
|
| 27 |
+
},
|
| 28 |
+
setItems: (pairs: Record<string, string>) => {
|
| 29 |
+
Object.entries(pairs).forEach(([key, value]) => {
|
| 30 |
+
localStorage.setItem(key, value);
|
| 31 |
+
});
|
| 32 |
+
},
|
| 33 |
+
removeAuthorization: () => {
|
| 34 |
+
localStorage.removeItem(Authorization);
|
| 35 |
+
},
|
| 36 |
+
removeAll: () => {
|
| 37 |
+
KeySet.forEach((x) => {
|
| 38 |
+
localStorage.removeItem(x);
|
| 39 |
+
});
|
| 40 |
+
},
|
| 41 |
+
};
|
| 42 |
+
|
| 43 |
+
export default storage;
|
web/src/utils/history.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { createBrowserHistory } from 'history';
|
| 2 |
+
|
| 3 |
+
export const history = createBrowserHistory();
|
web/src/utils/request.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
| 1 |
-
|
| 2 |
import { extend } from 'umi-request';
|
| 3 |
-
import { notification, message } from 'antd';
|
| 4 |
|
|
|
|
| 5 |
import api from '@/utils/api';
|
|
|
|
|
|
|
| 6 |
const { login } = api;
|
| 7 |
|
| 8 |
const ABORT_REQUEST_ERR_MESSAGE = 'The user aborted a request.'; // 手动中断请求。errorHandler 抛出的error message
|
| 9 |
|
| 10 |
-
|
| 11 |
-
|
| 12 |
const retcodeMessage = {
|
| 13 |
200: '服务器成功返回请求的数据。',
|
| 14 |
201: '新建或修改数据成功。',
|
|
@@ -24,7 +24,7 @@ const retcodeMessage = {
|
|
| 24 |
500: '服务器发生错误,请检查服务器。',
|
| 25 |
502: '网关错误。',
|
| 26 |
503: '服务不可用,服务器暂时过载或维护。',
|
| 27 |
-
504: '网关超时。'
|
| 28 |
};
|
| 29 |
type retcode =
|
| 30 |
| 200
|
|
@@ -49,16 +49,20 @@ interface responseType {
|
|
| 49 |
retcode: number;
|
| 50 |
data: any;
|
| 51 |
retmsg: string;
|
| 52 |
-
status: number
|
| 53 |
}
|
| 54 |
-
const errorHandler = (error: {
|
|
|
|
|
|
|
|
|
|
| 55 |
const { response } = error;
|
| 56 |
// 手动中断请求 abort
|
| 57 |
if (error.message === ABORT_REQUEST_ERR_MESSAGE) {
|
| 58 |
console.log('user abort request');
|
| 59 |
} else {
|
| 60 |
if (response && response.status) {
|
| 61 |
-
const errorText =
|
|
|
|
| 62 |
const { status, url } = response;
|
| 63 |
notification.error({
|
| 64 |
message: `请求错误 ${status}: ${url}`,
|
|
@@ -80,21 +84,21 @@ const errorHandler = (error: { response: Response, message: string }): Response
|
|
| 80 |
const request = extend({
|
| 81 |
errorHandler, // 默认错误处理
|
| 82 |
timeout: 3000000,
|
| 83 |
-
getResponse: true
|
| 84 |
});
|
| 85 |
|
| 86 |
request.interceptors.request.use((url: string, options: any) => {
|
| 87 |
-
const
|
| 88 |
return {
|
| 89 |
url,
|
| 90 |
options: {
|
| 91 |
...options,
|
| 92 |
headers: {
|
| 93 |
-
...(options.skipToken ? undefined : { Authorization }),
|
| 94 |
-
...options.headers
|
| 95 |
},
|
| 96 |
-
interceptors: true
|
| 97 |
-
}
|
| 98 |
};
|
| 99 |
});
|
| 100 |
|
|
@@ -103,7 +107,7 @@ request.interceptors.request.use((url: string, options: any) => {
|
|
| 103 |
* */
|
| 104 |
|
| 105 |
request.interceptors.response.use(async (response: any, request) => {
|
| 106 |
-
console.log(response, request)
|
| 107 |
const data: responseType = await response.clone().json();
|
| 108 |
// response 拦截
|
| 109 |
|
|
@@ -113,6 +117,8 @@ request.interceptors.response.use(async (response: any, request) => {
|
|
| 113 |
description: data.retmsg,
|
| 114 |
duration: 3,
|
| 115 |
});
|
|
|
|
|
|
|
| 116 |
} else if (data.retcode !== 0) {
|
| 117 |
if (data.retcode === 100) {
|
| 118 |
message.error(data.retmsg);
|
|
@@ -126,7 +132,6 @@ request.interceptors.response.use(async (response: any, request) => {
|
|
| 126 |
|
| 127 |
return response;
|
| 128 |
} else {
|
| 129 |
-
|
| 130 |
return response;
|
| 131 |
}
|
| 132 |
});
|
|
|
|
| 1 |
+
import { message, notification } from 'antd';
|
| 2 |
import { extend } from 'umi-request';
|
|
|
|
| 3 |
|
| 4 |
+
import { Authorization } from '@/constants/authorization';
|
| 5 |
import api from '@/utils/api';
|
| 6 |
+
import authorizationUtil from '@/utils/authorizationUtil';
|
| 7 |
+
|
| 8 |
const { login } = api;
|
| 9 |
|
| 10 |
const ABORT_REQUEST_ERR_MESSAGE = 'The user aborted a request.'; // 手动中断请求。errorHandler 抛出的error message
|
| 11 |
|
|
|
|
|
|
|
| 12 |
const retcodeMessage = {
|
| 13 |
200: '服务器成功返回请求的数据。',
|
| 14 |
201: '新建或修改数据成功。',
|
|
|
|
| 24 |
500: '服务器发生错误,请检查服务器。',
|
| 25 |
502: '网关错误。',
|
| 26 |
503: '服务不可用,服务器暂时过载或维护。',
|
| 27 |
+
504: '网关超时。',
|
| 28 |
};
|
| 29 |
type retcode =
|
| 30 |
| 200
|
|
|
|
| 49 |
retcode: number;
|
| 50 |
data: any;
|
| 51 |
retmsg: string;
|
| 52 |
+
status: number;
|
| 53 |
}
|
| 54 |
+
const errorHandler = (error: {
|
| 55 |
+
response: Response;
|
| 56 |
+
message: string;
|
| 57 |
+
}): Response => {
|
| 58 |
const { response } = error;
|
| 59 |
// 手动中断请求 abort
|
| 60 |
if (error.message === ABORT_REQUEST_ERR_MESSAGE) {
|
| 61 |
console.log('user abort request');
|
| 62 |
} else {
|
| 63 |
if (response && response.status) {
|
| 64 |
+
const errorText =
|
| 65 |
+
retcodeMessage[response.status as retcode] || response.statusText;
|
| 66 |
const { status, url } = response;
|
| 67 |
notification.error({
|
| 68 |
message: `请求错误 ${status}: ${url}`,
|
|
|
|
| 84 |
const request = extend({
|
| 85 |
errorHandler, // 默认错误处理
|
| 86 |
timeout: 3000000,
|
| 87 |
+
getResponse: true,
|
| 88 |
});
|
| 89 |
|
| 90 |
request.interceptors.request.use((url: string, options: any) => {
|
| 91 |
+
const authorization = authorizationUtil.getAuthorization();
|
| 92 |
return {
|
| 93 |
url,
|
| 94 |
options: {
|
| 95 |
...options,
|
| 96 |
headers: {
|
| 97 |
+
...(options.skipToken ? undefined : { [Authorization]: authorization }),
|
| 98 |
+
...options.headers,
|
| 99 |
},
|
| 100 |
+
interceptors: true,
|
| 101 |
+
},
|
| 102 |
};
|
| 103 |
});
|
| 104 |
|
|
|
|
| 107 |
* */
|
| 108 |
|
| 109 |
request.interceptors.response.use(async (response: any, request) => {
|
| 110 |
+
console.log(response, request);
|
| 111 |
const data: responseType = await response.clone().json();
|
| 112 |
// response 拦截
|
| 113 |
|
|
|
|
| 117 |
description: data.retmsg,
|
| 118 |
duration: 3,
|
| 119 |
});
|
| 120 |
+
authorizationUtil.removeAll();
|
| 121 |
+
// history.push('/login'); // Will not jump to the login page
|
| 122 |
} else if (data.retcode !== 0) {
|
| 123 |
if (data.retcode === 100) {
|
| 124 |
message.error(data.retmsg);
|
|
|
|
| 132 |
|
| 133 |
return response;
|
| 134 |
} else {
|
|
|
|
| 135 |
return response;
|
| 136 |
}
|
| 137 |
});
|
web/src/wrappers/auth.tsx
CHANGED
|
@@ -1,12 +1,11 @@
|
|
| 1 |
-
import {
|
|
|
|
| 2 |
|
| 3 |
-
export default (
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
}
|
| 12 |
-
}
|
|
|
|
| 1 |
+
import { useAuth } from '@/hooks/authHook';
|
| 2 |
+
import { Navigate, Outlet } from 'umi';
|
| 3 |
|
| 4 |
+
export default () => {
|
| 5 |
+
const { isLogin } = useAuth();
|
| 6 |
+
if (isLogin) {
|
| 7 |
+
return <Outlet />;
|
| 8 |
+
} else {
|
| 9 |
+
return <Navigate to="/login" />;
|
| 10 |
+
}
|
| 11 |
+
};
|
|
|
|
|
|