排版
現在做首頁的排版,依舊是偷antd里面的東西
使用card包裹list的樣式
import React from 'react'
import 'axios'
import { Card, Col, Row, List } from 'antd'
import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons';
import { Avatar } from 'antd';
const { Meta } = Card;function Home() {return (<div><Row gutter={16}><Col span={8}><Card title="用戶最常瀏覽" variant="border"><Listsize="small"dataSource={['qq', 'wx', 'dy']}renderItem={(item) => <List.Item>{item}</List.Item>}/></Card></Col><Col span={8}><Card title="用戶點贊最多" variant="border"><Listsize="small"dataSource={['qq', 'wx', 'dy']}renderItem={(item) => <List.Item>{item}</List.Item>}/></Card></Col><Col span={8}><Cardcover={<imgalt="example"src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"/>}actions={[<SettingOutlined key="setting" />,<EditOutlined key="edit" />,<EllipsisOutlined key="ellipsis" />,]}><Metaavatar={<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=8" />}title="Card title"description="This is the description"/></Card></Col></Row></div>)
}export default Home
數據
接下來就是寫數據請求之類的了
做后端數據請求+顯示:
import React, { useEffect } from 'react'
import 'axios'
import { Card, Col, Row, List } from 'antd'
import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons';
import { Avatar } from 'antd';
import axios from 'axios';
import { useState } from'react'
const { Meta } = Card;function Home() {const [viewList, setviewList] = useState([])const [starList, setstarList] = useState([])useEffect(()=>{axios.get("http://localhost:3000/news?publishState=2&_expand=category&_sort=view&_order=desc&_limit=6").then(res=>{setviewList(res.data)}).catch(err => {console.error('Request failed', err)})},[])useEffect(()=>{axios.get("http://localhost:3000/news?publishState=2&_expand=category&_sort=star&_order=desc&_limit=6").then(res=>{setstarList(res.data)}).catch(err => {console.error('Request failed', err)})},[])const {username,region,role:{roleName}} = JSON.parse(localStorage.getItem('token'))return (<div><Row gutter={16}><Col span={8}><Card title="用戶最常瀏覽" variant="border"><Listsize="small"dataSource={viewList}renderItem={(item) => <List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>}/></Card></Col><Col span={8}><Card title="用戶點贊最多" variant="border"><Listsize="small"dataSource={starList}renderItem={(item) => <List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>}/></Card></Col><Col span={8}><Cardcover={<imgalt="example"src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"/>}actions={[<SettingOutlined key="setting" />,<EditOutlined key="edit" />,<EllipsisOutlined key="ellipsis" />,]}><Metaavatar={<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=8" />}title={username}description={<div><b>{region?region:'全球'}</b><span style={{paddingLeft:"30px" }}>{roleName}</span> </div>}/></Card></Col></Row></div>)
}export default Home
柱狀圖
要做柱狀圖,需要用到一個開源的可視化的庫:Apache EChartshttps://echarts.apache.org/zh/index.html
echarts也是需要下載的:
npm i --save echarts
使用相對來說簡單,先做好模塊的初始化,然后進行導入,復制粘貼就好了:
import React, { useEffect } from 'react'
import 'axios'
import { Card, Col, Row, List } from 'antd'
import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons';
import { Avatar } from 'antd';
import axios from 'axios';
import * as Echarts from 'echarts';
// 把所有東西都導進打模塊中
import { useState } from'react'
const { Meta } = Card;function Home() {const [viewList, setviewList] = useState([])const [starList, setstarList] = useState([])useEffect(()=>{axios.get("http://localhost:3000/news?publishState=2&_expand=category&_sort=view&_order=desc&_limit=6").then(res=>{setviewList(res.data)}).catch(err => {console.error('Request failed', err)})},[])useEffect(()=>{axios.get("http://localhost:3000/news?publishState=2&_expand=category&_sort=star&_order=desc&_limit=6").then(res=>{setstarList(res.data)}).catch(err => {console.error('Request failed', err)})},[])useEffect(()=>{var myChart = Echarts.init(document.getElementById('main'));// 指定圖表的配置項和數據var option = {title: {text: 'ECharts 入門示例'},tooltip: {},legend: {data: ['銷量']},xAxis: {data: ['襯衫', '羊毛衫', '雪紡衫', '褲子', '高跟鞋', '襪子']},yAxis: {},series: [{name: '銷量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]};// 使用剛指定的配置項和數據顯示圖表。myChart.setOption(option);},[])const {username,region,role:{roleName}} = JSON.parse(localStorage.getItem('token'))return (<div><Row gutter={16}><Col span={8}><Card title="用戶最常瀏覽" variant="border"><Listsize="small"dataSource={viewList}renderItem={(item) => <List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>}/></Card></Col><Col span={8}><Card title="用戶點贊最多" variant="border"><Listsize="small"dataSource={starList}renderItem={(item) => <List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>}/></Card></Col><Col span={8}><Cardcover={<imgalt="example"src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"/>}actions={[<SettingOutlined key="setting" />,<EditOutlined key="edit" />,<EllipsisOutlined key="ellipsis" />,]}><Metaavatar={<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=8" />}title={username}description={<div><b>{region?region:'全球'}</b><span style={{paddingLeft:"30px" }}>{roleName}</span> </div>}/></Card></Col></Row><div id="main" style={{width:"100%",height:"400px",marginTop:"30px",}}></div></div>)
}export default Home
接下來做樣式的統一處理,引入lodash庫
import React, { useEffect, useRef } from 'react'
import 'axios'
import { Card, Col, Row, List } from 'antd'
import {EditOutlined,EllipsisOutlined,SettingOutlined,
} from '@ant-design/icons'
import { Avatar } from 'antd'
import axios from 'axios'
import * as Echarts from 'echarts'
// 把所有東西都導進打模塊中
import { useState } from 'react'
import _ from 'lodash'
const { Meta } = Cardfunction Home() {const [viewList, setviewList] = useState([])const [starList, setstarList] = useState([])const barRef = useRef(null)useEffect(() => {axios.get('http://localhost:3000/news?publishState=2&_expand=category&_sort=view&_order=desc&_limit=6').then((res) => {setviewList(res.data)}).catch((err) => {console.error('Request failed', err)})}, [])useEffect(() => {axios.get('http://localhost:3000/news?publishState=2&_expand=category&_sort=star&_order=desc&_limit=6').then((res) => {setstarList(res.data)}).catch((err) => {console.error('Request failed', err)})}, [])useEffect(() => {axios.get('/news?publishState=2&_expand=category').then((res) => {console.log(res.data)renderBarView(_.groupBy(res.data, (item) => item.category.title))}).catch((err) => {console.error('Request failed', err)})const renderBarView = (obj) => {var myChart = Echarts.init(barRef.current)// 指定圖表的配置項和數據var option = {title: {text: '新聞分類圖示',},tooltip: {},legend: {data: ['數量'],},xAxis: {data: Object.keys(obj),},yAxis: {},series: [{name: '數量',type: 'bar',// 把數組映射成長度data: Object.values(obj).map((item) => item.length),},],}// 使用剛指定的配置項和數據顯示圖表。myChart.setOption(option)return () => {myChart.dispose()}}}, [])const {username,region,role: { roleName },} = JSON.parse(localStorage.getItem('token'))return (<div><Row gutter={16}><Col span={8}><Card title="用戶最常瀏覽" variant="border"><Listsize="small"dataSource={viewList}renderItem={(item) => (<List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>)}/></Card></Col><Col span={8}><Card title="用戶點贊最多" variant="border"><Listsize="small"dataSource={starList}renderItem={(item) => (<List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>)}/></Card></Col><Col span={8}><Cardcover={<imgalt="example"src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"/>}actions={[<SettingOutlined key="setting" />,<EditOutlined key="edit" />,<EllipsisOutlined key="ellipsis" />,]}><Metaavatar={<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=8" />}title={username}description={<div><b>{region ? region : '全球'}</b><spanstyle={{paddingLeft: '30px',}}>{roleName}</span></div>}/></Card></Col></Row><divref={barRef}style={{width: '100%',height: '400px',marginTop: '30px',}}></div></div>)
}export default Home
現在的分類做出來了,但是沒有做響應式,所以優化一下
響應式
?進行響應式的優化:
import React, { useEffect, useRef } from 'react'
import { Card, Col, Row, List } from 'antd'
import {EditOutlined,EllipsisOutlined,SettingOutlined,
} from '@ant-design/icons'
import { Avatar } from 'antd'
import axios from 'axios'
import * as Echarts from 'echarts'
// 把所有東西都導進打模塊中
import { useState } from 'react'
import _ from 'lodash'
const { Meta } = Cardfunction Home() {const [viewList, setviewList] = useState([])const [starList, setstarList] = useState([])const barRef = useRef(null)useEffect(() => {axios.get('http://localhost:3000/news?publishState=2&_expand=category&_sort=view&_order=desc&_limit=6').then((res) => {setviewList(res.data)}).catch((err) => {console.error('Request failed', err)})}, [])useEffect(() => {axios.get('http://localhost:3000/news?publishState=2&_expand=category&_sort=star&_order=desc&_limit=6').then((res) => {setstarList(res.data)}).catch((err) => {console.error('Request failed', err)})}, [])useEffect(() => {axios.get('/news?publishState=2&_expand=category').then((res) => {renderBarView(_.groupBy(res.data, (item) => item.category.title))})return ()=>{window.onresize = null}}, [])const renderBarView = (obj) => {var myChart = Echarts.init(barRef.current)// 指定圖表的配置項和數據var option = {title: {text: '新聞分類圖示',},tooltip: {},legend: {data: ['數量'],},xAxis: {data: Object.keys(obj),axisLabel: {rotate: "60",//強制顯示interval: 0,},},yAxis: {// 讓顯示全是整數minInterval: 1},series: [{name: '數量',type: 'bar',// 把數組映射成長度data: Object.values(obj).map((item) => item.length),},],}// 使用剛指定的配置項和數據顯示圖表。myChart.setOption(option)window.onresize =()=>{//每次自動觸發myChart.resize()} return () => {myChart.dispose()}}const {username,region,role: { roleName },} = JSON.parse(localStorage.getItem('token'))return (<div><Row gutter={16}><Col span={8}><Card title="用戶最常瀏覽" variant="border"><Listsize="small"dataSource={viewList}renderItem={(item) => (<List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>)}/></Card></Col><Col span={8}><Card title="用戶點贊最多" variant="border"><Listsize="small"dataSource={starList}renderItem={(item) => (<List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>)}/></Card></Col><Col span={8}><Cardcover={<imgalt="example"src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"/>}actions={[<SettingOutlined key="setting" />,<EditOutlined key="edit" />,<EllipsisOutlined key="ellipsis" />,]}><Metaavatar={<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=8" />}title={username}description={<div><b>{region ? region : '全球'}</b><spanstyle={{paddingLeft: '30px',}}>{roleName}</span></div>}/></Card></Col></Row><divref={barRef}style={{width: '100%',height: '400px',marginTop: '30px',}}></div></div>)
}export default Home
用onresize即可
餅狀圖
最開始寫的代碼有問題,會出現顯示不及時或者顯示出來的格式是錯的的問題:
// import React, { useEffect, useRef, useState } from 'react';
// import { Card, Col, Row, List, Drawer } from 'antd';
// import {
// EditOutlined,
// EllipsisOutlined,
// SettingOutlined,
// } from '@ant-design/icons';
// import { Avatar } from 'antd';
// import axios from 'axios';
// import * as Echarts from 'echarts';
// import _ from 'lodash';// const { Meta } = Card;// function Home() {
// const [viewList, setviewList] = useState([]);
// const [starList, setstarList] = useState([]);
// const [visible, setvisible] = useState(false);// const barRef = useRef(null);
// const pieRef = useRef(null);// useEffect(() => {
// axios
// .get(
// 'http://localhost:3000/news?publishState=2&_expand=category&_sort=view&_order=desc&_limit=6'
// )
// .then((res) => {
// setviewList(res.data);
// })
// .catch((err) => {
// console.error('Request failed', err);
// });
// }, []);// useEffect(() => {
// axios
// .get(
// 'http://localhost:3000/news?publishState=2&_expand=category&_sort=star&_order=desc&_limit=6'
// )
// .then((res) => {
// setstarList(res.data);
// })
// .catch((err) => {
// console.error('Request failed', err);
// });
// }, []);// useEffect(() => {
// let barCleanup;
// let barResizeHandler;
// let pieCleanup;
// let pieResizeHandler;// const fetchDataAndRender = async () => {
// try {
// const res = await axios.get('/news?publishState=2&_expand=category');
// if (barRef.current) {
// barCleanup = renderBarView(
// _.groupBy(res.data, (item) => item.category.title)
// );
// barResizeHandler = () => {
// if (barCleanup) {
// const myChart = Echarts.getInstanceByDom(barRef.current);
// if (myChart) {
// myChart.resize();
// }
// }
// };
// window.addEventListener('resize', barResizeHandler);
// }
// } catch (err) {
// console.error('Request failed', err);
// }
// };// fetchDataAndRender();// return () => {
// if (typeof barCleanup === 'function') {
// barCleanup();
// }
// if (barResizeHandler) {
// window.removeEventListener('resize', barResizeHandler);
// }
// if (typeof pieCleanup === 'function') {
// pieCleanup();
// }
// if (pieResizeHandler) {
// window.removeEventListener('resize', pieResizeHandler);
// }
// };
// }, []);// const renderBarView = (obj) => {
// if (!barRef.current) return;
// var myChart = Echarts.init(barRef.current);// // 指定圖表的配置項和數據
// var option = {
// title: {
// text: '新聞分類圖示',
// },
// tooltip: {},
// legend: {
// data: ['數量'],
// },
// xAxis: {
// data: Object.keys(obj),
// axisLabel: {
// rotate: 60,
// // 強制顯示
// interval: 0,
// },
// },
// yAxis: {
// // 讓顯示全是整數
// minInterval: 1,
// },
// series: [
// {
// name: '數量',
// type: 'bar',
// // 把數組映射成長度
// data: Object.values(obj).map((item) => item.length),
// },
// ],
// };
// // 使用剛指定的配置項和數據顯示圖表。
// myChart.setOption(option);// return () => {
// myChart.dispose();
// };
// };// const renderPieView = (obj) => {
// if (!pieRef.current) return;
// var myChart = Echarts.init(pieRef.current);// var option = {
// title: {
// text: 'Referer of a Website',
// subtext: 'Fake Data',
// left: 'center',
// },
// tooltip: {
// trigger: 'item',
// },
// legend: {
// orient: 'vertical',
// left: 'left',
// },
// series: [
// {
// name: 'Access From',
// type: 'pie',
// radius: '50%',
// data: [
// { value: 1048, name: 'Search Engine' },
// { value: 735, name: 'Direct' },
// { value: 580, name: 'Email' },
// { value: 484, name: 'Union Ads' },
// { value: 300, name: 'Video Ads' },
// ],
// emphasis: {
// itemStyle: {
// shadowBlur: 10,
// shadowOffsetX: 0,
// shadowColor: 'rgba(0, 0, 0, 0.5)',
// },
// },
// },
// ],
// };
// option && myChart.setOption(option);// const resizeHandler = () => {
// myChart.resize();
// };
// window.addEventListener('resize', resizeHandler);// return () => {
// window.removeEventListener('resize', resizeHandler);
// myChart.dispose();
// };
// };// const tokenData = localStorage.getItem('token');
// const {
// username = '',
// region = '',
// role: { roleName = '' } = {},
// } = tokenData ? JSON.parse(tokenData) : {};// return (
// <div>
// <Row gutter={16}>
// <Col span={8}>
// <Card title="用戶最常瀏覽" variant="border">
// <List
// size="small"
// dataSource={viewList}
// renderItem={(item) => (
// <List.Item>
// <a href={`#/news-manage/preview/${item.id}`}>{item.title}</a>
// </List.Item>
// )}
// />
// </Card>
// </Col>
// <Col span={8}>
// <Card title="用戶點贊最多" variant="border">
// <List
// size="small"
// dataSource={starList}
// renderItem={(item) => (
// <List.Item>
// <a href={`#/news-manage/preview/${item.id}`}>{item.title}</a>
// </List.Item>
// )}
// />
// </Card>
// </Col>
// <Col span={8}>
// <Card
// cover={
// <img
// alt="example"
// src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
// />
// }
// actions={[
// <SettingOutlined
// key="setting"
// onClick={() => {
// setTimeout(() => {
// setvisible(true);
// //init初始化
// renderPieView();
// }, 0);
// }}
// />,
// <EditOutlined key="edit" />,
// <EllipsisOutlined key="ellipsis" />,
// ]}
// >
// <Meta
// avatar={
// <Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=8" />
// }
// title={username}
// description={
// <div>
// <b>{region ? region : '全球'}</b>
// <span
// style={{
// paddingLeft: '30px',
// }}
// >
// {roleName}
// </span>
// </div>
// }
// />
// </Card>
// </Col>
// </Row>// <Drawer
// width="500px"
// title="個人新聞分類"
// placement="right"
// closable={true}
// onClose={() => {
// setvisible(false);
// }}
// visible={visible}
// >
// <div
// ref={pieRef}
// style={{
// width: '100%',
// height: '400px',
// marginTop: '30px',
// }}
// ></div>
// </Drawer>// <div
// ref={barRef}
// style={{
// width: '100%',
// height: '400px',
// marginTop: '30px',
// }}
// ></div>
// </div>
// );
// }// export default Home;
拆特雞皮替告訴我是兩個問題導致的,一是我沒有傳數據給renderPieView(先獲取數據再分組),二是DOM沒有準備好(所以要延時):
<SettingOutlinedkey="setting"onClick={async () => {setvisible(true);// 延遲一點,等 Drawer 動畫打開再渲染圖表setTimeout(async () => {const token = JSON.parse(localStorage.getItem('token'));const username = token?.username;try {const res = await axios.get(`/news?author=${username}&publishState=2&_expand=category`);const groupedData = _.groupBy(res.data, (item) => item.category.title);const pieData = Object.keys(groupedData).map((key) => ({name: key,value: groupedData[key].length,}));renderPieView(pieData);} catch (err) {console.error('Failed to fetch pie data', err);}}, 300); // 等 Drawer 動畫展開后再繪制圖表}}
/>
?點擊圖標時觸發這個異步函數(async
),它將打開抽屜并加載圖表數據。打開 Drawer
,這是控制抽屜顯示的 visible
狀態。
Drawer 打開時有動畫,如果立即渲染圖表,容器尺寸可能為 0,Echarts 會渲染失敗或圖表不顯示。
用 setTimeout(..., 300)
延遲 300ms 再渲染圖表,確保 Drawer 打開完成、DOM 有尺寸
從本地存儲獲取當前用戶 token 并解析出用戶名,用于之后的請求過濾(只看當前用戶發布的新聞)
使用 lodash 的 groupBy
對新聞按分類標題進行分組,便于做餅圖
修改 renderPieView
函數接收參數為 data
(數組形式)?
const renderPieView = (data) => {if (!pieRef.current) return;const myChart = Echarts.init(pieRef.current);const option = {title: {text: '個人新聞分類',subtext: '按分類統計',left: 'center',},tooltip: {trigger: 'item',},legend: {orient: 'vertical',left: 'left',},series: [{name: '新聞數量',type: 'pie',radius: '50%',data: data,emphasis: {itemStyle: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)',},},},],};myChart.setOption(option);const resizeHandler = () => {myChart.resize();};window.addEventListener('resize', resizeHandler);return () => {window.removeEventListener('resize', resizeHandler);myChart.dispose();};
};
完整代碼:
import React, { useEffect, useRef, useState } from 'react';
import { Card, Col, Row, List, Drawer } from 'antd';
import {EditOutlined,EllipsisOutlined,SettingOutlined,
} from '@ant-design/icons';
import { Avatar } from 'antd';
import axios from 'axios';
import * as Echarts from 'echarts';
import _ from 'lodash';const { Meta } = Card;function Home() {const [viewList, setviewList] = useState([]);const [starList, setstarList] = useState([]);const [visible, setvisible] = useState(false);const barRef = useRef(null);const pieRef = useRef(null);useEffect(() => {axios.get('/news?publishState=2&_expand=category&_sort=view&_order=desc&_limit=6').then((res) => {setviewList(res.data);}).catch((err) => {console.error('Request failed', err);});}, []);useEffect(() => {axios.get('/news?publishState=2&_expand=category&_sort=star&_order=desc&_limit=6').then((res) => {setstarList(res.data);}).catch((err) => {console.error('Request failed', err);});}, []);useEffect(() => {let barCleanup;let barResizeHandler;const fetchDataAndRender = async () => {try {const res = await axios.get('/news?publishState=2&_expand=category');if (barRef.current) {barCleanup = renderBarView(_.groupBy(res.data, (item) => item.category.title));barResizeHandler = () => {if (barCleanup) {const myChart = Echarts.getInstanceByDom(barRef.current);if (myChart) {myChart.resize();}}};window.addEventListener('resize', barResizeHandler);}} catch (err) {console.error('Request failed', err);}};fetchDataAndRender();return () => {if (typeof barCleanup === 'function') {barCleanup();}if (barResizeHandler) {window.removeEventListener('resize', barResizeHandler);}};}, []);const renderBarView = (obj) => {if (!barRef.current) return;var myChart = Echarts.init(barRef.current);var option = {title: {text: '新聞分類圖示',},tooltip: {},legend: {data: ['數量'],},xAxis: {data: Object.keys(obj),axisLabel: {rotate: 60,interval: 0,},},yAxis: {minInterval: 1,},series: [{name: '數量',type: 'bar',data: Object.values(obj).map((item) => item.length),},],};myChart.setOption(option);return () => {myChart.dispose();};};const renderPieView = (data) => {if (!pieRef.current) return;const myChart = Echarts.init(pieRef.current);const option = {title: {text: '個人新聞分類',subtext: '按分類統計',left: 'center',},tooltip: {trigger: 'item',},legend: {orient: 'vertical',left: 'left',},series: [{name: '新聞數量',type: 'pie',radius: '50%',data: data,emphasis: {itemStyle: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)',},},},],};myChart.setOption(option);const resizeHandler = () => {myChart.resize();};window.addEventListener('resize', resizeHandler);return () => {window.removeEventListener('resize', resizeHandler);myChart.dispose();};};const tokenData = localStorage.getItem('token');const {username = '',region = '',role: { roleName = '' } = {},} = tokenData ? JSON.parse(tokenData) : {};return (<div><Row gutter={16}><Col span={8}><Card title="用戶最常瀏覽" variant="border"><Listsize="small"dataSource={viewList}renderItem={(item) => (<List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>)}/></Card></Col><Col span={8}><Card title="用戶點贊最多" variant="border"><Listsize="small"dataSource={starList}renderItem={(item) => (<List.Item><a href={`#/news-manage/preview/${item.id}`}>{item.title}</a></List.Item>)}/></Card></Col><Col span={8}><Cardcover={<imgalt="example"src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"/>}actions={[<SettingOutlinedkey="setting"onClick={async () => {setvisible(true);setTimeout(async () => {const token = JSON.parse(localStorage.getItem('token'));const username = token?.username;try {const res = await axios.get(`/news?author=${username}&publishState=2&_expand=category`);const groupedData = _.groupBy(res.data,(item) => item.category.title);const pieData = Object.keys(groupedData).map((key) => ({name: key,value: groupedData[key].length,}));renderPieView(pieData);} catch (err) {console.error('Failed to fetch pie data', err);}}, 300);}}/>,<EditOutlined key="edit" />,<EllipsisOutlined key="ellipsis" />,]}><Metaavatar={<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=8" />}title={username}description={<div><b>{region ? region : '全球'}</b><spanstyle={{paddingLeft: '30px',}}>{roleName}</span></div>}/></Card></Col></Row><Drawerwidth="500px"title="個人新聞分類"placement="right"closable={true}onClose={() => {setvisible(false);}}visible={visible}><divref={pieRef}style={{width: '100%',height: '400px',marginTop: '30px',}}></div></Drawer><divref={barRef}style={{width: '100%',height: '400px',marginTop: '30px',}}></div></div>);
}export default Home;