于添 5 luni în urmă
părinte
comite
9ae2a5fe6b

+ 110 - 26
src/api/statisticalAnalysis/analysisLearningBehaviors.js

@@ -3,7 +3,7 @@ import { moduleRequest } from '@/utils/request'
 import Mock from 'mockjs'
 
 const request = moduleRequest(`/api/webapp/`)
-
+import ForEach from "lodash-es/forEach";
 // Mock 数据配置
 Mock.setup({
 	timeout: '200-600'
@@ -229,18 +229,18 @@ const studentsData = [
 ]
 
 // Mock 接口定义
-Mock.mock(/\/api\/webapp\/analysis\/colleges/, 'get', {
-	code: 200,
-	message: '获取成功',
-	data: [
-		{ id: '', name: '全部学院' },
-		{ id: 'computer', name: '计算机学院' },
-		{ id: 'business', name: '商学院' },
-		{ id: 'art', name: '艺术学院' },
-		{ id: 'science', name: '理学院' },
-		{ id: 'engineering', name: '工程学院' }
-	]
-})
+// Mock.mock(/\/api\/webapp\/analysis\/colleges/, 'get', {
+// 	code: 200,
+// 	message: '获取成功',
+// 	data: [
+// 		{ id: '', name: '全部学院' },
+// 		{ id: 'computer', name: '计算机学院' },
+// 		{ id: 'business', name: '商学院' },
+// 		{ id: 'art', name: '艺术学院' },
+// 		{ id: 'science', name: '理学院' },
+// 		{ id: 'engineering', name: '工程学院' }
+// 	]
+// })
 
 Mock.mock(/\/api\/webapp\/analysis\/college-stats/, 'get', (options) => {
 	const params = new URLSearchParams(options.url.split('?')[1])
@@ -458,7 +458,7 @@ Mock.mock(/\/api\/webapp\/analysis\/college-course-details/, 'get', {
 			totalVisits: 4123,
 			avgCompletionRate: 76.8,
 			assignmentSubmissionRate: 83.5,
-			dropoutRate: 11.7
+			homeworkFinishRate: 11.7
 		}
 	]
 })
@@ -482,26 +482,110 @@ Mock.mock(/\/api\/webapp\/analysis\/search-students/, 'get', (options) => {
 })
 
 // API 函数导出
-export const getCollegeList = () => {
-	return request('analysis/colleges', '', 'get')
+export const getCollegeList = async (params) => {
+	let res = await request('disk/studyBehavior/collegeCourseDetailProgress', params, 'get')
+	console.log('什么呢1233', res)
+	let list = []
+	ForEach(res.records,(item) => {
+		list.push({id : item.collegeId , name : item.collegeIdName})
+	})
+
+
+	let json = {
+		code: 200,
+		data: list
+	}
+	// {
+	// 	"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('/resource-library/summary', params, 'get')
+	console.log('什么呢', json)
+	return list
+	// return request('analysis/colleges', '', 'get')
 }
 
-export const getCollegeStats = (params) => {
-	return request('analysis/college-stats', params, 'get')
+export const getCollegeStats = async (params) => {
+	let res1 = await request('disk/studyBehavior/courseVisitProgress', params, 'get')
+	let res2 = await request('disk/studyBehavior/userLoginProgress', params, 'get')
+	let res3 = await request('disk/studyBehavior/watchDurationProgress', params, 'get')
+		//
+	// console.log('courseVisitProgress', res)
+	let json = {
+		code: 200,
+		data : {...res1,...res2,...res3}
+	}
+	return json
 }
 
-export const getLoginTimeDistribution = (params) => {
-	return request('analysis/login-time-distribution', params, 'get')
+export const getLoginTimeDistribution = async (params) => {
+	let res = await request('disk/studyBehavior/loginFrameDistribution', params, 'get')
+	let hours = []
+	let loginCounts = []
+	ForEach(res.records,(item) => {
+		hours.push(item.createTime)
+		loginCounts.push(item.COUNT)
+	})
+
+
+	let json = {
+		code: 200,
+		hours,
+		loginCounts
+	}
+	return json
+
+
 }
 
-export const getCourseHeat = (params) => {
-	return request('analysis/course-heat', params, 'get')
+export const getCourseHeat = async (params) => {
+	let res = await request('disk/studyBehavior/courseVisitHeatRank', params, 'get')
+	let courses = []
+	let visits = []
+	ForEach(res.records,(item) => {
+		courses.push(item.courseName)
+		visits.push(item.watchCount)
+	})
+
+
+	let json = {
+		code: 200,
+		courses,
+		visits
+	}
+	return json
 }
 
-export const getCollegeCourseDetails = (params) => {
-	return request('analysis/college-course-details', params, 'get')
+export const getCollegeCourseDetails = async (params) => {
+	let res = await request('/disk/studyBehavior/collegeCourseDetailProgress', params, 'get')
+	console.log('1233123',res)
+	let json = {
+		code: 200,
+		data : res.records
+	}
+	return json
 }
 
-export const searchStudents = (params) => {
-	return request('analysis/search-students', params, 'get')
+export const searchStudents = async (params) => {
+
+
+	let res = await request('disk/studyBehavior/studentAnalyse', params, 'get')
+
+	console.log('1120',res)
+	let json = {
+		code: 200,
+		data : res.records
+	}
+	return json
 }

+ 19 - 170
src/api/statisticalAnalysis/videoAnalysis.js

@@ -24,164 +24,6 @@ const generateCourseOptions = () => {
 	})
 }
 
-// 生成视频分析统计数据
-const generateVideoStats = (options) => {
-	console.log('options-', options)
-	const params = new URLSearchParams(options.url.split('?')[1])
-	const courseId = params.get('courseId') || ''
-	const timeRange = params.get('timeRange') || '30'
-
-	// 根据时间范围调整数据规模
-	const timeMultiplier =
-		{
-			7: 0.3,
-			30: 1,
-			90: 2.5,
-			365: 8
-		}[timeRange] || 1
-	console.log('courseId', courseId)
-	// 根据课程选择调整数据规模 - 全部课程数据更多
-	const courseMultiplier = courseId === '' ? 3.5 : 1 // 全部课程是单个课程的3.5倍
-	console.log('courseMultiplier', courseMultiplier)
-	// 基础数据
-	const baseViewers = Math.floor(800 * timeMultiplier * courseMultiplier)
-	const baseCompleted = Math.floor(baseViewers * (0.65 + Math.random() * 0.2)) // 65%-85%完成率
-	const completionRate = Math.round((baseCompleted / baseViewers) * 100)
-
-	const baseDownloads = Math.floor(baseViewers * (0.25 + Math.random() * 0.15)) // 25%-40%下载率
-	const downloadRate = Math.round((baseDownloads / baseViewers) * 100)
-	const avgDownloads = Math.round((baseDownloads / baseViewers) * 100) / 100
-
-	const baseExits = Math.floor(baseViewers * (0.15 + Math.random() * 0.1)) // 15%-25%跳出率
-	const exitRate = Math.round((baseExits / baseViewers) * 100)
-
-	const baseNotes = Math.floor(baseViewers * (0.6 + Math.random() * 0.4)) // 60%-100%笔记率
-	const baseDiscussions = Math.floor(baseViewers * (0.3 + Math.random() * 0.2)) // 30%-50%讨论率
-	const baseReplies = Math.floor(baseDiscussions * (2 + Math.random() * 2)) // 每个讨论2-4个回复
-
-	return Mock.mock({
-		code: 200,
-		data: {
-			totalViewers: baseViewers + Math.floor(Math.random() * 200),
-			completedViewers: baseCompleted,
-			completionRate: completionRate,
-			totalDownloads: baseDownloads,
-			downloadRate: downloadRate,
-			avgDownloads: avgDownloads,
-			totalExits: baseExits,
-			exitRate: exitRate,
-			avgExitTime: '@pick(["08:45", "12:34", "15:23", "18:56", "22:15", "06:30", "14:20", "19:45"])',
-			totalNotes: baseNotes,
-			totalDiscussions: baseDiscussions,
-			totalReplies: baseReplies
-		}
-	})
-}
-
-// 生成学员详细数据
-const generateStudentData = (options) => {
-	const params = new URLSearchParams(options.url.split('?')[1])
-	const current = parseInt(params.get('current')) || 1
-	const pageSize = parseInt(params.get('pageSize')) || 10
-	const courseId = params.get('courseId') || ''
-	const timeRange = params.get('timeRange') || '30'
-
-	// 根据课程和时间范围调整总数
-	const timeMultiplier = { 7: 0.3, 30: 1, 90: 2.5, 365: 8 }[timeRange] || 1
-	const courseMultiplier = courseId === '' ? 3.5 : 1
-	const baseTotal = Math.floor(120 * timeMultiplier * courseMultiplier)
-
-	return Mock.mock({
-		code: 200,
-		[`data|${pageSize}`]: [
-			{
-				'key|+1': (current - 1) * pageSize + 1,
-				id: () => String((current - 1) * pageSize + Mock.Random.increment()).padStart(3, '0'),
-				name: '@cname',
-				totalTime: () => {
-					const minutes = Math.floor(Math.random() * 180) + 30 // 30-210分钟
-					const hours = Math.floor(minutes / 60)
-					const mins = minutes % 60
-					return hours > 0 ? `${hours}小时${mins}分钟` : `${mins}分钟`
-				},
-				'progress|20-100': () => Math.floor(Math.random() * 80) + 20,
-				'viewCount|1-12': () => Math.floor(Math.random() * 12) + 1,
-				'exitPoints|1-5': () => {
-					const count = Math.floor(Math.random() * 5) + 1
-					const points = []
-					for (let i = 0; i < count; i++) {
-						const minutes = Math.floor(Math.random() * 45)
-						const seconds = Math.floor(Math.random() * 60)
-						points.push(`${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`)
-					}
-					return points
-				},
-				'seekCount|2-25': () => Math.floor(Math.random() * 24) + 2,
-				'noteCount|0-15': () => Math.floor(Math.random() * 16),
-				'discussionCount|0-12': () => Math.floor(Math.random() * 13),
-				'replyCount|0-20': () => Math.floor(Math.random() * 21),
-				lastAccess: '@datetime("yyyy-MM-dd HH:mm")'
-			}
-		],
-		total: baseTotal + Math.floor(Math.random() * 50),
-		current,
-		pageSize
-	})
-}
-
-// 生成章节数据
-const generateChapterData = (options) => {
-	const params = new URLSearchParams(options.url.split('?')[1])
-	const courseId = params.get('courseId') || ''
-	const timeRange = params.get('timeRange') || '30'
-
-	// 根据课程和时间范围调整数据规模
-	const timeMultiplier = { 7: 0.3, 30: 1, 90: 2.5, 365: 8 }[timeRange] || 1
-	const courseMultiplier = courseId === '' ? 3.5 : 1
-
-	const chapterCount = Math.floor(Math.random() * 4) + 5 // 5-8章
-	const chapters = []
-
-	for (let i = 1; i <= chapterCount; i++) {
-		const baseViewers = Math.floor((800 - i * 50) * timeMultiplier * courseMultiplier) // 越后面章节观看人数越少
-		const completionRate = Math.max(95 - i * 5 - Math.random() * 10, 60) // 越后面完成率越低
-		const completed = Math.floor(baseViewers * (completionRate / 100))
-
-		// 生成视频时长
-		const totalMinutes = Math.floor(Math.random() * 30) + 15 // 15-45分钟
-		const minutes = totalMinutes % 60
-		const seconds = Math.floor(Math.random() * 60)
-		const duration = `${minutes}:${seconds.toString().padStart(2, '0')}`
-
-		// 平均观看时长应该小于等于视频时长
-		const avgWatchMinutes = Math.floor(totalMinutes * (0.7 + Math.random() * 0.3))
-		const avgWatchSeconds = Math.floor(Math.random() * 60)
-		const avgWatchTime = `${avgWatchMinutes}:${avgWatchSeconds.toString().padStart(2, '0')}`
-
-		chapters.push({
-			key: i,
-			chapter: `第${i}章:${
-				['课程介绍', '基础知识', '核心概念', '实战应用', '高级技巧', '项目实战', '总结回顾', '拓展学习'][i - 1] ||
-				'课程内容'
-			}`,
-			duration: duration,
-			viewers: baseViewers + Math.floor(Math.random() * 100),
-			completed: completed,
-			completionRate: Math.round(completionRate),
-			avgWatchTime: avgWatchTime,
-			exitRate: Math.min(Math.floor(5 + i * 3 + Math.random() * 10), 35), // 越后面跳出率越高
-			downloads: Math.floor(baseViewers * (0.1 + Math.random() * 0.15)), // 10%-25%下载率
-			notes: Math.floor(baseViewers * (0.4 + Math.random() * 0.3)), // 40%-70%笔记率
-			discussions: Math.floor(baseViewers * (0.15 + Math.random() * 0.15)) // 15%-30%讨论率
-		})
-	}
-
-	return {
-		code: 200,
-		data: chapters
-	}
-}
-
 // 生成图表数据
 const generateChartData = (options) => {
 	const params = new URLSearchParams(options.url.split('?')[1])
@@ -257,9 +99,6 @@ const generateChartData = (options) => {
 }
 // Mock 接口定义
 Mock.mock(/\/api\/webapp\/video-analysis\/course-options/, 'get', generateCourseOptions)
-Mock.mock(/\/api\/webapp\/video-analysis\/stats/, 'get', generateVideoStats)
-Mock.mock(/\/api\/webapp\/video-analysis\/students/, 'get', generateStudentData)
-Mock.mock(/\/api\/webapp\/video-analysis\/chapters/, 'get', generateChapterData)
 Mock.mock(/\/api\/webapp\/video-analysis\/charts/, 'get', generateChartData)
 
 // 导出的API函数
@@ -268,21 +107,31 @@ export const videoAnalysisApi = {
 	getCourseOptions() {
 		return request('/video-analysis/course-options', '', 'get')
 	},
-
-	// 获取视频分析统计数据
-	getVideoStats(params = {}) {
-		console.log('params=', params)
-		return request('/video-analysis/stats', params, 'get')
+	// 视频分析-观看人数统计
+	watchUserCountProgress(params = {}) {
+		return request('/disk/videoanalysis/watchUserCountProgress', params, 'get')
+	},
+	// 视频分析-讲义下载次数
+	teachMaterialsDownloadCount(params = {}) {
+		return request('/disk/videoanalysis/teachMaterialsDownloadCount', params, 'get')
+	},
+	// 视频分析-跳出时间分析
+	jumpTimeAnalyse(params = {}) {
+		return request('/disk/videoanalysis/jumpTimeAnalyse', params, 'get')
+	},
+	// 视频分析-互动统计分析
+	interactionDataAnalyse(params = {}) {
+		return request('/disk/videoanalysis/interactionDataAnalyse', params, 'get')
 	},
 
 	// 获取学员详细数据
-	getStudentData(params = {}) {
-		return request('/video-analysis/students', params, 'get')
+	studyBehaviorDetailData(params = {}) {
+		return request('/disk/videoanalysis/studyBehaviorDetailData', params, 'get')
 	},
 
 	// 获取章节数据
-	getChapterData(params = {}) {
-		return request('/video-analysis/chapters', params, 'get')
+	videoDetailDataAnalysis(params = {}) {
+		return request('/disk/videoanalysis/videoDetailDataAnalysis', params, 'get')
 	},
 
 	// 获取图表数据

+ 72 - 5
src/views/resourceCenter/components/ComplexChoices.vue

@@ -110,6 +110,20 @@
 							:index="index"
 						></MyRadioButton>
 					</MyRadioButtonGroup>
+					<MyRadioButtonGroup
+						ref="TypeSmail"
+						v-show="selectedTypesSmail.length > 0"
+						v-model="selectedTypeSmail"
+						@change="handleTypeChangeSmail"
+					>
+						<MyRadioButton
+							v-for="(item, index) in selectedTypesSmail"
+							:key="index"
+							:value="index"
+							:label="item.name"
+							:index="index"
+						></MyRadioButton>
+					</MyRadioButtonGroup>
 				</div>
 			</a-spin>
 		</div>
@@ -183,6 +197,7 @@
 	const selectedCourse = ref('')
 	const selectedTypeBig = ref('')
 	const selectedType = ref('')
+	const selectedTypeSmail = ref('')
 	const selectedFormat = ref('')
 	const Dept = ref(null)
 	const Big = ref(null)
@@ -190,6 +205,7 @@
 	const Course = ref(null)
 	const TypeBig = ref(null)
 	const Type = ref(null)
+	const TypeSmail = ref(null)
 	const Format = ref(null)
 
 	const selectedTags = ref([])
@@ -228,6 +244,7 @@
 	const selectedTypesBig = ref([])
 	const spinningSelectedTypesBig = ref(false)
 	const selectedTypes = ref([])
+	const selectedTypesSmail = ref([])
 	const selectedFormats = ref([])
 	const spinningSelectedFormats = ref(false)
 
@@ -263,18 +280,20 @@
 		updateSelectedTags()
 	}
 	const handleSelectedSmails = (e) => {
-		// if (e == 0) {
-		// 	selectedDeptSmails.value = []
-		// } else {
-		// 	selectedDeptSmails.value = selectedDeptSmailsList.value[e]
-		// }
+		if (e == 0) {
+			selectedDeptSmails.value = []
+		} else {
+			selectedDeptSmails.value = selectedDeptSmailsList.value[e]
+		}
 		// selectedDeptSmails.value = selectedDeptSmailsList.value[e]
 		updateSelectedTags()
 	}
 	// 处理课程类型选择变化
 	const handleTypeChangeBig = (e) => {
+		selectedTypesSmail.value = []
 		if (e == 0) {
 			selectedTypes.value = []
+
 		} else {
 			selectedTypes.value = selectedTypesBigList.value[e]
 		}
@@ -283,11 +302,32 @@
 		if (selectedTypes.value.length > 0) {
 			Type.value.setClean(-1)
 		}
+		if (selectedTypeSmail.value.length > 0) {
+			TypeSmail.value.setClean(-1)
+		}
 		selectedType.value = -1
+		selectedTypeSmail.value = -1
 		updateSelectedTags()
 	}
 	const handleTypeChange = (e) => {
 		console.log('handleTypeChange', ' e ', e, selectedTypes.value)
+		if (e == 0) {
+			selectedTypesSmail.value = []
+		} else {
+			selectedTypesSmail.value = selectedTypesList.value[e - 1]
+		}
+
+		// selectedFormat.value = undefined // 选择课程类型时,重置课件格式
+		// updateSelectedTags()
+		updateSelectedTags()
+	}
+	const handleTypeChangeSmail = (e) => {
+		console.log('handleTypeChange', ' e ', e, selectedTypes.value)
+		// if (e == 0) {
+		// 	selectedTypesSmail.value = []
+		// } else {
+		// 	selectedTypesSmail.value = selectedTypesList.value[e - 1]
+		// }
 		// selectedFormat.value = undefined // 选择课程类型时,重置课件格式
 		// updateSelectedTags()
 		updateSelectedTags()
@@ -405,6 +445,25 @@
 				queryData['resourceTwoType'] = selectedTypes.value[selectedType.value].id
 			}
 		}
+		if (
+			selectedTypeSmail.value !== undefined &&
+			selectedTypeSmail.value !== '' &&
+			selectedTypeSmail.value > 0 &&
+			selectedTypesSmail.value.length > 0
+		) {
+			if (selectedTypesSmail.value[selectedTypeSmail.value]) {
+				selectedTags.value.push(...[selectedTypesSmail.value[selectedTypeSmail.value].name])
+				selectedTagKeys.value.push({
+					listType: 6,
+					key: 'resourceThreeType',
+					index: selectedTypeSmail.value,
+					name: selectedTypesSmail.value[selectedTypeSmail.value].name,
+					id: selectedTypesSmail.value[selectedTypeSmail.value].id
+				})
+				queryData['resourceThreeType'] = selectedTypesSmail.value[selectedTypeSmail.value].id
+			}
+			console.log('123123',selectedTagKeys.value)
+		}
 		if (
 			selectedFormat.value !== undefined &&
 			selectedFormat.value !== '' &&
@@ -483,6 +542,13 @@
 			selectedDeptBig.value = -1
 			Dept.value.setClean(-1)
 			selectedDept.value = -1
+			TypeSmail.value.setClean(-1)
+			selectedTypeSmail.value = -1
+		}
+		if (tag.key == 'selectedTypeSmail') {
+
+			TypeSmail.value.setClean(-1)
+			selectedTypeSmail.value = -1
 		}
 		console.log('要删除的东西', tag)
 
@@ -572,6 +638,7 @@
 			})
 			spinningSelectedTypesBig.value = false
 		})
+		console.log('有数据吗',selectedTypesList.value)
 		spinningSelectedFormats.value = true
 		getAllListFileFormat().then((data) => {
 			selectedFormats.value = data.data

+ 2 - 2
src/views/statisticalAnalysis/analysisLearningBehaviors/index.vue

@@ -59,9 +59,9 @@
 
 				<div class="stat-card">
 					<h3>👥 用户登录统计</h3>
-					<div class="stat-number">{{ collegeStats.allLoginCount.toLocaleString() }}</div>
+					<div class="stat-number">{{ collegeStats.allLoginCount }}</div>
 					<div class="stat-label">总登录人次</div>
-					<div class="stat-number">{{ collegeStats.userCount.toLocaleString() }}</div>
+					<div class="stat-number">{{ collegeStats.userCount }}</div>
 					<div class="stat-label">独立用户数</div>
 					<div class="stat-number">{{ collegeStats.avgLoginCount }}</div>
 					<div class="stat-label">人均登录次数</div>

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
stats.html


Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff