@@ -45,26 +66,32 @@ - diff --git a/schoolNewsWeb/src/router/index.ts b/schoolNewsWeb/src/router/index.ts index 281b3fd..a4cde65 100644 --- a/schoolNewsWeb/src/router/index.ts +++ b/schoolNewsWeb/src/router/index.ts @@ -6,7 +6,7 @@ import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; export const routes: Array = [ { path: "/", - redirect: "/home", + redirect: "/login", }, { path: "/login", diff --git a/schoolNewsWeb/src/utils/permission.ts b/schoolNewsWeb/src/utils/permission.ts index 842a5c3..ba7581c 100644 --- a/schoolNewsWeb/src/utils/permission.ts +++ b/schoolNewsWeb/src/utils/permission.ts @@ -13,9 +13,8 @@ import { AuthState } from '@/store/modules/auth'; */ const WHITE_LIST = [ '/login', - '/register', + '/register', '/forgot-password', - '/home', '/403', '/404', // 404页面允许访问(但未登录时不会被路由到这里) '/500' diff --git a/schoolNewsWeb/src/views/admin/manage/study/components/TaskCard.vue b/schoolNewsWeb/src/views/admin/manage/study/components/TaskCard.vue index 0fd558d..4ce2e63 100644 --- a/schoolNewsWeb/src/views/admin/manage/study/components/TaskCard.vue +++ b/schoolNewsWeb/src/views/admin/manage/study/components/TaskCard.vue @@ -6,7 +6,7 @@

{{ task.learningTask.name }}

diff --git a/schoolNewsWeb/src/views/admin/overview/SystemOverviewView.vue b/schoolNewsWeb/src/views/admin/overview/SystemOverviewView.vue index 70df4db..d7c1fc2 100644 --- a/schoolNewsWeb/src/views/admin/overview/SystemOverviewView.vue +++ b/schoolNewsWeb/src/views/admin/overview/SystemOverviewView.vue @@ -68,6 +68,7 @@ import { ref, onMounted, onUnmounted } from 'vue'; import { ElRow, ElCol, ElCard, ElDatePicker } from 'element-plus'; import * as echarts from 'echarts'; +import { systemOverviewApi } from '@/apis/system/overview'; const dateRange = ref<[Date, Date] | null>(null); const activityChart = ref(null); @@ -75,51 +76,20 @@ const resourcePieChart = ref(null); let activityChartInstance: echarts.ECharts | null = null; let pieChartInstance: echarts.ECharts | null = null; -const statistics = ref([ - { - icon: '👥', - label: '总用户数', - value: '1,234', - change: '+12%', - trend: 'up', - color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' - }, - { - icon: '📚', - label: '总资源数', - value: '5,678', - change: '+8%', - trend: 'up', - color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' - }, - { - icon: '👁', - label: '今日访问量', - value: '892', - change: '+15%', - trend: 'up', - color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)' - }, - { - icon: '✅', - label: '活跃用户', - value: '456', - change: '+5%', - trend: 'up', - color: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)' - } -]); +const statistics = ref<{ + icon: string; + label: string; + value: string | number; + change: string; + trend: 'up' | 'down'; + color: string; +}[]>([]); -const visitStats = ref([ - { label: 'UV(独立访客)', value: '892' }, - { label: 'PV(页面浏览量)', value: '3,456' }, - { label: '平均访问时长', value: '5分32秒' }, - { label: '跳出率', value: '35.6%' } -]); +const visitStats = ref<{ label: string; value: string | number }[]>([]); -onMounted(() => { +onMounted(async () => { initCharts(); - // TODO: 加载实际数据 + await loadOverviewData(); }); onUnmounted(() => { @@ -131,54 +101,129 @@ onUnmounted(() => { } }); +async function loadOverviewData() { + try { + const [statRes, activeRes, pieRes, todayRes] = await Promise.all([ + systemOverviewApi.getStatistics(), + systemOverviewApi.getActiveUsersChart('2025-10-15', '2025-10-21'), + systemOverviewApi.getResourceCategoryStats(), + systemOverviewApi.getTodayVisits() + ]); + + if (statRes.success && statRes.data) { + const d = statRes.data; + statistics.value = [ + { + icon: '👥', + label: '总用户数', + value: d.totalUsers, + change: d.totalUsersChange, + trend: d.totalUsersChange.startsWith('-') ? 'down' : 'up', + color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' + }, + { + icon: '📚', + label: '总资源数', + value: d.totalResources, + change: d.totalResourcesChange, + trend: d.totalResourcesChange.startsWith('-') ? 'down' : 'up', + color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' + }, + { + icon: '👁', + label: '今日访问量', + value: d.todayVisits, + change: d.todayVisitsChange, + trend: d.todayVisitsChange.startsWith('-') ? 'down' : 'up', + color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)' + }, + { + icon: '✅', + label: '活跃用户', + value: d.activeUsers, + change: d.activeUsersChange, + trend: d.activeUsersChange.startsWith('-') ? 'down' : 'up', + color: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)' + } + ]; + } + + if (todayRes.success && todayRes.data) { + const t = todayRes.data; + visitStats.value = [ + { label: 'UV(独立访客)', value: t.uv }, + { label: 'PV(页面浏览量)', value: t.pv }, + { label: '平均访问时长', value: t.avgVisitDuration }, + { label: '跳出率', value: t.bounceRate } + ]; + } + + if (activeRes.success && activeRes.data) { + updateActivityChart(activeRes.data.labels, activeRes.data.values); + } + + if (pieRes.success && pieRes.data) { + updatePieChart(pieRes.data.items); + } + } catch (error) { + console.error('加载系统总览数据失败:', error); + } +} + function initCharts() { if (activityChart.value) { activityChartInstance = echarts.init(activityChart.value); - const activityOption = { - tooltip: { - trigger: 'axis' - }, - xAxis: { - type: 'category', - data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] - }, - yAxis: { - type: 'value' - }, - series: [{ - data: [120, 200, 150, 80, 70, 110, 130], - type: 'line', - smooth: true, - areaStyle: {} - }] - }; - activityChartInstance.setOption(activityOption); } if (resourcePieChart.value) { pieChartInstance = echarts.init(resourcePieChart.value); - const pieOption = { - tooltip: { - trigger: 'item' - }, - legend: { - orient: 'vertical', - left: 'left' - }, - series: [{ + } +} + +function updateActivityChart(labels: string[], values: number[]) { + if (!activityChartInstance) return; + const option = { + tooltip: { + trigger: 'axis' + }, + xAxis: { + type: 'category', + data: labels + }, + yAxis: { + type: 'value' + }, + series: [ + { + data: values, + type: 'line', + smooth: true, + areaStyle: {} + } + ] + }; + activityChartInstance.setOption(option); +} + +function updatePieChart(items: { name: string; value: number }[]) { + if (!pieChartInstance) return; + const option = { + tooltip: { + trigger: 'item' + }, + legend: { + orient: 'vertical', + left: 'left' + }, + series: [ + { type: 'pie', radius: '50%', - data: [ - { value: 1048, name: '文章' }, - { value: 735, name: '视频' }, - { value: 580, name: '音频' }, - { value: 484, name: '课程' }, - { value: 300, name: '其他' } - ] - }] - }; - pieChartInstance.setOption(pieOption); - } + data: items + } + ] + }; + pieChartInstance.setOption(option); }