Sfoglia il codice sorgente

保存完了 带统计的

于添 5 mesi fa
parent
commit
4d5d0f826f

+ 10 - 306
src/api/statisticalAnalysis/analysisTeachingActivities.js

@@ -9,48 +9,6 @@ Mock.setup({
 	timeout: '200-600'
 })
 
-// 课程选项数据
-const courseOptions = [
-	{ value: '', label: '全部课程' },
-	{ value: 'course1', label: 'JavaScript基础教程' },
-	{ value: 'course2', label: 'Python数据分析' },
-	{ value: 'course3', label: 'React前端开发' },
-	{ value: 'course4', label: '机器学习入门' },
-	{ value: 'course5', label: 'Vue.js实战开发' },
-	{ value: 'course6', label: 'Node.js后端开发' }
-]
-
-// 生成日期数据
-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, courseId = '') => {
-	const data = []
-	// 全部课程的访问量应该比单个课程高
-	const courseMultiplier = courseId ? 0.15 + Math.random() * 0.25 : 1.0
-
-	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 ? 450 : 680
-		const randomFactor = 0.7 + Math.random() * 0.6
-		const finalValue = Math.round(baseValue * randomFactor * courseMultiplier)
-		data.push(finalValue)
-	}
-	return data
-}
 
 // 讨论数据 - 这是全部课程的汇总讨论数据
 const discussionData = [
@@ -176,197 +134,6 @@ const discussionData = [
 	}
 ]
 
-// 文档数据 - 这是全部课程的汇总数据,数量较大
-const documentData = [
-	{
-		id: 1,
-		name: 'JavaScript基础语法',
-		type: 'PDF文档',
-		viewCount: 4856,
-		completedCount: 3234,
-		completionRate: 66.5,
-		avgReadTime: '25:30',
-		exitRate: 24.6,
-		downloadCount: 1456
-	},
-	{
-		id: 2,
-		name: 'Python数据分析入门',
-		type: '在线文档',
-		viewCount: 3234,
-		completedCount: 2587,
-		completionRate: 80.0,
-		avgReadTime: '32:15',
-		exitRate: 18.5,
-		downloadCount: 1234
-	},
-	{
-		id: 3,
-		name: 'React组件开发指南',
-		type: 'PDF文档',
-		viewCount: 2987,
-		completedCount: 2289,
-		completionRate: 76.6,
-		avgReadTime: '28:45',
-		exitRate: 22.3,
-		downloadCount: 989
-	},
-	{
-		id: 4,
-		name: '机器学习算法详解',
-		type: '在线文档',
-		viewCount: 2756,
-		completedCount: 1908,
-		completionRate: 69.2,
-		avgReadTime: '45:20',
-		exitRate: 30.8,
-		downloadCount: 823
-	},
-	{
-		id: 5,
-		name: '前端工程化实践',
-		type: 'PDF文档',
-		viewCount: 2523,
-		completedCount: 1665,
-		completionRate: 66.0,
-		avgReadTime: '38:15',
-		exitRate: 34.0,
-		downloadCount: 689
-	},
-	{
-		id: 6,
-		name: 'Vue.js进阶开发',
-		type: '在线文档',
-		viewCount: 2678,
-		completedCount: 1802,
-		completionRate: 67.3,
-		avgReadTime: '35:40',
-		exitRate: 32.7,
-		downloadCount: 756
-	},
-	{
-		id: 7,
-		name: 'Node.js后端开发',
-		type: 'PDF文档',
-		viewCount: 2345,
-		completedCount: 1567,
-		completionRate: 66.8,
-		avgReadTime: '42:10',
-		exitRate: 28.9,
-		downloadCount: 634
-	},
-	{
-		id: 8,
-		name: '数据库设计原理',
-		type: '在线文档',
-		viewCount: 2123,
-		completedCount: 1489,
-		completionRate: 70.1,
-		avgReadTime: '38:25',
-		exitRate: 26.4,
-		downloadCount: 567
-	},
-	{
-		id: 9,
-		name: 'Web安全防护',
-		type: 'PDF文档',
-		viewCount: 1987,
-		completedCount: 1345,
-		completionRate: 67.7,
-		avgReadTime: '33:50',
-		exitRate: 29.8,
-		downloadCount: 498
-	},
-	{
-		id: 10,
-		name: '移动端开发实战',
-		type: '在线文档',
-		viewCount: 1876,
-		completedCount: 1234,
-		completionRate: 65.8,
-		avgReadTime: '40:15',
-		exitRate: 31.2,
-		downloadCount: 445
-	}
-]
-
-// 生成课程选项数据
-const generateCourseOptions = () => {
-	return {
-		code: 200,
-		message: '获取成功',
-		data: courseOptions
-	}
-}
-
-// 生成核心统计数据
-const generateStatsData = (options) => {
-	const urlParts = options.url.split('?')
-	const params = urlParts.length > 1 ? new URLSearchParams(urlParts[1]) : new URLSearchParams()
-	const courseId = params.get('courseId') || ''
-	const timeRange = parseInt(params.get('timeRange')) || 30
-
-	// 全部课程的数据应该是所有课程的总和,单个课程数据相对较少
-	const baseMultiplier = courseId ? 0.15 + Math.random() * 0.25 : 1.0 // 单个课程占总数的15%-40%
-	const timeMultiplier = timeRange / 30
-
-	// 基础数据 - 全部课程的总数据
-	const baseStats = {
-		totalDocViewers: 8560,
-		completedDocViewers: 6234,
-		totalDocExits: 1890,
-		totalDiscussions: 1456,
-		totalReplies: 8934
-	}
-
-	const calculatedStats = {
-		totalDocViewers: Math.round(baseStats.totalDocViewers * baseMultiplier * timeMultiplier),
-		completedDocViewers: Math.round(baseStats.completedDocViewers * baseMultiplier * timeMultiplier),
-		totalDocExits: Math.round(baseStats.totalDocExits * baseMultiplier * timeMultiplier),
-		totalDiscussions: Math.round(baseStats.totalDiscussions * baseMultiplier * timeMultiplier),
-		totalReplies: Math.round(baseStats.totalReplies * baseMultiplier * timeMultiplier)
-	}
-
-	// 确保完成人数不超过总观看人数
-	if (calculatedStats.completedDocViewers > calculatedStats.totalDocViewers) {
-		calculatedStats.completedDocViewers = Math.round(calculatedStats.totalDocViewers * 0.7)
-	}
-
-	// 计算完成率
-	const docCompletionRate =
-		calculatedStats.totalDocViewers > 0
-			? parseFloat(((calculatedStats.completedDocViewers / calculatedStats.totalDocViewers) * 100).toFixed(1))
-			: 0
-
-	// 计算跳出率 - 单个课程跳出率可能更高
-	const baseExitRate = courseId ? 25 + Math.random() * 15 : 18 + Math.random() * 12
-	const docExitRate = parseFloat(baseExitRate.toFixed(1))
-
-	// 计算平均回帖数
-	const avgRepliesPerDiscussion =
-		calculatedStats.totalDiscussions > 0
-			? parseFloat((calculatedStats.totalReplies / calculatedStats.totalDiscussions).toFixed(1))
-			: 0
-
-	return {
-		code: 200,
-		message: '获取成功',
-		data: {
-			totalDocViewers: calculatedStats.totalDocViewers,
-			completedDocViewers: calculatedStats.completedDocViewers,
-			docCompletionRate,
-			totalDocExits: calculatedStats.totalDocExits,
-			docExitRate,
-			avgDocExitTime: `${String(Math.floor(Math.random() * 15) + 8).padStart(2, '0')}:${String(
-				Math.floor(Math.random() * 60)
-			).padStart(2, '0')}`,
-			totalDiscussions: calculatedStats.totalDiscussions,
-			totalReplies: calculatedStats.totalReplies,
-			avgRepliesPerDiscussion
-		}
-	}
-}
-
 // 生成每周统计数据
 const generateWeeklyStatsData = (options) => {
 	const urlParts = options.url.split('?')
@@ -405,26 +172,6 @@ const generateWeeklyStatsData = (options) => {
 	}
 }
 
-// 生成每日访问数据
-const generateDailyVisitsData = (options) => {
-	const urlParts = options.url.split('?')
-	const params = urlParts.length > 1 ? new URLSearchParams(urlParts[1]) : new URLSearchParams()
-	const courseId = params.get('courseId') || ''
-	const timeRange = parseInt(params.get('timeRange')) || 30
-
-	const dates = generateDateData(timeRange)
-	const visits = generateVisitData(timeRange, courseId)
-
-	return {
-		code: 200,
-		message: '获取成功',
-		data: {
-			dates,
-			visits
-		}
-	}
-}
-
 // 生成讨论数据
 const generateDiscussionData = (options) => {
 	const urlParts = options.url.split('?')
@@ -456,72 +203,29 @@ const generateDiscussionData = (options) => {
 	}
 }
 
-// 生成文档数据
-const generateDocumentData = (options) => {
-	const urlParts = options.url.split('?')
-	const params = urlParts.length > 1 ? new URLSearchParams(urlParts[1]) : new URLSearchParams()
-	const courseId = params.get('courseId') || ''
-	const page = parseInt(params.get('page')) || 1
-	const pageSize = parseInt(params.get('pageSize')) || 10
-
-	let filteredData = [...documentData]
-
-	if (courseId) {
-		// 单个课程只显示该课程相关的文档,数量相对较少
-		const courseDocumentCount = Math.floor(documentData.length * (0.25 + Math.random() * 0.35)) // 25%-60%
-		filteredData = documentData.slice(0, Math.max(courseDocumentCount, 3)) // 至少显示3条
-
-		// 调整单个课程文档的数据,使其相对较小但合理
-		filteredData = filteredData.map((doc) => ({
-			...doc,
-			viewCount: Math.round(doc.viewCount * (0.15 + Math.random() * 0.25)), // 15%-40%的观看量
-			completedCount: Math.round(doc.completedCount * (0.15 + Math.random() * 0.25)),
-			downloadCount: Math.round(doc.downloadCount * (0.15 + Math.random() * 0.25)),
-			// 完成率和跳出率保持相对合理的范围
-			completionRate: parseFloat((doc.completionRate + (Math.random() - 0.5) * 10).toFixed(1)),
-			exitRate: parseFloat((doc.exitRate + (Math.random() - 0.5) * 8).toFixed(1))
-		}))
-	}
-
-	const startIndex = (page - 1) * pageSize
-	const endIndex = startIndex + pageSize
-	const pageData = filteredData.slice(startIndex, endIndex)
-
-	return {
-		code: 200,
-		message: '获取成功',
-		data: {
-			list: pageData,
-			total: filteredData.length,
-			page,
-			pageSize
-		}
-	}
-}
-
 // Mock 接口定义
-Mock.mock(/\/api\/webapp\/teaching-analysis\/course-options/, 'get', generateCourseOptions)
-Mock.mock(/\/api\/webapp\/teaching-analysis\/stats/, 'get', generateStatsData)
 Mock.mock(/\/api\/webapp\/teaching-analysis\/weekly-stats/, 'get', generateWeeklyStatsData)
-Mock.mock(/\/api\/webapp\/teaching-analysis\/daily-visits/, 'get', generateDailyVisitsData)
 Mock.mock(/\/api\/webapp\/teaching-analysis\/discussions/, 'get', generateDiscussionData)
-Mock.mock(/\/api\/webapp\/teaching-analysis\/documents/, 'get', generateDocumentData)
 
 // 导出的API函数
 export const getCourseOptions = (params = {}) => {
-	return request('teaching-analysis/course-options', params, 'get')
+	return request('disk/courseinfo/allList', params, 'get')
 }
-
+// 文档观看统计
 export const getTeachingStats = (params = {}) => {
-	return request('teaching-analysis/stats', params, 'get')
+	return request('teachingActivity/documentStatistic', params, 'get')
+}
+// 文档跳出分析
+export const documentJumpStatistic = (params = {}) => {
+	return request('teachingActivity/documentJumpStatistic', params, 'get')
 }
 
 export const getWeeklyStats = (params = {}) => {
 	return request('teaching-analysis/weekly-stats', params, 'get')
 }
-
+// 开课每日访问人数统计
 export const getDailyVisits = (params = {}) => {
-	return request('teaching-analysis/daily-visits', params, 'get')
+	return request('teachingActivity/courseOpenStatistic', params, 'get')
 }
 
 export const getDiscussionData = (params = {}) => {
@@ -529,5 +233,5 @@ export const getDiscussionData = (params = {}) => {
 }
 
 export const getDocumentStats = (params = {}) => {
-	return request('teaching-analysis/documents', params, 'get')
+	return request('teachingActivity/documentDetailStatistic', params, 'get')
 }

+ 161 - 259
src/api/statisticalAnalysis/overviewLearningProgress.js

@@ -1,272 +1,174 @@
-// 文件模块相关接口
+// 学习进度统计分析相关接口
 import { moduleRequest } from '@/utils/request'
-import Mock from 'mockjs'
 
-const request = moduleRequest(`/api/webapp`)
-
-// Mock 数据配置
-Mock.setup({
-	timeout: '200-600'
-})
-
-// 课程名称列表
-const courseNames = [
-	'Python编程入门',
-	'数据结构与算法',
-	'机器学习基础',
-	'Web前端开发',
-	'Java后端开发',
-	'数据库设计',
-	'算法分析',
-	'人工智能导论',
-	'计算机网络',
-	'操作系统原理',
-	'软件工程',
-	'计算机图形学',
-	'编译原理',
-	'分布式系统',
-	'云计算技术'
-]
-
-// 生成完整的课程数据集(用于分页)
-const generateFullCourseData = () => {
-	return courseNames.map((courseName, index) => ({
-		id: index + 1,
-		courseName,
-		studentCount: Mock.Random.integer(80, 150),
-		visitCount: Mock.Random.integer(800, 2000),
-		videoDuration: Mock.Random.pick(['3h25m', '4h12m', '5h30m', '6h45m', '2h58m', '7h20m', '8h15m', '9h30m']),
-		documentVisit: Mock.Random.integer(300, 800),
-		submissionCount: Mock.Random.integer(70, 95),
-		numberStudentsDroppingCourses: Mock.Random.integer(5, 25)
-	}))
-}
-
-// 全局存储完整数据集
-let fullCourseData = generateFullCourseData()
-
-// 根据筛选条件调整数据
-const adjustDataByFilters = (data, courseName, contentType) => {
-	return data.map((item) => {
-		let adjustedItem = { ...item }
-
-		// 根据课程名称筛选调整数据
-		if (courseName && courseName !== '' && item.courseName !== courseName) {
-			// 如果不是选中的课程,数据为0或很小
-			adjustedItem.studentCount = 0
-			adjustedItem.visitCount = 0
-			adjustedItem.documentVisit = 0
-			adjustedItem.submissionCount = 0
-			adjustedItem.numberStudentsDroppingCourses = 0
-			adjustedItem.videoDuration = '0h0m'
-		} else if (courseName && courseName !== '' && item.courseName === courseName) {
-			// 如果是选中的课程,保持原数据或稍微增加
-			adjustedItem.studentCount = item.studentCount
-			adjustedItem.visitCount = item.visitCount
-			adjustedItem.documentVisit = item.documentVisit
-			adjustedItem.submissionCount = item.submissionCount
-		}
-
-		// 根据内容类型调整数据
-		if (contentType && contentType !== 'all') {
-			const reductionFactor = 0.6 // 具体类型的数据是全部的60%
-			switch (contentType) {
-				case 'video':
-					adjustedItem.visitCount = Math.floor(adjustedItem.visitCount * reductionFactor)
-					adjustedItem.documentVisit = Math.floor(adjustedItem.documentVisit * 0.3)
-					break
-				case 'document':
-					adjustedItem.documentVisit = Math.floor(adjustedItem.documentVisit * reductionFactor)
-					adjustedItem.visitCount = Math.floor(adjustedItem.visitCount * 0.4)
-					break
-				case 'exercise':
-					adjustedItem.submissionCount = Math.floor(adjustedItem.submissionCount * reductionFactor)
-					adjustedItem.visitCount = Math.floor(adjustedItem.visitCount * 0.3)
-					adjustedItem.documentVisit = Math.floor(adjustedItem.documentVisit * 0.2)
-					break
-			}
-		}
-
-		return adjustedItem
-	})
-}
-
-// 生成分页的课程列表数据
-const generateCourseList = (options) => {
-	// 解析查询参数
-	const url = new URL('http://localhost' + options.url)
-	const current = parseInt(url.searchParams.get('current')) || 1
-	const pageSize = parseInt(url.searchParams.get('pageSize')) || 6
-	const courseName = url.searchParams.get('courseName') || ''
-	const contentType = url.searchParams.get('contentType') || 'all'
-
-	// 根据筛选条件调整数据
-	let filteredData = adjustDataByFilters(fullCourseData, courseName, contentType)
-
-	// 如果选择了特定课程,只显示该课程
-	if (courseName && courseName !== '') {
-		filteredData = filteredData.filter((item) => item.courseName === courseName)
-	}
-
-	// 计算分页
-	const startIndex = (current - 1) * pageSize
-	const endIndex = startIndex + pageSize
-	const pageData = filteredData.slice(startIndex, endIndex)
-
-	return {
-		code: 200,
-		data: {
-			data: pageData,
-			total: filteredData.length,
-			current: current,
-			pageSize: pageSize
-		}
-	}
-}
-
-// 生成统计概览数据
-const generateOverviewStats = (options) => {
-	// 解析查询参数
-	const url = new URL('http://localhost' + options.url)
-	const courseName = url.searchParams.get('courseName') || ''
-	const contentType = url.searchParams.get('contentType') || 'all'
-
-	// 基础数据
-	let baseStats = {
-		totalStudents: 2846,
-		totalVisits: 12587,
-		totalSubmissions: 1924,
-		totalInteractions: 5362
-	}
-
-	// 根据课程名称调整数据
-	if (courseName && courseName !== '') {
-		// 选择特定课程时,数据减少到20-30%
-		baseStats.totalStudents = Math.floor(baseStats.totalStudents * Mock.Random.float(0.2, 0.3))
-		baseStats.totalVisits = Math.floor(baseStats.totalVisits * Mock.Random.float(0.2, 0.3))
-		baseStats.totalSubmissions = Math.floor(baseStats.totalSubmissions * Mock.Random.float(0.2, 0.3))
-		baseStats.totalInteractions = Math.floor(baseStats.totalInteractions * Mock.Random.float(0.2, 0.3))
-	}
-
-	// 根据内容类型调整数据
-	if (contentType && contentType !== 'all') {
-		const reductionFactor = 0.65 // 具体类型是全部的65%
-		switch (contentType) {
-			case 'video':
-				baseStats.totalVisits = Math.floor(baseStats.totalVisits * reductionFactor)
-				baseStats.totalSubmissions = Math.floor(baseStats.totalSubmissions * 0.3)
-				break
-			case 'document':
-				baseStats.totalVisits = Math.floor(baseStats.totalVisits * 0.4)
-				baseStats.totalSubmissions = Math.floor(baseStats.totalSubmissions * 0.2)
-				break
-			case 'exercise':
-				baseStats.totalSubmissions = Math.floor(baseStats.totalSubmissions * reductionFactor)
-				baseStats.totalVisits = Math.floor(baseStats.totalVisits * 0.3)
-				break
-		}
-	}
-
-	return {
-		code: 200,
-		data: baseStats
-	}
-}
-
-// 生成趋势图数据
-const generateTrendData = (options) => {
-	// 解析查询参数
-	const url = new URL('http://localhost' + options.url)
-	const courseName = url.searchParams.get('courseName') || ''
-	const contentType = url.searchParams.get('contentType') || 'all'
-
-	// 基础趋势数据
-	let baseVisitTrend = [2400, 2100, 2600, 2300, 2800, 2200, 2500]
-	let baseSubmissionTrend = [85, 78, 92, 88, 95, 82, 90]
-
-	// 根据课程名称调整数据
-	if (courseName && courseName !== '') {
-		baseVisitTrend = baseVisitTrend.map((val) => Math.floor(val * Mock.Random.float(0.25, 0.35)))
-		baseSubmissionTrend = baseSubmissionTrend.map((val) => Math.floor(val * Mock.Random.float(0.25, 0.35)))
-	}
-
-	// 根据内容类型调整数据
-	if (contentType && contentType !== 'all') {
-		const reductionFactor = 0.6
-		switch (contentType) {
-			case 'video':
-				baseVisitTrend = baseVisitTrend.map((val) => Math.floor(val * reductionFactor))
-				baseSubmissionTrend = baseSubmissionTrend.map((val) => Math.floor(val * 0.3))
-				break
-			case 'document':
-				baseVisitTrend = baseVisitTrend.map((val) => Math.floor(val * 0.4))
-				baseSubmissionTrend = baseSubmissionTrend.map((val) => Math.floor(val * 0.2))
-				break
-			case 'exercise':
-				baseSubmissionTrend = baseSubmissionTrend.map((val) => Math.floor(val * reductionFactor))
-				baseVisitTrend = baseVisitTrend.map((val) => Math.floor(val * 0.3))
-				break
-		}
-	}
-
-	return {
-		code: 200,
-		data: {
-			dates: ['4日', '5日', '6日', '7日', '8日', '9日', '10日'],
-			visitTrend: baseVisitTrend,
-			submissionTrend: baseSubmissionTrend
-		}
-	}
-}
-
-// 生成课程选项数据
-const generateCourseOptions = () => {
-	const options = courseNames.slice(0, 10).map((courseName, index) => ({
-		id: index + 1,
-		courseName
-	}))
-
-	return {
-		code: 200,
-		data: options
-	}
-}
-// Mock 接口定义 - 使用更宽松的正则表达式匹配
-Mock.mock(/\/api\/webapp\/?\/overview\/stats/, 'get', (options) => {
-	return generateOverviewStats(options)
-})
-
-Mock.mock(/\/api\/webapp\/?\/overview\/trend/, 'get', (options) => {
-	return generateTrendData(options)
-})
-
-Mock.mock(/\/api\/webapp\/?\/overview\/courses/, 'get', (options) => {
-	return generateCourseList(options)
-})
-
-Mock.mock(/\/api\/webapp\/?\/overview\/course-options/, 'get', () => {
-	return generateCourseOptions()
-})
+const request = moduleRequest('/api/webapp')
 
 // 导出的API函数
 export const overviewLearningProgressApi = {
-	// 获取统计概览数据
-	getOverviewStats(params = {}) {
-		return request('/overview/stats', params, 'get')
+	// 获取学习进度顶部基本数据
+	getTopFundamentalDetail(params = {}) {
+		return request('/disk/learningprogress/topFundamentalDetail', params, 'get')
 	},
 
-	// 获取趋势数据
-	getTrendData(params = {}) {
-		return request('/overview/trend', params, 'get')
+	// 获取访问人数趋势
+	getViewTendency(params = {}) {
+		return request('/disk/learningprogress/viewTendency', params, 'get')
 	},
 
-	// 获取课程列表数据
-	getCourseList(params = {}) {
-		return request('/overview/courses', params, 'get')
+	// 获取练习平均提交数趋势
+	getPaperSubmitTendency(params = {}) {
+		return request('/disk/learningprogress/paperSubmeitTendency', params, 'get')
 	},
 
-	// 获取课程选项
-	getCourseOptions() {
-		return request('/overview/course-options', '', 'get')
+	// 获取学习明细数据
+	getStudyDetail(params = {}) {
+		return request('/disk/learningprogress/studyDetail', params, 'get')
 	}
 }
+
+/**
+ * 真是接口文档
+ * 
+	学习进度-顶部基本数据
+	/disk/learningprogress/topFundamentalDetail?courseId=&startTime=&endTime=
+	Query请求参数
+
+参数名	参数值	是否必填	参数类型	描述
+courseId	-	否	string	
+课程id
+startTime	-	否	string	
+开始时间
+endTime	-	否	string	
+结束时间
+
+返回数据:
+courseOpenStuNum开课人数
+courseViewNum课程访问次数
+paperSubmitNum提交数(作业、测验)
+interactionNum互动数(发帖/回帖),这个数据先写假的
+
+
+
+----------------
+学习进度-访问人数趋势
+/disk/learningprogress/viewTendency?courseId=&startTime=&endTime=
+Query请求参数
+
+参数名	参数值	是否必填	参数类型	描述
+courseId	-	否	string	
+课程id
+startTime	-	否	string	
+开始时间
+endTime	-	否	string	
+结束时间
+
+返回数据:
+month月份
+viewTendencyNum访问人数
+
+
+--------------------
+学习进度-练习平均提交数
+/disk/learningprogress/paperSubmeitTendency?courseId=&startTime=&endTime=
+Query请求参数
+
+参数名	参数值	是否必填	参数类型	描述
+courseId	-	否	string	
+课程id
+startTime	-	否	string	
+开始时间
+endTime	-	否	string	
+结束时间
+
+返回数据:
+month月份
+SubmeitTendency提交数
+
+
+
+-------------------
+学习进度-学习明细数据
+/disk/learningprogress/studyDetail?courseId=&startTime=&endTime=
+Query请求参数
+
+参数名	参数值	是否必填	参数类型	描述
+courseId	-	否	string	
+课程id
+startTime	-	否	string	
+开始时间
+endTime	-	否	string	
+结束时间
+
+返回数据:
+courseId课程id
+courseName课程名称
+openStuNum开课人数
+viewCount课程访问量
+stayTime讲义访问量
+teachMaterialsNum练习提交量
+ */
+/**
+
+ * 真实接口文档
+ * 
+ * 学习进度-顶部基本数据
+ * /disk/learningprogress/topFundamentalDetail?courseId=&startTime=&endTime=
+ * Query请求参数
+ * 
+ * 参数名	参数值	是否必填	参数类型	描述
+ * courseId	-	否	string	课程id
+ * startTime	-	否	string	开始时间
+ * endTime	-	否	string	结束时间
+ * 
+ * 返回数据:
+ * courseOpenStuNum 开课人数
+ * courseViewNum 课程访问次数
+ * paperSubmitNum 提交数(作业、测验)
+ * interactionNum 互动数(发帖/回帖),这个数据先写假的
+ * 
+ * ----------------
+ * 学习进度-访问人数趋势
+ * /disk/learningprogress/viewTendency?courseId=&startTime=&endTime=
+ * Query请求参数
+ * 
+ * 参数名	参数值	是否必填	参数类型	描述
+ * courseId	-	否	string	课程id
+ * startTime	-	否	string	开始时间
+ * endTime	-	否	string	结束时间
+ * 
+ * 返回数据:
+ * month 月份
+ * viewTendencyNum 访问人数
+ * 
+ * --------------------
+ * 学习进度-练习平均提交数
+ * /disk/learningprogress/paperSubmeitTendency?courseId=&startTime=&endTime=
+ * Query请求参数
+ * 
+ * 参数名	参数值	是否必填	参数类型	描述
+ * courseId	-	否	string	课程id
+ * startTime	-	否	string	开始时间
+ * endTime	-	否	string	结束时间
+ * 
+ * 返回数据:
+ * month 月份
+ * SubmeitTendency 提交数
+ * 
+ * -------------------
+ * 学习进度-学习明细数据
+ * /disk/learningprogress/studyDetail?courseId=&startTime=&endTime=
+ * Query请求参数
+ * 
+ * 参数名	参数值	是否必填	参数类型	描述
+ * courseId	-	否	string	课程id
+ * startTime	-	否	string	开始时间
+ * endTime	-	否	string	结束时间
+ * 
+ * 返回数据:
+ * courseId 课程id
+ * courseName 课程名称
+ * openStuNum 开课人数
+ * viewCount 课程访问量
+ * stayTime 讲义访问量
+ * teachMaterialsNum 练习提交量
+ */

+ 211 - 61
src/api/statisticalAnalysis/platformStatusOverview.js

@@ -1,5 +1,6 @@
 // 平台状态总览相关接口
-import { moduleRequest } from '@/utils/request'
+import {moduleRequest} from '@/utils/request'
+import ForEach from "lodash-es/forEach";
 
 const request = moduleRequest(`/api/webapp/`)
 
@@ -131,76 +132,225 @@ const mockData = {
 }
 
 // 获取平台统计数据
-export const getPlatformStats = () => {
-	// 模拟异步请求
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			resolve(mockData.platformStats)
-		}, 300)
-	})
+export const getPlatformStats = async (params) => {
+	// // 模拟异步请求
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		resolve(mockData.platformStats)
+	// 	}, 300)
+	// })
+
+	let systemStatus = await request('platformStatusOverview/systemStatus', params, 'get')
+	console.log('010', systemStatus)
+
+	// 平台统计数据
+	let json = {
+		code: 200,
+		message: '获取成功',
+		data: {
+			totalCourses: systemStatus.COURSE_TOTAL,
+			openedCourses: systemStatus.COURSE_OPEN_TOTAL,
+			totalTeachers: systemStatus.TEACHER_TOTAL,
+			totalStudents: systemStatus.STUDENT_TOTAL
+		}
+	}
+
+	return json
 }
 
 // 获取热门课程列表
-export const getHotCourses = () => {
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			resolve(mockData.hotCourses)
-		}, 300)
+export const getHotCourses = async (params) => {
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		resolve(mockData.hotCourses)
+	// 	}, 300)
+	// })
+
+	let popularCourses = await request('platformStatusOverview/popularCourses', params, 'get')
+	console.log('011', popularCourses)
+	let data = []
+	// COLLECT_COUNT:1
+	// COURSE_ID:"1955176675276976130"
+	// COURSE_NAME:"机电实训楼"
+	// TEACHER_NAME:"王五"
+	// VIEW_COUNT:289
+	ForEach(popularCourses.popularCourses, (item) => {
+		data.push({
+			id: item.COURSE_ID,
+			rank: 1,
+			name: item.COURSE_NAME,
+			teacher: item.TEACHER_NAME,
+			visits: item.VIEW_COUNT,
+			references: item.COLLECT_COUNT
+		})
 	})
-}
 
+
+// 热门课程数据
+// 	hotCourses: {
+// 		code: 200,
+// 			message: '获取成功',
+// 			data: [
+// 			{
+// 				id: 1,
+// 				rank: 1,
+// 				name: 'Python数据分析',
+// 				teacher: '王老师',
+// 				visits: '2,345',
+// 				references: 56
+// 			},
+	// 平台统计数据
+	let json = {
+		code: 200,
+		message: '获取成功',
+		data
+	}
+
+	return json
+}
+function timestampToYYYYMMDD(timestamp) {
+	let date
+	if(timestamp == undefined){
+		date = new Date();
+		return date.toISOString().split('T')[0];
+	}
+	 date = new Date(timestamp);
+	return date.toISOString().split('T')[0];
+}
 // 获取开课信息列表
-export const getCourseInfo = (params = {}) => {
-	const { current = 1, size = 10 } = params
-
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			const response = {
-				...mockData.courseInfo,
-				data: {
-					...mockData.courseInfo.data,
-					current,
-					size
-				}
-			}
-			resolve(response)
-		}, 300)
+export const getCourseInfo = async (params = {}) => {
+	const {current = 1, size = 10} = params
+
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		const response = {
+	// 			...mockData.courseInfo,
+	// 			data: {
+	// 				...mockData.courseInfo.data,
+	// 				current,
+	// 				size
+	// 			}
+	// 		}
+	// 		resolve(response)
+	// 	}, 300)
+	// })
+	let allCourses = await request('platformStatusOverview/allCourses', params, 'get')
+	console.log('022', allCourses)
+	let records = []
+	ForEach(allCourses.allCourses, (item) => {
+		records.push({
+			id: item.COURSE_ID,
+			name: item.COURSE_NAME,
+			teacher: item.TEACHER_NAME,
+			startDate: timestampToYYYYMMDD(item.START_TIME),
+			studentCount: item.STUDENT_COUNT,
+			visits: item.VIEW_COUNT,
+		})
 	})
+	let json = {
+		code: 200,
+		message: '获取成功',
+		data : {
+			records,
+			total: 5,
+			current: 1,
+			size: 10
+		},
+
+	}
+
+	return json
+	// data: {
+	// 	records: [
+	// 		{
+	// 			id: 1,
+	// 			name: 'Python数据分析',
+	// 			teacher: '王老师',
+	// 			startDate: '2024-03-01',
+	// 			studentCount: 320,
+	// 			visits: '2,345'
+	// 		},
+	// 	],
+	// 		total: 5,
+	// 		current: 1,
+	// 		size: 10
+	// }
+
+
+
+	// {
+	// 	"TEACHER_ID": "1935565895337304066",
+	// 	"TEACHER_NAME": "王五",
+	// 	"VIEW_COUNT": 34,
+	// 	"COURSE_ID": "1954728193252552705",
+	// 	"STUDENT_COUNT": 0,
+	// 	"ID": "1954819544520286208",
+	// 	"COURSE_NAME": "农业课"
+	// }
+
+
 }
 
 // 获取课程访问统计
-export const getCourseVisitStats = (params) => {
-	const { courseName } = params
-
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			// 生成近7天的日期
-			const days = []
-			const today = new Date()
-			for (let i = 6; i >= 0; i--) {
-				const date = new Date(today)
-				date.setDate(date.getDate() - i)
-				const month = (date.getMonth() + 1).toString().padStart(2, '0')
-				const day = date.getDate().toString().padStart(2, '0')
-				days.push(`${month}-${day}`)
-			}
+export const getCourseVisitStats = async (params) => {
+	const {courseId} = params
 
-			// 生成模拟访问数据
-			const baseVisits = [120, 156, 178, 210, 234, 245, 267]
-			const visitData = baseVisits.map((base) => {
-				const randomFactor = 0.8 + Math.random() * 0.4
-				return Math.round(base * randomFactor)
-			})
-
-			const response = {
-				...mockData.courseVisitStats,
-				data: {
-					courseName,
-					visitData,
-					dateRange: days
-				}
-			}
-			resolve(response)
-		}, 300)
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		// 生成近7天的日期
+	// 		const days = []
+	// 		const today = new Date()
+	// 		for (let i = 6; i >= 0; i--) {
+	// 			const date = new Date(today)
+	// 			date.setDate(date.getDate() - i)
+	// 			const month = (date.getMonth() + 1).toString().padStart(2, '0')
+	// 			const day = date.getDate().toString().padStart(2, '0')
+	// 			days.push(`${month}-${day}`)
+	// 		}
+	//
+	// 		// 生成模拟访问数据
+	// 		const baseVisits = [120, 156, 178, 210, 234, 245, 267]
+	// 		const visitData = baseVisits.map((base) => {
+	// 			const randomFactor = 0.8 + Math.random() * 0.4
+	// 			return Math.round(base * randomFactor)
+	// 		})
+	//
+	// 		const response = {
+	// 			...mockData.courseVisitStats,
+	// 			data: {
+	// 				courseId,
+	// 				visitData,
+	// 				dateRange: days
+	// 			}
+	// 		}
+	// 		resolve(response)
+	// 	}, 300)
+	// })
+	let courseVisitTrend = await request('platformStatusOverview/courseVisitTrend', params, 'get')
+	console.log('033', courseVisitTrend)
+	const days = []
+	const today = new Date()
+	for (let i = 6; i >= 0; i--) {
+		const date = new Date(today)
+		date.setDate(date.getDate() - i)
+		const month = (date.getMonth() + 1).toString().padStart(2, '0')
+		const day = date.getDate().toString().padStart(2, '0')
+		days.push(`${month}-${day}`)
+	}
+	let visitData = []
+	ForEach(courseVisitTrend.visitTrend, (item) => {
+		visitData.push(item.visitCount)
 	})
+	let json = {
+		code: 200,
+		message: '获取成功',
+		data : {
+			courseId,
+			visitData,
+			dateRange: days
+		},
+
+	}
+
+	return json
 }

+ 345 - 39
src/api/statisticalAnalysis/statisticalAnalysisResourceLibrary.js

@@ -1,5 +1,6 @@
-import { moduleRequest } from '@/utils/request'
+import {moduleRequest} from '@/utils/request'
 import Mock from 'mockjs'
+import ForEach from "lodash-es/forEach";
 
 const request = moduleRequest(`/api/webapp/`)
 
@@ -116,6 +117,7 @@ const generateMockData = (filters = {}) => {
 	const formatCounts = generateFormatCounts()
 
 	return {
+		filterResponse: getFilterData(),
 		// 摘要数据
 		summaryData: {
 			code: 200,
@@ -233,73 +235,377 @@ const generateMockData = (filters = {}) => {
 }
 
 // API函数 - 每次调用都生成新的动态数据,传入筛选参数
-export const getSummaryData = (params = {}) => {
+export const getSummaryData = async (params = {}) => {
 	// return new Promise((resolve) => {
 	// 	setTimeout(() => {
 	// 		const mockData = generateMockData(params)
 	// 		resolve(mockData.summaryData)
 	// 	}, Mock.mock('@integer(200, 500)')) // 随机延迟
 	// })
+
+	let res = await request('/resourceStatistic/totalStatistic', params, 'get')
+	console.log('什么呢1233', res)
+	let json = {
+		code: 200,
+		data: {
+			totalResources: res.RESOURCE_TOTAL,
+			totalStorage: `${kbToTb(res.storageSize)}TB`,
+			totalCapacity: `${kbToTb(res.totalStorageSize)}TB`,
+			usageRate: `${((parseFloat(res.storageSize) / res.totalStorageSize) * 100).toFixed(0)}%`,
+			totalViews: res.WATCH_TOTAL,
+			totalFavorites: res.COLLECT_TOTAL
+		}
+	}
+	// {
+	// 	"RESOURCE_TOTAL": 34,  总资源数
+	// 	"TOTAL_STORAGE_SIZE": 20480, 总存储空间
+	// 	"COLLECT_TOTAL": 9, 总收藏数
+	// 	"WATCH_TOTAL": 471, 总观看数
+	// 	"storageSize": 1726487824,
+	// 	"totalStorageSize": 21474836480
+	// }
+	// totalResources: '0',
+	// totalStorage: '0 TB',
+	// totalCapacity: '10 TB',
+	// usageRate: '0%',
+	// totalViews: '0',
+	// totalFavorites: '0'
 	// 真实接口调用:
-	return request('resourceStatistic/totalStatistic', params, 'get')
+	// return request('/resource-library/summary', params, 'get')
+	console.log('什么呢', json)
+	return json
+}
+
+function kbToTb(kb) {
+	const tb = kb / 1073741824;
+	return parseFloat(tb.toFixed(2));
+}
+
+export const getFilterData = async (params = {}) => {
+	let colleges = await request('resourceStatistic/selectOrgList', params, 'get')
+	colleges.unshift({
+		id: 'all',
+		name: '全部院系'
+	})
+	console.log("什么呢sss", colleges)
+	let json = {
+		code: 200,
+		data: colleges
+	}
+
+	return json
 }
 
-export const getResourceTypeData = (params = {}) => {
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			const mockData = generateMockData(params)
-			resolve(mockData.resourceTypeData)
-		}, Mock.mock('@integer(200, 500)'))
+export const getResourceTypeData = async (params = {}) => {
+	let resourceTypeStatistic = await request('resourceStatistic/resourceTypeStatistic', params, 'get')
+	console.log('左面的', resourceTypeStatistic)
+	let types = []
+	let typeCounts = []
+	ForEach(resourceTypeStatistic, (item) => {
+		types.push(item.resourceTypeName)
+		typeCounts.push(item.num)
 	})
+
+	// types: types,
+	// 	typeCounts: typeCounts,
+	let json = {
+		code: 200,
+		data: {
+			types,
+			typeCounts,
+			typeStorage: []
+		}
+	}
+	return json
+
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		const mockData = generateMockData(params)
+	// 		resolve(mockData.resourceTypeData)
+	// 	}, Mock.mock('@integer(200, 500)'))
+	// })
 	// return request('/resource-library/type-distribution', params, 'get')
+
 }
 
-export const getDepartmentData = (params = {}) => {
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			const mockData = generateMockData(params)
-			resolve(mockData.departmentData)
-		}, Mock.mock('@integer(200, 500)'))
+export const getDepartmentData = async (params = {}) => {
+	let collegeStatistic = await request('resourceStatistic/collegeStatistic', params, 'get')
+	let departments = []
+	let departmentCounts = []
+	ForEach(collegeStatistic, (item) => {
+		departments.push(item.collegeName)
+		departmentCounts.push(item.num)
 	})
+	let json = {
+		code: 200,
+		data: {
+			departments,
+			departmentCounts,
+			departmentStorage: []
+		}
+	}
+	return json
+
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		const mockData = generateMockData(params)
+	// 		resolve(mockData.departmentData)
+	// 	}, Mock.mock('@integer(200, 500)'))
+	// })
+	//
+	// departments: departments,
+	// 	departmentCounts: departmentCounts,
+	// 	departmentStorage: departmentCounts.map((count) =>
 	// return request('/resource-library/department-distribution', params, 'get')
 }
 
-export const getVisibilityData = (params = {}) => {
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			const mockData = generateMockData(params)
-			resolve(mockData.visibilityData)
-		}, Mock.mock('@integer(200, 500)'))
+export const getVisibilityData = async (params = {}) => {
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		const mockData = generateMockData(params)
+	// 		resolve(mockData.visibilityData)
+	// 	}, Mock.mock('@integer(200, 500)'))
+	// })
+	let resourcePublicStatistic = await request('resourceStatistic/resourcePublicStatistic', params, 'get')
+	let visibility = ['非公开', '公开']
+	let visibilityCounts = []
+	ForEach(resourcePublicStatistic, (item) => {
+		visibilityCounts.push(item.num)
 	})
+	let hotness = []
+	let hotnessCounts = []
+	let recommended = ['已推荐', '未推荐']
+
+	let hotStatistic = await request('resourceStatistic/hotStatistic', params, 'get')
+	ForEach(hotStatistic, (item) => {
+		//1推荐  2热门  3推荐和热门
+		if (item.type == 1) {
+			hotness.push('推荐')
+		}
+		if (item.type == 2) {
+			hotness.push('热门')
+		}
+		if (item.type == 3) {
+			hotness.push('推荐和热门')
+		}
+		hotnessCounts.push(item.num)
+	})
+
+
+	console.log('接口看看', hotStatistic)
+	let recommendedCounts = [12, 13]
+
+
+	let json = {
+		code: 200,
+		data: {
+			visibility,
+			visibilityCounts,
+			hotness,
+			hotnessCounts,
+			recommended,
+			recommendedCounts
+		}
+	}
+	return json
+	// data: {
+	// 	visibility: ['公开', '非公开'],
+	// 		visibilityCounts: [
+	// 		Math.floor(adjustedTotalResources * 0.75), // 75%公开
+	// 		Math.floor(adjustedTotalResources * 0.25) // 25%非公开
+	// 	],
+	// 		hotness: ['热门', '非热门'],
+	// 		hotnessCounts: [
+	// 		Math.floor(adjustedTotalResources * 0.2), // 20%热门
+	// 		Math.floor(adjustedTotalResources * 0.8) // 80%非热门
+	// 	],
+	// 		recommended: ['已推荐', '未推荐'],
+	// 		recommendedCounts: [
+	// 		Math.floor(adjustedTotalResources * 0.15), // 15%已推荐
+	// 		Math.floor(adjustedTotalResources * 0.85) // 85%未推荐
+	// 	]
+	// }
+
+
 	// return request('/resource-library/visibility-analysis', params, 'get')
 }
 
-export const getFormatData = (params = {}) => {
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			const mockData = generateMockData(params)
-			resolve(mockData.formatData)
-		}, Mock.mock('@integer(200, 500)'))
+export const getFormatData = async (params = {}) => {
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		const mockData = generateMockData(params)
+	// 		resolve(mockData.formatData)
+	// 	}, Mock.mock('@integer(200, 500)'))
+	// })
+	let formatStatistic = await request('resourceStatistic/formatStatistic', params, 'get')
+	let formats = []
+	let formatCounts = []
+	ForEach(formatStatistic, (item) => {
+		formats.push(item.extendName)
+		formatCounts.push(item.num)
+	})
+	let storageStatistic = await request('resourceStatistic/storageStatistic', params, 'get')
+	console.log('内存', storageStatistic)
+	let formatAvgSize = []
+	ForEach(storageStatistic, (item) => {
+		formatAvgSize.push(item.extendName)
 	})
+
+	let json = {
+		code: 200,
+		data: {
+			formats,
+			formatCounts,
+			formatStorage: storageStatistic.map((item) => {
+					let size = (item.FILESIZE) * parseFloat(1).toFixed(2)
+					console.log("asdasd", item.FILESIZE)
+					return `${(item.FILESIZE / 1000 / 1000).toFixed(2)}`
+				}
+			),
+			formatAvgSize: storageStatistic.map((format, index) => {
+				// 根据文件类型设置合理的平均大小
+				const size = format.avgSize
+				// if (size > 1000) return `${(size / 1000).toFixed(1)}MB`
+				return `${(size / 1000 / 1000).toFixed(2)}MB`
+			})
+		}
+	}
+	return json
+
+	// formatData: {
+	// 	code: 200,
+	// 		data: {
+	// 		formats: formats,
+	// 			formatCounts: formatCounts,
+	// 			formatStorage: formatCounts.map((count) =>
+	// 			((count / adjustedTotalResources) * parseFloat(adjustedUsedStorage)).toFixed(2)
+	// 		),
+	// 			formatAvgSize: formats.map((format, index) => {
+	// 			// 根据文件类型设置合理的平均大小
+	// 			const sizeMap = {
+	// 				mp4: Mock.mock('@integer(200, 800)'),
+	// 				avi: Mock.mock('@integer(300, 1000)'),
+	// 				wmv: Mock.mock('@integer(150, 600)'),
+	// 				mkv: Mock.mock('@integer(400, 1200)'),
+	// 				pdf: Mock.mock('@integer(5, 50)'),
+	// 				docx: Mock.mock('@integer(2, 20)'),
+	// 				pptx: Mock.mock('@integer(10, 100)'),
+	// 				xlsx: Mock.mock('@integer(1, 15)'),
+	// 				jpg: Mock.mock('@integer(1, 10)'),
+	// 				other: Mock.mock('@integer(5, 200)')
+	// 			}
+	//
+	// 			const size = sizeMap[format] || Mock.mock('@integer(1, 100)')
+	// 			if (size > 1000) return `${(size / 1000).toFixed(1)}GB`
+	// 			return `${size}MB`
+	// 		})
+	// 	}
+	// },
+
+
 	// return request('/resource-library/format-distribution', params, 'get')
 }
 
-export const getEngagementData = (params = {}) => {
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			const mockData = generateMockData(params)
-			resolve(mockData.engagementData)
-		}, Mock.mock('@integer(200, 500)'))
+export const getEngagementData = async (params = {}) => {
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		const mockData = generateMockData(params)
+	// 		resolve(mockData.engagementData)
+	// 	}, Mock.mock('@integer(200, 500)'))
+	// })
+	let selectResourceUse = await request('resourceStatistic/selectResourceUse', params, 'get')
+	let selectResourceCans = await request('resourceStatistic/selectResourceCans', params, 'get')
+	console.log('001 ', selectResourceUse)
+	console.log('003 ', selectResourceCans)
+	let engagement = []
+	let engagementCounts = []
+	let typeViewCounts = []
+	ForEach(selectResourceUse, (item) => {
+		//1、资源观看 2资源收藏 3资源分享
+		if (item.type == 1) {
+			engagement.push('资源观看')
+			engagementCounts.push(item.num)
+		}
+		if (item.type == 2) {
+			engagement.push('资源收藏')
+			engagementCounts.push(item.num)
+		}
+		if (item.type == 3) {
+			engagement.push('资源分享')
+			engagementCounts.push(item.num)
+		}
 	})
+	ForEach(selectResourceCans, (item) => {
+		//1、资源观看 2资源收藏 3资源分享
+		typeViewCounts.push(item.num)
+	})
+
+
+	let json = {
+		code: 200,
+		data: {
+			engagement,
+			engagementCounts,
+			typeViewCounts
+		}
+	}
+	return json
 	// return request('/resource-library/engagement-analysis', params, 'get')
+	// 用户参与度数据
+	// engagementData: {
+	// 	code: 200,
+	// 		data: {
+	// 		engagement: ['观看', '收藏', '分享'],
+	// 			engagementCounts: [
+	// 			adjustedViews,
+	// 			adjustedFavorites,
+	// 			Math.floor(adjustedFavorites * 0.3) // 分享数约为收藏数的30%
+	// 		],
+	// 			typeViewCounts: typeCounts.map((count) => Math.floor(count * (2 + Math.random() * 3))) // 每个资源平均2-5次观看
+	// 	}
+	// },
+
 }
 
-export const getTrendData = (params = {}) => {
-	return new Promise((resolve) => {
-		setTimeout(() => {
-			const mockData = generateMockData(params)
-			resolve(mockData.trendData)
-		}, Mock.mock('@integer(200, 500)'))
+export const getTrendData = async (params = {}) => {
+	// return new Promise((resolve) => {
+	// 	setTimeout(() => {
+	// 		const mockData = generateMockData(params)
+	// 		resolve(mockData.trendData)
+	// 	}, Mock.mock('@integer(200, 500)'))
+	// })
+	let selectResourceUpload = await request('resourceStatistic/selectResourceUpload', params, 'get')
+	console.log('002 ',selectResourceUpload)
+	let engagement = []
+	let trendLabels = []
+	let uploadTrend = []
+	let viewTrend = []
+	ForEach(selectResourceUpload, (item) => {
+		//1、资源观看 2资源收藏 3资源分享
+		trendLabels.push(item.createMonth)
+		uploadTrend.push(item.uploadNum)
+		viewTrend.push(item.seeNum)
 	})
+
+
+
+	let json = {
+		code: 200,
+		data : {
+			trendLabels,
+			uploadTrend,
+			viewTrend
+		}
+	}
+	return json
+	// 时间趋势数据
+	// trendData: {
+	// 	code: 200,
+	// 		data: {
+	// 		trendLabels: months,
+	// 			uploadTrend: months.map(() => Math.floor((adjustedTotalResources / 12) * (0.6 + Math.random() * 0.8))), // 月均上传量有波动
+	// 			viewTrend: months.map(() => Math.floor((adjustedViews / 12) * (0.7 + Math.random() * 0.6))) // 月均观看量有波动
+	// 	}
+	// }
 	// return request('/resource-library/trend-analysis', params, 'get')
 }

+ 58 - 49
src/views/statisticalAnalysis/analysisTeachingActivities/index.vue

@@ -12,19 +12,25 @@
 			<div class="filter-controls">
 				<div class="filter-group">
 					<label>选择课程</label>
-					<a-select v-model:value="filters.courseId" placeholder="全部课程" @change="updateStats" :loading="loading">
-						<a-select-option v-for="option in courseOptions" :key="option.value" :value="option.value">
-							{{ option.label }}
+					<a-select
+						v-model:value="filters.courseId"
+						placeholder="全部课程"
+						@change="updateStats"
+						:loading="loading"
+						allowClear
+					>
+						<a-select-option v-for="option in courseOptions" :key="option.courseId" :value="option.courseId">
+							{{ option.courseName }}
 						</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-option :value="1">最近30天</a-select-option>
+						<a-select-option :value="2">最近90天</a-select-option>
+						<a-select-option :value="3">最近180天</a-select-option>
+						<a-select-option :value="4">最近一年</a-select-option>
 					</a-select>
 				</div>
 				<div class="filter-group">
@@ -37,29 +43,29 @@
 		<div class="stats-grid">
 			<div class="stat-card">
 				<h3>📖 文档观看统计</h3>
-				<div class="stat-number">{{ stats.totalDocViewers.toLocaleString() }}</div>
+				<div class="stat-number">{{ stats.allUserCount }}</div>
 				<div class="stat-label">总观看人数</div>
-				<div class="stat-number">{{ stats.completedDocViewers.toLocaleString() }}</div>
+				<div class="stat-number">{{ stats.alreadyUserCount }}</div>
 				<div class="stat-label">完成观看人数</div>
-				<div class="completion-rate">{{ stats.docCompletionRate }}%</div>
+				<div class="completion-rate">{{ stats.finishRate }}%</div>
 				<div class="stat-label">完成率</div>
 			</div>
 
 			<div class="stat-card">
 				<h3>🚪 文档跳出分析</h3>
-				<div class="stat-number">{{ stats.totalDocExits.toLocaleString() }}</div>
+				<div class="stat-number">{{ stats.allHourCount }}</div>
 				<div class="stat-label">总跳出次数</div>
-				<div class="stat-number">{{ stats.docExitRate }}%</div>
+				<div class="stat-number">{{ stats.allHourCount }}%</div>
 				<div class="stat-label">跳出率</div>
-				<div class="stat-number">{{ stats.avgDocExitTime }}</div>
+				<div class="stat-number">{{ stats.jumpAvgTime }}</div>
 				<div class="stat-label">平均跳出时间</div>
 			</div>
 
-			<div class="stat-card">
+			<div class="stat-card" v-if="forumType">
 				<h3>💬 讨论互动统计</h3>
-				<div class="stat-number">{{ stats.totalDiscussions.toLocaleString() }}</div>
+				<div class="stat-number">{{ stats.totalDiscussions }}</div>
 				<div class="stat-label">讨论总数</div>
-				<div class="stat-number">{{ stats.totalReplies.toLocaleString() }}</div>
+				<div class="stat-number">{{ stats.totalReplies }}</div>
 				<div class="stat-label">回帖总数</div>
 				<div class="stat-number">{{ stats.avgRepliesPerDiscussion }}</div>
 				<div class="stat-label">平均回帖数</div>
@@ -73,7 +79,7 @@
 		</div>
 
 		<!-- 每周发帖回帖统计 -->
-		<div class="weekly-stats">
+		<div class="weekly-stats" v-if="forumType">
 			<div class="weekly-card">
 				<h4>👨‍🎓 学员每周发帖统计</h4>
 				<div class="weekly-number">{{ weeklyStats.studentWeeklyPosts }}</div>
@@ -96,7 +102,7 @@
 		</div>
 
 		<!-- 讨论详情表格 -->
-		<div class="data-table">
+		<div class="data-table" v-if="forumType">
 			<h3>💬 课程讨论详情</h3>
 			<a-table
 				:columns="discussionColumns"
@@ -129,25 +135,21 @@
 	import {
 		getCourseOptions,
 		getTeachingStats,
+		documentJumpStatistic,
 		getWeeklyStats,
 		getDailyVisits,
 		getDiscussionData,
 		getDocumentStats
 	} from '@/api/statisticalAnalysis/analysisTeachingActivities'
-
+	import tool from '@/utils/tool'
+	const forumType = computed(() => (tool.dictList('FORUM_TYPE')[0].value == 1 ? true : false))
 	// 响应式数据
 	const filters = reactive({
 		courseId: '',
-		timeRange: 30
+		timeRange: 1
 	})
 
 	const stats = reactive({
-		totalDocViewers: 0,
-		completedDocViewers: 0,
-		docCompletionRate: 0,
-		totalDocExits: 0,
-		docExitRate: 0,
-		avgDocExitTime: '00:00',
 		totalDiscussions: 0,
 		totalReplies: 0,
 		avgRepliesPerDiscussion: 0
@@ -210,31 +212,31 @@
 	const documentColumns = [
 		{
 			title: '文档名称',
-			dataIndex: 'name',
-			key: 'name'
+			dataIndex: 'fileName',
+			key: 'fileName'
 		},
 		{
 			title: '文档类型',
-			dataIndex: 'type',
-			key: 'type',
+			dataIndex: 'fileSuffix',
+			key: 'fileSuffix',
 			width: '100px'
 		},
 		{
 			title: '观看人数',
-			dataIndex: 'viewCount',
-			key: 'viewCount',
+			dataIndex: 'seeNum',
+			key: 'seeNum',
 			width: '100px'
 		},
 		{
 			title: '完成人数',
-			dataIndex: 'completedCount',
-			key: 'completedCount',
+			dataIndex: 'finishNum',
+			key: 'finishNum',
 			width: '100px'
 		},
 		{
 			title: '完成率',
-			dataIndex: 'completionRate',
-			key: 'completionRate',
+			dataIndex: 'finishRate',
+			key: 'finishRate',
 			customRender: ({ text }) => {
 				const rate = parseFloat(text)
 				const className = rate >= 70 ? 'completion-rate' : rate < 50 ? 'low-engagement' : ''
@@ -243,14 +245,14 @@
 		},
 		{
 			title: '平均阅读时长',
-			dataIndex: 'avgReadTime',
-			key: 'avgReadTime',
+			dataIndex: 'jumpAvgTime',
+			key: 'jumpAvgTime',
 			width: '130px'
 		},
 		{
 			title: '跳出率',
-			dataIndex: 'exitRate',
-			key: 'exitRate',
+			dataIndex: 'jumpRate',
+			key: 'jumpRate',
 			customRender: ({ text }) => {
 				const rate = parseFloat(text)
 				const className = rate > 30 ? 'low-engagement' : ''
@@ -259,8 +261,8 @@
 		},
 		{
 			title: '下载次数',
-			dataIndex: 'downloadCount',
-			key: 'downloadCount',
+			dataIndex: 'downNum',
+			key: 'downNum',
 			width: '100px'
 		}
 	]
@@ -429,9 +431,14 @@
 		try {
 			const response = await getTeachingStats({
 				courseId: filters.courseId,
-				timeRange: filters.timeRange
+				type: filters.timeRange
 			})
-			Object.assign(stats, response)
+			const statistic = await documentJumpStatistic({
+				courseId: filters.courseId,
+				type: filters.timeRange
+			})
+
+			Object.assign(stats, response, statistic)
 		} catch (error) {
 			console.error('获取统计数据失败:', error)
 		}
@@ -453,10 +460,11 @@
 	const loadDailyVisits = async () => {
 		try {
 			const response = await getDailyVisits({
-				timeRange: filters.timeRange
+				type: filters.timeRange,
+				courseId: filters.courseId
 			})
-			chartData.dates = response.dates
-			chartData.visits = response.visits
+			chartData.dates = response.map((r) => r.TIME)
+			chartData.visits = response.map((r) => r.num)
 			updateChartData()
 		} catch (error) {
 			console.error('获取每日访问数据失败:', error)
@@ -484,9 +492,10 @@
 			const response = await getDocumentStats({
 				courseId: filters.courseId,
 				page: documentPagination.current,
-				pageSize: documentPagination.pageSize
+				pageSize: documentPagination.pageSize,
+				type: filters.timeRange
 			})
-			documentData.value = response.list
+			documentData.value = response
 			documentPagination.total = response.total
 		} catch (error) {
 			console.error('获取文档数据失败:', error)

+ 104 - 178
src/views/statisticalAnalysis/overviewLearningProgress/index.vue

@@ -3,39 +3,25 @@
 		<div class="w-full mx-auto">
 			<!-- 顶部筛选区 -->
 			<div class="bg-white rounded-lg shadow-sm p-6 mb-6 h-25 flex items-center">
-				<!-- 讲座选择 -->
+				<!-- 课程ID输入 -->
 				<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 v-for="course in courseOptions" :key="course.id" :value="course.courseName">
-								{{ course.courseName }}
-							</a-select-option>
-						</a-select>
-					</div>
+					<label class="block text-sm font-medium text-gray-700 mb-1">课程ID</label>
+					<a-select class="w-full" v-model:value="filters.courseId" placeholder="请选择课程" allow-clear>
+						<a-select-option v-for="item in courseinfoAllListOptions" :key="item.courseId" :value="item.courseId">
+							{{ item.courseName }}
+						</a-select-option>
+					</a-select>
 				</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>
+					<label class="block text-sm font-medium text-gray-700 mb-1">开始时间</label>
+					<a-date-picker v-model:value="startDate" class="w-full" placeholder="开始时间" />
 				</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 class="flex-1 mr-4">
+					<label class="block text-sm font-medium text-gray-700 mb-1">结束时间</label>
+					<a-date-picker v-model:value="endDate" class="w-full" placeholder="结束时间" />
 				</div>
 
 				<!-- 操作按钮 -->
@@ -62,7 +48,7 @@
 						<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 class="font-size-30 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" />
@@ -97,25 +83,10 @@
 				<a-table
 					:columns="tableColumns"
 					:data-source="tableData"
-					:pagination="pagination"
+					:pagination="false"
 					: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>
+				></a-table>
 			</div>
 		</div>
 	</div>
@@ -127,35 +98,35 @@
 	import * as echarts from 'echarts'
 	import dayjs from 'dayjs'
 	import { overviewLearningProgressApi } from '@/api/statisticalAnalysis/overviewLearningProgress'
+	import { courseinfoAllList } from '@/api/semester/index.js'
+
 	import { message } from 'ant-design-vue'
 
 	// 响应式数据
 	const loading = ref(false)
 	const lineChartRef = ref(null)
 	const barChartRef = ref(null)
+	const courseinfoAllListOptions = ref([])
 	let lineChart = null
 	let barChart = null
 
+	// 日期选择器
+	const startDate = ref(dayjs('2025-08-04'))
+	const endDate = ref(dayjs('2025-08-10'))
+
 	// 筛选条件
 	const filters = reactive({
-		courseName: '',
-		contentType: 'all',
-		dateRange: [dayjs('2025-08-04'), dayjs('2025-08-10')]
+		courseId: '',
+		startTime: '2025-08-04',
+		endTime: '2025-08-10'
 	})
 
-	// 内容类型选项
-	const contentTypes = [
-		{ label: '全部', value: 'all' },
-		{ label: '视频', value: 'video' },
-		{ label: '文档', value: 'document' },
-		{ label: '练习', value: 'exercise' }
-	]
-
 	// 统计卡片数据
 	const statsCards = reactive([
 		{
 			title: '开课人数',
-			value: 2846,
+			value: 0,
+			key: 'courseOpenStuNum',
 			icon: UserOutlined,
 			borderClass: 'border-l-4 !border-blue-500',
 			iconBgClass: 'bg-blue-100',
@@ -163,7 +134,8 @@
 		},
 		{
 			title: '课程访问次数',
-			value: 12587,
+			value: 0,
+			key: 'courseViewNum',
 			icon: EyeOutlined,
 			borderClass: 'border-l-4 !border-green-500',
 			iconBgClass: 'bg-green-100',
@@ -171,7 +143,8 @@
 		},
 		{
 			title: '提交数(作业、测验)',
-			value: 1924,
+			value: 0,
+			key: 'paperSubmitNum',
 			icon: FileTextOutlined,
 			borderClass: 'border-l-4 !border-orange-500',
 			iconBgClass: 'bg-orange-100',
@@ -179,7 +152,8 @@
 		},
 		{
 			title: '互动数(发帖/回帖)',
-			value: 5362,
+			value: 0,
+			key: 'interactionNum',
 			icon: MessageOutlined,
 			borderClass: 'border-l-4 !border-blue-500',
 			iconBgClass: 'bg-blue-100',
@@ -189,81 +163,40 @@
 
 	const tableColumns = [
 		{
-			title: '讲座名称',
+			title: '课程名称',
 			dataIndex: 'courseName',
-			key: 'courseName',
-			sorter: true
+			key: 'courseName'
 		},
 		{
 			title: '开课人数',
-			dataIndex: 'studentCount',
-			key: 'studentCount',
-			sorter: true
+			dataIndex: 'openStuNum',
+			key: 'openStuNum'
 		},
 		{
 			title: '课程访问量',
-			dataIndex: 'visitCount',
-			key: 'visitCount',
-			sorter: true
-		},
-		{
-			title: '学习视频总时长',
-			dataIndex: 'videoDuration',
-			key: 'videoDuration',
-			sorter: true
+			dataIndex: 'viewCount',
+			key: 'viewCount'
 		},
 		{
 			title: '讲义访问量',
-			dataIndex: 'documentVisit',
-			key: 'documentVisit',
-			sorter: true
+			dataIndex: 'stayTime',
+			key: 'stayTime'
 		},
 		{
 			title: '练习提交量',
-			dataIndex: 'submissionCount',
-			key: 'submissionCount',
-			sorter: true
-		},
-		{
-			title: '退课人数',
-			dataIndex: 'numberStudentsDroppingCourses',
-			key: 'numberStudentsDroppingCourses',
-			sorter: true
+			dataIndex: 'teachMaterialsNum',
+			key: 'teachMaterialsNum'
 		}
 	]
 
-	// 表格数据
-	const tableData = ref([])
-
 	// 图表数据
 	const chartData = reactive({
-		dates: [],
 		visitTrend: [],
 		submissionTrend: []
 	})
 
-	// 课程选项
-	const courseOptions = ref([])
-
-	// 分页配置
-	const pagination = reactive({
-		current: 1,
-		pageSize: 6,
-		total: 0,
-		showSizeChanger: true,
-		showQuickJumper: true,
-		showTotal: (total, range) => `显示 ${range[0]}-${range[1]} 条,共 ${total} 条`,
-		onChange: (page, pageSize) => {
-			pagination.current = page
-			pagination.pageSize = pageSize
-			fetchCourseList()
-		},
-		onShowSizeChange: (current, size) => {
-			pagination.current = 1
-			pagination.pageSize = size
-			fetchCourseList()
-		}
-	})
+	// 表格数据
+	const tableData = ref([])
 
 	// 初始化折线图
 	const initLineChart = () => {
@@ -282,17 +215,17 @@
 			tooltip: { trigger: 'axis' },
 			xAxis: {
 				type: 'category',
-				data: chartData.dates
+				data: chartData.visitTrend.map((item) => item.month)
 			},
 			yAxis: { type: 'value', name: '访问人数' },
 			series: [
 				{
-					name: '访问人数',
+					name: '访问人数',
 					type: 'line',
 					smooth: true,
 					symbol: 'circle',
 					symbolSize: 8,
-					data: chartData.visitTrend,
+					data: chartData.visitTrend.map((item) => item.viewTendencyNum),
 					lineStyle: { color: '#3A7BFF', width: 3 },
 					itemStyle: { color: '#3A7BFF' },
 					areaStyle: {
@@ -324,15 +257,15 @@
 			tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
 			xAxis: {
 				type: 'category',
-				data: chartData.dates
+				data: chartData.submissionTrend.map((item) => item.month)
 			},
-			yAxis: { type: 'value', name: '平均提交数' },
+			yAxis: { type: 'value', name: '提交数' },
 			series: [
 				{
-					name: '练习平均提交数',
+					name: '练习提交数',
 					type: 'bar',
 					barWidth: 28,
-					data: chartData.submissionTrend,
+					data: chartData.submissionTrend.map((item) => item.SubmeitTendency),
 					itemStyle: {
 						color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
 							{ offset: 0, color: '#5B8EFF' },
@@ -348,11 +281,8 @@
 
 	// 格式化日期范围显示
 	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')
+		const start = startDate.value ? startDate.value.format('YYYY/MM/DD') : filters.startTime
+		const end = endDate.value ? endDate.value.format('YYYY/MM/DD') : filters.endTime
 		return `${start}至${end}`
 	}
 
@@ -360,16 +290,15 @@
 	const fetchOverviewStats = async () => {
 		try {
 			const params = {
-				courseName: filters.courseName,
-				contentType: filters.contentType,
-				dateRange: filters.dateRange
+				courseId: filters.courseId,
+				startTime: startDate.value ? startDate.value.format('YYYY-MM-DD') : filters.startTime,
+				endTime: endDate.value ? endDate.value.format('YYYY-MM-DD') : filters.endTime
 			}
-			const data = await overviewLearningProgressApi.getOverviewStats(params)
+			const data = await overviewLearningProgressApi.getTopFundamentalDetail(params)
 			// 更新统计卡片数据
-			statsCards[0].value = data.totalStudents
-			statsCards[1].value = data.totalVisits
-			statsCards[2].value = data.totalSubmissions
-			statsCards[3].value = data.totalInteractions
+			statsCards.forEach((card) => {
+				card.value = data[card.key] || 0
+			})
 		} catch (error) {
 			console.error('获取统计数据失败:', error)
 			message.error('获取统计数据失败')
@@ -380,16 +309,20 @@
 	const fetchTrendData = async () => {
 		try {
 			const params = {
-				courseName: filters.courseName,
-				contentType: filters.contentType,
-				dateRange: filters.dateRange
+				courseId: filters.courseId,
+				startTime: startDate.value ? startDate.value.format('YYYY-MM-DD') : filters.startTime,
+				endTime: endDate.value ? endDate.value.format('YYYY-MM-DD') : filters.endTime
 			}
-			const data = await overviewLearningProgressApi.getTrendData(params)
+
+			// 并行获取访问趋势和提交趋势数据
+			const [visitData, submitData] = await Promise.all([
+				overviewLearningProgressApi.getViewTendency(params),
+				overviewLearningProgressApi.getPaperSubmitTendency(params)
+			])
 
 			// 更新图表数据
-			chartData.dates = data.dates
-			chartData.visitTrend = data.visitTrend
-			chartData.submissionTrend = data.submissionTrend
+			chartData.visitTrend = visitData || []
+			chartData.submissionTrend = submitData || []
 
 			// 更新图表
 			updateLineChart()
@@ -400,38 +333,23 @@
 		}
 	}
 
-	// 获取课程选项
-	const fetchCourseOptions = async () => {
-		try {
-			const data = await overviewLearningProgressApi.getCourseOptions()
-			courseOptions.value = data
-		} catch (error) {
-			console.error('获取课程选项失败:', error)
-		}
-	}
-
-	// 获取课程列表数据
-	const fetchCourseList = async () => {
+	// 获取学习明细数据
+	const fetchStudyDetail = async () => {
 		try {
 			const params = {
-				courseName: filters.courseName,
-				contentType: filters.contentType,
-				dateRange: filters.dateRange,
-				current: pagination.current,
-				pageSize: pagination.pageSize
+				courseId: filters.courseId,
+				startTime: startDate.value ? startDate.value.format('YYYY-MM-DD') : filters.startTime,
+				endTime: endDate.value ? endDate.value.format('YYYY-MM-DD') : filters.endTime
 			}
-			const response = await overviewLearningProgressApi.getCourseList(params)
+			const data = await overviewLearningProgressApi.getStudyDetail(params)
 			// 更新表格数据
-			tableData.value = response.data.map((item, index) => ({
+			tableData.value = (data.records || []).map((item, index) => ({
 				...item,
-				key: item.id || index + 1
+				key: item.courseId || index + 1
 			}))
-
-			// 更新分页信息
-			pagination.total = response.total
 		} catch (error) {
-			console.error('获取课程列表失败:', error)
-			message.error('获取课程列表失败')
+			console.error('获取学习明细数据失败:', error)
+			message.error('获取学习明细数据失败')
 		}
 	}
 
@@ -439,7 +357,11 @@
 	const refreshData = async () => {
 		loading.value = true
 		try {
-			await Promise.all([fetchOverviewStats(), fetchTrendData(), fetchCourseList()])
+			// 更新筛选条件
+			filters.startTime = startDate.value ? startDate.value.format('YYYY-MM-DD') : filters.startTime
+			filters.endTime = endDate.value ? endDate.value.format('YYYY-MM-DD') : filters.endTime
+
+			await Promise.all([fetchOverviewStats(), fetchTrendData(), fetchStudyDetail()])
 		} catch (error) {
 			console.error('刷新数据失败:', error)
 		} finally {
@@ -447,26 +369,26 @@
 		}
 	}
 
-	// 初始化数据
-	const initData = async () => {
-		// 先获取课程选项
-		await fetchCourseOptions()
-		// 再获取其他数据
-		await refreshData()
-	}
-
 	// 窗口大小变化处理
 	const handleResize = () => {
 		if (lineChart) lineChart.resize()
 		if (barChart) barChart.resize()
 	}
 
+	const getCourseinfoAllList = () => {
+		courseinfoAllList()
+			.then((res) => {
+				courseinfoAllListOptions.value = res.data
+			})
+			.catch((err) => {
+				console.log(err)
+			})
+	}
+
 	// 监听筛选条件变化
 	watch(
-		() => [filters.courseName, filters.contentType, filters.dateRange],
+		() => [filters.courseId, startDate.value, endDate.value],
 		() => {
-			// 筛选条件变化时重置到第一页
-			pagination.current = 1
 			refreshData()
 		},
 		{ deep: true }
@@ -480,7 +402,8 @@
 		window.addEventListener('resize', handleResize)
 
 		// 初始化数据
-		await initData()
+		await refreshData()
+		getCourseinfoAllList()
 	})
 
 	onUnmounted(() => {
@@ -506,4 +429,7 @@
 		border: 1px solid #e4e7ed;
 		border-radius: 4px;
 	}
+	.font-size-30 {
+		font-size: 30px;
+	}
 </style>

+ 7 - 4
src/views/statisticalAnalysis/platformStatusOverview/index.vue

@@ -153,7 +153,8 @@
 			key: 'action',
 			align: 'center',
 			customRender: ({ record }) => {
-				return h('button', { class: 'btn-view', onClick: () => showVisitModal(record.name) }, '查看')
+				console.log("分析呢",record)
+				return h('button', { class: 'btn-view', onClick: () => showVisitModal(record.id) }, '查看')
 			}
 		}
 	]
@@ -194,6 +195,7 @@
 	const loadCourseInfo = async (params = {}) => {
 		try {
 			const response = await getCourseInfo(params)
+			console.log("888",response)
 			courseInfoData.value = response.data.records
 			courseInfoPagination.total = response.data.total
 			courseInfoPagination.current = response.data.current
@@ -213,12 +215,13 @@
 	}
 
 	// 显示访问统计弹窗
-	const showVisitModal = async (courseName) => {
-		modalTitle.value = `${courseName} - 近7天访问统计`
+	const showVisitModal = async (courseId) => {
+		modalTitle.value = `${courseId} - 近7天访问统计`
 		visitModalVisible.value = true
 
 		try {
-			const response = await getCourseVisitStats({ courseName })
+			const response = await getCourseVisitStats({ courseId })
+			console.log('如家七天',response)
 			nextTick(() => {
 				initVisitChart(response.data)
 			})

+ 32 - 23
src/views/statisticalAnalysis/statisticalAnalysisResourceLibrary/index.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="resource-statistics">
-		<div class="container">
+		<div class="containers">
 			<h1>资源库统计分析</h1>
 
 			<!-- 摘要信息 -->
@@ -35,27 +35,22 @@
 
 			<!-- 筛选器 -->
 			<div class="filters">
-				<label>筛选单位:</label>
+				<label>筛选院系:</label>
 				<a-select
 					v-model:value="filters.department"
 					style="width: 150px; margin-right: 20px"
 					@change="handleDepartmentChange"
 				>
-					<a-select-option value="all">全部单位</a-select-option>
-					<a-select-option value="aviation">航空学院</a-select-option>
-					<a-select-option value="military">军事管理系</a-select-option>
-					<a-select-option value="politics">政治工作部</a-select-option>
-					<a-select-option value="maintenance">地面维修中心</a-select-option>
-					<a-select-option value="other">其他部门</a-select-option>
+					<a-select-option :value="item.id" v-for="(item, index) in filterData">{{item.name}}</a-select-option>
 				</a-select>
 
 				<label>时间范围:</label>
 				<a-select v-model:value="filters.timeRange" style="width: 120px" @change="handleTimeChange">
 					<a-select-option value="all">全部时间</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="180">最近180天</a-select-option>
-					<a-select-option value="365">最近1年</a-select-option>
+					<a-select-option value="1">最近30天</a-select-option>
+					<a-select-option value="2">最近90天</a-select-option>
+					<a-select-option value="3">最近180天</a-select-option>
+					<a-select-option value="4">最近1年</a-select-option>
 				</a-select>
 			</div>
 
@@ -134,7 +129,7 @@
 		getVisibilityData,
 		getFormatData,
 		getEngagementData,
-		getTrendData
+		getTrendData, getFilterData
 	} from '@/api/statisticalAnalysis/statisticalAnalysisResourceLibrary'
 
 	// 响应式数据
@@ -146,6 +141,7 @@
 		totalViews: '0',
 		totalFavorites: '0'
 	})
+	const filterData = ref([])
 
 	const filters = ref({
 		department: 'all',
@@ -209,6 +205,7 @@
 		try {
 			// 并行加载所有数据
 			const [
+				filterResponse,
 				summaryResponse,
 				typeResponse,
 				departmentResponse,
@@ -217,6 +214,7 @@
 				engagementResponse,
 				trendResponse
 			] = await Promise.all([
+				getFilterData(),
 				getSummaryData(getFilterParams()),
 				getResourceTypeData(getFilterParams()),
 				getDepartmentData(getFilterParams()),
@@ -225,7 +223,9 @@
 				getEngagementData(getFilterParams()),
 				getTrendData(getFilterParams())
 			])
-
+			if(filterResponse.code === 200){
+				filterData.value = filterResponse.data
+			}
 			// 更新摘要数据
 			if (summaryResponse.code === 200) {
 				summaryData.value = summaryResponse.data
@@ -237,6 +237,11 @@
 				chartData.value.types = types
 				chartData.value.typeCounts = typeCounts
 				chartData.value.typeStorage = typeStorage
+
+				console.log('现在获取到的 types',chartData.value.types)
+				console.log('现在获取到的 typeCounts',chartData.value.typeCounts)
+				console.log('现在获取到的 typeStorage',chartData.value.typeStorage)
+
 			}
 
 			if (departmentResponse.code === 200) {
@@ -285,10 +290,14 @@
 
 	// 获取筛选参数
 	const getFilterParams = () => {
-		return {
-			department: filters.value.department,
-			timeRange: filters.value.timeRange
+		let json = JSON.parse(JSON.stringify(filters.value))
+		if(filters.value.department == 'all'){
+			json.department = undefined
+		}
+		if(filters.value.timeRange == 'all'){
+			json.timeRange = undefined
 		}
+		return json
 	}
 
 	// 获取或创建图表实例
@@ -325,7 +334,7 @@
 					series: [
 						{
 							type: 'pie',
-							radius: ['40%', '70%'],
+							radius: ['40%', '60%'],
 							data: chartData.value.types.map((name, index) => ({
 								value: chartData.value.typeCounts[index],
 								name
@@ -349,7 +358,7 @@
 			if (departmentChart) {
 				departmentChart.setOption({
 					title: {
-						text: '按单位分布 (数量)',
+						text: '按院系分布 (数量)',
 						left: 'center'
 					},
 					tooltip: {
@@ -428,14 +437,14 @@
 					},
 					angleAxis: {
 						type: 'category',
-						data: ['热门资源', '推荐资源', '热门且推荐']
+						data: chartData.value.hotness
 					},
 					radiusAxis: {},
 					polar: {},
 					series: [
 						{
 							type: 'bar',
-							data: [chartData.value.hotnessCounts[0], chartData.value.recommendedCounts[0], 89],
+							data: chartData.value.hotnessCounts,
 							coordinateSystem: 'polar',
 							name: '资源数量',
 							itemStyle: {
@@ -506,7 +515,7 @@
 						trigger: 'item',
 						formatter: function (params) {
 							const index = params.dataIndex
-							return `${params.name}: ${params.value} TB<br/>文件数量: ${chartData.value.formatCounts[index]}<br/>平均大小: ${chartData.value.formatAvgSize[index]}`
+							return `${params.name}: ${params.value} MB<br/>文件数量: ${chartData.value.formatCounts[index]}<br/>平均大小: ${chartData.value.formatAvgSize[index]}`
 						}
 					},
 					legend: {
@@ -732,7 +741,7 @@
 		color: #333;
 	}
 
-	.container {
+	.containers {
 		margin: 0 auto;
 		background-color: white;
 		padding: 30px;