| @@ -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({ | |||
| // }, | |||
| // }, | |||
| }); | |||
| @@ -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; | |||
| @@ -0,0 +1,3 @@ | |||
| export const Authorization = 'Authorization'; | |||
| export const Token = 'token'; | |||
| export const UserInfo = 'userInfo'; | |||
| @@ -0,0 +1,10 @@ | |||
| import authorizationUtil from '@/utils/authorizationUtil'; | |||
| import { useState } from 'react'; | |||
| export const useAuth = () => { | |||
| const [isLogin, setIsLogin] = useState( | |||
| () => !!authorizationUtil.getAuthorization(), | |||
| ); | |||
| return { isLogin }; | |||
| }; | |||
| @@ -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: ( | |||
| <Button type="text" onClick={logout}>{t('header.logout')}</Button> | |||
| ), | |||
| }, | |||
| { | |||
| key: '2', | |||
| label: ( | |||
| <Button type="text" onClick={toSetting}>{t('header.setting')}</Button> | |||
| ), | |||
| }, | |||
| ] | |||
| }, []); | |||
| const { t } = useTranslation(); | |||
| const logout = () => { | |||
| authorizationUtil.removeAll(); | |||
| history.push('/login'); | |||
| }; | |||
| const toSetting = () => { | |||
| history.push('/setting'); | |||
| }; | |||
| const items: MenuProps['items'] = useMemo(() => { | |||
| return [ | |||
| { | |||
| key: '1', | |||
| label: ( | |||
| <Button type="text" onClick={logout}> | |||
| {t('header.logout')} | |||
| </Button> | |||
| ), | |||
| }, | |||
| { | |||
| key: '2', | |||
| label: ( | |||
| <Button type="text" onClick={toSetting}> | |||
| {t('header.setting')} | |||
| </Button> | |||
| ), | |||
| }, | |||
| ]; | |||
| }, []); | |||
| return (<> | |||
| <Dropdown menu={{ items }} placement="bottomLeft" arrow> | |||
| <img | |||
| style={{ width: '50px', height: '50px', borderRadius: '25px' }} | |||
| src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" | |||
| /> | |||
| </Dropdown> | |||
| </>) | |||
| } | |||
| return ( | |||
| <> | |||
| <Dropdown menu={{ items }} placement="bottomLeft" arrow> | |||
| <img | |||
| style={{ width: '50px', height: '50px', borderRadius: '25px' }} | |||
| src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" | |||
| /> | |||
| </Dropdown> | |||
| </> | |||
| ); | |||
| }; | |||
| export default App; | |||
| export default App; | |||
| @@ -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 ( | |||
| <Layout className={styles.layout} > | |||
| <Layout className={styles.layout}> | |||
| <Layout> | |||
| <Header style={{ padding: '0 8px', background: colorBgContainer, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> | |||
| <Header | |||
| style={{ | |||
| padding: '0 8px', | |||
| background: colorBgContainer, | |||
| display: 'flex', | |||
| justifyContent: 'space-between', | |||
| alignItems: 'center', | |||
| }} | |||
| > | |||
| <img src={logo} alt="" style={{ height: 30, width: 30 }} /> | |||
| <Space size={[0, 8]} wrap> | |||
| {tagsData.map((item) => | |||
| (<span key={item.name} className={classnames(styles['tag'], { | |||
| [styles['checked']]: current === item.name | |||
| })} onClick={() => handleChange(item.path)}> | |||
| {item.name} | |||
| </span>) | |||
| )} | |||
| {tagsData.map((item) => ( | |||
| <span | |||
| key={item.name} | |||
| className={classnames(styles['tag'], { | |||
| [styles['checked']]: current === item.name, | |||
| })} | |||
| onClick={() => handleChange(item.path)} | |||
| > | |||
| {item.name} | |||
| </span> | |||
| ))} | |||
| </Space> | |||
| <User ></User> | |||
| <User></User> | |||
| </Header> | |||
| <Content | |||
| style={{ | |||
| @@ -61,14 +72,14 @@ const App: React.FC = (props) => { | |||
| minHeight: 280, | |||
| background: colorBgContainer, | |||
| borderRadius: borderRadiusLG, | |||
| overflow: 'auto' | |||
| overflow: 'auto', | |||
| }} | |||
| > | |||
| <Outlet /> | |||
| </Content> | |||
| </Layout> | |||
| </Layout > | |||
| </Layout> | |||
| ); | |||
| }; | |||
| export default App; | |||
| export default App; | |||
| @@ -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<chunkModelState>; | |||
| }; | |||
| 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; | |||
| @@ -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; | |||
| @@ -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<KnowledgeProps> = ({ 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 (<> | |||
| <div className={styles.knowledge}> | |||
| <FloatButton onClick={handleAddKnowledge} icon={<PlusOutlined />} type="primary" style={{ right: 24, top: 100 }} /> | |||
| <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}> | |||
| { | |||
| data.map((item: any) => { | |||
| return (<Col className="gutter-row" key={item.name} xs={24} sm={12} md={8} lg={6}> | |||
| <Card className={styles.card} | |||
| onClick={() => { handleEditKnowledge(item.id) }} | |||
| }, []); | |||
| return ( | |||
| <> | |||
| <div className={styles.knowledge}> | |||
| <FloatButton | |||
| onClick={handleAddKnowledge} | |||
| icon={<PlusOutlined />} | |||
| type="primary" | |||
| style={{ right: 24, top: 100 }} | |||
| /> | |||
| <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}> | |||
| {data.map((item: any) => { | |||
| return ( | |||
| <Col | |||
| className="gutter-row" | |||
| key={item.name} | |||
| xs={24} | |||
| sm={12} | |||
| md={8} | |||
| lg={6} | |||
| > | |||
| <div className={styles.container}> | |||
| <div className={styles.content}> | |||
| <span className={styles.context}> | |||
| {item.name} | |||
| </span> | |||
| <span className={styles.delete}> | |||
| <Popconfirm | |||
| title="Delete the task" | |||
| description="Are you sure to delete this task?" | |||
| onConfirm={(e: any) => { | |||
| e.stopPropagation(); | |||
| e.nativeEvent.stopImmediatePropagation() | |||
| confirm(item.id) | |||
| }} | |||
| okText="Yes" | |||
| cancelText="No" | |||
| > | |||
| <DeleteOutlined onClick={(e) => { | |||
| e.stopPropagation(); | |||
| e.nativeEvent.stopImmediatePropagation() | |||
| }} /> | |||
| </Popconfirm> | |||
| </span> | |||
| </div> | |||
| <div className={styles.footer}> | |||
| <span className={styles.text}> | |||
| <MinusSquareOutlined />{item.doc_num}文档 | |||
| </span> | |||
| <span className={styles.text}> | |||
| <MinusSquareOutlined />{item.chunk_num}个 | |||
| </span> | |||
| <span className={styles.text}> | |||
| <MinusSquareOutlined />{item.token_num}千字符 | |||
| </span> | |||
| <span style={{ float: 'right' }}> | |||
| {formatDate(item.update_date)} | |||
| </span> | |||
| <Card | |||
| className={styles.card} | |||
| onClick={() => { | |||
| handleEditKnowledge(item.id); | |||
| }} | |||
| > | |||
| <div className={styles.container}> | |||
| <div className={styles.content}> | |||
| <span className={styles.context}>{item.name}</span> | |||
| <span className={styles.delete}> | |||
| <Popconfirm | |||
| title="Delete the task" | |||
| description="Are you sure to delete this task?" | |||
| onConfirm={(e: any) => { | |||
| e.stopPropagation(); | |||
| e.nativeEvent.stopImmediatePropagation(); | |||
| confirm(item.id); | |||
| }} | |||
| okText="Yes" | |||
| cancelText="No" | |||
| > | |||
| <DeleteOutlined | |||
| onClick={(e) => { | |||
| e.stopPropagation(); | |||
| e.nativeEvent.stopImmediatePropagation(); | |||
| }} | |||
| /> | |||
| </Popconfirm> | |||
| </span> | |||
| </div> | |||
| <div className={styles.footer}> | |||
| <span className={styles.text}> | |||
| <MinusSquareOutlined /> | |||
| {item.doc_num}文档 | |||
| </span> | |||
| <span className={styles.text}> | |||
| <MinusSquareOutlined /> | |||
| {item.chunk_num}个 | |||
| </span> | |||
| <span className={styles.text}> | |||
| <MinusSquareOutlined /> | |||
| {item.token_num}千字符 | |||
| </span> | |||
| <span style={{ float: 'right' }}> | |||
| {formatDate(item.update_date)} | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </Card> | |||
| </Col>) | |||
| }) | |||
| } | |||
| </Row> | |||
| </div> | |||
| </> | |||
| ) | |||
| </Card> | |||
| </Col> | |||
| ); | |||
| })} | |||
| </Row> | |||
| </div> | |||
| </> | |||
| ); | |||
| }; | |||
| export default connect(({ knowledgeModel, loading }) => ({ knowledgeModel, loading }))(Index); | |||
| export default connect(({ knowledgeModel, loading }) => ({ | |||
| knowledgeModel, | |||
| loading, | |||
| }))(Index); | |||
| @@ -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<knowledgeModelState>; | |||
| }; | |||
| 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); | |||
| @@ -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<LoginProps> = ({ | |||
| dispatch, | |||
| }) => { | |||
| const [title, setTitle] = useState('login') | |||
| const View: FC<LoginProps> = ({ 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<LoginProps> = ({ | |||
| 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<LoginProps> = ({ | |||
| password: rsaPassWord, | |||
| }, | |||
| callback() { | |||
| setTitle('login') | |||
| } | |||
| setTitle('login'); | |||
| }, | |||
| }); | |||
| } | |||
| } catch (errorInfo) { | |||
| @@ -56,103 +57,124 @@ const View: FC<LoginProps> = ({ | |||
| // 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 ( | |||
| <div className={styles.loginPage}> | |||
| <div className={styles.loginLeft}> | |||
| <div className={styles.modal}> | |||
| <div className={styles.loginTitle}> | |||
| <div> | |||
| {title === 'login' ? 'Sign in' : 'Create an account'} | |||
| </div> | |||
| <span > | |||
| {title === 'login' ? 'We’re so excited to see you again!' : 'Glad to have you on board!'} | |||
| <div>{title === 'login' ? 'Sign in' : 'Create an account'}</div> | |||
| <span> | |||
| {title === 'login' | |||
| ? 'We’re so excited to see you again!' | |||
| : 'Glad to have you on board!'} | |||
| </span> | |||
| </div> | |||
| <Form form={form} layout="vertical" name="dynamic_rule" style={{ maxWidth: 600 }}> | |||
| <Form | |||
| form={form} | |||
| layout="vertical" | |||
| name="dynamic_rule" | |||
| style={{ maxWidth: 600 }} | |||
| > | |||
| <Form.Item | |||
| {...formItemLayout} | |||
| name="email" | |||
| label="Email" | |||
| rules={[{ required: true, message: 'Please input value' }]} | |||
| > | |||
| <Input size='large' placeholder="Please input value" /> | |||
| <Input size="large" placeholder="Please input value" /> | |||
| </Form.Item> | |||
| { | |||
| title === 'register' && <Form.Item | |||
| {title === 'register' && ( | |||
| <Form.Item | |||
| {...formItemLayout} | |||
| name="nickname" | |||
| label="Nickname" | |||
| rules={[{ required: true, message: 'Please input your nickname' }]} | |||
| rules={[ | |||
| { required: true, message: 'Please input your nickname' }, | |||
| ]} | |||
| > | |||
| <Input size='large' placeholder="Please input your nickname" /> | |||
| <Input size="large" placeholder="Please input your nickname" /> | |||
| </Form.Item> | |||
| } | |||
| )} | |||
| <Form.Item | |||
| {...formItemLayout} | |||
| name="password" | |||
| label="Password" | |||
| rules={[{ required: true, message: 'Please input value' }]} | |||
| > | |||
| <Input size='large' placeholder="Please input value" /> | |||
| <Input size="large" placeholder="Please input value" /> | |||
| </Form.Item> | |||
| { | |||
| title === 'login' && <Form.Item | |||
| name="remember" | |||
| valuePropName="checked" | |||
| > | |||
| {title === 'login' && ( | |||
| <Form.Item name="remember" valuePropName="checked"> | |||
| <Checkbox> Remember me</Checkbox> | |||
| </Form.Item> | |||
| } | |||
| <div> { | |||
| title === 'login' && (<div> | |||
| Don’t have an account? | |||
| <Button type="link" onClick={changeTitle}> | |||
| Sign up | |||
| </Button> | |||
| </div>) | |||
| } | |||
| { | |||
| title === 'register' && (<div> | |||
| )} | |||
| <div> | |||
| {' '} | |||
| {title === 'login' && ( | |||
| <div> | |||
| Don’t have an account? | |||
| <Button type="link" onClick={changeTitle}> | |||
| Sign up | |||
| </Button> | |||
| </div> | |||
| )} | |||
| {title === 'register' && ( | |||
| <div> | |||
| Already have an account? | |||
| <Button type="link" onClick={changeTitle}> | |||
| Sign in | |||
| </Button> | |||
| </div>) | |||
| } | |||
| </div> | |||
| )} | |||
| </div> | |||
| <Button type="primary" block size='large' onClick={onCheck}> | |||
| <Button type="primary" block size="large" onClick={onCheck}> | |||
| {title === 'login' ? 'Sign in' : 'Continue'} | |||
| </Button> | |||
| { | |||
| title === 'login' && (<><Button block size='large' onClick={toGoogle} style={{ marginTop: 15 }}> | |||
| <div > | |||
| <Icon icon="local:google" style={{ verticalAlign: 'middle', marginRight: 5 }} /> | |||
| Sign in with Google | |||
| </div> | |||
| </Button> | |||
| <Button block size='large' onClick={toGoogle} style={{ marginTop: 15 }}> | |||
| <div > | |||
| <Icon icon="local:github" style={{ verticalAlign: 'middle', marginRight: 5 }} /> | |||
| {title === 'login' && ( | |||
| <> | |||
| <Button | |||
| block | |||
| size="large" | |||
| onClick={toGoogle} | |||
| style={{ marginTop: 15 }} | |||
| > | |||
| <div> | |||
| <Icon | |||
| icon="local:google" | |||
| style={{ verticalAlign: 'middle', marginRight: 5 }} | |||
| /> | |||
| Sign in with Google | |||
| </div> | |||
| </Button> | |||
| <Button | |||
| block | |||
| size="large" | |||
| onClick={toGoogle} | |||
| style={{ marginTop: 15 }} | |||
| > | |||
| <div> | |||
| <Icon | |||
| icon="local:github" | |||
| style={{ verticalAlign: 'middle', marginRight: 5 }} | |||
| /> | |||
| Sign in with Github | |||
| </div> | |||
| </Button></>) | |||
| } | |||
| </Button> | |||
| </> | |||
| )} | |||
| </Form> | |||
| </div> | |||
| </div> | |||
| <div className={styles.loginRight}> | |||
| </div> | |||
| <div className={styles.loginRight}></div> | |||
| </div> | |||
| ); | |||
| }; | |||
| export default connect(({ loginModel, loading }) => ({ loginModel, loading }))(View); | |||
| export default connect(({ loginModel, loading }) => ({ loginModel, loading }))( | |||
| View, | |||
| ); | |||
| @@ -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; | |||
| @@ -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<CPwModalProps> = ({ 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 ( | |||
| <div className={styles.settingPage}> | |||
| <div className={styles.avatar}> | |||
| <img style={{ width: 50, marginRight: 5 }} src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" alt="" /> | |||
| <div> | |||
| <div>账号:{userInfo.name}</div> | |||
| <div><span>密码:******</span><Button type='link' onClick={showCPwModal}>修改密码</Button></div> | |||
| </div> | |||
| </div > | |||
| <div> | |||
| <Button type="link" onClick={showTntModal}> | |||
| 租户 | |||
| </Button> | |||
| <Button type="link" onClick={showSSModal}> | |||
| 系统模型设置 | |||
| </Button> | |||
| <List /> | |||
| </div> | |||
| <CPwModal /> | |||
| <SAKModal /> | |||
| <SSModal /> | |||
| <TntModal /> | |||
| <FloatButton shape='square' description={t('setting.btn')} onClick={() => i18n.changeLanguage(i18n.language == 'en' ? 'zh' : 'en')} type="default" style={{ right: 94, fontSize: 14 }} /> | |||
| </div > | |||
| ); | |||
| } | |||
| 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 ( | |||
| <div className={styles.settingPage}> | |||
| <div className={styles.avatar}> | |||
| <img | |||
| style={{ width: 50, marginRight: 5 }} | |||
| src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" | |||
| alt="" | |||
| /> | |||
| <div> | |||
| <div>账号:{userInfo.name}</div> | |||
| <div> | |||
| <span>密码:******</span> | |||
| <Button type="link" onClick={showCPwModal}> | |||
| 修改密码 | |||
| </Button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <Button type="link" onClick={showTntModal}> | |||
| 租户 | |||
| </Button> | |||
| <Button type="link" onClick={showSSModal}> | |||
| 系统模型设置 | |||
| </Button> | |||
| <List /> | |||
| </div> | |||
| <CPwModal /> | |||
| <SAKModal /> | |||
| <SSModal /> | |||
| <TntModal /> | |||
| <FloatButton | |||
| shape="square" | |||
| description={t('setting.btn')} | |||
| onClick={() => i18n.changeLanguage(i18n.language == 'en' ? 'zh' : 'en')} | |||
| type="default" | |||
| style={{ right: 94, fontSize: 14 }} | |||
| /> | |||
| </div> | |||
| ); | |||
| }; | |||
| export default connect(({ settingModel, loading }) => ({ | |||
| settingModel, | |||
| loading, | |||
| }))(Index); | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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<string, string>) => { | |||
| Object.entries(pairs).forEach(([key, value]) => { | |||
| localStorage.setItem(key, value); | |||
| }); | |||
| }, | |||
| removeAuthorization: () => { | |||
| localStorage.removeItem(Authorization); | |||
| }, | |||
| removeAll: () => { | |||
| KeySet.forEach((x) => { | |||
| localStorage.removeItem(x); | |||
| }); | |||
| }, | |||
| }; | |||
| export default storage; | |||
| @@ -0,0 +1,3 @@ | |||
| import { createBrowserHistory } from 'history'; | |||
| export const history = createBrowserHistory(); | |||
| @@ -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; | |||
| } | |||
| }); | |||
| @@ -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 <Outlet />; | |||
| } else { | |||
| return <Navigate to="/login" />; | |||
| } | |||
| } | |||
| export default () => { | |||
| const { isLogin } = useAuth(); | |||
| if (isLogin) { | |||
| return <Outlet />; | |||
| } else { | |||
| return <Navigate to="/login" />; | |||
| } | |||
| }; | |||