diff --git a/web/.umirc.ts b/web/.umirc.ts index 46f100657..2d66b3c9f 100644 --- a/web/.umirc.ts +++ b/web/.umirc.ts @@ -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/', diff --git a/web/src/assets/filter.svg b/web/src/assets/filter.svg new file mode 100644 index 000000000..b2aa28abc --- /dev/null +++ b/web/src/assets/filter.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/src/assets/svg/chat-star.svg b/web/src/assets/svg/chat-star.svg new file mode 100644 index 000000000..eb34c34b3 --- /dev/null +++ b/web/src/assets/svg/chat-star.svg @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/web/src/assets/svg/logo.svg b/web/src/assets/svg/logo.svg new file mode 100644 index 000000000..8e7968d21 --- /dev/null +++ b/web/src/assets/svg/logo.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/web/src/assets/svg/more.svg b/web/src/assets/svg/more.svg new file mode 100644 index 000000000..58ae40b2b --- /dev/null +++ b/web/src/assets/svg/more.svg @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/web/src/layouts/components/header/index.less b/web/src/layouts/components/header/index.less new file mode 100644 index 000000000..b396f0739 --- /dev/null +++ b/web/src/layouts/components/header/index.less @@ -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; +} diff --git a/web/src/layouts/components/header/index.tsx b/web/src/layouts/components/header/index.tsx new file mode 100644 index 000000000..fab3ee416 --- /dev/null +++ b/web/src/layouts/components/header/index.tsx @@ -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 ( +
+ + + + + + + {tagsData.map((item) => ( + handleChange(item.path)} + > + + + {item.name} + + + ))} + + + +
+ ); +}; + +export default RagHeader; diff --git a/web/src/layouts/index.less b/web/src/layouts/index.less index fc201abe1..d52ab516a 100644 --- a/web/src/layouts/index.less +++ b/web/src/layouts/index.less @@ -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; -} \ No newline at end of file diff --git a/web/src/layouts/index.tsx b/web/src/layouts/index.tsx index 3c809f14b..06eb101e8 100644 --- a/web/src/layouts/index.tsx +++ b/web/src/layouts/index.tsx @@ -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 ( -
- - - {tagsData.map((item) => ( - handleChange(item.path)} - > - {item.name} - - ))} - - -
+
+ { diff --git a/web/src/pages/add-knowledge/model.ts b/web/src/pages/add-knowledge/model.ts index 32a75ef4d..082074925 100644 --- a/web/src/pages/add-knowledge/model.ts +++ b/web/src/pages/add-knowledge/model.ts @@ -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 = { state: { isShowPSwModal: false, isShowTntModal: false, - loading: false, tenantIfo: {}, activeKey: 'setting', id: '', diff --git a/web/src/pages/knowledge/index.less b/web/src/pages/knowledge/index.less index e9d499b9f..37174f960 100644 --- a/web/src/pages/knowledge/index.less +++ b/web/src/pages/knowledge/index.less @@ -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; -} diff --git a/web/src/pages/knowledge/index.tsx b/web/src/pages/knowledge/index.tsx index 8af444f9c..44734dace 100644 --- a/web/src/pages/knowledge/index.tsx +++ b/web/src/pages/knowledge/index.tsx @@ -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 ( - <> -
- } - type="primary" - style={{ right: 24, top: 100 }} - /> - - {data.map((item: any) => { - return ( - - { - handleEditKnowledge(item.id); - }} - > -
-
- {item.name} - - { - e.stopPropagation(); - e.nativeEvent.stopImmediatePropagation(); - confirm(item.id); - }} - okText="Yes" - cancelText="No" - > - { - e.stopPropagation(); - e.nativeEvent.stopImmediatePropagation(); - }} - /> - - -
-
- - - {item.doc_num}文档 - - - - {item.chunk_num}个 - - - - {item.token_num}千字符 - - - {formatDate(item.update_date)} - -
-
-
- - ); - })} -
+
+
+
+ Welcome back, Zing +

+ Which database are we going to use today? +

+
+ + + +
- + + {data.map((item: any) => { + return ( + + + + ); + })} + +
); }; diff --git a/web/src/pages/knowledge/knowledge-card/index.less b/web/src/pages/knowledge/knowledge-card/index.less new file mode 100644 index 000000000..17b6bb642 --- /dev/null +++ b/web/src/pages/knowledge/knowledge-card/index.less @@ -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; + } +} diff --git a/web/src/pages/knowledge/knowledge-card/index.tsx b/web/src/pages/knowledge/knowledge-card/index.tsx new file mode 100644 index 000000000..2536641c0 --- /dev/null +++ b/web/src/pages/knowledge/knowledge-card/index.tsx @@ -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) => { + e.stopPropagation(); + }; + + const items: MenuProps['items'] = [ + { + key: '1', + label: ( + + 删除 + + + ), + }, + ]; + + 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) => { + e?.stopPropagation(); + e?.nativeEvent.stopImmediatePropagation(); + confirm(item.id); + }; + + return ( + +
+
+ } /> + + + {/* + + */} + + + + +
+
+ {item.name} +

A comprehensive knowledge base for crafting effective resumes.

+
+
+
+
+ + + {item.doc_num}文档 + +
+
+
+
+ + + {formatDate(item.update_date)} + +
+ + + + K + + + } + /> + + } + /> + +
+
+
+
+ ); +}; + +export default KnowledgeCard; diff --git a/web/src/pages/knowledge/model.ts b/web/src/pages/knowledge/model.ts index 0621f763a..51ab284bc 100644 --- a/web/src/pages/knowledge/model.ts +++ b/web/src/pages/knowledge/model.ts @@ -19,7 +19,7 @@ const model: DvaModel = { }, }, effects: { - *rmKb({ payload = {}, callback }, { call, put }) { + *rmKb({ payload = {} }, { call, put }) { const { data } = yield call(kbService.rmKb, payload); const { retcode } = data; if (retcode === 0) { diff --git a/web/src/pages/login/index.tsx b/web/src/pages/login/index.tsx index a0696b361..3493673b2 100644 --- a/web/src/pages/login/index.tsx +++ b/web/src/pages/login/index.tsx @@ -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']; diff --git a/web/src/pages/login/model.ts b/web/src/pages/login/model.ts index 257879f6d..0c2dd4abd 100644 --- a/web/src/pages/login/model.ts +++ b/web/src/pages/login/model.ts @@ -32,10 +32,8 @@ const model: DvaModel = { }, 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('登录成功!'); diff --git a/web/src/pages/setting/CPwModal.tsx b/web/src/pages/setting/CPwModal.tsx index 031d611c7..c9713709d 100644 --- a/web/src/pages/setting/CPwModal.tsx +++ b/web/src/pages/setting/CPwModal.tsx @@ -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 = ({ 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 ( - -
- - label="旧密码" - name="password" - rules={[{ required: true, message: 'Please input value' }]} - > - - - - label="新密码" - name="newPassword" - rules={[{ required: true, message: 'Please input your newPassword!' }]} - > - - - - -
- - - ); -} -export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index); + return ( + +
+ + label="旧密码" + name="password" + rules={[{ required: true, message: 'Please input value' }]} + > + + + + label="新密码" + name="newPassword" + rules={[ + { required: true, message: 'Please input your newPassword!' }, + ]} + > + + + +
+ ); +}; +export default CpwModal; diff --git a/web/src/pages/setting/List.tsx b/web/src/pages/setting/List.tsx index 86e0a3bf6..35c8191db 100644 --- a/web/src/pages/setting/List.tsx +++ b/web/src/pages/setting/List.tsx @@ -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 = ({ 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 = [ - { title: 'Name', dataIndex: 'name', key: 'name' }, - { title: 'Age', dataIndex: 'age', key: 'age' }, - { - title: 'Action', - dataIndex: '', - key: 'x', - render: () => Delete, - }, - ]; - 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 ( -
{ + dispatch({ + type: 'settingModel/factories_list', + payload: {}, + }); + dispatch({ + type: 'settingModel/llm_list', + payload: {}, + }); + dispatch({ + type: 'settingModel/my_llm', + payload: {}, + }); + }, []); + + return ( +
+ {myLlm.map((item: any) => { + return ( + 可折叠-图标自定义
} + collapsibleIconRender={({ + collapsed: buildInCollapsed, + }: { + collapsed: boolean; + }) => { + return ( +
+

+ + {item.llm_factory} +

+
+ {item.tags.split(',').map((d: string) => { + return {d}; + })} +
+ {buildInCollapsed ? ( + 显示{OpenAI.length}个模型 + ) : ( + 收起{OpenAI.length}个模型 + )} +
+ ); }} - > - { - myLlm.map((item: any) => { - return (可折叠-图标自定义
} - collapsibleIconRender={({ - collapsed: buildInCollapsed, - }: { - collapsed: boolean; - }) => { - return (
-

{item.llm_factory}

-
{item.tags.split(',').map((d: string) => { - return {d} - })}
- { - buildInCollapsed ? 显示{OpenAI.length}个模型 : 收起{OpenAI.length}个模型 - } -
) - }} - extra={ - - } - style={{ marginBlockStart: 16 }} - headerBordered - collapsible - defaultCollapsed - > - {/*
    - {OpenAI.map(item => { - return
  • - {item.llm_name} - - -
  • - })} -
*/} - ) - }) + extra={ + } + style={{ marginBlockStart: 16 }} + headerBordered + collapsible + defaultCollapsed + > + ); + })} - - - - { - factoriesList.map((item: any) => { - return ( - { - e.stopPropagation(); - dispatch({ - type: 'settingModel/updateState', - payload: { - llm_factory: item.name, - isShowSAKModal: true - } - }); - }} - > - 设置 - - }> - -
- { - item.tags.split(',').map((d: string) => { - return {d} - }) - } -
-
- ) - }) + + {factoriesList.map((item: any) => { + return ( + + { + e.stopPropagation(); + dispatch({ + type: 'settingModel/updateState', + payload: { + llm_factory: item.name, + isShowSAKModal: true, + }, + }); + }} + > + 设置 + } - -
- ); -} -export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index); + > +
+ {item.tags.split(',').map((d: string) => { + return {d}; + })} +
+ + + ); + })} + + + ); +}; +export default SettingList; diff --git a/web/src/pages/setting/SAKModal.tsx b/web/src/pages/setting/SAKModal.tsx index 94da17bb4..43744cb12 100644 --- a/web/src/pages/setting/SAKModal.tsx +++ b/web/src/pages/setting/SAKModal.tsx @@ -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 = ({ 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 ( - -
- - label="API Key" - name="api_key" - rules={[{ required: true, message: 'Please input ' }]} - > - - - - -
- - - ); -} -export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index); + return ( + +
+ + label="API Key" + name="api_key" + rules={[{ required: true, message: 'Please input ' }]} + > + + + +
+ ); +}; +export default SakModal; diff --git a/web/src/pages/setting/SSModal.tsx b/web/src/pages/setting/SSModal.tsx index 097933745..6e89669b4 100644 --- a/web/src/pages/setting/SSModal.tsx +++ b/web/src/pages/setting/SSModal.tsx @@ -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 = ({ 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({ + 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 ( - -
- - label="embedding 模型" - name="embd_id" - rules={[{ required: true, message: 'Please input value' }]} - initialValue={tenantIfo.embd_id} + const handleChange = () => {}; - > - { - 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 } - })} - /> - - - label="image2text 模型" - name="img2txt_id" - rules={[{ required: true, message: 'Please input value' }]} - initialValue={tenantIfo.img2txt_id} - - > - { - 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 } - })} - /> - - - - -
- - - ); -} -export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index); + return ( + +
+ + label="embedding 模型" + name="embd_id" + rules={[{ required: true, message: 'Please input value' }]} + initialValue={tenantIfo.embd_id} + > + { + 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 }; + })} + /> + + + label="image2text 模型" + name="img2txt_id" + rules={[{ required: true, message: 'Please input value' }]} + initialValue={tenantIfo.img2txt_id} + > + { + 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 }; + })} + /> + + +
+ ); +}; +export default SsModal; diff --git a/web/src/pages/setting/TntModal.tsx b/web/src/pages/setting/TntModal.tsx index 21c99b0a7..72a5ef809 100644 --- a/web/src/pages/setting/TntModal.tsx +++ b/web/src/pages/setting/TntModal.tsx @@ -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 = ({ 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 = [ - { title: '姓名', dataIndex: 'name', key: 'name' }, - { title: '活动时间', dataIndex: 'update_date', key: 'update_date' }, - { title: '角色', dataIndex: 'role', key: 'age' }, + const columns: ColumnsType = [ + { 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 ( - -
- {tenantIfo.name} -
- - - ); -} -export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index); + const handleOk = async () => { + dispatch({ + type: 'settingModel/updateState', + payload: { + isShowTntModal: false, + }, + }); + }; + + return ( + +
{tenantIfo.name}
+
+ + ); +}; +export default TntModal; diff --git a/web/src/pages/setting/index.tsx b/web/src/pages/setting/index.tsx index 988552945..dbb6bccc1 100644 --- a/web/src/pages/setting/index.tsx +++ b/web/src/pages/setting/index.tsx @@ -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 = ({ 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 = ({ settingModel, dispatch }) => { isShowSSModal: true, }, }); - // dispatch({ - // type: 'settingModel/getTenantInfo', - // payload: { - // } - // }); }; return (
@@ -99,7 +95,4 @@ const Index: FC = ({ settingModel, dispatch }) => {
); }; -export default connect(({ settingModel, loading }) => ({ - settingModel, - loading, -}))(Index); +export default Setting; diff --git a/web/src/pages/setting/model.ts b/web/src/pages/setting/model.ts index 604b87fda..bc3a5f1d9 100644 --- a/web/src/pages/setting/model.ts +++ b/web/src/pages/setting/model.ts @@ -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 = { isShowSAKModal: false, isShowSSModal: false, llm_factory: '', - loading: false, tenantIfo: {}, llmInfo: {}, myLlm: [], @@ -44,12 +42,21 @@ const model: DvaModel = { }, }, 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 = { 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 = { } }, *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 = { type: 'getTenantInfo', }); } + return retcode; }, *factories_list({ payload = {} }, { call, put }) { @@ -157,12 +159,17 @@ const model: DvaModel = { }); } }, - *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, + }, + }); } }, }, diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts index 6e2976768..70b4f066f 100644 --- a/web/src/utils/api.ts +++ b/web/src/utils/api.ts @@ -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`, - }; diff --git a/web/src/utils/date.ts b/web/src/utils/date.ts index 9f806e9dc..dc9272d30 100644 --- a/web/src/utils/date.ts +++ b/web/src/utils/date.ts @@ -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'); } diff --git a/web/src/utils/request.ts b/web/src/utils/request.ts index 536c6746e..2005a8218 100644 --- a/web/src/utils/request.ts +++ b/web/src/utils/request.ts @@ -83,7 +83,7 @@ const errorHandler = (error: { */ const request: RequestMethod = extend({ errorHandler, // 默认错误处理 - timeout: 3000000, + timeout: 300000, getResponse: true, });