From 2da1c185097b05ea0667ed0146d202066daa87aa Mon Sep 17 00:00:00 2001 From: billchen Date: Wed, 31 Jan 2024 16:47:21 +0800 Subject: [PATCH] feat: layout the knowledge list page --- web/.umirc.ts | 5 + web/src/assets/filter.svg | 3 + web/src/assets/svg/more.svg | 11 ++ web/src/layouts/components/header/index.less | 13 ++ web/src/layouts/components/header/index.tsx | 64 +++++++++ web/src/layouts/index.less | 14 +- web/src/layouts/index.tsx | 64 ++------- web/src/less/variable.less | 1 + web/src/pages/knowledge/index.less | 65 +++++---- web/src/pages/knowledge/index.tsx | 135 ++++++------------ .../pages/knowledge/knowledge-card/index.less | 73 ++++++++++ .../pages/knowledge/knowledge-card/index.tsx | 123 ++++++++++++++++ web/src/utils/date.ts | 4 +- 13 files changed, 383 insertions(+), 192 deletions(-) create mode 100644 web/src/assets/filter.svg create mode 100644 web/src/assets/svg/more.svg create mode 100644 web/src/layouts/components/header/index.less create mode 100644 web/src/layouts/components/header/index.tsx create mode 100644 web/src/less/variable.less create mode 100644 web/src/pages/knowledge/knowledge-card/index.less create mode 100644 web/src/pages/knowledge/knowledge-card/index.tsx 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/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..898fc95a0 --- /dev/null +++ b/web/src/layouts/components/header/index.less @@ -0,0 +1,13 @@ +.tag { + height: 40px; + padding: 0 30px; + margin: 0 5px; + border: 1px solid #000; + border-radius: 10px; + cursor: pointer; +} + +.checked { + color: #1677ff; + border-color: #1677ff; +} diff --git a/web/src/layouts/components/header/index.tsx b/web/src/layouts/components/header/index.tsx new file mode 100644 index 000000000..8307ae013 --- /dev/null +++ b/web/src/layouts/components/header/index.tsx @@ -0,0 +1,64 @@ +import logo from '@/assets/logo.png'; +import { Layout, Space, theme } from 'antd'; +import classnames from 'classnames'; + +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} - - ))} - - -
+
+ { 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/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'); }