mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-04-19 12:39:59 +08:00
feat: layout the knowledge list page and modify the page switching button in the header (#48)
* feat: remove unnecessary 'loading' fields from other files * feat: layout the knowledge list page * feat: modify the page switching button in the header
This commit is contained in:
parent
362ec6c364
commit
af3ef26977
@ -16,6 +16,11 @@ export default defineConfig({
|
||||
},
|
||||
plugins: ['@react-dev-inspector/umi4-plugin', '@umijs/plugins/dist/dva'],
|
||||
dva: {},
|
||||
lessLoader: {
|
||||
modifyVars: {
|
||||
hack: `true; @import "~@/less/variable.less";`,
|
||||
},
|
||||
},
|
||||
// proxy: {
|
||||
// '/v1': {
|
||||
// 'target': 'http://54.80.112.79:9380/',
|
||||
|
3
web/src/assets/filter.svg
Normal file
3
web/src/assets/filter.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5 10H15M2.5 5H17.5M7.5 15H12.5" stroke="#344054" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 234 B |
12
web/src/assets/svg/chat-star.svg
Normal file
12
web/src/assets/svg/chat-star.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1164_5493)">
|
||||
<path
|
||||
d="M3.08282 12.894V10.0795M3.08282 4.45031V1.63574M1.67554 3.04303H4.49011M1.67554 11.4867H4.49011M7.86759 2.19866L6.8914 4.73676C6.73265 5.1495 6.65328 5.35588 6.52984 5.52947C6.42045 5.68332 6.28603 5.81774 6.13218 5.92713C5.95858 6.05057 5.75221 6.12994 5.33947 6.28869L2.80137 7.26488L5.33947 8.24107C5.75221 8.39982 5.95859 8.4792 6.13218 8.60263C6.28603 8.71203 6.42045 8.84645 6.52984 9.0003C6.65328 9.17389 6.73265 9.38026 6.8914 9.79301L7.86759 12.3311L8.84378 9.79301C9.00253 9.38026 9.08191 9.17389 9.20534 9.0003C9.31474 8.84645 9.44916 8.71203 9.60301 8.60263C9.7766 8.4792 9.98297 8.39982 10.3957 8.24107L12.9338 7.26488L10.3957 6.28869C9.98297 6.12994 9.7766 6.05057 9.60301 5.92713C9.44916 5.81774 9.31474 5.68332 9.20534 5.52947C9.08191 5.35588 9.00253 5.1495 8.84378 4.73676L7.86759 2.19866Z"
|
||||
stroke="black" stroke-width="1.68874" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1164_5493">
|
||||
<rect width="13.5099" height="13.5099" fill="white" transform="translate(0.549805 0.509888)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
5
web/src/assets/svg/logo.svg
Normal file
5
web/src/assets/svg/logo.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M18.1777 8C23.2737 8 23.2737 16 18.1777 16C13.0827 16 11.0447 8 5.43875 8C0.85375 8 0.85375 16 5.43875 16C11.0447 16 13.0828 8 18.1788 8H18.1777Z"
|
||||
stroke="#7F56D9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
After Width: | Height: | Size: 362 B |
11
web/src/assets/svg/more.svg
Normal file
11
web/src/assets/svg/more.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="24" height="6" viewBox="0 0 24 6" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M12 4.25C12.6904 4.25 13.25 3.69036 13.25 3C13.25 2.30964 12.6904 1.75 12 1.75C11.3096 1.75 10.75 2.30964 10.75 3C10.75 3.69036 11.3096 4.25 12 4.25Z"
|
||||
stroke="#98A2B3" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<path
|
||||
d="M20.75 4.25C21.4404 4.25 22 3.69036 22 3C22 2.30964 21.4404 1.75 20.75 1.75C20.0596 1.75 19.5 2.30964 19.5 3C19.5 3.69036 20.0596 4.25 20.75 4.25Z"
|
||||
stroke="#98A2B3" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<path
|
||||
d="M3.25 4.25C3.94036 4.25 4.5 3.69036 4.5 3C4.5 2.30964 3.94036 1.75 3.25 1.75C2.55964 1.75 2 2.30964 2 3C2 3.69036 2.55964 4.25 3.25 4.25Z"
|
||||
stroke="#98A2B3" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
After Width: | Height: | Size: 883 B |
46
web/src/layouts/components/header/index.less
Normal file
46
web/src/layouts/components/header/index.less
Normal file
@ -0,0 +1,46 @@
|
||||
.tag {
|
||||
height: 40px;
|
||||
padding: 0 30px;
|
||||
margin: 0 5px;
|
||||
border: 1px solid #000;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.checked {
|
||||
color: #1677ff;
|
||||
border-color: #1677ff;
|
||||
}
|
||||
|
||||
.appIcon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.appName {
|
||||
vertical-align: middle;
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.radioGroup {
|
||||
background: rgba(249, 249, 249, 1) !important;
|
||||
& > label {
|
||||
border: 0 !important;
|
||||
&::before {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
:global(.ant-radio-button-wrapper-checked) {
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked {
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
.radioButtonIcon {
|
||||
vertical-align: middle;
|
||||
}
|
74
web/src/layouts/components/header/index.tsx
Normal file
74
web/src/layouts/components/header/index.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import { ReactComponent as StarIon } from '@/assets/svg/chat-star.svg';
|
||||
import { ReactComponent as Logo } from '@/assets/svg/logo.svg';
|
||||
import { Layout, Radio, Space, theme } from 'antd';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useLocation, useNavigate } from 'umi';
|
||||
import User from '../user';
|
||||
|
||||
const { Header } = Layout;
|
||||
|
||||
const RagHeader = () => {
|
||||
const {
|
||||
token: { colorBgContainer },
|
||||
} = theme.useToken();
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const tagsData = [
|
||||
{ path: '/knowledge', name: 'knowledge' },
|
||||
{ path: '/chat', name: 'chat' },
|
||||
{ path: '/file', name: 'file' },
|
||||
];
|
||||
|
||||
const currentPath = useMemo(() => {
|
||||
return tagsData.find((x) => x.path === pathname)?.name || 'knowledge';
|
||||
}, [pathname]);
|
||||
|
||||
const handleChange = (path: string) => {
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
return (
|
||||
<Header
|
||||
style={{
|
||||
padding: '0 16px',
|
||||
background: colorBgContainer,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
height: '72px',
|
||||
}}
|
||||
>
|
||||
<Space size={12}>
|
||||
<Logo className={styles.appIcon}></Logo>
|
||||
<label className={styles.appName}>Infinity flow</label>
|
||||
</Space>
|
||||
<Space size={[0, 8]} wrap>
|
||||
<Radio.Group
|
||||
defaultValue="a"
|
||||
buttonStyle="solid"
|
||||
className={styles.radioGroup}
|
||||
value={currentPath}
|
||||
>
|
||||
{tagsData.map((item) => (
|
||||
<Radio.Button
|
||||
value={item.name}
|
||||
onClick={() => handleChange(item.path)}
|
||||
>
|
||||
<Space>
|
||||
<StarIon className={styles.radioButtonIcon}></StarIon>
|
||||
{item.name}
|
||||
</Space>
|
||||
</Radio.Button>
|
||||
))}
|
||||
</Radio.Group>
|
||||
</Space>
|
||||
<User></User>
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
||||
export default RagHeader;
|
@ -18,16 +18,6 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tag {
|
||||
height: 40px;
|
||||
padding: 0 30px;
|
||||
margin: 0 5px;
|
||||
border: 1px solid #000;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
.divider {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.checked {
|
||||
color: #1677ff;
|
||||
border-color: #1677ff;
|
||||
}
|
@ -1,74 +1,26 @@
|
||||
import logo from '@/assets/logo.png';
|
||||
import { Layout, Space, theme } from 'antd';
|
||||
import classnames from 'classnames';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Divider, Layout, theme } from 'antd';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Outlet, useLocation, useNavigate } from 'umi';
|
||||
import { Outlet } from 'umi';
|
||||
import '../locales/config';
|
||||
import User from './components/user';
|
||||
import Header from './components/header';
|
||||
import styles from './index.less';
|
||||
|
||||
const { Header, Content } = Layout;
|
||||
const { Content } = Layout;
|
||||
|
||||
const App: React.FC = (props) => {
|
||||
const App: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
token: { colorBgContainer, borderRadiusLG },
|
||||
} = theme.useToken();
|
||||
const [current, setCurrent] = useState('knowledge');
|
||||
|
||||
const location = useLocation();
|
||||
useEffect(() => {
|
||||
if (location.pathname !== '/') {
|
||||
const path = location.pathname.split('/');
|
||||
// setCurrent(path[1]);
|
||||
}
|
||||
console.log(location.pathname.split('/'));
|
||||
}, [location.pathname]);
|
||||
|
||||
const handleChange = (path: string) => {
|
||||
// setCurrent(path)
|
||||
navigate(path);
|
||||
};
|
||||
const tagsData = [
|
||||
{ path: '/knowledge', name: 'knowledge' },
|
||||
{ path: '/chat', name: 'chat' },
|
||||
{ path: '/file', name: 'file' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout className={styles.layout}>
|
||||
<Layout>
|
||||
<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>
|
||||
))}
|
||||
</Space>
|
||||
<User></User>
|
||||
</Header>
|
||||
<Header></Header>
|
||||
<Divider orientationMargin={0} className={styles.divider} />
|
||||
<Content
|
||||
style={{
|
||||
margin: '24px 16px',
|
||||
|
||||
minHeight: 280,
|
||||
background: colorBgContainer,
|
||||
borderRadius: borderRadiusLG,
|
||||
|
1
web/src/less/variable.less
Normal file
1
web/src/less/variable.less
Normal file
@ -0,0 +1 @@
|
||||
@fontWeight600: 600;
|
@ -1,5 +1,4 @@
|
||||
import { Button, Result } from 'antd';
|
||||
import React from 'react';
|
||||
import { history } from 'umi';
|
||||
|
||||
const NoFoundPage = () => {
|
||||
|
@ -2,7 +2,6 @@ import { DvaModel } from 'umi';
|
||||
export interface kAModelState {
|
||||
isShowPSwModal: boolean;
|
||||
isShowTntModal: boolean;
|
||||
loading: boolean;
|
||||
tenantIfo: any;
|
||||
activeKey: string;
|
||||
id: string;
|
||||
@ -14,7 +13,6 @@ const model: DvaModel<kAModelState> = {
|
||||
state: {
|
||||
isShowPSwModal: false,
|
||||
isShowTntModal: false,
|
||||
loading: false,
|
||||
tenantIfo: {},
|
||||
activeKey: 'setting',
|
||||
id: '',
|
||||
|
@ -1,40 +1,43 @@
|
||||
// @import '~@/less/variable.less';
|
||||
|
||||
.knowledge {
|
||||
padding: 24px;
|
||||
padding: 48px 60px;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100px;
|
||||
.topWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding-bottom: 72px;
|
||||
|
||||
.content {
|
||||
.title {
|
||||
font-family: Inter;
|
||||
font-size: 30px;
|
||||
font-style: normal;
|
||||
font-weight: @fontWeight600;
|
||||
line-height: 38px;
|
||||
color: rgba(16, 24, 40, 1);
|
||||
}
|
||||
.description {
|
||||
font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
color: rgba(71, 84, 103, 1);
|
||||
}
|
||||
|
||||
.topButton {
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: @fontWeight600;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.filterButton {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.context {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
height: 20px;
|
||||
|
||||
.text {
|
||||
margin-left: 10px;
|
||||
}
|
||||
align-items: center;
|
||||
.topButton();
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
:global {
|
||||
.ant-card-body {
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
import { formatDate } from '@/utils/date';
|
||||
import {
|
||||
DeleteOutlined,
|
||||
MinusSquareOutlined,
|
||||
PlusOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Card, Col, FloatButton, Popconfirm, Row } from 'antd';
|
||||
import { ReactComponent as FilterIcon } from '@/assets/filter.svg';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Col, Row, Space } from 'antd';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useDispatch, useNavigate, useSelector } from 'umi';
|
||||
import styles from './index.less';
|
||||
import KnowledgeCard from './knowledge-card';
|
||||
|
||||
const Knowledge = () => {
|
||||
const dispatch = useDispatch();
|
||||
@ -22,98 +19,54 @@ const Knowledge = () => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const confirm = (id: string) => {
|
||||
dispatch({
|
||||
type: 'knowledgeModel/rmKb',
|
||||
payload: {
|
||||
kb_id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
const handleAddKnowledge = () => {
|
||||
navigate(`add/setting?activeKey=setting`);
|
||||
};
|
||||
const handleEditKnowledge = (id: string) => {
|
||||
navigate(`add/setting?activeKey=file&id=${id}`);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchList();
|
||||
}, [fetchList]);
|
||||
|
||||
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);
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
<div className={styles.knowledge}>
|
||||
<div className={styles.topWrapper}>
|
||||
<div>
|
||||
<span className={styles.title}>Welcome back, Zing</span>
|
||||
<p className={styles.description}>
|
||||
Which database are we going to use today?
|
||||
</p>
|
||||
</div>
|
||||
<Space size={'large'}>
|
||||
<Button icon={<FilterIcon />} className={styles.filterButton}>
|
||||
Filters
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={handleAddKnowledge}
|
||||
className={styles.topButton}
|
||||
>
|
||||
Create knowledge base
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</>
|
||||
<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}
|
||||
>
|
||||
<KnowledgeCard item={item}></KnowledgeCard>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
73
web/src/pages/knowledge/knowledge-card/index.less
Normal file
73
web/src/pages/knowledge/knowledge-card/index.less
Normal file
@ -0,0 +1,73 @@
|
||||
.container {
|
||||
height: 251px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.context {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
// text-align: left;
|
||||
}
|
||||
.footerTop {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(234, 236, 240, 1);
|
||||
box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
|
||||
padding: 24px;
|
||||
min-width: 300px;
|
||||
cursor: pointer;
|
||||
|
||||
.titleWrapper {
|
||||
// flex: 1;
|
||||
.title {
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
}
|
||||
.description {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
.ant-card-body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
.bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.bottomLeft {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.leftIcon {
|
||||
margin-right: 10px;
|
||||
font-size: 18px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.rightText {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
123
web/src/pages/knowledge/knowledge-card/index.tsx
Normal file
123
web/src/pages/knowledge/knowledge-card/index.tsx
Normal file
@ -0,0 +1,123 @@
|
||||
import { ReactComponent as MoreIcon } from '@/assets/svg/more.svg';
|
||||
import { formatDate } from '@/utils/date';
|
||||
import {
|
||||
AntDesignOutlined,
|
||||
CalendarOutlined,
|
||||
DeleteOutlined,
|
||||
FileTextOutlined,
|
||||
UserOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Avatar, Card, Dropdown, MenuProps, Space, Tooltip } from 'antd';
|
||||
import { MouseEvent } from 'react';
|
||||
import { useDispatch, useNavigate } from 'umi';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
interface IProps {
|
||||
item: any;
|
||||
}
|
||||
|
||||
const KnowledgeCard = ({ item }: IProps) => {
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleDelete = (e: MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
label: (
|
||||
<Space>
|
||||
删除
|
||||
<DeleteOutlined onClick={handleDelete} />
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const confirm = (id: string) => {
|
||||
dispatch({
|
||||
type: 'knowledgeModel/rmKb',
|
||||
payload: {
|
||||
kb_id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleCardClick = () => {
|
||||
navigate(`add/setting?activeKey=file&id=${item.id}`);
|
||||
};
|
||||
|
||||
const onConfirmDelete = (e?: MouseEvent<HTMLElement>) => {
|
||||
e?.stopPropagation();
|
||||
e?.nativeEvent.stopImmediatePropagation();
|
||||
confirm(item.id);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className={styles.card} onClick={handleCardClick}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<Avatar size={34} icon={<UserOutlined />} />
|
||||
|
||||
<span className={styles.delete}>
|
||||
{/* <Popconfirm
|
||||
title="Delete the task"
|
||||
description="Are you sure to delete this task?"
|
||||
onConfirm={onConfirmDelete}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<DeleteOutlined onClick={handleDelete} />
|
||||
</Popconfirm> */}
|
||||
<Dropdown menu={{ items }}>
|
||||
<MoreIcon />
|
||||
</Dropdown>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.titleWrapper}>
|
||||
<span className={styles.title}>{item.name}</span>
|
||||
<p>A comprehensive knowledge base for crafting effective resumes.</p>
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
<div className={styles.footerTop}>
|
||||
<div className={styles.bottomLeft}>
|
||||
<FileTextOutlined className={styles.leftIcon} />
|
||||
<span className={styles.rightText}>
|
||||
<Space>{item.doc_num}文档</Space>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.bottom}>
|
||||
<div className={styles.bottomLeft}>
|
||||
<CalendarOutlined className={styles.leftIcon} />
|
||||
<span className={styles.rightText}>
|
||||
{formatDate(item.update_date)}
|
||||
</span>
|
||||
</div>
|
||||
<Avatar.Group size={25}>
|
||||
<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=1" />
|
||||
<a href="https://ant.design">
|
||||
<Avatar style={{ backgroundColor: '#f56a00' }}>K</Avatar>
|
||||
</a>
|
||||
<Tooltip title="Ant User" placement="top">
|
||||
<Avatar
|
||||
style={{ backgroundColor: '#87d068' }}
|
||||
icon={<UserOutlined />}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Avatar
|
||||
style={{ backgroundColor: '#1677ff' }}
|
||||
icon={<AntDesignOutlined />}
|
||||
/>
|
||||
</Avatar.Group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default KnowledgeCard;
|
@ -19,7 +19,7 @@ const model: DvaModel<KnowledgeModelState> = {
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
*rmKb({ payload = {}, callback }, { call, put }) {
|
||||
*rmKb({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(kbService.rmKb, payload);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
|
@ -12,6 +12,8 @@ const Login = () => {
|
||||
(state) => state.loading.effects,
|
||||
);
|
||||
|
||||
// TODO: When the server address request is not accessible, the value of dva-loading always remains true.
|
||||
|
||||
const signLoading =
|
||||
effectsLoading['loginModel/login'] || effectsLoading['loginModel/register'];
|
||||
|
||||
|
@ -32,10 +32,8 @@ const model: DvaModel<LoginModelState> = {
|
||||
},
|
||||
effects: {
|
||||
*login({ payload = {} }, { call, put }) {
|
||||
console.log(111, payload);
|
||||
const { data, response } = yield call(userService.login, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
console.log();
|
||||
const { retcode, data: res } = data;
|
||||
const authorization = response.headers.get(Authorization);
|
||||
if (retcode === 0) {
|
||||
message.success('登录成功!');
|
||||
|
@ -1,92 +1,78 @@
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Input, Modal, Form } from 'antd'
|
||||
import { rsaPsw } from '@/utils'
|
||||
import styles from './index.less';
|
||||
import { FC } from 'react';
|
||||
import { rsaPsw } from '@/utils';
|
||||
import { Form, Input, Modal } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
|
||||
type FieldType = {
|
||||
newPassword?: string;
|
||||
password?: string;
|
||||
newPassword?: string;
|
||||
password?: string;
|
||||
};
|
||||
interface CPwModalProps {
|
||||
dispatch: Dispatch;
|
||||
settingModel: any
|
||||
}
|
||||
const Index: FC<CPwModalProps> = ({ settingModel, dispatch }) => {
|
||||
const { isShowPSwModal } = settingModel
|
||||
const { t } = useTranslation()
|
||||
const handleCancel = () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowPSwModal: false
|
||||
}
|
||||
});
|
||||
};
|
||||
const [form] = Form.useForm()
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
var password = rsaPsw(values.password)
|
||||
var new_password = rsaPsw(values.newPassword)
|
||||
|
||||
dispatch({
|
||||
type: 'settingModel/setting',
|
||||
payload: {
|
||||
password,
|
||||
new_password
|
||||
},
|
||||
callback: () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowPSwModal: false
|
||||
}
|
||||
});
|
||||
dispatch({
|
||||
type: 'settingModel/getUserInfo',
|
||||
payload: {
|
||||
const CpwModal = () => {
|
||||
const dispatch = useDispatch();
|
||||
const settingModel = useSelector((state: any) => state.settingModel);
|
||||
const { isShowPSwModal } = settingModel;
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
const handleCancel = () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowPSwModal: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
var password = rsaPsw(values.password);
|
||||
var new_password = rsaPsw(values.newPassword);
|
||||
|
||||
} catch (errorInfo) {
|
||||
console.log('Failed:', errorInfo);
|
||||
}
|
||||
};
|
||||
dispatch({
|
||||
type: 'settingModel/setting',
|
||||
payload: {
|
||||
password,
|
||||
new_password,
|
||||
},
|
||||
});
|
||||
} catch (errorInfo) {
|
||||
console.log('Failed:', errorInfo);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal title="Basic Modal" open={isShowPSwModal} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Form
|
||||
form={form}
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
style={{ maxWidth: 600 }}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<FieldType>
|
||||
label="旧密码"
|
||||
name="password"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="新密码"
|
||||
name="newPassword"
|
||||
rules={[{ required: true, message: 'Please input your newPassword!' }]}
|
||||
>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
|
||||
</Form>
|
||||
</Modal >
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);
|
||||
return (
|
||||
<Modal
|
||||
title="Basic Modal"
|
||||
open={isShowPSwModal}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
style={{ maxWidth: 600 }}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<FieldType>
|
||||
label="旧密码"
|
||||
name="password"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="新密码"
|
||||
name="newPassword"
|
||||
rules={[
|
||||
{ required: true, message: 'Please input your newPassword!' },
|
||||
]}
|
||||
>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
export default CpwModal;
|
||||
|
@ -1,196 +1,146 @@
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import styles from './index.less';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { useEffect, useState, FC } from 'react';
|
||||
|
||||
import { RadarChartOutlined } from '@ant-design/icons';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { Button, Tag, Row, Col, Card } from 'antd';
|
||||
|
||||
import { Button, Card, Col, Row, Tag } from 'antd';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
|
||||
interface DataType {
|
||||
key: React.Key;
|
||||
name: string;
|
||||
age: number;
|
||||
address: string;
|
||||
description: string;
|
||||
key: React.Key;
|
||||
name: string;
|
||||
age: number;
|
||||
address: string;
|
||||
description: string;
|
||||
}
|
||||
interface ListProps {
|
||||
dispatch: Dispatch;
|
||||
settingModel: any
|
||||
}
|
||||
const Index: FC<ListProps> = ({ settingModel, dispatch }) => {
|
||||
const { llmInfo = {}, factoriesList, myLlm = [] } = settingModel
|
||||
const { OpenAI = [], tongyi = [] } = llmInfo
|
||||
console.log(OpenAI)
|
||||
const [collapsed, setCollapsed] = useState(true);
|
||||
const { t } = useTranslation()
|
||||
const columns: ColumnsType<DataType> = [
|
||||
{ title: 'Name', dataIndex: 'name', key: 'name' },
|
||||
{ title: 'Age', dataIndex: 'age', key: 'age' },
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: '',
|
||||
key: 'x',
|
||||
render: () => <a>Delete</a>,
|
||||
},
|
||||
];
|
||||
useEffect(() => {
|
||||
dispatch({
|
||||
type: 'settingModel/factories_list',
|
||||
payload: {
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: 'settingModel/llm_list',
|
||||
payload: {
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: 'settingModel/my_llm',
|
||||
payload: {
|
||||
},
|
||||
});
|
||||
|
||||
}, [])
|
||||
const data: DataType[] = [
|
||||
{
|
||||
key: 1,
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
name: 'Jim Green',
|
||||
age: 42,
|
||||
address: 'London No. 1 Lake Park',
|
||||
description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
name: 'Not Expandable',
|
||||
age: 29,
|
||||
address: 'Jiangsu No. 1 Lake Park',
|
||||
description: 'This not expandable',
|
||||
},
|
||||
{
|
||||
key: 4,
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
description: 'My name is Joe Black, I am 32 years old, living in Sydney No. 1 Lake Park.',
|
||||
},
|
||||
];
|
||||
const SettingList = () => {
|
||||
const dispatch = useDispatch();
|
||||
const settingModel = useSelector((state: any) => state.settingModel);
|
||||
const { llmInfo = {}, factoriesList, myLlm = [] } = settingModel;
|
||||
const { OpenAI = [], tongyi = [] } = llmInfo;
|
||||
const [collapsed, setCollapsed] = useState(true);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.list}
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: 24,
|
||||
gap: 12,
|
||||
useEffect(() => {
|
||||
dispatch({
|
||||
type: 'settingModel/factories_list',
|
||||
payload: {},
|
||||
});
|
||||
dispatch({
|
||||
type: 'settingModel/llm_list',
|
||||
payload: {},
|
||||
});
|
||||
dispatch({
|
||||
type: 'settingModel/my_llm',
|
||||
payload: {},
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.list}
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: 24,
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
{myLlm.map((item: any) => {
|
||||
return (
|
||||
<ProCard
|
||||
key={item.llm_factory}
|
||||
// title={<div>可折叠-图标自定义</div>}
|
||||
collapsibleIconRender={({
|
||||
collapsed: buildInCollapsed,
|
||||
}: {
|
||||
collapsed: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
<h3>
|
||||
<RadarChartOutlined />
|
||||
{item.llm_factory}
|
||||
</h3>
|
||||
<div>
|
||||
{item.tags.split(',').map((d: string) => {
|
||||
return <Tag key={d}>{d}</Tag>;
|
||||
})}
|
||||
</div>
|
||||
{buildInCollapsed ? (
|
||||
<span>显示{OpenAI.length}个模型</span>
|
||||
) : (
|
||||
<span>收起{OpenAI.length}个模型 </span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
>
|
||||
{
|
||||
myLlm.map((item: any) => {
|
||||
return (<ProCard
|
||||
key={item.llm_factory}
|
||||
// title={<div>可折叠-图标自定义</div>}
|
||||
collapsibleIconRender={({
|
||||
collapsed: buildInCollapsed,
|
||||
}: {
|
||||
collapsed: boolean;
|
||||
}) => {
|
||||
return (<div>
|
||||
<h3><RadarChartOutlined />{item.llm_factory}</h3>
|
||||
<div>{item.tags.split(',').map((d: string) => {
|
||||
return <Tag key={d}>{d}</Tag>
|
||||
})}</div>
|
||||
{
|
||||
buildInCollapsed ? <span>显示{OpenAI.length}个模型</span> : <span>收起{OpenAI.length}个模型 </span>
|
||||
}
|
||||
</div>)
|
||||
}}
|
||||
extra={
|
||||
<Button
|
||||
size="small"
|
||||
type='link'
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
llm_factory: item.llm_factory,
|
||||
isShowSAKModal: true
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
设置
|
||||
</Button>
|
||||
}
|
||||
style={{ marginBlockStart: 16 }}
|
||||
headerBordered
|
||||
collapsible
|
||||
defaultCollapsed
|
||||
>
|
||||
{/* <ul>
|
||||
{OpenAI.map(item => {
|
||||
return <li key={item.llm_name}>
|
||||
<span>{item.llm_name}</span>
|
||||
<span className={styles[item.available ? 'statusAvailable' : 'statusDisaabled']}>
|
||||
</span>
|
||||
</li>
|
||||
})}
|
||||
</ul> */}
|
||||
</ProCard>)
|
||||
})
|
||||
extra={
|
||||
<Button
|
||||
size="small"
|
||||
type="link"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
llm_factory: item.llm_factory,
|
||||
isShowSAKModal: true,
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
设置
|
||||
</Button>
|
||||
}
|
||||
style={{ marginBlockStart: 16 }}
|
||||
headerBordered
|
||||
collapsible
|
||||
defaultCollapsed
|
||||
></ProCard>
|
||||
);
|
||||
})}
|
||||
|
||||
|
||||
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
|
||||
{
|
||||
factoriesList.map((item: any) => {
|
||||
return (<Col key={item.name} xs={24} sm={12} md={8} lg={6}>
|
||||
<Card title={item.name} bordered={false} extra={
|
||||
<Button
|
||||
size="small"
|
||||
type='link'
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
llm_factory: item.name,
|
||||
isShowSAKModal: true
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
设置
|
||||
</Button>
|
||||
}>
|
||||
|
||||
<div>
|
||||
{
|
||||
item.tags.split(',').map((d: string) => {
|
||||
return <Tag key={d}>{d}</Tag>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</Card>
|
||||
</Col>)
|
||||
})
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
|
||||
{factoriesList.map((item: any) => {
|
||||
return (
|
||||
<Col key={item.name} xs={24} sm={12} md={8} lg={6}>
|
||||
<Card
|
||||
title={item.name}
|
||||
bordered={false}
|
||||
extra={
|
||||
<Button
|
||||
size="small"
|
||||
type="link"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
llm_factory: item.name,
|
||||
isShowSAKModal: true,
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
设置
|
||||
</Button>
|
||||
}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);
|
||||
>
|
||||
<div>
|
||||
{item.tags.split(',').map((d: string) => {
|
||||
return <Tag key={d}>{d}</Tag>;
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default SettingList;
|
||||
|
@ -1,83 +1,66 @@
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import i18n from 'i18next';
|
||||
import { FC } from 'react'
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Input, Modal, Form } from 'antd'
|
||||
import styles from './index.less';
|
||||
import { Form, Input, Modal } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
|
||||
type FieldType = {
|
||||
api_key?: string;
|
||||
api_key?: string;
|
||||
};
|
||||
interface SAKModalProps {
|
||||
dispatch: Dispatch;
|
||||
settingModel: any
|
||||
}
|
||||
const Index: FC<SAKModalProps> = ({ settingModel, dispatch }) => {
|
||||
const { isShowSAKModal, llm_factory } = settingModel
|
||||
console.log(llm_factory)
|
||||
const { t } = useTranslation()
|
||||
const handleCancel = () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowSAKModal: false
|
||||
}
|
||||
});
|
||||
};
|
||||
const [form] = Form.useForm()
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
|
||||
dispatch({
|
||||
type: 'settingModel/set_api_key',
|
||||
payload: {
|
||||
api_key: values.api_key,
|
||||
llm_factory: llm_factory
|
||||
},
|
||||
callback: () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowSAKModal: false
|
||||
}
|
||||
});
|
||||
// dispatch({
|
||||
// type: 'settingModel/getUserInfo',
|
||||
// payload: {
|
||||
const SakModal = () => {
|
||||
const dispatch = useDispatch();
|
||||
const settingModel = useSelector((state: any) => state.settingModel);
|
||||
const { isShowSAKModal, llm_factory } = settingModel;
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
// }
|
||||
// });
|
||||
}
|
||||
});
|
||||
const handleCancel = () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowSAKModal: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
|
||||
} catch (errorInfo) {
|
||||
console.log('Failed:', errorInfo);
|
||||
}
|
||||
};
|
||||
dispatch({
|
||||
type: 'settingModel/set_api_key',
|
||||
payload: {
|
||||
api_key: values.api_key,
|
||||
llm_factory: llm_factory,
|
||||
},
|
||||
});
|
||||
} catch (errorInfo) {
|
||||
console.log('Failed:', errorInfo);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal title="Basic Modal" open={isShowSAKModal} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Form
|
||||
form={form}
|
||||
name="validateOnly"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
style={{ maxWidth: 600 }}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<FieldType>
|
||||
label="API Key"
|
||||
name="api_key"
|
||||
rules={[{ required: true, message: 'Please input ' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
</Form>
|
||||
</Modal >
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);
|
||||
return (
|
||||
<Modal
|
||||
title="Basic Modal"
|
||||
open={isShowSAKModal}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
name="validateOnly"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
style={{ maxWidth: 600 }}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<FieldType>
|
||||
label="API Key"
|
||||
name="api_key"
|
||||
rules={[{ required: true, message: 'Please input ' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
export default SakModal;
|
||||
|
@ -1,152 +1,144 @@
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import { FC } from 'react'
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Input, Modal, Form, Select } from 'antd'
|
||||
import styles from './index.less';
|
||||
import { Form, Modal, Select } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
|
||||
type FieldType = {
|
||||
embd_id?: string;
|
||||
img2txt_id?: string;
|
||||
llm_id?: string;
|
||||
asr_id?: string
|
||||
embd_id?: string;
|
||||
img2txt_id?: string;
|
||||
llm_id?: string;
|
||||
asr_id?: string;
|
||||
};
|
||||
interface SSModalProps {
|
||||
dispatch: Dispatch;
|
||||
settingModel: any
|
||||
}
|
||||
const Index: FC<SSModalProps> = ({ settingModel, dispatch }) => {
|
||||
const { isShowSSModal, llmInfo = {}, tenantIfo } = settingModel
|
||||
|
||||
const { t } = useTranslation()
|
||||
const handleCancel = () => {
|
||||
const SsModal = () => {
|
||||
const dispatch = useDispatch();
|
||||
const settingModel = useSelector((state: any) => state.settingModel);
|
||||
const { isShowSSModal, llmInfo = {}, tenantIfo } = settingModel;
|
||||
const [form] = Form.useForm();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleCancel = () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowSSModal: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
const retcode = await dispatch<any>({
|
||||
type: 'settingModel/set_tenant_info',
|
||||
payload: {
|
||||
...values,
|
||||
tenant_id: tenantIfo.tenant_id,
|
||||
},
|
||||
});
|
||||
retcode === 0 &&
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowSSModal: false
|
||||
}
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowSSModal: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
const [form] = Form.useForm()
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
console.log(values)
|
||||
dispatch({
|
||||
type: 'settingModel/set_tenant_info',
|
||||
payload: {
|
||||
...values,
|
||||
tenant_id: tenantIfo.tenant_id,
|
||||
},
|
||||
callback: () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowSSModal: false
|
||||
}
|
||||
});
|
||||
// dispatch({
|
||||
// type: 'settingModel/getUserInfo',
|
||||
// payload: {
|
||||
|
||||
// }
|
||||
// });
|
||||
}
|
||||
});
|
||||
|
||||
} catch (errorInfo) {
|
||||
console.log('Failed:', errorInfo);
|
||||
}
|
||||
};
|
||||
const handleChange = () => {
|
||||
|
||||
} catch (errorInfo) {
|
||||
console.log('Failed:', errorInfo);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal title="Basic Modal" open={isShowSSModal} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Form
|
||||
form={form}
|
||||
name="validateOnly"
|
||||
// labelCol={{ span: 8 }}
|
||||
// wrapperCol={{ span: 16 }}
|
||||
style={{ maxWidth: 600 }}
|
||||
autoComplete="off"
|
||||
layout="vertical"
|
||||
>
|
||||
<Form.Item<FieldType>
|
||||
label="embedding 模型"
|
||||
name="embd_id"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
initialValue={tenantIfo.embd_id}
|
||||
const handleChange = () => {};
|
||||
|
||||
>
|
||||
<Select
|
||||
// style={{ width: 200 }}
|
||||
onChange={handleChange}
|
||||
// fieldNames={label:}
|
||||
options={Object.keys(llmInfo).map(t => {
|
||||
const options = llmInfo[t].filter((d: any) => d.model_type === 'embedding').map((d: any) => ({ label: d.llm_name, value: d.llm_name, }))
|
||||
return { label: t, options }
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="chat 模型"
|
||||
name="llm_id"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
initialValue={tenantIfo.llm_id}
|
||||
|
||||
>
|
||||
<Select
|
||||
// style={{ width: 200 }}
|
||||
onChange={handleChange}
|
||||
// fieldNames={label:}
|
||||
options={Object.keys(llmInfo).map(t => {
|
||||
const options = llmInfo[t].filter((d: any) => d.model_type === 'chat').map((d: any) => ({ label: d.llm_name, value: d.llm_name, }))
|
||||
return { label: t, options }
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="image2text 模型"
|
||||
name="img2txt_id"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
initialValue={tenantIfo.img2txt_id}
|
||||
|
||||
>
|
||||
<Select
|
||||
// style={{ width: 200 }}
|
||||
onChange={handleChange}
|
||||
// fieldNames={label:}
|
||||
options={Object.keys(llmInfo).map(t => {
|
||||
const options = llmInfo[t].filter((d: any) => d.model_type === 'image2text').map((d: any) => ({ label: d.llm_name, value: d.llm_name, }))
|
||||
return { label: t, options }
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="speech2text 模型"
|
||||
name="asr_id"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
initialValue={tenantIfo.asr_id}
|
||||
|
||||
>
|
||||
<Select
|
||||
// style={{ width: 200 }}
|
||||
onChange={handleChange}
|
||||
// fieldNames={label:}
|
||||
options={Object.keys(llmInfo).map(t => {
|
||||
const options = llmInfo[t].filter((d: any) => d.model_type === 'speech2text').map((d: any) => ({ label: d.llm_name, value: d.llm_name, }))
|
||||
return { label: t, options }
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
|
||||
</Form>
|
||||
</Modal >
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);
|
||||
return (
|
||||
<Modal
|
||||
title="Basic Modal"
|
||||
open={isShowSSModal}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
name="validateOnly"
|
||||
// labelCol={{ span: 8 }}
|
||||
// wrapperCol={{ span: 16 }}
|
||||
style={{ maxWidth: 600 }}
|
||||
autoComplete="off"
|
||||
layout="vertical"
|
||||
>
|
||||
<Form.Item<FieldType>
|
||||
label="embedding 模型"
|
||||
name="embd_id"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
initialValue={tenantIfo.embd_id}
|
||||
>
|
||||
<Select
|
||||
// style={{ width: 200 }}
|
||||
onChange={handleChange}
|
||||
// fieldNames={label:}
|
||||
options={Object.keys(llmInfo).map((t) => {
|
||||
const options = llmInfo[t]
|
||||
.filter((d: any) => d.model_type === 'embedding')
|
||||
.map((d: any) => ({ label: d.llm_name, value: d.llm_name }));
|
||||
return { label: t, options };
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="chat 模型"
|
||||
name="llm_id"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
initialValue={tenantIfo.llm_id}
|
||||
>
|
||||
<Select
|
||||
// style={{ width: 200 }}
|
||||
onChange={handleChange}
|
||||
// fieldNames={label:}
|
||||
options={Object.keys(llmInfo).map((t) => {
|
||||
const options = llmInfo[t]
|
||||
.filter((d: any) => d.model_type === 'chat')
|
||||
.map((d: any) => ({ label: d.llm_name, value: d.llm_name }));
|
||||
return { label: t, options };
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="image2text 模型"
|
||||
name="img2txt_id"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
initialValue={tenantIfo.img2txt_id}
|
||||
>
|
||||
<Select
|
||||
// style={{ width: 200 }}
|
||||
onChange={handleChange}
|
||||
// fieldNames={label:}
|
||||
options={Object.keys(llmInfo).map((t) => {
|
||||
const options = llmInfo[t]
|
||||
.filter((d: any) => d.model_type === 'image2text')
|
||||
.map((d: any) => ({ label: d.llm_name, value: d.llm_name }));
|
||||
return { label: t, options };
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="speech2text 模型"
|
||||
name="asr_id"
|
||||
rules={[{ required: true, message: 'Please input value' }]}
|
||||
initialValue={tenantIfo.asr_id}
|
||||
>
|
||||
<Select
|
||||
// style={{ width: 200 }}
|
||||
onChange={handleChange}
|
||||
// fieldNames={label:}
|
||||
options={Object.keys(llmInfo).map((t) => {
|
||||
const options = llmInfo[t]
|
||||
.filter((d: any) => d.model_type === 'speech2text')
|
||||
.map((d: any) => ({ label: d.llm_name, value: d.llm_name }));
|
||||
return { label: t, options };
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
export default SsModal;
|
||||
|
@ -1,58 +1,65 @@
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import { FC } from 'react'
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Modal, Table } from 'antd'
|
||||
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
|
||||
import { Modal, Table } from 'antd';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
import styles from './index.less';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
|
||||
|
||||
interface DataType {
|
||||
key: React.Key;
|
||||
name: string;
|
||||
role: string;
|
||||
time: string;
|
||||
key: React.Key;
|
||||
name: string;
|
||||
role: string;
|
||||
time: string;
|
||||
}
|
||||
|
||||
interface TntodalProps {
|
||||
dispatch: Dispatch;
|
||||
settingModel: any
|
||||
}
|
||||
const TntModal = () => {
|
||||
const dispatch = useDispatch();
|
||||
const settingModel = useSelector((state: any) => state.settingModel);
|
||||
const { isShowTntModal, tenantIfo, factoriesList } = settingModel;
|
||||
const { t } = useTranslation();
|
||||
const loading = useOneNamespaceEffectsLoading('settingModel', [
|
||||
'getTenantInfo',
|
||||
]);
|
||||
|
||||
const Index: FC<TntodalProps> = ({ settingModel, dispatch }) => {
|
||||
const { isShowTntModal, tenantIfo, loading, factoriesList } = settingModel
|
||||
const { t } = useTranslation()
|
||||
const handleCancel = () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowTntModal: false
|
||||
}
|
||||
});
|
||||
};
|
||||
console.log(tenantIfo)
|
||||
const handleOk = async () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowTntModal: false
|
||||
}
|
||||
});
|
||||
};
|
||||
const columns: ColumnsType<DataType> = [
|
||||
{ title: '姓名', dataIndex: 'name', key: 'name' },
|
||||
{ title: '活动时间', dataIndex: 'update_date', key: 'update_date' },
|
||||
{ title: '角色', dataIndex: 'role', key: 'age' },
|
||||
const columns: ColumnsType<DataType> = [
|
||||
{ title: '姓名', dataIndex: 'name', key: 'name' },
|
||||
{ title: '活动时间', dataIndex: 'update_date', key: 'update_date' },
|
||||
{ title: '角色', dataIndex: 'role', key: 'age' },
|
||||
];
|
||||
|
||||
];
|
||||
const handleCancel = () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowTntModal: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal title="用户" open={isShowTntModal} onOk={handleOk} onCancel={handleCancel}>
|
||||
<div className={styles.tenantIfo}>
|
||||
{tenantIfo.name}
|
||||
</div>
|
||||
<Table rowKey='name' loading={loading} columns={columns} dataSource={factoriesList} />
|
||||
</Modal >
|
||||
);
|
||||
}
|
||||
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);
|
||||
const handleOk = async () => {
|
||||
dispatch({
|
||||
type: 'settingModel/updateState',
|
||||
payload: {
|
||||
isShowTntModal: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="用户"
|
||||
open={isShowTntModal}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<div className={styles.tenantIfo}>{tenantIfo.name}</div>
|
||||
<Table
|
||||
rowKey="name"
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
dataSource={factoriesList}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
export default TntModal;
|
||||
|
@ -1,34 +1,35 @@
|
||||
import { Button, FloatButton } from 'antd';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Dispatch, connect } from 'umi';
|
||||
|
||||
import authorizationUtil from '@/utils/authorizationUtil';
|
||||
import { FC, useEffect } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
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';
|
||||
interface CPwModalProps {
|
||||
dispatch: Dispatch;
|
||||
settingModel: any;
|
||||
}
|
||||
const Index: FC<CPwModalProps> = ({ settingModel, dispatch }) => {
|
||||
// const [llm_factory, set_llm_factory] = useState('')
|
||||
|
||||
const Setting = () => {
|
||||
const dispatch = useDispatch();
|
||||
const settingModel = useSelector((state: any) => state.settingModel);
|
||||
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',
|
||||
@ -52,11 +53,6 @@ const Index: FC<CPwModalProps> = ({ settingModel, dispatch }) => {
|
||||
isShowSSModal: true,
|
||||
},
|
||||
});
|
||||
// dispatch({
|
||||
// type: 'settingModel/getTenantInfo',
|
||||
// payload: {
|
||||
// }
|
||||
// });
|
||||
};
|
||||
return (
|
||||
<div className={styles.settingPage}>
|
||||
@ -99,7 +95,4 @@ const Index: FC<CPwModalProps> = ({ settingModel, dispatch }) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default connect(({ settingModel, loading }) => ({
|
||||
settingModel,
|
||||
loading,
|
||||
}))(Index);
|
||||
export default Setting;
|
||||
|
@ -9,7 +9,6 @@ export interface SettingModelState {
|
||||
isShowSAKModal: boolean;
|
||||
isShowSSModal: boolean;
|
||||
llm_factory: string;
|
||||
loading: boolean;
|
||||
tenantIfo: any;
|
||||
llmInfo: any;
|
||||
myLlm: any[];
|
||||
@ -24,7 +23,6 @@ const model: DvaModel<SettingModelState> = {
|
||||
isShowSAKModal: false,
|
||||
isShowSSModal: false,
|
||||
llm_factory: '',
|
||||
loading: false,
|
||||
tenantIfo: {},
|
||||
llmInfo: {},
|
||||
myLlm: [],
|
||||
@ -44,12 +42,21 @@ const model: DvaModel<SettingModelState> = {
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
*setting({ payload = {}, callback }, { call, put }) {
|
||||
const { data, response } = yield call(userService.setting, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
*setting({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(userService.setting, payload);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('密码修改成功!');
|
||||
callback && callback();
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
isShowPSwModal: false,
|
||||
},
|
||||
});
|
||||
yield put({
|
||||
type: 'getUserInfo',
|
||||
payload: {},
|
||||
});
|
||||
}
|
||||
},
|
||||
*getUserInfo({ payload = {} }, { call, put }) {
|
||||
@ -72,11 +79,8 @@ const model: DvaModel<SettingModelState> = {
|
||||
loading: true,
|
||||
},
|
||||
});
|
||||
const { data, response } = yield call(
|
||||
userService.get_tenant_info,
|
||||
payload,
|
||||
);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
const { data } = yield call(userService.get_tenant_info, payload);
|
||||
const { retcode, data: res } = data;
|
||||
// llm_id 对应chat_id
|
||||
// asr_id 对应speech2txt
|
||||
|
||||
@ -98,11 +102,8 @@ const model: DvaModel<SettingModelState> = {
|
||||
}
|
||||
},
|
||||
*set_tenant_info({ payload = {} }, { call, put }) {
|
||||
const { data, response } = yield call(
|
||||
userService.set_tenant_info,
|
||||
payload,
|
||||
);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
const { data } = yield call(userService.set_tenant_info, payload);
|
||||
const { retcode } = data;
|
||||
// llm_id 对应chat_id
|
||||
// asr_id 对应speech2txt
|
||||
if (retcode === 0) {
|
||||
@ -116,6 +117,7 @@ const model: DvaModel<SettingModelState> = {
|
||||
type: 'getTenantInfo',
|
||||
});
|
||||
}
|
||||
return retcode;
|
||||
},
|
||||
|
||||
*factories_list({ payload = {} }, { call, put }) {
|
||||
@ -157,12 +159,17 @@ const model: DvaModel<SettingModelState> = {
|
||||
});
|
||||
}
|
||||
},
|
||||
*set_api_key({ payload = {}, callback }, { call, put }) {
|
||||
const { data, response } = yield call(userService.set_api_key, payload);
|
||||
const { retcode, data: res, retmsg } = data;
|
||||
*set_api_key({ payload = {} }, { call, put }) {
|
||||
const { data } = yield call(userService.set_api_key, payload);
|
||||
const { retcode } = data;
|
||||
if (retcode === 0) {
|
||||
message.success('设置API KEY成功!');
|
||||
callback && callback();
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
isShowSAKModal: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -1,14 +1,8 @@
|
||||
|
||||
|
||||
|
||||
let api_host = `http://54.80.112.79:9380/v1`;
|
||||
|
||||
let api_host = `http://223.111.148.200:9380/v1`;
|
||||
|
||||
export { api_host };
|
||||
|
||||
export default {
|
||||
|
||||
|
||||
// 用户
|
||||
login: `${api_host}/user/login`,
|
||||
register: `${api_host}/user/register`,
|
||||
@ -23,8 +17,6 @@ export default {
|
||||
my_llm: `${api_host}/llm/my_llms`,
|
||||
set_api_key: `${api_host}/llm/set_api_key`,
|
||||
|
||||
|
||||
|
||||
//知识库管理
|
||||
kb_list: `${api_host}/kb/list`,
|
||||
create_kb: `${api_host}/kb/create`,
|
||||
@ -41,9 +33,6 @@ export default {
|
||||
rm_chunk: `${api_host}/chunk/rm`,
|
||||
retrieval_test: `${api_host}/chunk/retrieval_test`,
|
||||
|
||||
|
||||
|
||||
|
||||
// 上传
|
||||
upload: `${api_host}/document/upload`,
|
||||
get_document_list: `${api_host}/document/list`,
|
||||
@ -51,5 +40,4 @@ export default {
|
||||
document_rm: `${api_host}/document/rm`,
|
||||
document_create: `${api_host}/document/create`,
|
||||
document_change_parser: `${api_host}/document/change_parser`,
|
||||
|
||||
};
|
||||
|
@ -12,9 +12,9 @@ export function lastWeek() {
|
||||
return formatDate(moment().subtract(1, 'weeks'));
|
||||
}
|
||||
|
||||
export function formatDate(date) {
|
||||
export function formatDate(date: any) {
|
||||
if (!date) {
|
||||
return '';
|
||||
}
|
||||
return moment(date).format('YYYY-MM-DD');
|
||||
return moment(date).format('DD/MM/YYYY');
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ const errorHandler = (error: {
|
||||
*/
|
||||
const request: RequestMethod = extend({
|
||||
errorHandler, // 默认错误处理
|
||||
timeout: 3000000,
|
||||
timeout: 300000,
|
||||
getResponse: true,
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user