mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 22:57:17 +08:00 
			
		
		
		
	feat: 完善仪表盘访客地域分布区块内容
This commit is contained in:
		| @@ -16,6 +16,11 @@ export interface DashboardPopularModuleRecord { | ||||
|   newPvFromYesterday: number; | ||||
| } | ||||
|  | ||||
| export interface DashboardGeoDistributionRecord { | ||||
|   locations: string[]; | ||||
|   locationIpStatistics: []; | ||||
| } | ||||
|  | ||||
| export interface DashboardAnnouncementRecord { | ||||
|   id: string; | ||||
|   title: string; | ||||
| @@ -32,6 +37,12 @@ export function listPopularModule() { | ||||
|   ); | ||||
| } | ||||
|  | ||||
| export function getGeoDistribution() { | ||||
|   return axios.get<DashboardGeoDistributionRecord>( | ||||
|     `${BASE_URL}/geo/distribution` | ||||
|   ); | ||||
| } | ||||
|  | ||||
| export function listAnnouncement() { | ||||
|   return axios.get<DashboardAnnouncementRecord[]>(`${BASE_URL}/announcement`); | ||||
| } | ||||
| @@ -43,15 +54,4 @@ export interface ContentDataRecord { | ||||
|  | ||||
| export function queryContentData() { | ||||
|   return axios.get<ContentDataRecord[]>('/api/content-data'); | ||||
| } | ||||
|  | ||||
| export interface PopularRecord { | ||||
|   key: number; | ||||
|   clickNumber: string; | ||||
|   title: string; | ||||
|   increases: number; | ||||
| } | ||||
|  | ||||
| export function queryPopularList(params: { type: string }) { | ||||
|   return axios.get<TableData[]>('/api/popular/list', { params }); | ||||
| } | ||||
| } | ||||
| @@ -1,114 +0,0 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card | ||||
|       class="general-card" | ||||
|       :header-style="{ paddingBottom: '0' }" | ||||
|       :body-style="{ | ||||
|         padding: '20px', | ||||
|       }" | ||||
|     > | ||||
|       <template #title> | ||||
|         {{ $t('workplace.categoriesPercent') }} | ||||
|       </template> | ||||
|       <Chart height="310px" :option="chartOption" /> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
|   import useLoading from '@/hooks/loading'; | ||||
|   import useChartOption from '@/hooks/chart-option'; | ||||
|  | ||||
|   const { loading } = useLoading(); | ||||
|   const { chartOption } = useChartOption((isDark) => { | ||||
|     // echarts support https://echarts.apache.org/zh/theme-builder.html | ||||
|     // It's not used here | ||||
|     return { | ||||
|       legend: { | ||||
|         left: 'center', | ||||
|         data: ['纯文本', '图文类', '视频类'], | ||||
|         bottom: 0, | ||||
|         icon: 'circle', | ||||
|         itemWidth: 8, | ||||
|         textStyle: { | ||||
|           color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969', | ||||
|         }, | ||||
|         itemStyle: { | ||||
|           borderWidth: 0, | ||||
|         }, | ||||
|       }, | ||||
|       tooltip: { | ||||
|         show: true, | ||||
|         trigger: 'item', | ||||
|       }, | ||||
|       graphic: { | ||||
|         elements: [ | ||||
|           { | ||||
|             type: 'text', | ||||
|             left: 'center', | ||||
|             top: '40%', | ||||
|             style: { | ||||
|               text: '内容量', | ||||
|               textAlign: 'center', | ||||
|               fill: isDark ? '#ffffffb3' : '#4E5969', | ||||
|               fontSize: 14, | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|             type: 'text', | ||||
|             left: 'center', | ||||
|             top: '50%', | ||||
|             style: { | ||||
|               text: '928,531', | ||||
|               textAlign: 'center', | ||||
|               fill: isDark ? '#ffffffb3' : '#1D2129', | ||||
|               fontSize: 16, | ||||
|               fontWeight: 500, | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|       series: [ | ||||
|         { | ||||
|           type: 'pie', | ||||
|           radius: ['50%', '70%'], | ||||
|           center: ['50%', '50%'], | ||||
|           label: { | ||||
|             formatter: '{d}%', | ||||
|             fontSize: 14, | ||||
|             color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969', | ||||
|           }, | ||||
|           itemStyle: { | ||||
|             borderColor: isDark ? '#232324' : '#fff', | ||||
|             borderWidth: 1, | ||||
|           }, | ||||
|           data: [ | ||||
|             { | ||||
|               value: [148564], | ||||
|               name: '纯文本', | ||||
|               itemStyle: { | ||||
|                 color: isDark ? '#3D72F6' : '#249EFF', | ||||
|               }, | ||||
|             }, | ||||
|             { | ||||
|               value: [334271], | ||||
|               name: '图文类', | ||||
|               itemStyle: { | ||||
|                 color: isDark ? '#A079DC' : '#313CA9', | ||||
|               }, | ||||
|             }, | ||||
|             { | ||||
|               value: [445694], | ||||
|               name: '视频类', | ||||
|               itemStyle: { | ||||
|                 color: isDark ? '#6CAAF5' : '#21CCFF', | ||||
|               }, | ||||
|             }, | ||||
|           ], | ||||
|         }, | ||||
|       ], | ||||
|     }; | ||||
|   }); | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"></style> | ||||
| @@ -3,8 +3,8 @@ | ||||
|     class="general-card" | ||||
|     :title="$t('workplace.docs')" | ||||
|     :header-style="{ paddingBottom: 0 }" | ||||
|     :body-style="{ paddingTop: 0 }" | ||||
|     style="height: 166px" | ||||
|     :body-style="{ paddingTop: '10px', paddingBottom: '10px' }" | ||||
|     style="height: 198px" | ||||
|   > | ||||
|     <template #extra> | ||||
|       <a-link href="https://doc.charles7c.top" target="_blank" rel="noopener">{{ | ||||
| @@ -48,6 +48,24 @@ | ||||
|           {{ $t('workplace.docs.changelog') }} | ||||
|         </a-link> | ||||
|       </a-col> | ||||
|       <a-col :span="12"> | ||||
|         <a-link | ||||
|           href="https://blog.charles7c.top" | ||||
|           target="_blank" | ||||
|           rel="noopener" | ||||
|         > | ||||
|           {{ $t('workplace.docs.authorSite') }}👋 | ||||
|         </a-link> | ||||
|       </a-col> | ||||
|       <a-col :span="12"> | ||||
|         <a-link | ||||
|           href="https://doc.charles7c.top/require.html" | ||||
|           target="_blank" | ||||
|           rel="noopener" | ||||
|         > | ||||
|           {{ $t('workplace.docs.require') }}✨ | ||||
|         </a-link> | ||||
|       </a-col> | ||||
|     </a-row> | ||||
|   </a-card> | ||||
| </template> | ||||
| @@ -58,3 +76,4 @@ | ||||
|     color: rgb(var(--gray-8)); | ||||
|   } | ||||
| </style> | ||||
| <script setup lang="ts"></script> | ||||
| @@ -0,0 +1,90 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card | ||||
|       class="general-card" | ||||
|       :header-style="{ paddingBottom: '0' }" | ||||
|       :body-style="{ | ||||
|         padding: '0 20px', | ||||
|       }" | ||||
|     > | ||||
|       <template #title> | ||||
|         {{ $t('workplace.geoDistribution') }} | ||||
|       </template> | ||||
|       <Chart height="480px" :option="chartOption" /> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
|   import { ref } from 'vue'; | ||||
|   import useLoading from '@/hooks/loading'; | ||||
|   import useChartOption from '@/hooks/chart-option'; | ||||
|   import { | ||||
|     DashboardGeoDistributionRecord, | ||||
|     getGeoDistribution, | ||||
|   } from '@/api/common/dashboard'; | ||||
|  | ||||
|   const { loading, setLoading } = useLoading(); | ||||
|   const statisticsData = ref<DashboardGeoDistributionRecord>({ | ||||
|     locations: [], | ||||
|     locationIpStatistics: [], | ||||
|   }); | ||||
|  | ||||
|   /** | ||||
|    * 查询访客地域分布信息 | ||||
|    */ | ||||
|   const getData = async () => { | ||||
|     try { | ||||
|       setLoading(true); | ||||
|       const { data } = await getGeoDistribution(); | ||||
|       statisticsData.value = data; | ||||
|     } catch (err) { | ||||
|       // you can report use errorHandler or other | ||||
|     } finally { | ||||
|       setLoading(false); | ||||
|     } | ||||
|   }; | ||||
|   getData(); | ||||
|  | ||||
|   const { chartOption } = useChartOption((isDark) => { | ||||
|     // echarts support https://echarts.apache.org/zh/theme-builder.html | ||||
|     // It's not used here | ||||
|     return { | ||||
|       legend: { | ||||
|         left: 'center', | ||||
|         data: statisticsData.value.locations, | ||||
|         bottom: -5, | ||||
|         icon: 'circle', | ||||
|         itemStyle: { | ||||
|           borderWidth: 0, | ||||
|         }, | ||||
|       }, | ||||
|       tooltip: { | ||||
|         show: true, | ||||
|         trigger: 'item', | ||||
|       }, | ||||
|       series: [ | ||||
|         { | ||||
|           type: 'pie', | ||||
|           radius: '70%', | ||||
|           label: { | ||||
|             formatter: '{d}%', | ||||
|             fontSize: 14, | ||||
|             color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969', | ||||
|           }, | ||||
|           itemStyle: { | ||||
|             borderColor: isDark ? '#232324' : '#fff', | ||||
|             borderWidth: 1, | ||||
|           }, | ||||
|           data: statisticsData.value.locationIpStatistics, | ||||
|         }, | ||||
|       ], | ||||
|     }; | ||||
|   }); | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
|   .general-card { | ||||
|     min-height: 566px; | ||||
|   } | ||||
| </style> | ||||
| @@ -3,7 +3,7 @@ | ||||
|     <a-card | ||||
|       class="general-card" | ||||
|       :header-style="{ paddingBottom: '0' }" | ||||
|       :body-style="{ padding: '17px 20px 21px 20px' }" | ||||
|       :body-style="{ padding: '17px 20px 20px 20px' }" | ||||
|     > | ||||
|       <template #title> | ||||
|         {{ $t('workplace.popularModule') }} | ||||
| @@ -13,7 +13,7 @@ | ||||
|           :data="dataList" | ||||
|           :pagination="false" | ||||
|           :bordered="false" | ||||
|           :scroll="{ x: '100%', y: '310px' }" | ||||
|           :scroll="{ x: '100%', y: '484px' }" | ||||
|         > | ||||
|           <template #columns> | ||||
|             <a-table-column title="排名"> | ||||
| @@ -89,7 +89,7 @@ | ||||
|  | ||||
| <style scoped lang="less"> | ||||
|   .general-card { | ||||
|     min-height: 395px; | ||||
|     min-height: 400px; | ||||
|   } | ||||
|   :deep(.arco-table-tr) { | ||||
|     height: 44px; | ||||
|   | ||||
| @@ -46,7 +46,7 @@ | ||||
|   import DataPanel from './components/data-panel.vue'; | ||||
|   import ContentChart from './components/content-chart.vue'; | ||||
|   import PopularModule from './components/popular-module.vue'; | ||||
|   import CategoriesPercent from './components/categories-percent.vue'; | ||||
|   import CategoriesPercent from './components/geo-distribution.vue'; | ||||
|   import RecentlyVisited from './components/recently-visited.vue'; | ||||
|   import QuickOperation from './components/quick-operation.vue'; | ||||
|   import Announcement from './components/announcement.vue'; | ||||
|   | ||||
| @@ -14,6 +14,8 @@ export default { | ||||
|   'workplace.docs.userGuide': 'User Guide', | ||||
|   'workplace.docs.faq': 'FAQ', | ||||
|   'workplace.docs.changelog': 'Change Log', | ||||
|   'workplace.docs.authorSite': 'Author Site', | ||||
|   'workplace.docs.require': 'Require', | ||||
|   'workplace.announcement': 'Announcement', | ||||
|   'workplace.recently.visited': 'Recently Visited', | ||||
|   'workplace.record.nodata': 'No data', | ||||
| @@ -23,8 +25,8 @@ export default { | ||||
|   'workplace.loadMore': 'More', | ||||
|   'workplace.viewMore': 'More', | ||||
|   'workplace.contentData': 'Content Data', | ||||
|   'workplace.popularModule': 'Popular Module', | ||||
|   'workplace.categoriesPercent': 'Categories Percent', | ||||
|   'workplace.popularModule': 'Popular Module(Top10)', | ||||
|   'workplace.geoDistribution': 'Geo Distribution(Top10)', | ||||
|   'workplace.unit.pecs': 'pecs', | ||||
|   'workplace.unit.times': 'times', | ||||
| }; | ||||
|   | ||||
| @@ -14,6 +14,8 @@ export default { | ||||
|   'workplace.docs.userGuide': '使用指南', | ||||
|   'workplace.docs.faq': '常见问题', | ||||
|   'workplace.docs.changelog': '更新日志', | ||||
|   'workplace.docs.authorSite': '作者主页', | ||||
|   'workplace.docs.require': '需求墙', | ||||
|   'workplace.announcement': '公告', | ||||
|   'workplace.recently.visited': '最近访问', | ||||
|   'workplace.record.nodata': '暂无数据', | ||||
| @@ -23,8 +25,8 @@ export default { | ||||
|   'workplace.loadMore': '加载更多', | ||||
|   'workplace.viewMore': '查看更多', | ||||
|   'workplace.contentData': '内容数据', | ||||
|   'workplace.popularModule': '热门模块', | ||||
|   'workplace.categoriesPercent': '内容类型占比', | ||||
|   'workplace.popularModule': '热门模块(Top10)', | ||||
|   'workplace.geoDistribution': '访客地域分布(Top10)', | ||||
|   'workplace.unit.pecs': '个', | ||||
|   'workplace.unit.times': '次', | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user