Просмотр исходного кода

feat(statisticalAnalysis): 新增学习进度、教学活动、视频分析和学习行为分析页面

添加四个统计分析的Vue组件:
1. 学习进度概览页面,包含筛选区、数据看板和明细表格
2. 教学活动分析页面,展示文档观看、讨论互动等统计数据
3. 视频分析页面,提供视频观看、讲义下载等详细分析
4. 学习行为分析页面,支持学院和学员维度的数据分析

各页面均包含筛选功能、数据卡片、图表展示和详细表格,使用ECharts实现数据可视化
tanshanming 6 месяцев назад
Родитель
Сommit
79a82cf0eb

+ 998 - 0
src/views/statisticalAnalysis/analysisLearningBehaviors/index.vue

@@ -0,0 +1,998 @@
+<template>
+	<div class="learning-behavior-analysis">
+		<!-- 页面头部 -->
+		<div class="header">
+			<h1>📊 学习行为分析</h1>
+			<p>全面分析学院教学情况和学员学习行为</p>
+		</div>
+
+		<!-- 导航标签 -->
+		<div class="nav-tabs">
+			<div class="nav-tab" :class="{ active: activeTab === 'college' }" @click="switchTab('college')">
+				🏫 学院维度分析
+			</div>
+			<div class="nav-tab" :class="{ active: activeTab === 'student' }" @click="switchTab('student')">
+				👤 学员维度分析
+			</div>
+		</div>
+
+		<!-- 学院维度分析 -->
+		<div v-show="activeTab === 'college'" class="tab-content">
+			<!-- 筛选条件 -->
+			<div class="filter-section">
+				<h3>🔍 数据筛选</h3>
+				<div class="filter-controls">
+					<div class="filter-group">
+						<label>选择学院</label>
+						<a-select v-model:value="collegeFilters.collegeId" placeholder="全部学院" @change="updateCollegeData">
+							<a-select-option value="">全部学院</a-select-option>
+							<a-select-option value="computer">计算机学院</a-select-option>
+							<a-select-option value="business">商学院</a-select-option>
+							<a-select-option value="art">艺术学院</a-select-option>
+							<a-select-option value="science">理学院</a-select-option>
+						</a-select>
+					</div>
+					<div class="filter-group">
+						<label>时间范围</label>
+						<a-select v-model:value="collegeFilters.timeRange" @change="updateCollegeData">
+							<a-select-option :value="7">最近7天</a-select-option>
+							<a-select-option :value="30">最近30天</a-select-option>
+							<a-select-option :value="90">最近90天</a-select-option>
+							<a-select-option :value="365">最近一年</a-select-option>
+						</a-select>
+					</div>
+					<div class="filter-group">
+						<a-button type="primary" @click="updateCollegeData">查询</a-button>
+					</div>
+				</div>
+			</div>
+
+			<!-- 学院整体统计 -->
+			<div class="stats-grid">
+				<div class="stat-card">
+					<h3>📚 课程访问统计</h3>
+					<div class="stat-number">{{ collegeStats.totalCourses }}</div>
+					<div class="stat-label">总课程数</div>
+					<div class="stat-number">{{ collegeStats.activeCourses }}</div>
+					<div class="stat-label">活跃课程数</div>
+					<div class="stat-number">{{ collegeStats.courseAccessRate }}%</div>
+					<div class="stat-label">课程访问率</div>
+				</div>
+
+				<div class="stat-card">
+					<h3>👥 用户登录统计</h3>
+					<div class="stat-number">{{ collegeStats.totalLogins.toLocaleString() }}</div>
+					<div class="stat-label">总登录人次</div>
+					<div class="stat-number">{{ collegeStats.uniqueUsers.toLocaleString() }}</div>
+					<div class="stat-label">独立用户数</div>
+					<div class="stat-number">{{ collegeStats.avgLoginPerUser }}</div>
+					<div class="stat-label">人均登录次数</div>
+				</div>
+
+				<div class="stat-card">
+					<h3>⏰ 观看时长统计</h3>
+					<div class="stat-number">{{ collegeStats.totalOnlineTime }}h</div>
+					<div class="stat-label">总观看时长</div>
+					<div class="stat-number">{{ collegeStats.avgSessionTime }}min</div>
+					<div class="stat-label">平均时长</div>
+					<div class="stat-number">{{ collegeStats.peakOnlineUsers }}</div>
+					<div class="stat-label">峰值观看人数</div>
+				</div>
+			</div>
+
+			<!-- 登录时段分析图表 -->
+			<div class="chart-container">
+				<h3>⏰ 用户登录时段分布</h3>
+				<div ref="loginTimeChart" class="chart"></div>
+			</div>
+
+			<!-- 课程访问热度图表 -->
+			<div class="chart-container">
+				<h3>🔥 课程访问热度排行</h3>
+				<div ref="courseHeatChart" class="chart"></div>
+			</div>
+
+			<!-- 学院课程详细统计 -->
+			<div class="data-table">
+				<h3>📊 学院课程详细统计</h3>
+				<a-table
+					:columns="collegeColumns"
+					:data-source="collegeTableData"
+					:pagination="{ pageSize: 10 }"
+					row-key="id"
+				/>
+			</div>
+		</div>
+
+		<!-- 学员维度分析 -->
+		<div v-show="activeTab === 'student'" class="tab-content">
+			<!-- 学员搜索 -->
+			<div class="filter-section">
+				<h3>🔍 学员搜索</h3>
+				<div class="filter-controls">
+					<div class="filter-group">
+						<label>学员姓名/学号</label>
+						<a-input v-model:value="studentSearch" placeholder="输入学员姓名或学号" @pressEnter="searchStudent" />
+					</div>
+					<div class="filter-group">
+						<a-button type="primary" @click="searchStudent">搜索</a-button>
+					</div>
+					<div class="filter-group">
+						<a-button @click="clearSearch">清除</a-button>
+					</div>
+				</div>
+			</div>
+
+			<!-- 学员学习行为卡片 -->
+			<div class="student-cards">
+				<div
+					v-for="student in filteredStudents"
+					:key="student.id"
+					class="student-card"
+					:class="{ highlighted: student.highlighted }"
+				>
+					<div class="student-header">
+						<div class="student-info">
+							<h4>{{ student.name }} ({{ student.studentId }})</h4>
+							<div class="student-meta">{{ student.college }} | {{ student.major }} | {{ student.grade }}</div>
+						</div>
+						<div class="student-stats">
+							<div class="stat-item">
+								<div class="stat-value">{{ student.overallProgress }}%</div>
+								<div class="stat-label">总体进度</div>
+							</div>
+						</div>
+					</div>
+
+					<div class="course-progress">
+						<div v-for="course in student.courses" :key="course.id" class="course-item">
+							<div class="course-name">{{ course.name }}</div>
+							<div class="course-stats">
+								<div class="stat-item">
+									<div class="stat-value">{{ course.progress }}%</div>
+									<div class="stat-label">学习进度</div>
+								</div>
+								<div class="stat-item">
+									<div class="stat-value">{{ course.completedAssignments }}/{{ course.totalAssignments }}</div>
+									<div class="stat-label">作业完成</div>
+								</div>
+								<div class="stat-item">
+									<div class="stat-value">{{ course.discussionParticipation }}</div>
+									<div class="stat-label">讨论参与</div>
+								</div>
+								<div class="stat-item">
+									<div class="stat-value">{{ course.questionCount }}</div>
+									<div class="stat-label">提问次数</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script setup>
+	import { ref, reactive, computed, onMounted, nextTick } from 'vue'
+	import * as echarts from 'echarts'
+
+	// 当前活动标签
+	const activeTab = ref('college')
+
+	// 学院维度筛选条件
+	const collegeFilters = reactive({
+		collegeId: '',
+		timeRange: 30
+	})
+
+	// 学院统计数据
+	const collegeStats = reactive({
+		totalCourses: 156,
+		activeCourses: 142,
+		courseAccessRate: 91.0,
+		totalLogins: 12456,
+		uniqueUsers: 3234,
+		avgLoginPerUser: 3.85,
+		totalOnlineTime: 2456,
+		avgSessionTime: 45.2,
+		peakOnlineUsers: 234
+	})
+
+	// 图表引用
+	const loginTimeChart = ref(null)
+	const courseHeatChart = ref(null)
+	let loginTimeChartInstance = null
+	let courseHeatChartInstance = null
+
+	// 学院表格列定义
+	const collegeColumns = [
+		{
+			title: '学院名称',
+			dataIndex: 'name',
+			key: 'name'
+		},
+		{
+			title: '课程数量',
+			dataIndex: 'courseCount',
+			key: 'courseCount'
+		},
+		{
+			title: '总访问量',
+			dataIndex: 'totalVisits',
+			key: 'totalVisits'
+		},
+		{
+			title: '平均完成率',
+			dataIndex: 'avgCompletionRate',
+			key: 'avgCompletionRate',
+			customRender: ({ text }) => `<span class="completion-rate">${text}%</span>`
+		},
+		{
+			title: '作业提交率',
+			dataIndex: 'assignmentSubmissionRate',
+			key: 'assignmentSubmissionRate',
+			customRender: ({ text }) => `<span class="completion-rate">${text}%</span>`
+		}
+	]
+
+	// 学院表格数据
+	const collegeTableData = ref([
+		{
+			id: 1,
+			name: '计算机学院',
+			courseCount: 45,
+			totalVisits: 5234,
+			avgCompletionRate: 78.5,
+			assignmentSubmissionRate: 85.2
+		},
+		{
+			id: 2,
+			name: '商学院',
+			courseCount: 38,
+			totalVisits: 4567,
+			avgCompletionRate: 72.3,
+			assignmentSubmissionRate: 79.8
+		},
+		{
+			id: 3,
+			name: '艺术学院',
+			courseCount: 28,
+			totalVisits: 3123,
+			avgCompletionRate: 68.9,
+			assignmentSubmissionRate: 76.4
+		},
+		{
+			id: 4,
+			name: '理学院',
+			courseCount: 35,
+			totalVisits: 3890,
+			avgCompletionRate: 75.2,
+			assignmentSubmissionRate: 82.1
+		}
+	])
+
+	// 学员搜索
+	const studentSearch = ref('')
+
+	// 学员数据
+	const studentsData = ref([
+		{
+			id: 1,
+			name: '张三',
+			studentId: '2021001',
+			college: '计算机学院',
+			major: '计算机科学与技术',
+			grade: '大三',
+			overallProgress: 85.6,
+			highlighted: false,
+			courses: [
+				{
+					id: 1,
+					name: 'JavaScript程序设计',
+					progress: 92,
+					completedAssignments: 8,
+					totalAssignments: 10,
+					discussionParticipation: 15,
+					questionCount: 5
+				},
+				{
+					id: 2,
+					name: '数据结构与算法',
+					progress: 78,
+					completedAssignments: 6,
+					totalAssignments: 8,
+					discussionParticipation: 12,
+					questionCount: 3
+				}
+			]
+		},
+		{
+			id: 2,
+			name: '李四',
+			studentId: '2021002',
+			college: '商学院',
+			major: '工商管理',
+			grade: '大二',
+			overallProgress: 72.3,
+			highlighted: false,
+			courses: [
+				{
+					id: 3,
+					name: '管理学原理',
+					progress: 85,
+					completedAssignments: 7,
+					totalAssignments: 9,
+					discussionParticipation: 8,
+					questionCount: 2
+				},
+				{
+					id: 4,
+					name: '市场营销学',
+					progress: 65,
+					completedAssignments: 4,
+					totalAssignments: 7,
+					discussionParticipation: 6,
+					questionCount: 1
+				}
+			]
+		},
+		{
+			id: 3,
+			name: '王五',
+			studentId: '2021003',
+			college: '艺术学院',
+			major: '视觉传达设计',
+			grade: '大一',
+			overallProgress: 91.2,
+			highlighted: false,
+			courses: [
+				{
+					id: 5,
+					name: '设计基础',
+					progress: 95,
+					completedAssignments: 10,
+					totalAssignments: 10,
+					discussionParticipation: 20,
+					questionCount: 8
+				},
+				{
+					id: 6,
+					name: '色彩构成',
+					progress: 88,
+					completedAssignments: 8,
+					totalAssignments: 9,
+					discussionParticipation: 15,
+					questionCount: 6
+				}
+			]
+		}
+	])
+
+	// 过滤后的学员数据
+	const filteredStudents = computed(() => {
+		if (!studentSearch.value.trim()) {
+			return studentsData.value.map((student) => ({ ...student, highlighted: false }))
+		}
+
+		const searchTerm = studentSearch.value.trim().toLowerCase()
+		return studentsData.value
+			.filter((student) => {
+				const matchName = student.name.toLowerCase().includes(searchTerm)
+				const matchId = student.studentId.includes(searchTerm)
+				return matchName || matchId
+			})
+			.map((student) => ({ ...student, highlighted: true }))
+	}) // 切换标签
+	const switchTab = (tabName) => {
+		activeTab.value = tabName
+
+		if (tabName === 'college') {
+			nextTick(() => {
+				initCollegeCharts()
+			})
+		}
+	}
+
+	// 更新学院数据
+	const updateCollegeData = () => {
+		console.log('更新学院数据:', collegeFilters)
+
+		// 根据筛选条件更新统计数据
+		if (collegeFilters.collegeId === 'computer') {
+			Object.assign(collegeStats, {
+				totalCourses: 45,
+				activeCourses: 42,
+				totalLogins: 5234,
+				uniqueUsers: 1234,
+				avgLoginPerUser: 4.24,
+				totalOnlineTime: 1234,
+				avgSessionTime: 52.3,
+				peakOnlineUsers: 156
+			})
+		} else if (collegeFilters.collegeId === 'business') {
+			Object.assign(collegeStats, {
+				totalCourses: 38,
+				activeCourses: 35,
+				totalLogins: 4567,
+				uniqueUsers: 987,
+				avgLoginPerUser: 4.63,
+				totalOnlineTime: 987,
+				avgSessionTime: 48.7,
+				peakOnlineUsers: 123
+			})
+		} else {
+			// 全部学院
+			Object.assign(collegeStats, {
+				totalCourses: 156,
+				activeCourses: 142,
+				totalLogins: 12456,
+				uniqueUsers: 3234,
+				avgLoginPerUser: 3.85,
+				totalOnlineTime: 2456,
+				avgSessionTime: 45.2,
+				peakOnlineUsers: 234
+			})
+		}
+
+		// 重新初始化图表
+		initCollegeCharts()
+	}
+
+	// 搜索学员
+	const searchStudent = () => {
+		if (!studentSearch.value.trim()) {
+			return
+		}
+
+		const found = filteredStudents.value.length > 0
+		if (!found) {
+			alert(`未找到包含"${studentSearch.value}"的学员`)
+		}
+	}
+
+	// 清除搜索
+	const clearSearch = () => {
+		studentSearch.value = ''
+	}
+
+	// 初始化学院维度图表
+	const initCollegeCharts = () => {
+		initLoginTimeChart()
+		initCourseHeatChart()
+	}
+
+	// 登录时段分布图表
+	const initLoginTimeChart = () => {
+		if (!loginTimeChart.value) return
+
+		if (loginTimeChartInstance) {
+			loginTimeChartInstance.dispose()
+		}
+
+		loginTimeChartInstance = echarts.init(loginTimeChart.value)
+
+		const hours = [
+			'00:00',
+			'02:00',
+			'04:00',
+			'06:00',
+			'08:00',
+			'10:00',
+			'12:00',
+			'14:00',
+			'16:00',
+			'18:00',
+			'20:00',
+			'22:00'
+		]
+		const loginCounts = [45, 23, 12, 8, 156, 234, 189, 267, 312, 298, 345, 289]
+
+		const option = {
+			title: {
+				text: '24小时登录时段分布',
+				left: 'center',
+				textStyle: {
+					color: '#2c3e50',
+					fontSize: 16,
+					fontWeight: 'bold'
+				}
+			},
+			tooltip: {
+				trigger: 'axis',
+				backgroundColor: 'rgba(255, 255, 255, 0.95)',
+				borderColor: '#3498db',
+				borderWidth: 1,
+				textStyle: {
+					color: '#333'
+				}
+			},
+			xAxis: {
+				type: 'category',
+				data: hours,
+				axisLine: {
+					lineStyle: {
+						color: '#bdc3c7'
+					}
+				},
+				axisLabel: {
+					color: '#2c3e50'
+				}
+			},
+			yAxis: {
+				type: 'value',
+				name: '登录人次',
+				nameTextStyle: {
+					color: '#2c3e50'
+				},
+				axisLine: {
+					lineStyle: {
+						color: '#bdc3c7'
+					}
+				},
+				axisLabel: {
+					color: '#2c3e50'
+				},
+				splitLine: {
+					lineStyle: {
+						color: '#ecf0f1'
+					}
+				}
+			},
+			series: [
+				{
+					name: '登录人次',
+					type: 'bar',
+					data: loginCounts,
+					itemStyle: {
+						color: {
+							type: 'linear',
+							x: 0,
+							y: 0,
+							x2: 0,
+							y2: 1,
+							colorStops: [
+								{
+									offset: 0,
+									color: '#3498db'
+								},
+								{
+									offset: 1,
+									color: '#2980b9'
+								}
+							]
+						}
+					},
+					emphasis: {
+						itemStyle: {
+							color: '#e74c3c'
+						}
+					}
+				}
+			]
+		}
+
+		loginTimeChartInstance.setOption(option)
+	}
+
+	// 课程访问热度图表
+	const initCourseHeatChart = () => {
+		if (!courseHeatChart.value) return
+
+		if (courseHeatChartInstance) {
+			courseHeatChartInstance.dispose()
+		}
+
+		courseHeatChartInstance = echarts.init(courseHeatChart.value)
+
+		const courses = [
+			'JavaScript程序设计',
+			'数据结构与算法',
+			'管理学原理',
+			'设计基础',
+			'市场营销学',
+			'色彩构成',
+			'Python数据分析',
+			'React前端开发'
+		]
+		const visits = [1234, 1156, 987, 856, 789, 756, 678, 645]
+
+		const option = {
+			title: {
+				text: '课程访问热度TOP8',
+				left: 'center',
+				textStyle: {
+					color: '#2c3e50',
+					fontSize: 16,
+					fontWeight: 'bold'
+				}
+			},
+			tooltip: {
+				trigger: 'axis',
+				backgroundColor: 'rgba(255, 255, 255, 0.95)',
+				borderColor: '#3498db',
+				borderWidth: 1,
+				textStyle: {
+					color: '#333'
+				}
+			},
+			xAxis: {
+				type: 'value',
+				name: '访问量',
+				nameTextStyle: {
+					color: '#2c3e50'
+				},
+				axisLine: {
+					lineStyle: {
+						color: '#bdc3c7'
+					}
+				},
+				axisLabel: {
+					color: '#2c3e50'
+				},
+				splitLine: {
+					lineStyle: {
+						color: '#ecf0f1'
+					}
+				}
+			},
+			yAxis: {
+				type: 'category',
+				data: courses,
+				axisLine: {
+					lineStyle: {
+						color: '#bdc3c7'
+					}
+				},
+				axisLabel: {
+					color: '#2c3e50'
+				}
+			},
+			series: [
+				{
+					name: '访问量',
+					type: 'bar',
+					data: visits,
+					itemStyle: {
+						color: {
+							type: 'linear',
+							x: 0,
+							y: 0,
+							x2: 1,
+							y2: 0,
+							colorStops: [
+								{
+									offset: 0,
+									color: '#e74c3c'
+								},
+								{
+									offset: 1,
+									color: '#f39c12'
+								}
+							]
+						}
+					},
+					emphasis: {
+						itemStyle: {
+							color: '#3498db'
+						}
+					}
+				}
+			]
+		}
+
+		courseHeatChartInstance.setOption(option)
+	}
+
+	// 响应式处理
+	const handleResize = () => {
+		loginTimeChartInstance?.resize()
+		courseHeatChartInstance?.resize()
+	}
+
+	// 组件挂载后初始化
+	onMounted(() => {
+		nextTick(() => {
+			initCollegeCharts()
+			window.addEventListener('resize', handleResize)
+		})
+	})
+
+	// 组件卸载时清理
+	onUnmounted(() => {
+		window.removeEventListener('resize', handleResize)
+		loginTimeChartInstance?.dispose()
+		courseHeatChartInstance?.dispose()
+	})
+</script>
+
+<style scoped>
+	.learning-behavior-analysis {
+		padding: 20px;
+	}
+
+	.header {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 30px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+		text-align: center;
+	}
+
+	.header h1 {
+		color: #2c3e50;
+		font-size: 2.5em;
+		margin-bottom: 10px;
+	}
+
+	.header p {
+		color: #7f8c8d;
+		font-size: 1.1em;
+	}
+
+	.nav-tabs {
+		display: flex;
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 5px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.nav-tab {
+		flex: 1;
+		padding: 15px 20px;
+		text-align: center;
+		cursor: pointer;
+		border-radius: 10px;
+		transition: all 0.3s ease;
+		font-weight: 600;
+		color: #7f8c8d;
+	}
+
+	.nav-tab.active {
+		background: linear-gradient(135deg, #3498db, #2980b9);
+		color: white;
+		box-shadow: 0 4px 15px rgba(52, 152, 219, 0.4);
+	}
+
+	.nav-tab:hover:not(.active) {
+		background: rgba(52, 152, 219, 0.1);
+		color: #3498db;
+	}
+
+	.tab-content {
+		display: block;
+	}
+
+	.filter-section {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.filter-section h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	.filter-controls {
+		display: grid;
+		grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+		gap: 15px;
+		align-items: end;
+	}
+
+	.filter-group {
+		display: flex;
+		flex-direction: column;
+	}
+
+	.filter-group label {
+		margin-bottom: 8px;
+		color: #2c3e50;
+		font-weight: 600;
+	}
+
+	.stats-grid {
+		display: grid;
+		grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+		gap: 25px;
+		margin-bottom: 30px;
+	}
+
+	.stat-card {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+		transition: transform 0.3s ease, box-shadow 0.3s ease;
+	}
+
+	.stat-card:hover {
+		transform: translateY(-5px);
+		box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
+	}
+
+	.stat-card h3 {
+		color: #2c3e50;
+		margin-bottom: 15px;
+		font-size: 1.2em;
+		border-bottom: 2px solid #3498db;
+		padding-bottom: 10px;
+	}
+
+	.stat-number {
+		font-size: 2.2em;
+		font-weight: bold;
+		color: #3498db;
+		margin-bottom: 8px;
+	}
+
+	.stat-label {
+		color: #7f8c8d;
+		font-size: 0.9em;
+	}
+
+	.chart-container {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.chart-container h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	.chart {
+		height: 400px;
+		border-radius: 10px;
+	}
+
+	.data-table {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.data-table h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	.student-cards {
+		display: flex;
+		flex-direction: column;
+		gap: 20px;
+	}
+
+	.student-card {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 20px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+		transition: transform 0.3s ease;
+	}
+
+	.student-card:hover {
+		transform: translateY(-3px);
+	}
+
+	.student-card.highlighted {
+		border: 2px solid #3498db;
+		box-shadow: 0 8px 32px rgba(52, 152, 219, 0.2);
+	}
+
+	.student-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-bottom: 15px;
+		padding-bottom: 10px;
+		border-bottom: 2px solid #ecf0f1;
+	}
+
+	.student-info h4 {
+		color: #2c3e50;
+		font-size: 1.3em;
+		margin-bottom: 5px;
+	}
+
+	.student-meta {
+		color: #7f8c8d;
+		font-size: 0.9em;
+	}
+
+	.course-progress {
+		margin-bottom: 15px;
+	}
+
+	.course-item {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		padding: 10px 0;
+		border-bottom: 1px solid #ecf0f1;
+	}
+
+	.course-name {
+		font-weight: 600;
+		color: #2c3e50;
+	}
+
+	.course-stats {
+		display: flex;
+		gap: 20px;
+		font-size: 0.9em;
+	}
+
+	.stat-item {
+		text-align: center;
+	}
+
+	.stat-value {
+		font-weight: bold;
+		color: #3498db;
+	}
+
+	.stat-label {
+		color: #7f8c8d;
+		font-size: 0.8em;
+	}
+
+	:deep(.completion-rate) {
+		color: #27ae60;
+		font-weight: bold;
+	}
+
+	:deep(.low-engagement) {
+		color: #e74c3c;
+		font-weight: bold;
+	}
+
+	@media (max-width: 768px) {
+		.stats-grid {
+			grid-template-columns: 1fr;
+		}
+
+		.filter-controls {
+			grid-template-columns: 1fr;
+		}
+
+		.header h1 {
+			font-size: 2em;
+		}
+
+		.nav-tabs {
+			flex-direction: column;
+		}
+
+		.student-header {
+			flex-direction: column;
+			align-items: flex-start;
+		}
+
+		.course-stats {
+			flex-direction: column;
+			gap: 10px;
+		}
+	}
+</style>

+ 712 - 0
src/views/statisticalAnalysis/analysisTeachingActivities/index.vue

@@ -0,0 +1,712 @@
+<template>
+	<div class="teaching-activity-analysis">
+		<!-- 页面头部 -->
+		<div class="header">
+			<h1>📚 教学活动分析</h1>
+			<p>为教学过程及课程内容改进提供数据支撑</p>
+		</div>
+
+		<!-- 筛选条件 -->
+		<div class="filter-section">
+			<h3>🔍 数据筛选</h3>
+			<div class="filter-controls">
+				<div class="filter-group">
+					<label>选择课程</label>
+					<a-select v-model:value="filters.courseId" placeholder="全部课程" @change="updateStats">
+						<a-select-option value="">全部课程</a-select-option>
+						<a-select-option value="course1">JavaScript基础教程</a-select-option>
+						<a-select-option value="course2">Python数据分析</a-select-option>
+						<a-select-option value="course3">React前端开发</a-select-option>
+						<a-select-option value="course4">机器学习入门</a-select-option>
+					</a-select>
+				</div>
+				<div class="filter-group">
+					<label>时间范围</label>
+					<a-select v-model:value="filters.timeRange" @change="updateStats">
+						<a-select-option :value="7">最近7天</a-select-option>
+						<a-select-option :value="30">最近30天</a-select-option>
+						<a-select-option :value="90">最近90天</a-select-option>
+						<a-select-option :value="365">最近一年</a-select-option>
+					</a-select>
+				</div>
+				<div class="filter-group">
+					<a-button type="primary" @click="updateStats">查询</a-button>
+				</div>
+			</div>
+		</div>
+
+		<!-- 核心统计数据 -->
+		<div class="stats-grid">
+			<div class="stat-card">
+				<h3>📖 文档观看统计</h3>
+				<div class="stat-number">{{ stats.totalDocViewers.toLocaleString() }}</div>
+				<div class="stat-label">总观看人数</div>
+				<div class="stat-number">{{ stats.completedDocViewers.toLocaleString() }}</div>
+				<div class="stat-label">完成观看人数</div>
+				<div class="completion-rate">{{ stats.docCompletionRate }}%</div>
+				<div class="stat-label">完成率</div>
+			</div>
+
+			<div class="stat-card">
+				<h3>🚪 文档跳出分析</h3>
+				<div class="stat-number">{{ stats.totalDocExits.toLocaleString() }}</div>
+				<div class="stat-label">总跳出次数</div>
+				<div class="stat-number">{{ stats.docExitRate }}%</div>
+				<div class="stat-label">跳出率</div>
+				<div class="stat-number">{{ stats.avgDocExitTime }}</div>
+				<div class="stat-label">平均跳出时间</div>
+			</div>
+
+			<div class="stat-card">
+				<h3>💬 讨论互动统计</h3>
+				<div class="stat-number">{{ stats.totalDiscussions.toLocaleString() }}</div>
+				<div class="stat-label">讨论总数</div>
+				<div class="stat-number">{{ stats.totalReplies.toLocaleString() }}</div>
+				<div class="stat-label">回帖总数</div>
+				<div class="stat-number">{{ stats.avgRepliesPerDiscussion }}</div>
+				<div class="stat-label">平均回帖数</div>
+			</div>
+		</div>
+
+		<!-- 每日访问统计图表 -->
+		<div class="chart-container">
+			<h3>📈 开课每日访问人数统计</h3>
+			<div ref="dailyVisitsChart" class="chart"></div>
+		</div>
+
+		<!-- 每周发帖回帖统计 -->
+		<div class="weekly-stats">
+			<div class="weekly-card">
+				<h4>👨‍🎓 学员每周发帖统计</h4>
+				<div class="weekly-number">{{ weeklyStats.studentWeeklyPosts }}</div>
+				<div class="weekly-label">本周发帖数</div>
+				<div class="weekly-number">{{ weeklyStats.studentWeeklyReplies }}</div>
+				<div class="weekly-label">本周回帖数</div>
+				<div class="weekly-number">{{ weeklyStats.studentAvgPostsPerDay }}</div>
+				<div class="weekly-label">日均发帖数</div>
+			</div>
+
+			<div class="weekly-card">
+				<h4>👨‍🏫 教员每周发帖统计</h4>
+				<div class="weekly-number">{{ weeklyStats.teacherWeeklyPosts }}</div>
+				<div class="weekly-label">本周发帖数</div>
+				<div class="weekly-number">{{ weeklyStats.teacherWeeklyReplies }}</div>
+				<div class="weekly-label">本周回帖数</div>
+				<div class="weekly-number">{{ weeklyStats.teacherAvgPostsPerDay }}</div>
+				<div class="weekly-label">日均发帖数</div>
+			</div>
+		</div>
+
+		<!-- 讨论详情表格 -->
+		<div class="data-table">
+			<h3>💬 课程讨论详情</h3>
+			<a-table :columns="discussionColumns" :data-source="discussionData" :pagination="{ pageSize: 10 }" row-key="id" />
+		</div>
+
+		<!-- 文档观看详细统计 -->
+		<div class="data-table">
+			<h3>📚 文档观看详细统计</h3>
+			<a-table :columns="documentColumns" :data-source="documentData" :pagination="{ pageSize: 10 }" row-key="id" />
+		</div>
+	</div>
+</template>
+
+<script setup>
+	import { ref, reactive, onMounted, nextTick } from 'vue'
+	import * as echarts from 'echarts'
+
+	// 响应式数据
+	const filters = reactive({
+		courseId: '',
+		timeRange: 30
+	})
+
+	const stats = reactive({
+		totalDocViewers: 1856,
+		completedDocViewers: 1234,
+		docCompletionRate: 66.5,
+		totalDocExits: 456,
+		docExitRate: 24.6,
+		avgDocExitTime: '08:45',
+		totalDiscussions: 234,
+		totalReplies: 1567,
+		avgRepliesPerDiscussion: 6.7
+	})
+
+	const weeklyStats = reactive({
+		studentWeeklyPosts: 67,
+		studentWeeklyReplies: 234,
+		studentAvgPostsPerDay: 9.6,
+		teacherWeeklyPosts: 23,
+		teacherWeeklyReplies: 89,
+		teacherAvgPostsPerDay: 3.3
+	})
+
+	// 图表引用
+	const dailyVisitsChart = ref(null)
+	let chartInstance = null
+
+	// 讨论表格列定义
+	const discussionColumns = [
+		{
+			title: '讨论主题',
+			dataIndex: 'title',
+			key: 'title'
+		},
+		{
+			title: '发起人',
+			dataIndex: 'author',
+			key: 'author'
+		},
+		{
+			title: '发起时间',
+			dataIndex: 'createTime',
+			key: 'createTime'
+		},
+		{
+			title: '回帖数',
+			dataIndex: 'replyCount',
+			key: 'replyCount'
+		},
+		{
+			title: '最后回复',
+			dataIndex: 'lastReplyTime',
+			key: 'lastReplyTime'
+		}
+	]
+
+	// 讨论数据
+	const discussionData = ref([
+		{
+			id: 1,
+			title: 'JavaScript闭包概念理解',
+			author: '张三',
+			createTime: '2024-01-15 10:30',
+			replyCount: 15,
+			lastReplyTime: '2024-01-16 14:20'
+		},
+		{
+			id: 2,
+			title: 'Python数据分析库选择',
+			author: '李四',
+			createTime: '2024-01-14 16:45',
+			replyCount: 8,
+			lastReplyTime: '2024-01-15 09:15'
+		},
+		{
+			id: 3,
+			title: 'React组件生命周期',
+			author: '王五',
+			createTime: '2024-01-13 11:20',
+			replyCount: 12,
+			lastReplyTime: '2024-01-14 17:30'
+		},
+		{
+			id: 4,
+			title: '机器学习算法选择',
+			author: '赵六',
+			createTime: '2024-01-12 14:15',
+			replyCount: 6,
+			lastReplyTime: '2024-01-13 10:45'
+		},
+		{
+			id: 5,
+			title: '前端性能优化技巧',
+			author: '钱七',
+			createTime: '2024-01-11 09:30',
+			replyCount: 20,
+			lastReplyTime: '2024-01-15 16:20'
+		}
+	])
+
+	// 文档表格列定义
+	const documentColumns = [
+		{
+			title: '文档名称',
+			dataIndex: 'name',
+			key: 'name'
+		},
+		{
+			title: '文档类型',
+			dataIndex: 'type',
+			key: 'type',
+			width: '100px'
+		},
+		{
+			title: '观看人数',
+			dataIndex: 'viewCount',
+			key: 'viewCount',
+			width: '100px'
+		},
+		{
+			title: '完成人数',
+			dataIndex: 'completedCount',
+			key: 'completedCount',
+			width: '100px'
+		},
+		{
+			title: '完成率',
+			dataIndex: 'completionRate',
+			key: 'completionRate',
+			customRender: ({ text }) => {
+				const rate = parseFloat(text)
+				const className = rate >= 70 ? 'completion-rate' : rate < 50 ? 'low-engagement' : ''
+				return h('span', { class: className }, `${text}%`)
+			}
+		},
+		{
+			title: '平均阅读时长',
+			dataIndex: 'avgReadTime',
+			key: 'avgReadTime',
+			width: '130px'
+		},
+		{
+			title: '跳出率',
+			dataIndex: 'exitRate',
+			key: 'exitRate',
+			customRender: ({ text }) => {
+				const rate = parseFloat(text)
+				const className = rate > 30 ? 'low-engagement' : ''
+				return h('span', { class: className }, `${text}$`)
+			}
+		},
+		{
+			title: '下载次数',
+			dataIndex: 'downloadCount',
+			key: 'downloadCount',
+			width: '100px'
+		}
+	]
+
+	// 文档数据
+	const documentData = ref([
+		{
+			id: 1,
+			name: 'JavaScript基础语法',
+			type: 'PDF文档',
+			viewCount: 1856,
+			completedCount: 1234,
+			completionRate: 66.5,
+			avgReadTime: '25:30',
+			exitRate: 24.6,
+			downloadCount: 456
+		},
+		{
+			id: 2,
+			name: 'Python数据分析入门',
+			type: '在线文档',
+			viewCount: 1234,
+			completedCount: 987,
+			completionRate: 80.0,
+			avgReadTime: '32:15',
+			exitRate: 18.5,
+			downloadCount: 234
+		},
+		{
+			id: 3,
+			name: 'React组件开发指南',
+			type: 'PDF文档',
+			viewCount: 987,
+			completedCount: 756,
+			completionRate: 76.6,
+			avgReadTime: '28:45',
+			exitRate: 22.3,
+			downloadCount: 189
+		},
+		{
+			id: 4,
+			name: '机器学习算法详解',
+			type: '在线文档',
+			viewCount: 756,
+			completedCount: 523,
+			completionRate: 69.2,
+			avgReadTime: '45:20',
+			exitRate: 30.8,
+			downloadCount: 123
+		},
+		{
+			id: 5,
+			name: '前端工程化实践',
+			type: 'PDF文档',
+			viewCount: 523,
+			completedCount: 345,
+			completionRate: 66.0,
+			avgReadTime: '38:15',
+			exitRate: 34.0,
+			downloadCount: 89
+		}
+	])
+	// 生成日期数据
+
+	const generateDateData = (days) => {
+		const dates = []
+		const today = new Date()
+
+		for (let i = days - 1; i >= 0; i--) {
+			const date = new Date(today)
+			date.setDate(date.getDate() - i)
+			dates.push(date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' }))
+		}
+
+		return dates
+	}
+
+	// 生成访问数据
+	const generateVisitData = (days) => {
+		const data = []
+		for (let i = 0; i < days; i++) {
+			// 模拟真实数据:工作日访问量较高,周末较低
+			const dayOfWeek = (new Date().getDay() - days + i + 7) % 7
+			const isWeekend = dayOfWeek === 0 || dayOfWeek === 6
+			const baseValue = isWeekend ? 120 : 200
+			const randomFactor = 0.7 + Math.random() * 0.6 // 0.7-1.3的随机因子
+			data.push(Math.round(baseValue * randomFactor))
+		}
+		return data
+	}
+
+	// 初始化图表
+	const initChart = () => {
+		if (!dailyVisitsChart.value) return
+
+		chartInstance = echarts.init(dailyVisitsChart.value)
+		updateChartData()
+
+		// 响应式处理
+		window.addEventListener('resize', () => {
+			chartInstance?.resize()
+		})
+	}
+
+	// 更新图表数据
+	const updateChartData = () => {
+		if (!chartInstance) return
+
+		const days = filters.timeRange
+		const dates = generateDateData(days)
+		const visits = generateVisitData(days)
+
+		const option = {
+			title: {
+				text: `最近${days}天访问人数趋势`,
+				left: 'center',
+				textStyle: {
+					color: '#2c3e50',
+					fontSize: 16,
+					fontWeight: 'bold'
+				}
+			},
+			tooltip: {
+				trigger: 'axis',
+				backgroundColor: 'rgba(255, 255, 255, 0.95)',
+				borderColor: '#3498db',
+				borderWidth: 1,
+				textStyle: {
+					color: '#333'
+				},
+				formatter: function (params) {
+					let result = params[0].name + '<br/>'
+					params.forEach((param) => {
+						result += param.marker + param.seriesName + ': ' + param.value + '人<br/>'
+					})
+					return result
+				}
+			},
+			legend: {
+				data: ['访问人数'],
+				top: 30,
+				textStyle: {
+					color: '#2c3e50'
+				}
+			},
+			grid: {
+				left: '3%',
+				right: '4%',
+				bottom: '3%',
+				containLabel: true
+			},
+			xAxis: {
+				type: 'category',
+				boundaryGap: false,
+				data: dates,
+				axisLine: {
+					lineStyle: {
+						color: '#bdc3c7'
+					}
+				},
+				axisLabel: {
+					color: '#2c3e50',
+					rotate: days > 30 ? 45 : 0
+				}
+			},
+			yAxis: {
+				type: 'value',
+				name: '访问人数',
+				nameTextStyle: {
+					color: '#2c3e50'
+				},
+				axisLine: {
+					lineStyle: {
+						color: '#bdc3c7'
+					}
+				},
+				axisLabel: {
+					color: '#2c3e50'
+				},
+				splitLine: {
+					lineStyle: {
+						color: '#ecf0f1'
+					}
+				}
+			},
+			series: [
+				{
+					name: '访问人数',
+					type: 'line',
+					smooth: true,
+					data: visits,
+					itemStyle: {
+						color: '#3498db'
+					},
+					areaStyle: {
+						color: {
+							type: 'linear',
+							x: 0,
+							y: 0,
+							x2: 0,
+							y2: 1,
+							colorStops: [
+								{
+									offset: 0,
+									color: 'rgba(52, 152, 219, 0.3)'
+								},
+								{
+									offset: 1,
+									color: 'rgba(52, 152, 219, 0.1)'
+								}
+							]
+						}
+					},
+					lineStyle: {
+						width: 3
+					},
+					symbol: 'circle',
+					symbolSize: 8
+				}
+			]
+		}
+
+		chartInstance.setOption(option, true)
+	}
+
+	// 更新统计数据
+	const updateStats = () => {
+		// 模拟数据更新
+		updateChartData()
+	}
+
+	// 组件挂载后初始化
+	onMounted(() => {
+		nextTick(() => {
+			initChart()
+		})
+	})
+</script>
+
+<style scoped>
+	.teaching-activity-analysis {
+		padding: 20px;
+		/* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */
+	}
+
+	.header {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 30px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+		text-align: center;
+	}
+
+	.header h1 {
+		color: #2c3e50;
+		font-size: 2.5em;
+		margin-bottom: 10px;
+	}
+
+	.header p {
+		color: #7f8c8d;
+		font-size: 1.1em;
+	}
+
+	.filter-section {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.filter-section h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	.filter-controls {
+		display: grid;
+		grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+		gap: 15px;
+		align-items: end;
+	}
+
+	.filter-group {
+		display: flex;
+		flex-direction: column;
+	}
+
+	.filter-group label {
+		margin-bottom: 8px;
+		color: #2c3e50;
+		font-weight: 600;
+	}
+
+	.stats-grid {
+		display: grid;
+		grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+		gap: 25px;
+		margin-bottom: 30px;
+	}
+
+	.stat-card {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+		transition: transform 0.3s ease, box-shadow 0.3s ease;
+	}
+
+	.stat-card:hover {
+		transform: translateY(-5px);
+		box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
+	}
+
+	.stat-card h3 {
+		color: #2c3e50;
+		margin-bottom: 15px;
+		font-size: 1.3em;
+		border-bottom: 2px solid #3498db;
+		padding-bottom: 10px;
+	}
+
+	.stat-number {
+		font-size: 2.5em;
+		font-weight: bold;
+		color: #3498db;
+		margin-bottom: 10px;
+	}
+
+	.stat-label {
+		color: #7f8c8d;
+		font-size: 0.9em;
+	}
+
+	.chart-container {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.chart-container h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	.chart {
+		height: 400px;
+		border-radius: 10px;
+	}
+
+	.weekly-stats {
+		display: grid;
+		grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+		gap: 20px;
+		margin-bottom: 30px;
+	}
+
+	.weekly-card {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 20px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.weekly-card h4 {
+		color: #2c3e50;
+		margin-bottom: 15px;
+		font-size: 1.2em;
+	}
+
+	.weekly-number {
+		font-size: 2em;
+		font-weight: bold;
+		color: #3498db;
+		margin-bottom: 5px;
+	}
+
+	.weekly-label {
+		color: #7f8c8d;
+		font-size: 0.9em;
+	}
+
+	.data-table {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.data-table h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	:deep(.completion-rate) {
+		color: #27ae60;
+		font-weight: bold;
+	}
+
+	:deep(.low-engagement) {
+		color: #e74c3c;
+		font-weight: bold;
+	}
+
+	@media (max-width: 768px) {
+		.stats-grid {
+			grid-template-columns: 1fr;
+		}
+
+		.filter-controls {
+			grid-template-columns: 1fr;
+		}
+
+		.header h1 {
+			font-size: 2em;
+		}
+
+		.weekly-stats {
+			grid-template-columns: 1fr;
+		}
+	}
+</style>

+ 425 - 0
src/views/statisticalAnalysis/overviewLearningProgress/index.vue

@@ -0,0 +1,425 @@
+<template>
+	<div class="p-6 flex justify-center min-h-screen">
+		<div class="w-full mx-auto">
+			<!-- 顶部筛选区 -->
+			<div class="bg-white rounded-lg shadow-sm p-6 mb-6 h-25 flex items-center">
+				<!-- 讲座选择 -->
+				<div class="flex-1 mr-4">
+					<label class="block text-sm font-medium text-gray-700 mb-1">讲座名称</label>
+					<div class="relative">
+						<a-select v-model:value="filters.courseName" class="w-full" placeholder="全部课程">
+							<a-select-option value="">全部课程</a-select-option>
+							<a-select-option value="python">Python编程入门</a-select-option>
+							<a-select-option value="datastructure">数据结构与算法</a-select-option>
+							<a-select-option value="ml">机器学习基础</a-select-option>
+							<a-select-option value="frontend">Web前端开发</a-select-option>
+						</a-select>
+					</div>
+				</div>
+
+				<!-- 内容类型 -->
+				<div class="flex-1 mr-4">
+					<label class="block text-sm font-medium text-gray-700 mb-1">内容类型</label>
+					<div class="flex space-x-2">
+						<a-button
+							v-for="type in contentTypes"
+							:key="type.value"
+							:type="filters.contentType === type.value ? 'primary' : 'default'"
+							size="small"
+							@click="filters.contentType = type.value"
+						>
+							{{ type.label }}
+						</a-button>
+					</div>
+				</div>
+
+				<!-- 日期范围选择 -->
+				<div class="flex-1">
+					<label class="block text-sm font-medium text-gray-700 mb-1">日期范围(周次)</label>
+					<a-range-picker v-model:value="filters.dateRange" class="w-full" :placeholder="['开始日期', '结束日期']" />
+				</div>
+
+				<!-- 操作按钮 -->
+				<div class="flex space-x-2 ml-4 mt-6">
+					<a-button @click="refreshData" :loading="loading">
+						<template #icon>
+							<ReloadOutlined />
+						</template>
+						刷新
+					</a-button>
+				</div>
+			</div>
+
+			<!-- 核心数据看板 -->
+			<div class="mb-6">
+				<!-- 数据卡片 -->
+				<div class="grid grid-cols-4 gap-6 mb-6">
+					<div
+						v-for="(card, index) in statsCards"
+						:key="index"
+						class="card-header bg-white p-5 rounded-lg shadow-sm"
+						:class="card.borderClass"
+					>
+						<div class="flex justify-between items-start">
+							<div>
+								<div class="text-gray-500 text-sm">{{ card.title }}</div>
+								<div class="text-4xl font-bold text-gray-800 mt-2">{{ card.value.toLocaleString() }}</div>
+							</div>
+							<div :class="card.iconBgClass" class="p-2 rounded-full">
+								<component :is="card.icon" :class="card.iconClass" class="text-xl" />
+							</div>
+						</div>
+					</div>
+				</div>
+
+				<!-- 图表区 -->
+				<div class="grid grid-cols-2 gap-6">
+					<!-- 折线图 -->
+					<div class="chart-container p-4 bg-white border border-gray-200 rounded">
+						<h3 class="font-bold text-gray-800 mb-4">访问人数趋势</h3>
+						<div ref="lineChartRef" class="h-48"></div>
+					</div>
+
+					<!-- 柱状图 -->
+					<div class="chart-container p-4 bg-white border border-gray-200 rounded">
+						<h3 class="font-bold text-gray-800 mb-4">练习平均提交数</h3>
+						<div ref="barChartRef" class="h-48"></div>
+					</div>
+				</div>
+			</div>
+
+			<!-- 明细表格区 -->
+			<div class="bg-white rounded-lg shadow-sm p-6">
+				<div class="flex justify-between items-center mb-4">
+					<h2 class="text-xl font-bold text-gray-800">学习明细数据</h2>
+					<div class="text-sm text-gray-500">({{ formatDateRange() }})注:从查询条件时间范围落下来的</div>
+				</div>
+
+				<a-table
+					:columns="tableColumns"
+					:data-source="tableData"
+					:pagination="pagination"
+					:loading="loading"
+					size="small"
+				>
+					<template #bodyCell="{ column, record }">
+						<template v-if="column.key === 'submissionCount'">
+							<span
+								:class="{
+									'text-green-500': record.submissionCount >= 90,
+									'text-orange-500': record.submissionCount >= 70 && record.submissionCount < 90,
+									'text-red-500': record.submissionCount < 70
+								}"
+								class="font-semibold"
+							>
+								{{ record.submissionCount }}
+							</span>
+						</template>
+					</template>
+				</a-table>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script setup>
+	import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'
+	import { ReloadOutlined, UserOutlined, EyeOutlined, FileTextOutlined, MessageOutlined } from '@ant-design/icons-vue'
+	import * as echarts from 'echarts'
+	import dayjs from 'dayjs'
+
+	// 响应式数据
+	const loading = ref(false)
+	const lineChartRef = ref(null)
+	const barChartRef = ref(null)
+	let lineChart = null
+	let barChart = null
+
+	// 筛选条件
+	const filters = reactive({
+		courseName: '',
+		contentType: 'all',
+		dateRange: [dayjs('2025-08-04'), dayjs('2025-08-10')]
+	})
+
+	// 内容类型选项
+	const contentTypes = [
+		{ label: '全部', value: 'all' },
+		{ label: '视频', value: 'video' },
+		{ label: '文档', value: 'document' },
+		{ label: '练习', value: 'exercise' }
+	]
+
+	// 统计卡片数据
+	const statsCards = reactive([
+		{
+			title: '开课人数',
+			value: 2846,
+			icon: UserOutlined,
+			borderClass: 'border-l-4 !border-blue-500',
+			iconBgClass: 'bg-blue-100',
+			iconClass: 'text-blue-600'
+		},
+		{
+			title: '课程访问次数',
+			value: 12587,
+			icon: EyeOutlined,
+			borderClass: 'border-l-4 !border-green-500',
+			iconBgClass: 'bg-green-100',
+			iconClass: 'text-green-600'
+		},
+		{
+			title: '提交数(作业、测验)',
+			value: 1924,
+			icon: FileTextOutlined,
+			borderClass: 'border-l-4 !border-orange-500',
+			iconBgClass: 'bg-orange-100',
+			iconClass: 'text-orange-500'
+		},
+		{
+			title: '互动数(发帖/回帖)',
+			value: 5362,
+			icon: MessageOutlined,
+			borderClass: 'border-l-4 !border-blue-500',
+			iconBgClass: 'bg-blue-100',
+			iconClass: 'text-blue-600'
+		}
+	])
+
+	const tableColumns = [
+		{
+			title: '讲座名称',
+			dataIndex: 'courseName',
+			key: 'courseName',
+			sorter: true
+		},
+		{
+			title: '开课人数',
+			dataIndex: 'studentCount',
+			key: 'studentCount',
+			sorter: true
+		},
+		{
+			title: '课程访问量',
+			dataIndex: 'visitCount',
+			key: 'visitCount',
+			sorter: true
+		},
+		{
+			title: '学习视频总时长',
+			dataIndex: 'videoDuration',
+			key: 'videoDuration',
+			sorter: true
+		},
+		{
+			title: '讲义访问量',
+			dataIndex: 'documentVisit',
+			key: 'documentVisit',
+			sorter: true
+		},
+		{
+			title: '练习提交量',
+			dataIndex: 'submissionCount',
+			key: 'submissionCount',
+			sorter: true
+		}
+	]
+
+	// 表格数据
+	const tableData = ref([
+		{
+			key: '1',
+			courseName: 'Python编程基础',
+			studentCount: 60,
+			visitCount: 1245,
+			videoDuration: '5h12m30s',
+			documentVisit: 453,
+			submissionCount: 94
+		},
+		{
+			key: '2',
+			courseName: '数据结构 - 栈与队列',
+			studentCount: 70,
+			visitCount: 1087,
+			videoDuration: '5h12m30s',
+			documentVisit: 389,
+			submissionCount: 88
+		},
+		{
+			key: '3',
+			courseName: 'Web前端框架实战',
+			studentCount: 80,
+			visitCount: 987,
+			videoDuration: '5h12m30s',
+			documentVisit: 326,
+			submissionCount: 79
+		},
+		{
+			key: '4',
+			courseName: '机器学习入门',
+			studentCount: 90,
+			visitCount: 856,
+			videoDuration: '5h12m30s',
+			documentVisit: 278,
+			submissionCount: 75
+		},
+		{
+			key: '5',
+			courseName: '数据库设计原理',
+			studentCount: 100,
+			visitCount: 723,
+			videoDuration: '5h12m30s',
+			documentVisit: 214,
+			submissionCount: 72
+		},
+		{
+			key: '6',
+			courseName: '算法复杂度分析',
+			studentCount: 110,
+			visitCount: 634,
+			videoDuration: '5h12m30s',
+			documentVisit: 196,
+			submissionCount: 68
+		}
+	])
+
+	// 分页配置
+	const pagination = reactive({
+		current: 1,
+		pageSize: 6,
+		total: 32,
+		showSizeChanger: true,
+		showQuickJumper: true,
+		showTotal: (total, range) => `显示 ${range[0]}-${range[1]} 条,共 ${total} 条`
+	})
+
+	// 初始化折线图
+	const initLineChart = () => {
+		if (!lineChartRef.value) return
+
+		lineChart = echarts.init(lineChartRef.value)
+		const option = {
+			grid: { top: 30, right: 20, bottom: 20, left: 40 },
+			tooltip: { trigger: 'axis' },
+			xAxis: {
+				type: 'category',
+				data: ['4日', '5日', '6日', '7日', '8日', '9日', '10日']
+			},
+			yAxis: { type: 'value', name: '访问人数' },
+			series: [
+				{
+					name: '周访问人数',
+					type: 'line',
+					smooth: true,
+					symbol: 'circle',
+					symbolSize: 8,
+					data: [2150, 2380, 1920, 2650, 2210, 2490, 2000],
+					lineStyle: { color: '#3A7BFF', width: 3 },
+					itemStyle: { color: '#3A7BFF' },
+					areaStyle: {
+						color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+							{ offset: 0, color: 'rgba(58, 123, 255, 0.3)' },
+							{ offset: 1, color: 'rgba(58, 123, 255, 0.05)' }
+						])
+					}
+				}
+			]
+		}
+		lineChart.setOption(option)
+	}
+
+	// 初始化柱状图
+	const initBarChart = () => {
+		if (!barChartRef.value) return
+
+		barChart = echarts.init(barChartRef.value)
+		const option = {
+			grid: { top: 30, right: 20, bottom: 20, left: 40 },
+			tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
+			xAxis: {
+				type: 'category',
+				data: ['4日', '5日', '6日', '7日', '8日', '9日', '10日']
+			},
+			yAxis: { type: 'value', name: '平均提交数' },
+			series: [
+				{
+					name: '练习平均提交数',
+					type: 'bar',
+					barWidth: 28,
+					data: [82, 85, 78, 89, 76, 91, 83],
+					itemStyle: {
+						color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+							{ offset: 0, color: '#5B8EFF' },
+							{ offset: 1, color: '#3A7BFF' }
+						]),
+						borderRadius: [4, 4, 0, 0]
+					}
+				}
+			]
+		}
+		barChart.setOption(option)
+	}
+
+	// 格式化日期范围显示
+	const formatDateRange = () => {
+		if (!filters.dateRange || filters.dateRange.length !== 2) {
+			return '2025/08/04至2025/08/10'
+		}
+		const start = filters.dateRange[0].format('YYYY/MM/DD')
+		const end = filters.dateRange[1].format('YYYY/MM/DD')
+		return `${start}至${end}`
+	}
+
+	// 刷新数据
+	const refreshData = async () => {
+		loading.value = true
+		try {
+			// 模拟API调用
+			await new Promise((resolve) => setTimeout(resolve, 1000))
+			// 这里可以调用实际的API来获取数据
+			console.log('刷新数据', filters)
+		} catch (error) {
+			console.error('刷新数据失败:', error)
+		} finally {
+			loading.value = false
+		}
+	}
+
+	// 窗口大小变化处理
+	const handleResize = () => {
+		if (lineChart) lineChart.resize()
+		if (barChart) barChart.resize()
+	}
+
+	// 生命周期
+	onMounted(async () => {
+		await nextTick()
+		initLineChart()
+		initBarChart()
+		window.addEventListener('resize', handleResize)
+	})
+
+	onUnmounted(() => {
+		if (lineChart) {
+			lineChart.dispose()
+			lineChart = null
+		}
+		if (barChart) {
+			barChart.dispose()
+			barChart = null
+		}
+		window.removeEventListener('resize', handleResize)
+	})
+</script>
+
+<style scoped>
+	.card-header {
+		border-left: 4px solid;
+	}
+
+	.chart-container {
+		background-color: white;
+		border: 1px solid #e4e7ed;
+		border-radius: 4px;
+	}
+</style>

+ 781 - 0
src/views/statisticalAnalysis/videoAnalysis/index.vue

@@ -0,0 +1,781 @@
+<template>
+	<div class="video-analysis-container">
+		<!-- 页面头部 -->
+		<div class="header">
+			<h1>📊 视频分析</h1>
+			<p>为教学过程及课程内容改进提供数据支撑</p>
+		</div>
+
+		<!-- 筛选条件 -->
+		<div class="filter-section">
+			<h3>🔍 数据筛选</h3>
+			<div class="filter-controls">
+				<div class="filter-group">
+					<label>选择课程</label>
+					<a-select v-model:value="filters.courseId" placeholder="全部课程" style="width: 100%">
+						<a-select-option value="">全部课程</a-select-option>
+						<a-select-option value="course1">JavaScript基础教程</a-select-option>
+						<a-select-option value="course2">Python数据分析</a-select-option>
+						<a-select-option value="course3">React前端开发</a-select-option>
+						<a-select-option value="course4">机器学习入门</a-select-option>
+					</a-select>
+				</div>
+				<div class="filter-group">
+					<label>时间范围</label>
+					<a-select v-model:value="filters.timeRange" style="width: 100%">
+						<a-select-option value="7">最近7天</a-select-option>
+						<a-select-option value="30">最近30天</a-select-option>
+						<a-select-option value="90">最近90天</a-select-option>
+						<a-select-option value="365">最近一年</a-select-option>
+					</a-select>
+				</div>
+				<div class="filter-group">
+					<a-button type="primary" @click="updateStats">查询</a-button>
+				</div>
+			</div>
+		</div>
+
+		<!-- 核心统计数据 -->
+		<div class="stats-grid">
+			<div class="stat-card">
+				<h3>👥 观看人数统计</h3>
+				<div class="stat-number">{{ stats.totalViewers.toLocaleString() }}</div>
+				<div class="stat-label">总观看人数</div>
+				<div class="stat-number">{{ stats.completedViewers.toLocaleString() }}</div>
+				<div class="stat-label">完成观看人数</div>
+				<div class="completion-rate">{{ stats.completionRate }}%</div>
+				<div class="stat-label">完成率</div>
+			</div>
+
+			<div class="stat-card">
+				<h3>📥 讲义下载统计</h3>
+				<div class="stat-number">{{ stats.totalDownloads.toLocaleString() }}</div>
+				<div class="stat-label">总下载次数</div>
+				<div class="stat-number">{{ stats.downloadRate }}%</div>
+				<div class="stat-label">下载率</div>
+				<div class="stat-number">{{ stats.avgDownloads }}</div>
+				<div class="stat-label">人均下载次数</div>
+			</div>
+
+			<div class="stat-card">
+				<h3>⏱️ 跳出时间分析</h3>
+				<div class="stat-number">{{ stats.totalExits.toLocaleString() }}</div>
+				<div class="stat-label">总跳出次数</div>
+				<div class="stat-number">{{ stats.exitRate }}%</div>
+				<div class="stat-label">跳出率</div>
+				<div class="stat-number">{{ stats.avgExitTime }}</div>
+				<div class="stat-label">平均跳出时间</div>
+			</div>
+
+			<div class="stat-card">
+				<h3>📝 互动数据统计</h3>
+				<div class="stat-number">{{ stats.totalNotes.toLocaleString() }}</div>
+				<div class="stat-label">笔记总数</div>
+				<div class="stat-number">{{ stats.totalDiscussions.toLocaleString() }}</div>
+				<div class="stat-label">讨论总数</div>
+				<div class="stat-number">{{ stats.totalReplies.toLocaleString() }}</div>
+				<div class="stat-label">回帖总数</div>
+			</div>
+		</div>
+
+		<!-- ECharts 图表区域 -->
+		<div class="charts-section">
+			<!-- 学习进度分布图 -->
+			<div class="chart-container">
+				<h3>📈 学习进度分布</h3>
+				<div ref="progressChart" class="chart"></div>
+			</div>
+
+			<!-- 观看时长趋势图 -->
+			<div class="chart-container">
+				<h3>📊 观看时长趋势</h3>
+				<div ref="timeChart" class="chart"></div>
+			</div>
+
+			<!-- 章节完成率对比图 -->
+			<div class="chart-container">
+				<h3>📚 章节完成率对比</h3>
+				<div ref="chapterChart" class="chart"></div>
+			</div>
+
+			<!-- 互动数据统计图 -->
+			<div class="chart-container">
+				<h3>💬 互动数据统计</h3>
+				<div ref="interactionChart" class="chart"></div>
+			</div>
+		</div>
+
+		<!-- 学员详细数据表格 -->
+		<div class="data-table">
+			<h3>👤 学员学习行为详细数据</h3>
+			<a-table
+				:columns="studentColumns"
+				:data-source="studentData"
+				:pagination="{ pageSize: 10 }"
+				:scroll="{ x: 1200 }"
+			>
+				<template #bodyCell="{ column, record }">
+					<template v-if="column.key === 'progress'">
+						<div class="progress-container">
+							<a-progress :percent="record.progress" size="small" />
+							<span :class="{ 'low-engagement': record.progress < 50 }"> {{ record.progress }}% </span>
+						</div>
+					</template>
+					<template v-else-if="column.key === 'exitPoints'">
+						<span v-for="point in record.exitPoints" :key="point" class="time-point">
+							{{ point }}
+						</span>
+					</template>
+				</template>
+			</a-table>
+		</div>
+
+		<!-- 视频章节详细统计 -->
+		<div class="data-table">
+			<h3>📚 视频章节详细统计</h3>
+			<a-table :columns="chapterColumns" :data-source="chapterData" :pagination="false">
+				<template #bodyCell="{ column, record }">
+					<template v-if="column.key === 'completionRate'">
+						<span
+							:class="{ 'completion-rate': record.completionRate >= 70, 'low-engagement': record.completionRate < 70 }"
+						>
+							{{ record.completionRate }}%
+						</span>
+					</template>
+					<template v-else-if="column.key === 'exitRate'">
+						<span :class="{ 'low-engagement': record.exitRate > 25 }"> {{ record.exitRate }}% </span>
+					</template>
+				</template>
+			</a-table>
+		</div>
+	</div>
+</template>
+
+<script setup>
+	import { ref, reactive, onMounted, nextTick } from 'vue'
+	import { message } from 'ant-design-vue'
+	import * as echarts from 'echarts'
+
+	// 筛选条件
+	const filters = reactive({
+		courseId: '',
+		timeRange: '30'
+	})
+
+	// 统计数据
+	const stats = reactive({
+		totalViewers: 1247,
+		completedViewers: 892,
+		completionRate: 71.6,
+		totalDownloads: 456,
+		downloadRate: 36.6,
+		avgDownloads: 0.37,
+		totalExits: 234,
+		exitRate: 18.8,
+		avgExitTime: '12:34',
+		totalNotes: 1089,
+		totalDiscussions: 567,
+		totalReplies: 2341
+	})
+
+	// 图表引用
+	const progressChart = ref(null)
+	const timeChart = ref(null)
+	const chapterChart = ref(null)
+	const interactionChart = ref(null)
+
+	// 学员数据表格列定义
+	const studentColumns = [
+		{ title: '学员ID', dataIndex: 'id', key: 'id', width: 80 },
+		{ title: '姓名', dataIndex: 'name', key: 'name', width: 100 },
+		{ title: '访问总时长', dataIndex: 'totalTime', key: 'totalTime', width: 120 },
+		{ title: '学习进度', dataIndex: 'progress', key: 'progress', width: 150 },
+		{ title: '观看次数', dataIndex: 'viewCount', key: 'viewCount', width: 100 },
+		{ title: '跳出时间点', dataIndex: 'exitPoints', key: 'exitPoints', width: 200 },
+		{ title: '快进快退次数', dataIndex: 'seekCount', key: 'seekCount', width: 120 },
+		{ title: '笔记数', dataIndex: 'noteCount', key: 'noteCount', width: 80 },
+		{ title: '讨论数', dataIndex: 'discussionCount', key: 'discussionCount', width: 80 },
+		{ title: '回帖数', dataIndex: 'replyCount', key: 'replyCount', width: 80 },
+		{ title: '最后访问', dataIndex: 'lastAccess', key: 'lastAccess', width: 150 }
+	]
+
+	// 学员数据
+	const studentData = ref([
+		{
+			key: '1',
+			id: '001',
+			name: '张三',
+			totalTime: '2小时35分钟',
+			progress: 85,
+			viewCount: '3次',
+			exitPoints: ['05:23', '18:45'],
+			seekCount: '12次',
+			noteCount: 5,
+			discussionCount: 3,
+			replyCount: 8,
+			lastAccess: '2024-01-15 14:30'
+		},
+		{
+			key: '2',
+			id: '002',
+			name: '李四',
+			totalTime: '1小时48分钟',
+			progress: 60,
+			viewCount: '2次',
+			exitPoints: ['08:12', '25:30', '42:15'],
+			seekCount: '8次',
+			noteCount: 2,
+			discussionCount: 1,
+			replyCount: 3,
+			lastAccess: '2024-01-15 16:45'
+		},
+		{
+			key: '3',
+			id: '003',
+			name: '王五',
+			totalTime: '3小时12分钟',
+			progress: 95,
+			viewCount: '5次',
+			exitPoints: ['03:45'],
+			seekCount: '15次',
+			noteCount: 8,
+			discussionCount: 5,
+			replyCount: 12,
+			lastAccess: '2024-01-15 20:15'
+		},
+		{
+			key: '4',
+			id: '004',
+			name: '赵六',
+			totalTime: '45分钟',
+			progress: 25,
+			viewCount: '1次',
+			exitPoints: ['12:30', '18:20', '28:45'],
+			seekCount: '3次',
+			noteCount: 0,
+			discussionCount: 0,
+			replyCount: 0,
+			lastAccess: '2024-01-15 10:20'
+		},
+		{
+			key: '5',
+			id: '005',
+			name: '钱七',
+			totalTime: '2小时08分钟',
+			progress: 78,
+			viewCount: '4次',
+			exitPoints: ['07:15', '22:40'],
+			seekCount: '10次',
+			noteCount: 4,
+			discussionCount: 2,
+			replyCount: 6,
+			lastAccess: '2024-01-15 19:30'
+		}
+	])
+
+	// 章节数据表格列定义
+	const chapterColumns = [
+		{ title: '章节', dataIndex: 'chapter', key: 'chapter', width: 200 },
+		{ title: '视频时长', dataIndex: 'duration', key: 'duration', width: 100 },
+		{ title: '观看人数', dataIndex: 'viewers', key: 'viewers', width: 100 },
+		{ title: '完成人数', dataIndex: 'completed', key: 'completed', width: 100 },
+		{ title: '完成率', dataIndex: 'completionRate', key: 'completionRate', width: 100 },
+		{ title: '平均观看时长', dataIndex: 'avgWatchTime', key: 'avgWatchTime', width: 120 },
+		{ title: '跳出率', dataIndex: 'exitRate', key: 'exitRate', width: 100 },
+		{ title: '下载次数', dataIndex: 'downloads', key: 'downloads', width: 100 },
+		{ title: '笔记数', dataIndex: 'notes', key: 'notes', width: 80 },
+		{ title: '讨论数', dataIndex: 'discussions', key: 'discussions', width: 80 }
+	]
+
+	// 章节数据
+	const chapterData = ref([
+		{
+			key: '1',
+			chapter: '第1章:课程介绍',
+			duration: '15:30',
+			viewers: 1247,
+			completed: 1156,
+			completionRate: 92.7,
+			avgWatchTime: '14:25',
+			exitRate: 7.3,
+			downloads: 89,
+			notes: 45,
+			discussions: 12
+		},
+		{
+			key: '2',
+			chapter: '第2章:基础知识',
+			duration: '28:15',
+			viewers: 1156,
+			completed: 987,
+			completionRate: 85.4,
+			avgWatchTime: '24:30',
+			exitRate: 14.6,
+			downloads: 156,
+			notes: 78,
+			discussions: 23
+		},
+		{
+			key: '3',
+			chapter: '第3章:核心概念',
+			duration: '35:20',
+			viewers: 987,
+			completed: 756,
+			completionRate: 76.6,
+			avgWatchTime: '28:45',
+			exitRate: 23.4,
+			downloads: 123,
+			notes: 89,
+			discussions: 34
+		},
+		{
+			key: '4',
+			chapter: '第4章:实战应用',
+			duration: '42:10',
+			viewers: 756,
+			completed: 523,
+			completionRate: 69.2,
+			avgWatchTime: '32:15',
+			exitRate: 30.8,
+			downloads: 88,
+			notes: 67,
+			discussions: 28
+		},
+		{
+			key: '5',
+			chapter: '第5章:高级技巧',
+			duration: '38:45',
+			viewers: 523,
+			completed: 345,
+			completionRate: 66.0,
+			avgWatchTime: '29:20',
+			exitRate: 34.0,
+			downloads: 67,
+			notes: 45,
+			discussions: 19
+		}
+	])
+
+	// 初始化图表
+	const initCharts = () => {
+		initProgressChart()
+		initTimeChart()
+		initChapterChart()
+		initInteractionChart()
+	}
+
+	// 学习进度分布图
+	const initProgressChart = () => {
+		const chart = echarts.init(progressChart.value)
+		const option = {
+			title: {
+				text: '学习进度分布',
+				left: 'center'
+			},
+			tooltip: {
+				trigger: 'item',
+				formatter: '{a} <br/>{b}: {c} ({d}%)'
+			},
+			legend: {
+				orient: 'vertical',
+				left: 'left'
+			},
+			series: [
+				{
+					name: '学习进度',
+					type: 'pie',
+					radius: '50%',
+					data: [
+						{ value: 234, name: '0-25%' },
+						{ value: 189, name: '26-50%' },
+						{ value: 345, name: '51-75%' },
+						{ value: 479, name: '76-100%' }
+					],
+					emphasis: {
+						itemStyle: {
+							shadowBlur: 10,
+							shadowOffsetX: 0,
+							shadowColor: 'rgba(0, 0, 0, 0.5)'
+						}
+					}
+				}
+			]
+		}
+		chart.setOption(option)
+	}
+
+	// 观看时长趋势图
+	const initTimeChart = () => {
+		const chart = echarts.init(timeChart.value)
+		const option = {
+			title: {
+				// text: '观看时长趋势',
+				left: 'center'
+			},
+			tooltip: {
+				trigger: 'axis'
+			},
+			legend: {
+				data: ['观看时长', '完成人数']
+			},
+			xAxis: {
+				type: 'category',
+				data: ['第1章', '第2章', '第3章', '第4章', '第5章']
+			},
+			yAxis: [
+				{
+					type: 'value',
+					name: '时长(分钟)',
+					position: 'left'
+				},
+				{
+					type: 'value',
+					name: '人数',
+					position: 'right'
+				}
+			],
+			series: [
+				{
+					name: '观看时长',
+					type: 'bar',
+					data: [14.4, 24.5, 28.8, 32.3, 29.3],
+					itemStyle: {
+						color: '#3498db'
+					}
+				},
+				{
+					name: '完成人数',
+					type: 'line',
+					yAxisIndex: 1,
+					data: [1156, 987, 756, 523, 345],
+					itemStyle: {
+						color: '#e74c3c'
+					}
+				}
+			]
+		}
+		chart.setOption(option)
+	}
+
+	// 章节完成率对比图
+	const initChapterChart = () => {
+		const chart = echarts.init(chapterChart.value)
+		const option = {
+			title: {
+				text: '章节完成率对比',
+				left: 'center'
+			},
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'shadow'
+				}
+			},
+			grid: {
+				left: '3%',
+				right: '4%',
+				bottom: '3%',
+				containLabel: true
+			},
+			xAxis: {
+				type: 'value',
+				max: 100
+			},
+			yAxis: {
+				type: 'category',
+				data: ['第5章', '第4章', '第3章', '第2章', '第1章']
+			},
+			series: [
+				{
+					name: '完成率',
+					type: 'bar',
+					data: [66.0, 69.2, 76.6, 85.4, 92.7],
+					itemStyle: {
+						color: function (params) {
+							const value = params.value
+							if (value >= 80) return '#27ae60'
+							if (value >= 60) return '#f39c12'
+							return '#e74c3c'
+						}
+					}
+				}
+			]
+		}
+		chart.setOption(option)
+	}
+
+	// 互动数据统计图
+	const initInteractionChart = () => {
+		const chart = echarts.init(interactionChart.value)
+		const option = {
+			title: {
+				// text: '互动数据统计',
+				left: 'center'
+			},
+			tooltip: {
+				trigger: 'axis'
+			},
+			legend: {
+				data: ['笔记数', '讨论数', '回帖数']
+			},
+			xAxis: {
+				type: 'category',
+				data: ['第1章', '第2章', '第3章', '第4章', '第5章']
+			},
+			yAxis: {
+				type: 'value'
+			},
+			series: [
+				{
+					name: '笔记数',
+					type: 'bar',
+					data: [45, 78, 89, 67, 45],
+					itemStyle: {
+						color: '#3498db'
+					}
+				},
+				{
+					name: '讨论数',
+					type: 'bar',
+					data: [12, 23, 34, 28, 19],
+					itemStyle: {
+						color: '#2ecc71'
+					}
+				},
+				{
+					name: '回帖数',
+					type: 'bar',
+					data: [25, 45, 67, 56, 38],
+					itemStyle: {
+						color: '#f39c12'
+					}
+				}
+			]
+		}
+		chart.setOption(option)
+	}
+
+	// 更新统计数据
+	const updateStats = () => {
+		// 模拟数据更新
+		stats.totalViewers = Math.floor(Math.random() * 500) + 1000
+		stats.completedViewers = Math.floor(stats.totalViewers * 0.7)
+		stats.completionRate = Number(((stats.completedViewers / stats.totalViewers) * 100).toFixed(1))
+
+		// 重新初始化图表
+		nextTick(() => {
+			initCharts()
+		})
+
+		// 显示更新提示
+		message.success('数据已更新!')
+	}
+
+	// 组件挂载后初始化图表
+	onMounted(() => {
+		nextTick(() => {
+			initCharts()
+		})
+
+		// 监听窗口大小变化,重新调整图表
+		window.addEventListener('resize', () => {
+			const charts = [progressChart, timeChart, chapterChart, interactionChart]
+			charts.forEach((chartRef) => {
+				if (chartRef.value) {
+					const chart = echarts.getInstanceByDom(chartRef.value)
+					if (chart) {
+						chart.resize()
+					}
+				}
+			})
+		})
+	})
+</script>
+
+<style scoped>
+	.video-analysis-container {
+		padding: 20px;
+		/* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */
+	}
+
+	.header {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 30px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+		text-align: center;
+	}
+
+	.header h1 {
+		color: #2c3e50;
+		font-size: 2.5em;
+		margin-bottom: 10px;
+	}
+
+	.header p {
+		color: #7f8c8d;
+		font-size: 1.1em;
+	}
+
+	.filter-section {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.filter-section h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	.filter-controls {
+		display: grid;
+		grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+		gap: 15px;
+		align-items: end;
+	}
+
+	.filter-group {
+		display: flex;
+		flex-direction: column;
+	}
+
+	.filter-group label {
+		margin-bottom: 8px;
+		color: #2c3e50;
+		font-weight: 600;
+	}
+
+	.stats-grid {
+		display: grid;
+		grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+		gap: 25px;
+		margin-bottom: 30px;
+	}
+
+	.stat-card {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+		transition: transform 0.3s ease, box-shadow 0.3s ease;
+	}
+
+	.stat-card:hover {
+		transform: translateY(-5px);
+		box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
+	}
+
+	.stat-card h3 {
+		color: #2c3e50;
+		margin-bottom: 15px;
+		font-size: 1.3em;
+		border-bottom: 2px solid #3498db;
+		padding-bottom: 10px;
+	}
+
+	.stat-number {
+		font-size: 2.5em;
+		font-weight: bold;
+		color: #3498db;
+		margin-bottom: 10px;
+	}
+
+	.stat-label {
+		color: #7f8c8d;
+		font-size: 0.9em;
+		margin-bottom: 15px;
+	}
+
+	.charts-section {
+		display: grid;
+		grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
+		gap: 25px;
+		margin-bottom: 30px;
+	}
+
+	.chart-container {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.chart-container h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	.chart {
+		height: 400px;
+		width: 100%;
+	}
+
+	.data-table {
+		background: rgba(255, 255, 255, 0.95);
+		backdrop-filter: blur(10px);
+		border-radius: 15px;
+		padding: 25px;
+		margin-bottom: 30px;
+		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+	}
+
+	.data-table h3 {
+		color: #2c3e50;
+		margin-bottom: 20px;
+		font-size: 1.5em;
+	}
+
+	.progress-container {
+		display: flex;
+		align-items: center;
+		gap: 10px;
+	}
+
+	.time-point {
+		display: inline-block;
+		background: #e74c3c;
+		color: white;
+		padding: 2px 8px;
+		border-radius: 12px;
+		font-size: 0.8em;
+		margin: 2px;
+	}
+
+	.completion-rate {
+		color: #27ae60;
+		font-weight: bold;
+	}
+
+	.low-engagement {
+		color: #e74c3c;
+		font-weight: bold;
+	}
+
+	@media (max-width: 768px) {
+		.stats-grid {
+			grid-template-columns: 1fr;
+		}
+
+		.charts-section {
+			grid-template-columns: 1fr;
+		}
+
+		.filter-controls {
+			grid-template-columns: 1fr;
+		}
+
+		.header h1 {
+			font-size: 2em;
+		}
+	}
+</style>