### What problem does this PR solve? Feat: Add TagWorkCloud #4368 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.16.0
| "@ant-design/icons": "^5.2.6", | "@ant-design/icons": "^5.2.6", | ||||
| "@ant-design/pro-components": "^2.6.46", | "@ant-design/pro-components": "^2.6.46", | ||||
| "@ant-design/pro-layout": "^7.17.16", | "@ant-design/pro-layout": "^7.17.16", | ||||
| "@antv/g2": "^5.2.10", | |||||
| "@antv/g6": "^5.0.10", | "@antv/g6": "^5.0.10", | ||||
| "@hookform/resolvers": "^3.9.1", | "@hookform/resolvers": "^3.9.1", | ||||
| "@js-preview/excel": "^1.7.8", | "@js-preview/excel": "^1.7.8", |
| import camelCase from 'lodash/camelCase'; | import camelCase from 'lodash/camelCase'; | ||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import { TagTable } from './tag-table'; | |||||
| import { TagTabs } from './tag-tabs'; | |||||
| import { ImageMap } from './utils'; | import { ImageMap } from './utils'; | ||||
| const { Title, Text } = Typography; | const { Title, Text } = Typography; | ||||
| <SvgIcon name={'chunk-method/chunk-empty'} width={'100%'}></SvgIcon> | <SvgIcon name={'chunk-method/chunk-empty'} width={'100%'}></SvgIcon> | ||||
| </Empty> | </Empty> | ||||
| )} | )} | ||||
| {chunkMethod === 'tag' && <TagTable></TagTable>} | |||||
| {chunkMethod === 'tag' && <TagTabs></TagTabs>} | |||||
| </section> | </section> | ||||
| ); | ); | ||||
| }; | }; |
| import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; | |||||
| import { TagTable } from './tag-table'; | |||||
| import { TagWordCloud } from './tag-word-cloud'; | |||||
| export function TagTabs() { | |||||
| return ( | |||||
| <Tabs defaultValue="account" className="mt-4"> | |||||
| <TabsList> | |||||
| <TabsTrigger value="account">Word cloud</TabsTrigger> | |||||
| <TabsTrigger value="password">Table</TabsTrigger> | |||||
| </TabsList> | |||||
| <TabsContent value="account"> | |||||
| <TagWordCloud></TagWordCloud> | |||||
| </TabsContent> | |||||
| <TabsContent value="password"> | |||||
| <TagTable></TagTable> | |||||
| </TabsContent> | |||||
| </Tabs> | |||||
| ); | |||||
| } |
| import { useFetchTagList } from '@/hooks/knowledge-hooks'; | |||||
| import { Chart } from '@antv/g2'; | |||||
| import { useCallback, useEffect, useRef } from 'react'; | |||||
| export function TagWordCloud() { | |||||
| const domRef = useRef<HTMLDivElement>(null); | |||||
| let chartRef = useRef<Chart>(); | |||||
| const { list } = useFetchTagList(); | |||||
| const renderWordCloud = useCallback(() => { | |||||
| if (domRef.current) { | |||||
| chartRef.current = new Chart({ container: domRef.current }); | |||||
| chartRef.current.options({ | |||||
| type: 'wordCloud', | |||||
| autoFit: true, | |||||
| layout: { fontSize: [20, 100] }, | |||||
| data: { | |||||
| type: 'inline', | |||||
| value: list.map((x) => ({ text: x[0], value: x[1], name: x[0] })), | |||||
| }, | |||||
| encode: { color: 'text' }, | |||||
| legend: false, | |||||
| tooltip: false, | |||||
| }); | |||||
| chartRef.current.render(); | |||||
| } | |||||
| }, [list]); | |||||
| useEffect(() => { | |||||
| renderWordCloud(); | |||||
| return () => { | |||||
| chartRef.current?.destroy(); | |||||
| }; | |||||
| }, [renderWordCloud]); | |||||
| return <div ref={domRef} className="w-full h-[38vh]"></div>; | |||||
| } |
| dataUrl: string, | dataUrl: string, | ||||
| filename: string = 'file', | filename: string = 'file', | ||||
| ) => { | ) => { | ||||
| console.log('transformBase64ToFile', dataUrl); | |||||
| let arr = dataUrl.split(','), | let arr = dataUrl.split(','), | ||||
| bstr = atob(arr[1]), | bstr = atob(arr[1]), | ||||
| n = bstr.length, | n = bstr.length, | ||||
| }; | }; | ||||
| export const normFile = (e: any) => { | export const normFile = (e: any) => { | ||||
| console.log('normFile', e); | |||||
| if (Array.isArray(e)) { | if (Array.isArray(e)) { | ||||
| return e; | return e; | ||||
| } | } | ||||
| }; | }; | ||||
| export const getUploadFileListFromBase64 = (avatar: string) => { | export const getUploadFileListFromBase64 = (avatar: string) => { | ||||
| console.log('getUploadFileListFromBase64', avatar); | |||||
| let fileList: UploadFile[] = []; | let fileList: UploadFile[] = []; | ||||
| if (avatar) { | if (avatar) { | ||||
| }; | }; | ||||
| export const getBase64FromUploadFileList = async (fileList?: UploadFile[]) => { | export const getBase64FromUploadFileList = async (fileList?: UploadFile[]) => { | ||||
| console.log('getBase64FromUploadFileList', fileList); | |||||
| if (Array.isArray(fileList) && fileList.length > 0) { | if (Array.isArray(fileList) && fileList.length > 0) { | ||||
| const file = fileList[0]; | const file = fileList[0]; | ||||
| const originFileObj = file.originFileObj; | const originFileObj = file.originFileObj; | ||||
| const Units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; | const Units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; | ||||
| export const formatBytes = (x: string | number) => { | export const formatBytes = (x: string | number) => { | ||||
| console.log('formatBytes', x); | |||||
| let l = 0, | let l = 0, | ||||
| n = (typeof x === 'string' ? parseInt(x, 10) : x) || 0; | n = (typeof x === 'string' ? parseInt(x, 10) : x) || 0; | ||||