diff --git a/src/api/dashboard/index.js b/src/api/dashboard/index.js new file mode 100644 index 0000000..1c19517 --- /dev/null +++ b/src/api/dashboard/index.js @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +/** + * 获取物种统计信息 + * @returns {Promise} 返回物种统计数据 + */ +export function getSpeciesStatistics() { + return request.get('/api/admin/species/statistics/overview') +} + +/** + * 获取巡护任务统计信息 + * @returns {Promise} 返回巡护任务统计数据 + */ +export function getPatrolStatistics() { + return request.get('/api/admin/patrol/records/statistics/overview') +} + +/** + * 获取设备列表信息 + * @returns {Promise} 返回设备列表数据 + */ +export function getDeviceList() { + return request.get('/api/device/list') +} \ No newline at end of file diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue index ee3732f..2d74fac 100644 --- a/src/views/dashboard/index.vue +++ b/src/views/dashboard/index.vue @@ -1,5 +1,5 @@ @@ -616,76 +790,23 @@ onMounted(() => { } } - .activity-card { - border: none; - border-radius: 8px; - transition: all 0.3s; + .charts-container { + display: flex; + gap: 20px; + margin-bottom: 20px; - &:hover { - transform: translateY(-2px); - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.08); - } - } + .chart-item { + flex: 1; - .activity-list { - .activity-item { - display: flex; - align-items: flex-start; - padding: 16px 0; - - &.with-border { - border-bottom: 1px solid #f0f2f5; + .chart-title { + font-size: 16px; + font-weight: 500; + color: v.$text-primary; + margin-bottom: 8px; } - .activity-icon { - width: 32px; - height: 32px; - border-radius: 6px; - display: flex; - align-items: center; - justify-content: center; - margin-right: 16px; - - &.primary { - background: rgba(64, 158, 255, 0.1); - color: v.$primary-color; - } - - &.warning { - background: rgba(230, 162, 60, 0.1); - color: v.$warning-color; - } - - &.success { - background: rgba(103, 194, 58, 0.1); - color: v.$success-color; - } - - .el-icon { - font-size: 16px; - } - } - - .activity-content { - flex: 1; - - .activity-title { - font-size: 14px; - font-weight: 500; - color: v.$text-primary; - margin-bottom: 4px; - } - - .activity-desc { - font-size: 13px; - color: v.$text-secondary; - } - } - - .activity-time { - font-size: 12px; - color: v.$text-secondary; - margin-left: 16px; + .chart-content { + height: 400px; } } } diff --git a/src/views/monitor/species/index.vue b/src/views/monitor/species/index.vue index eee2f6e..2fec4cc 100644 --- a/src/views/monitor/species/index.vue +++ b/src/views/monitor/species/index.vue @@ -100,9 +100,7 @@ const statistics = ref({ }) // 图表实例 -const categoryChartRef = ref(null) const protectionChartRef = ref(null) -let categoryChart = null let protectionChart = null // 基础URL @@ -126,9 +124,6 @@ const getFullImageUrl = (url) => { // 初始化图表 const initCharts = () => { - if (categoryChartRef.value) { - categoryChart = echarts.init(categoryChartRef.value) - } if (protectionChartRef.value) { protectionChart = echarts.init(protectionChartRef.value) } @@ -136,75 +131,14 @@ const initCharts = () => { // 更新图表数据 const updateCharts = () => { - // 物种类别图表数据 - const categoryData = reverseArray( - Object.entries(statistics.value.categories) - .filter(([_, count]) => count.total_count > 0) - .map(([category, count]) => ({ - name: categoryOptions.find(item => item.value === category)?.label || category, - value: count.total_count - })) - .sort((a, b) => a.value - b.value) - ) - // 保护等级图表数据 - const protectionData = reverseArray( - Object.entries(statistics.value.protection_levels) - .filter(([_, count]) => count > 0) - .map(([level, count]) => ({ - name: protectionLevelOptions.find(item => item.value === level)?.label || level, - value: count - })) - .sort((a, b) => a.value - b.value) - ) - - // 设置物种类别图表 - categoryChart?.setOption({ - title: { - text: '物种类别统计', - left: 'center' - }, - tooltip: { - trigger: 'item', - formatter: '{b}: {c}种' - }, - legend: { - orient: 'vertical', - left: 'left', - top: 'middle' - }, - series: [ - { - name: '物种数量', - type: 'pie', - radius: ['40%', '70%'], - center: ['60%', '50%'], - avoidLabelOverlap: true, - itemStyle: { - borderRadius: 10, - borderColor: '#fff', - borderWidth: 2 - }, - label: { - show: true, - formatter: '{b}: {c}种' - }, - emphasis: { - label: { - show: true, - fontSize: 14, - fontWeight: 'bold' - }, - itemStyle: { - shadowBlur: 10, - shadowOffsetX: 0, - shadowColor: 'rgba(0, 0, 0, 0.5)' - } - }, - data: categoryData - } - ] - }) + const protectionData = Object.entries(statistics.value.protection_levels) + .filter(([_, count]) => count > 0) + .map(([level, count]) => ({ + name: protectionLevelOptions.find(item => item.value === level)?.label || level, + value: count + })) + .sort((a, b) => b.value - a.value) // 设置保护等级图表 protectionChart?.setOption({ @@ -265,7 +199,6 @@ const updateCharts = () => { // 监听窗口大小变化 const handleResize = () => { - categoryChart?.resize() protectionChart?.resize() } @@ -520,7 +453,6 @@ onMounted(() => { onUnmounted(() => { // 销毁图表实例 - categoryChart?.dispose() protectionChart?.dispose() window.removeEventListener('resize', handleResize) }) @@ -530,12 +462,7 @@ onUnmounted(() => {
- - -
-
-
- +