于添 5 місяців тому
батько
коміт
c1171f2448

+ 22 - 1
src/utils/tool.js

@@ -1,4 +1,4 @@
- 
+
 /*
  * @Descripttion: 工具集
  * @version: 1.1
@@ -219,4 +219,25 @@ tool.writeText = (text) => {
 	document.body.removeChild(copyInput)
 }
 
+
+// 添加上面的 formatValue 函数
+tool.formatValue = (value) => {
+	if (value === 0 || value === '0') {
+		return '0'+'%';
+	}
+
+	const num = typeof value === 'string' ? parseFloat(value) : value;
+	const result = num * 100;
+
+	// 转为带两位小数的字符串,然后去除末尾不必要的0
+	let formatted = result.toFixed(2);
+	if (formatted.endsWith('.00')) {
+		formatted = formatted.slice(0, -3); // 去掉 .00
+	} else if (formatted.endsWith('0')) {
+		formatted = formatted.slice(0, -1); // 去掉末尾的0
+	}
+
+	return formatted + '%';
+}
+
 export default tool

+ 43 - 17
src/views/courseAdd/components/courseInfo.vue

@@ -8,7 +8,7 @@
 		:wrapper-col="{ span: 21 }"
 	>
 		<a-form-item label="教室名称" name="courseName">
-			<a-input v-model:value="formState.courseName" placeholder="输入教室名称" />
+			<a-input v-model:value="formState.courseName" placeholder="输入教室名称" show-count maxlength="50"/>
 		</a-form-item>
 
 		<a-form-item label="授课教师" name="teacherId">
@@ -52,14 +52,16 @@
 		</a-form-item> -->
 
 		<a-form-item label="教室描述" name="courseDesc">
-			<quill-editor
-				ref="quillEditorRef"
-				placeholder="请输入教室描述"
-				v-model:content="formState.courseDesc"
-				style="height: 200px"
-				contentType="html"
-				theme="snow"
-			/>
+<!--			<quill-editor-->
+<!--				ref="quillEditorRef"-->
+<!--				placeholder="请输入教室描述"-->
+<!--				v-model:content="formState.courseDesc"-->
+<!--				style="height: 200px"-->
+<!--				contentType="html"-->
+<!--				theme="snow"-->
+<!--			/>-->
+<!--			<span>{{MIN_LENGTH}}/{{MAX_LENGTH}}</span>-->
+			<a-textarea v-model:value="formState.courseDesc" :maxlength="100" show-count ></a-textarea>
 		</a-form-item>
 
 		<a-form-item :wrapper-col="{ offset: 11, span: 2 }">
@@ -89,6 +91,8 @@
 			default: null
 		}
 	})
+	const MAX_LENGTH = ref(50) //教师
+	const MIN_LENGTH = ref(0) //教师
 	const formState = reactive({
 		courseName: null,
 		teacherId: null,
@@ -131,7 +135,7 @@
 		// }
 
 		// courseDesc.ops
-		formState.courseDesc = toRaw(quillEditorRef.value).getHTML()
+		// formState.courseDesc = toRaw(quillEditorRef.value).getHTML()
 		courseCenterApi
 			.add(formState)
 			.then((res) => {
@@ -145,7 +149,7 @@
 	}
 	const handleEdit = () => {
 		// collegeId
-		formState.courseDesc = toRaw(quillEditorRef.value).getHTML()
+		// formState.courseDesc = toRaw(quillEditorRef.value).getHTML()
 		courseCenterApi
 			.edit({ ...formState, courseId: courseInfoId.value })
 			.then((res) => {
@@ -176,7 +180,7 @@
 	//获取教师人员
 	const getlecturerListSelector = () => {
 		courseCenterApi
-			.lecturerList()
+			.lecturerList({eduIdentity:1})
 			.then((res) => {
 				teacherOptions.value = res.data
 			})
@@ -250,7 +254,7 @@
 			getCollegeMajor(formState.collegeTwoId)
 			formState.courseType = res.data.courseType
 			formState.courseDesc = res.data.courseDesc
-			toRaw(quillEditorRef.value).setHTML(formState.courseDesc)
+			// toRaw(quillEditorRef.value).setHTML(formState.courseDesc)
 			formState.coverImageId = res.data.coverImageId
 			coverImagePath.value = res.data.coverImagePath
 			formState.majorId = res.data.majorId
@@ -263,9 +267,9 @@
 			formState.courseDesc = ''
 			coverImagePath.value = undefined
 			// 重置富文本编辑器内容
-			if (quillEditorRef.value) {
-				toRaw(quillEditorRef.value).setHTML('')
-			}
+			// if (quillEditorRef.value) {
+			// 	toRaw(quillEditorRef.value).setHTML('')
+			// }
 		}
 	}
 
@@ -285,7 +289,24 @@
 		},
 		{ immediate: true }
 	)
-
+	nextTick(()=>{
+		// let quill = quillEditorRef.value.getQuill()
+		// console.log('看看',quill)
+		// quill.root.addEventListener('paste', handlePaste, false);
+		// // 限制最大字符数
+		// // const MAX_LENGTH = 100;
+		//
+		// quill.on('text-change', function(delta, oldDelta, source) {
+		// 	const text = quill.getText();
+		// 	console.log('看看记录',text.length)
+		// 	MIN_LENGTH.value = text.length-1
+		// 	if (text.length > MAX_LENGTH.value) {
+		//
+		// 		// 截断超出部分
+		// 		quill.deleteText(MAX_LENGTH.value, text.length - MAX_LENGTH.value);
+		// 	}
+		// });
+	})
 	// 初始化数据
 	// onMounted(() => {
 	// 	// toRaw(quillEditorRef.value).setHTML(props.value)
@@ -297,6 +318,11 @@
 	// 		getDetail()
 	// 	}
 	// })
+	onMounted(()=>{
+		resetForm()
+	})
+
+	defineExpose({resetForm})
 </script>
 
 <style scoped>

+ 3 - 1
src/views/courseAdd/components/courseProduction/addDialog.vue

@@ -98,7 +98,7 @@ const open = () => {
 	activeKey.value = '1'
 	modeTag.value = 'add'
 	nextTick(() => {
-		addClassHoursRef.value.reset()
+		addClassHoursRef.value.handleReset()
 		addClassHoursRef.value.open()
 		item1.value = item1.value+1
 
@@ -191,6 +191,8 @@ const edit = (item) => {
 	modeTag.value = 'edit'
 	console.log('有没有', addClassHoursRef.value)
 	nextTick(() => {
+		exListRef.value.handleReset()
+		exListsRef.value.handleReset()
 		addClassHoursRef.value.edit(item)
 		item1.value = item1.value+1
 	})

+ 1 - 1
src/views/courseAdd/components/courseProduction/exList.vue

@@ -310,7 +310,7 @@
 	}
 	// 生命周期
 	onMounted(async () => {
-		console.log('打开了  2')
+		console.log('打开了  作业')
 	})
 
 	defineExpose({getItemData,edit,open,editNot,handleReset})

+ 1 - 1
src/views/courseAdd/components/courseProduction/exLists.vue

@@ -305,7 +305,7 @@
 	// 生命周期
 	onMounted(async () => {
 		// examStore.initSubject(search)
-		console.log('打开了  3')
+		console.log('打开了  章节测验')
 	})
 	const open=() =>{
 		examStore.initSubject(search)

+ 4 - 0
src/views/courseAdd/components/courseProduction/index.vue

@@ -232,6 +232,7 @@
 	}
 	// 获取章节列表
 	const getList = () => {
+		console.log('获取列表章节')
 		courseProductionApi
 			.allList({ courseId: props.courseInfoId })
 			.then((res) => {
@@ -271,6 +272,9 @@
 	// onMounted(() => {
 	// 	getList()
 	// })
+	defineExpose({
+		getList
+	})
 </script>
 
 <style scoped>

+ 16 - 4
src/views/courseAdd/index.vue

@@ -2,12 +2,12 @@
 	<div style="overflow-y: auto">
 		<!-- <img :src="images" style="width: 100%; height: 100%" /> -->
 		<div>
-			<a-tabs v-model:activeKey="activeKey" type="card">
-				<a-tab-pane key="1" tab="教室信息">
+			<a-tabs v-model:activeKey="activeKey" type="card" @change="change">
+				<a-tab-pane key="1" tab="教室信息" forceRender>
 					<courseInfo :courseInfoId="courseInfoId" @nextStep="nextStep" />
 				</a-tab-pane>
-				<a-tab-pane key="2" tab="课程制作" :disabled="courseInfoId == null">
-					<courseProduction :courseInfoId="courseInfoId" />
+				<a-tab-pane key="2" tab="课程制作" :disabled="courseInfoId == null" forceRender>
+					<courseProduction ref="courseProductionRef" :courseInfoId="courseInfoId" />
 				</a-tab-pane>
 				<!-- <a-tab-pane key="3" tab="学员管理" :disabled="courseInfoId == null">
 					<StudentDetails :courseInfoId="courseInfoId"></StudentDetails>
@@ -29,6 +29,7 @@
 	import courseProduction from './components/courseProduction/index.vue'
 	import StudentDetails from './components/StudentDetails.vue'
 	const activeKey = ref('1') // 默认选中的标签页
+	const courseProductionRef = ref('1') // 默认选中的标签页
 	const props = defineProps({
 		courseInfoId: {
 			type: String,
@@ -59,6 +60,17 @@
 		localCourseInfoId.value = id
 		activeKey.value = '2'
 	}
+	const  change = (key) => {
+		if(key == '1'){
+			nextTick(()=>{
+				courseProductionRef.value.getList()
+			})
+		}
+		if(key == '2'){
+
+		}
+	}
+
 	// onMounted(() => {
 	// })
 </script>

+ 15 - 15
src/views/courseManagement/components/QueryView.vue

@@ -5,23 +5,23 @@
 				<a-form-item label="" style="width: 20%">
 					<a-input v-model:value="formState.courseName" placeholder="请输入课程名称" allowClear />
 				</a-form-item>
-				<a-form-item label="" style="width: 15%">
-<!--					<a-cascader-->
-<!--						v-model:value="formState.loacl"-->
-<!--						:options="options"-->
-<!--						placeholder="选择院校"-->
-<!--						change-on-select-->
+<!--				<a-form-item label="" style="width: 15%">-->
+<!--&lt;!&ndash;					<a-cascader&ndash;&gt;-->
+<!--&lt;!&ndash;						v-model:value="formState.loacl"&ndash;&gt;-->
+<!--&lt;!&ndash;						:options="options"&ndash;&gt;-->
+<!--&lt;!&ndash;						placeholder="选择院校"&ndash;&gt;-->
+<!--&lt;!&ndash;						change-on-select&ndash;&gt;-->
+<!--&lt;!&ndash;						allowClear&ndash;&gt;-->
+<!--&lt;!&ndash;						:field-names="{ label: 'name', value: 'id', children: 'children' }"&ndash;&gt;-->
+<!--&lt;!&ndash;					/>&ndash;&gt;-->
+<!--					<a-select-->
+<!--						v-model:value="formState.collegeTwoId"-->
+<!--						:fieldNames="{ label: 'name', value: 'id' }"-->
+<!--						:options="collegeMajorOptions"-->
+<!--						placeholder="请选择院系"-->
 <!--						allowClear-->
-<!--						:field-names="{ label: 'name', value: 'id', children: 'children' }"-->
 <!--					/>-->
-					<a-select
-						v-model:value="formState.collegeTwoId"
-						:fieldNames="{ label: 'name', value: 'id' }"
-						:options="collegeMajorOptions"
-						placeholder="请选择院系"
-						allowClear
-					/>
-				</a-form-item>
+<!--				</a-form-item>-->
 				<a-form-item label="" style="width: 20%">
 <!--					<a-input v-model:value="formState.type" placeholder="选择课程类型" allowClear />-->
 					<a-select

+ 3 - 1
src/views/dev/log/vislog/detail.vue

@@ -12,7 +12,7 @@
 			<a-descriptions-item label="地址">{{ formData.opAddress }}</a-descriptions-item>
 			<a-descriptions-item label="浏览器">{{ formData.opBrowser }}</a-descriptions-item>
 			<a-descriptions-item label="设备">{{ formData.opOs }}</a-descriptions-item>
-			<a-descriptions-item label="时间">{{ formData.opTime }}</a-descriptions-item>
+			<a-descriptions-item label="时间">{{dayjs(formData.opTime).format('YYYY-MM-DD HH:mm:ss')}}</a-descriptions-item>
 			<a-descriptions-item label="用户">{{ formData.opUser }}</a-descriptions-item>
 		</a-descriptions>
 	</xn-form-container>
@@ -20,6 +20,8 @@
 
 <script setup name="vislogDetail">
 	// 默认是关闭状态
+	import dayjs from "dayjs";
+
 	let visible = $ref(false)
 	// 表单数据
 	const formData = ref({})

+ 5 - 5
src/views/notice/index.vue

@@ -38,13 +38,13 @@
 			:pagination="pagination"
 			row-key="noticeId"
 			@change="handleTableChange"
-			:scroll="{ x: 1500, y: 300 }"
-		>
+			:scroll="{ x: 1500, y: 300 }">
+<!--		>1-课程,2-考试,3-系统-->
 			<template #bodyCell="{ column, record }">
 				<template v-if="column.key === 'platform'">
-					<a-tag :color="record.platform === 1 ? 'blue' : 'green'">
-						{{ record.platform === 1 ? '课程' : '考试' }}
-					</a-tag>
+					<a-tag v-if="record.platform == 1" color="blue">课程</a-tag>
+					<a-tag v-if="record.platform == 2" color="green">考试</a-tag>
+					<a-tag v-if="record.platform == 3" color="red">系统</a-tag>
 				</template>
 
 				<template v-if="column.key === 'noticeStatus'">

+ 26 - 20
src/views/statisticalAnalysis/analysisLearningBehaviors/index.vue

@@ -24,7 +24,7 @@
 				<div class="filter-controls">
 					<div class="filter-group">
 						<label>选择学院</label>
-						<a-select v-model:value="collegeFilters.collegeId" placeholder="全部学院" @change="updateCollegeData">
+						<a-select v-model:value="collegeFilters.collegeId" placeholder="全部学院" @change="updateCollegeData" allowClear>
 							<a-select-option v-for="college in collegeList" :key="college.id" :value="college.id">
 								{{ college.name }}
 							</a-select-option>
@@ -32,12 +32,13 @@
 					</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>
+<!--						<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>-->
+						<a-range-picker class="w-full" v-model:value="times" />
 					</div>
 					<div class="filter-group">
 						<a-button type="primary" @click="updateCollegeData">查询</a-button>
@@ -182,14 +183,17 @@
 		getCollegeCourseDetails,
 		searchStudents
 	} from '@/api/statisticalAnalysis/analysisLearningBehaviors'
+	import dayjs from "dayjs";
 
 	// 当前活动标签
 	const activeTab = ref('college')
+	const times = ref([])
 
 	// 学院维度筛选条件
 	const collegeFilters = reactive({
 		collegeId: '',
-		timeRange: 30
+		startTime: computed(() => (  times.value && times.value[0] ? dayjs(times.value[0]).format('YYYY-MM-DD') :  undefined)),
+		endTime: computed(() => (times.value && times.value[1] ? dayjs(times.value[1]).format('YYYY-MM-DD') :  undefined))
 	})
 
 	// 学院列表
@@ -439,8 +443,8 @@
 			// 获取学院统计数据 船锚
 			const statsResponse = await getCollegeStats({
 				orgId: collegeFilters.collegeId,
-				startTime : formatDateWithDays(0),
-				endTime : formatDateWithDays(collegeFilters.timeRange)
+				startTime : collegeFilters.startTime,
+				endTime : collegeFilters.endTime
 			})
 			console.log("asdasd",statsResponse.data)
 			// Object.assign(collegeStats, statsResponse.data)
@@ -448,8 +452,8 @@
 			// 获取课程详细统计
 			const detailsResponse = await getCollegeCourseDetails({
 				orgId: collegeFilters.collegeId,
-				startTime : formatDateWithDays(0),
-				endTime : formatDateWithDays(collegeFilters.timeRange)
+				startTime : collegeFilters.startTime,
+				endTime : collegeFilters.endTime
 			})
 			collegeTableData.value = detailsResponse.data
 
@@ -506,8 +510,8 @@
 		try {
 			const response = await getLoginTimeDistribution({
 				orgId: collegeFilters.collegeId,
-				startTime : formatDateWithDays(0),
-				endTime : formatDateWithDays(1),
+				startTime : collegeFilters.startTime,
+				endTime : collegeFilters.endTime,
 				current : 1,
 				size : 24
 			})
@@ -617,14 +621,16 @@
 		try {
 			const response = await getCourseHeat({
 				orgId: collegeFilters.collegeId,
-				startTime : formatDateWithDays(0),
-				endTime : formatDateWithDays(1),
+				startTime : collegeFilters.startTime,
+				endTime : collegeFilters.endTime,
 				current : 1,
 				size : 8
 			})
 
 			const { courses, visits } = response
-
+			console.log('热门数组是什么',courses,visits)
+			let list = [...courses].reverse();
+			let lists = [...visits].reverse();
 			const option = {
 				title: {
 					text: '课程访问热度TOP8',
@@ -666,7 +672,7 @@
 				},
 				yAxis: {
 					type: 'category',
-					data: courses,
+					data: list,
 					axisLine: {
 						lineStyle: {
 							color: '#bdc3c7'
@@ -680,7 +686,7 @@
 					{
 						name: '访问量',
 						type: 'bar',
-						data: visits,
+						data: lists,
 						itemStyle: {
 							color: {
 								type: 'linear',
@@ -727,7 +733,7 @@
 			// 获取学院列表
 			const colleges = await getCollegeList()
 			collegeList.value = colleges
-			collegeFilters.collegeId = colleges.length > 0 ? colleges[0].id : undefined
+			// collegeFilters.collegeId = colleges.length > 0 ? colleges[0].id : undefined
 			// 获取初始学员数据
 			// await searchStudent()
 

+ 27 - 18
src/views/statisticalAnalysis/analysisTeachingActivities/index.vue

@@ -26,12 +26,13 @@
 				</div>
 				<div class="filter-group">
 					<label>时间范围</label>
-					<a-select v-model:value="filters.timeRange" @change="updateStats">
-						<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>
+<!--					<a-select v-model:value="filters.timeRange" @change="updateStats">-->
+<!--						<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>-->
+					<a-range-picker class="w-full" v-model:value="times" />
 				</div>
 				<div class="filter-group">
 					<a-button type="primary" @click="updateStats" :loading="loading">查询</a-button>
@@ -47,7 +48,7 @@
 				<div class="stat-label">总观看人数</div>
 				<div class="stat-number">{{ stats.alreadyUserCount }}</div>
 				<div class="stat-label">完成观看人数</div>
-				<div class="completion-rate">{{ stats.finishRate }}%</div>
+				<div class="completion-rate">{{tool.formatValue(stats.finishRate) }}</div>
 				<div class="stat-label">完成率</div>
 			</div>
 
@@ -55,7 +56,7 @@
 				<h3>🚪 文档跳出分析</h3>
 				<div class="stat-number">{{ stats.allHourCount }}</div>
 				<div class="stat-label">总跳出次数</div>
-				<div class="stat-number">{{ stats.allHourCount }}%</div>
+				<div class="stat-number">{{tool.formatValue(stats.allHourCount)  }}</div>
 				<div class="stat-label">跳出率</div>
 				<div class="stat-number">{{ stats.jumpAvgTime }}</div>
 				<div class="stat-label">平均跳出时间</div>
@@ -130,7 +131,7 @@
 </template>
 
 <script setup>
-	import { ref, reactive, onMounted, nextTick, h } from 'vue'
+import {ref, reactive, onMounted, nextTick, h, computed} from 'vue'
 	import * as echarts from 'echarts'
 	import {
 		getCourseOptions,
@@ -142,11 +143,16 @@
 		getDocumentStats
 	} from '@/api/statisticalAnalysis/analysisTeachingActivities'
 	import tool from '@/utils/tool'
+import dayjs from "dayjs";
+// 课程选项
+const courseOptions = ref([])
+const times = ref([])
 	const forumType = computed(() => (tool.dictList('FORUM_TYPE')[0].value == 1 ? true : false))
 	// 响应式数据
 	const filters = reactive({
-		courseId: '',
-		timeRange: 1
+		courseId: undefined,
+		startTime: computed(() => (  times.value && times.value[0] ? dayjs(times.value[0]).format('YYYY-MM-DD') :  undefined)),
+		endTime: computed(() => (times.value && times.value[1] ? dayjs(times.value[1]).format('YYYY-MM-DD') :  undefined))
 	})
 
 	const stats = reactive({
@@ -164,8 +170,7 @@
 		teacherAvgPostsPerDay: 0
 	})
 
-	// 课程选项
-	const courseOptions = ref([])
+
 
 	// 图表引用
 	const dailyVisitsChart = ref(null)
@@ -305,7 +310,7 @@
 
 		const option = {
 			title: {
-				text: `最近${days}天访问人数趋势`,
+				text: `最近一个月访问人数趋势`,
 				left: 'center',
 				textStyle: {
 					color: '#2c3e50',
@@ -431,11 +436,13 @@
 		try {
 			const response = await getTeachingStats({
 				courseId: filters.courseId,
-				type: filters.timeRange
+				startTime: filters.startTime,
+				endTime: filters.endTime,
 			})
 			const statistic = await documentJumpStatistic({
 				courseId: filters.courseId,
-				type: filters.timeRange
+				startTime: filters.startTime,
+				endTime: filters.endTime,
 			})
 
 			Object.assign(stats, response, statistic)
@@ -460,7 +467,6 @@
 	const loadDailyVisits = async () => {
 		try {
 			const response = await getDailyVisits({
-				type: filters.timeRange,
 				courseId: filters.courseId
 			})
 			chartData.dates = response.map((r) => r.TIME)
@@ -476,6 +482,8 @@
 		try {
 			const response = await getDiscussionData({
 				courseId: filters.courseId,
+				startTime: filters.startTime,
+				endTime: filters.endTime,
 				page: discussionPagination.current,
 				pageSize: discussionPagination.pageSize
 			})
@@ -493,7 +501,8 @@
 				courseId: filters.courseId,
 				page: documentPagination.current,
 				pageSize: documentPagination.pageSize,
-				type: filters.timeRange
+				startTime: filters.startTime,
+				endTime: filters.endTime,
 			})
 			documentData.value = response
 			documentPagination.total = response.total

+ 4 - 4
src/views/statisticalAnalysis/overviewLearningProgress/index.vue

@@ -181,13 +181,13 @@
 		},
 		{
 			title: '讲义访问量',
-			dataIndex: 'stayTime',
-			key: 'stayTime'
+			dataIndex: 'teachMaterialsNum',
+			key: 'teachMaterialsNum'
 		},
 		{
 			title: '练习提交量',
-			dataIndex: 'teachMaterialsNum',
-			key: 'teachMaterialsNum'
+			dataIndex: 'paperSubmitNum',
+			key: 'paperSubmitNum'
 		}
 	]
 

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

@@ -113,7 +113,7 @@
 			</div>
 
 			<footer>
-				<p>数据更新时间: {{ updateTime }} | 资源库统计分析系统</p>
+				<p>数据更新 资源库统计分析系统</p>
 			</footer>
 		</div>
 	</div>
@@ -482,7 +482,7 @@
 					},
 					xAxis: {
 						type: 'value',
-						name: '文件数量'
+						name: ''
 					},
 					yAxis: {
 						type: 'category',

+ 4 - 3
src/views/statisticalAnalysis/videoAnalysis/index.vue

@@ -45,7 +45,7 @@
 				<div class="stat-label">总观看人数</div>
 				<div class="stat-number">{{ stats.countData.completeWatchUserCount }}</div>
 				<div class="stat-label">完成观看人数</div>
-				<div class="completion-rate">{{ stats.countData.completeRate*100 }}%</div>
+				<div class="completion-rate">{{ tool.formatValue(stats.countData.completeRate) }}</div>
 				<div class="stat-label">完成率</div>
 			</div>
 
@@ -53,7 +53,7 @@
 				<h3>📥 讲义下载统计</h3>
 				<div class="stat-number">{{ stats.downData.allDownloadCount }}</div>
 				<div class="stat-label">总下载次数</div>
-				<div class="stat-number">{{ stats.downData.downloadRate*100 }}%</div>
+				<div class="stat-number">{{tool.formatValue(stats.downData.downloadRate)}}</div>
 				<div class="stat-label">下载率</div>
 				<div class="stat-number">{{ stats.downData.avgDownloadCount }}</div>
 				<div class="stat-label">人均下载次数</div>
@@ -63,7 +63,7 @@
 				<h3>⏱️ 跳出时间分析</h3>
 				<div class="stat-number">{{ stats.jumpData.jumpOutCount }}</div>
 				<div class="stat-label">总跳出次数</div>
-				<div class="stat-number">{{ stats.jumpData.jumpOutRate*100 }}%</div>
+				<div class="stat-number">{{tool.formatValue(stats.jumpData.jumpOutRate)}}</div>
 				<div class="stat-label">跳出率</div>
 				<div class="stat-number">{{ stats.jumpData.jumpAvgTime }}</div>
 				<div class="stat-label">平均跳出时间</div>
@@ -168,6 +168,7 @@
 	import { getCourseOptions } from '@/api/statisticalAnalysis/analysisTeachingActivities'
 	import { videoAnalysisApi } from '@/api/statisticalAnalysis/videoAnalysis'
 	import dayjs from 'dayjs'
+	import tool from "@/utils/tool";
 
 	// 筛选条件
 	const times = ref([])