### What problem does this PR solve? Feat: Add ParsedPageCard component #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.17.0
| import { Routes } from '@/routes'; | import { Routes } from '@/routes'; | ||||
| import { useCallback } from 'react'; | import { useCallback } from 'react'; | ||||
| import { useNavigate, useSearchParams } from 'umi'; | |||||
| import { useNavigate, useParams, useSearchParams } from 'umi'; | |||||
| export enum QueryStringMap { | export enum QueryStringMap { | ||||
| KnowledgeId = 'knowledgeId', | KnowledgeId = 'knowledgeId', | ||||
| export const useNavigatePage = () => { | export const useNavigatePage = () => { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const [searchParams] = useSearchParams(); | const [searchParams] = useSearchParams(); | ||||
| const { id } = useParams(); | |||||
| const navigateToDatasetList = useCallback(() => { | const navigateToDatasetList = useCallback(() => { | ||||
| navigate(Routes.Datasets); | navigate(Routes.Datasets); | ||||
| [searchParams], | [searchParams], | ||||
| ); | ); | ||||
| const navigateToChunk = useCallback( | |||||
| (route: Routes) => { | |||||
| navigate( | |||||
| `${route}/${id}?${QueryStringMap.KnowledgeId}=${getQueryString(QueryStringMap.KnowledgeId)}`, | |||||
| ); | |||||
| }, | |||||
| [getQueryString, id, navigate], | |||||
| ); | |||||
| return { | return { | ||||
| navigateToDatasetList, | navigateToDatasetList, | ||||
| navigateToDataset, | navigateToDataset, | ||||
| navigateToChat, | navigateToChat, | ||||
| navigateToChunkParsedResult, | navigateToChunkParsedResult, | ||||
| getQueryString, | getQueryString, | ||||
| navigateToChunk, | |||||
| }; | }; | ||||
| }; | }; |
| import { Card, CardContent } from '@/components/ui/card'; | |||||
| interface ParsedPageCardProps { | |||||
| page: string; | |||||
| content: string; | |||||
| } | |||||
| export function ParsedPageCard({ page, content }: ParsedPageCardProps) { | |||||
| return ( | |||||
| <Card className="bg-colors-outline-neutral-standard border-colors-outline-neutral-strong rounded-3xl"> | |||||
| <CardContent className="p-4"> | |||||
| <p className="text-colors-text-neutral-standard text-base">{page}</p> | |||||
| <div className="text-colors-text-neutral-strong text-lg mt-2"> | |||||
| {content} | |||||
| </div> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ); | |||||
| } | |||||
| interface ChunkCardProps { | |||||
| activated: boolean; | |||||
| } | |||||
| export function ChunkCard({}: ChunkCardProps) { | |||||
| return ( | |||||
| <Card className="bg-colors-outline-neutral-standard border-colors-outline-neutral-strong rounded-3xl"> | |||||
| <CardContent className="p-4"> | |||||
| <p className="text-colors-text-neutral-standard text-base">{}</p> | |||||
| <div className="text-colors-text-neutral-strong text-lg mt-2">{}</div> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ); | |||||
| } |
| import ParsedResultPanel from '../parsed-result-panel'; | |||||
| export default function ChunkResult() { | export default function ChunkResult() { | ||||
| return <div>ChunkResult</div>; | |||||
| return ( | |||||
| <section className="flex"> | |||||
| <ParsedResultPanel></ParsedResultPanel> | |||||
| <div className="flex-1"></div> | |||||
| </section> | |||||
| ); | |||||
| } | } |
| import { Button } from '@/components/ui/button'; | |||||
| import { Copy } from 'lucide-react'; | |||||
| export function ChunkToolbar() { | |||||
| return ( | |||||
| <div className="flex justify-between px-9"> | |||||
| <span className="text-colors-text-neutral-strong text-3xl font-bold"> | |||||
| Parsed results | |||||
| </span> | |||||
| <div className="flex items-center gap-3"> | |||||
| <Button variant={'icon'} size={'icon'}> | |||||
| <Copy /> | |||||
| </Button> | |||||
| <Button variant={'outline'} size={'sm'}> | |||||
| Export | |||||
| </Button> | |||||
| </div> | |||||
| </div> | |||||
| ); | |||||
| } |
| import { PageHeader } from '@/components/page-header'; | import { PageHeader } from '@/components/page-header'; | ||||
| import { Button } from '@/components/ui/button'; | |||||
| import { Segmented, SegmentedValue } from '@/components/ui/segmented'; | |||||
| import { | import { | ||||
| QueryStringMap, | QueryStringMap, | ||||
| useNavigatePage, | useNavigatePage, | ||||
| } from '@/hooks/logic-hooks/navigate-hooks'; | } from '@/hooks/logic-hooks/navigate-hooks'; | ||||
| import { Outlet } from 'umi'; | |||||
| import { Routes } from '@/routes'; | |||||
| import { EllipsisVertical } from 'lucide-react'; | |||||
| import { useMemo } from 'react'; | |||||
| import { Outlet, useLocation } from 'umi'; | |||||
| export default function ChunkPage() { | export default function ChunkPage() { | ||||
| const { navigateToDataset, getQueryString } = useNavigatePage(); | |||||
| const { navigateToDataset, getQueryString, navigateToChunk } = | |||||
| useNavigatePage(); | |||||
| const location = useLocation(); | |||||
| const options = useMemo(() => { | |||||
| return [ | |||||
| { | |||||
| label: 'Parsed results', | |||||
| value: Routes.ParsedResult, | |||||
| }, | |||||
| { | |||||
| label: 'Chunk result', | |||||
| value: Routes.ChunkResult, | |||||
| }, | |||||
| { | |||||
| label: 'Result view', | |||||
| value: Routes.ResultView, | |||||
| }, | |||||
| ]; | |||||
| }, []); | |||||
| const path = useMemo(() => { | |||||
| return location.pathname.split('/').slice(0, 3).join('/'); | |||||
| }, [location.pathname]); | |||||
| return ( | return ( | ||||
| <section> | <section> | ||||
| <PageHeader | <PageHeader | ||||
| back={navigateToDataset( | back={navigateToDataset( | ||||
| getQueryString(QueryStringMap.KnowledgeId) as string, | getQueryString(QueryStringMap.KnowledgeId) as string, | ||||
| )} | )} | ||||
| ></PageHeader> | |||||
| > | |||||
| <div> | |||||
| <Segmented | |||||
| options={options} | |||||
| value={path} | |||||
| onChange={navigateToChunk as (val: SegmentedValue) => void} | |||||
| className="bg-colors-background-inverse-standard text-colors-text-neutral-standard" | |||||
| ></Segmented> | |||||
| </div> | |||||
| <div className="flex items-center gap-2"> | |||||
| <Button variant={'icon'} size={'icon'}> | |||||
| <EllipsisVertical /> | |||||
| </Button> | |||||
| <Button variant={'tertiary'} size={'sm'}> | |||||
| Save | |||||
| </Button> | |||||
| </div> | |||||
| </PageHeader> | |||||
| <Outlet /> | <Outlet /> | ||||
| </section> | </section> | ||||
| ); | ); |
| import { ParsedPageCard } from './chunk-card'; | |||||
| import { ChunkToolbar } from './chunk-toolbar'; | |||||
| const list = new Array(10).fill({ | |||||
| page: 'page 1', | |||||
| content: `Word并不像 TeX/LaTeX为我们提供了合适的定理环境,因此需要我们另想办法。 | |||||
| 第1节 自定义定理环境 | |||||
| 我们已经使用了“定理样式”作为定理排版的样式,如: | |||||
| 定理1.1.对顶角相等。 | |||||
| 如果大家需要其他的如引理,公理,定义等环境可以仿照定义。 | |||||
| 定理1.2.三边对应相等的三角形全等。 | |||||
| 我们将这个过程也定义成了宏,在工具栏Theorem里面。书写过程如下:先写好定理本身,然后在该段落处放置光标,打开Theorem工具栏,点SetTheorem,即可见到效果。请尝试下面一个例子:`, | |||||
| }); | |||||
| export default function ParsedResultPanel() { | |||||
| return ( | |||||
| <div className="flex-1 py-6 border-l space-y-6"> | |||||
| <ChunkToolbar></ChunkToolbar> | |||||
| <div className="space-y-6 overflow-auto max-h-[94vh] px-9"> | |||||
| {list.map((x, idx) => ( | |||||
| <ParsedPageCard | |||||
| key={idx} | |||||
| page={x.page} | |||||
| content={x.content} | |||||
| ></ParsedPageCard> | |||||
| ))} | |||||
| </div> | |||||
| </div> | |||||
| ); | |||||
| } |
| import ParsedResultPanel from '../parsed-result-panel'; | |||||
| export default function ParsedResult() { | export default function ParsedResult() { | ||||
| return <div>ParsedResult</div>; | |||||
| return ( | |||||
| <section className="flex"> | |||||
| <div className="flex-1"></div> | |||||
| <ParsedResultPanel></ParsedResultPanel> | |||||
| </section> | |||||
| ); | |||||
| } | } |