Quellcode durchsuchen

论坛-技术纠错展示
课程详情-问答/笔记跳转视频时间
课程详情-讲义切换显示问题
课程中心-学习进度
学习足迹-学习课时
考试-任务
章节测试/作业-课程下挂载作业/章节
课程中心埋点问题
网页功能-外部链接/文字

canghailong vor 6 Monaten
Ursprung
Commit
33dd78127f

+ 7 - 0
src/router/student.js

@@ -10,6 +10,13 @@ const forum = [
 		path: '/student',
 		component: () => import('@/views/portal/index.vue'),
 		children: [
+			{
+				path: '/webEmpty',
+				component: () => import('@/views/student/classCentre/webEmpty.vue'),
+				meta: {
+					title: '第三方网址链接'
+				}
+			},
 			{
 				path: '/userInfo',
 				component: () => import('@/views/student/user/index.vue'),

+ 4 - 1
src/views/courseCenter/components/ResourceList.vue

@@ -56,7 +56,10 @@
 					</div>
 					<div style="display: flex; flex-direction: column; padding: 5px 10px">
 						<span style="font-size: 16px; font-weight: bold">{{ item.courseName || '-' }}</span>
-						<div><a-progress :percent="item.progressVal" /></div>
+						<div>
+							<div>学习进度</div>
+							<a-progress :percent="item.progressVal" />
+						</div>
 						<span style="font-size: 12px">{{ item.majorIdName || '-' }}</span>
 						<span style="font-size: 12px">{{ item.teacherIdName || '-' }}</span>
 					</div>

+ 17 - 0
src/views/forum/detail.vue

@@ -33,6 +33,20 @@
 						</a-button>
 					</a-tooltip>
 				</div>
+				<a-descriptions title="设备信息" class="equ" v-if="detailObj.forumSupportEnv">
+					<a-descriptions-item label="浏览器类型:">
+						<span>{{ detailObj.forumSupportEnv.browserType }}</span>
+					</a-descriptions-item>
+					<a-descriptions-item label="浏览器版本号:">
+						<span>{{ detailObj.forumSupportEnv.browserVersion }}</span>
+					</a-descriptions-item>
+					<a-descriptions-item label="操作系统:">
+						<span>{{ detailObj.forumSupportEnv.osType }}</span>
+					</a-descriptions-item>
+					<a-descriptions-item label="操作系统版本号:">
+						<span>{{ detailObj.forumSupportEnv.osVersion }}</span>
+					</a-descriptions-item>
+				</a-descriptions>
 				<div class="htmlContent" v-html="detailObj.postContent"></div>
 				<div class="flc">
 					<div v-if="detailObj.userNickName">
@@ -224,6 +238,9 @@
 	:deep(.htmlContent img) {
 		max-width: 100% !important;
 	}
+	:deep(.equ .ant-descriptions-header){
+		margin-bottom: 10px;
+	}
 	.snowy-index-card-left-one-username {
 		margin-left: 8px;
 		display: flex;

+ 1 - 1
src/views/forum/form.vue

@@ -124,7 +124,7 @@
 		})
 		getUserAllList()
 		if (module) {
-			if (record.appointUser) {
+			if (record?.appointUser) {
 				record.appointUserArr = record.appointUser.split(',')
 			}
 			formData.value = Object.assign(formData.value, record)

+ 1 - 1
src/views/student/classCentre/ask.vue

@@ -184,7 +184,7 @@
 					return {
 						...r,
 						loading: false,
-						startTime: r.recordTime ?? 0,
+						startTime: parseFloat(r.recordTime)/1000 ?? 0,
 						videoStopTime: formatTime(r.recordTime ?? 0)
 					}
 				})

+ 22 - 9
src/views/student/classCentre/handouts.vue

@@ -5,9 +5,11 @@
 			<a-button type="primary" @click="downPdf">下载讲义</a-button>
 		</div>
 		<vue-office-pdf
-			:src="props.itemObj.url"
+			v-if="showPdf"
+			:src="pdfSrc"
+			@rendered="renderedHandler"
 			@error="errorHandler"
-			ref="scrollDiv"
+			ref="pdfRef"
 			@scroll="handleScroll"
 			:options="{ width: '100%' }"
 			style="height: calc(100% - 50px)"
@@ -19,8 +21,9 @@
 	import classCentre from '@/api/student/classCentre'
 	import { message } from 'ant-design-vue'
 	import VueOfficePdf from '@vue-office/pdf'
-	const scrollDiv = ref(null)
+	const pdfRef = ref(null)
 	const scrollPercent = ref(0)
+	const maxStr = ref(0)
 	const showPdf = ref(true)
 	const props = defineProps({
 		itemObj: {
@@ -32,12 +35,19 @@
 			default: 0
 		}
 	})
-	function errorHandler() {
+	const pdfSrc = computed(()=>props.itemObj.url)
+	watch(() => pdfSrc.value, (newUrl, oldUrl) => {
+		showPdf.value = true
+		scrollPercent.value = 0
+		maxStr.value = 0
+	}, { immediate: true })
+	
+	function errorHandler(e) {
+		pdfSrc.value = ''
 		showPdf.value = false
 	}
-	const maxStr = ref(0)
 	function handleScroll() {
-		const el = scrollDiv.value.$el
+		const el = pdfRef.value.$el
 		if (!el) return
 		const scrollTop = el.scrollTop
 		const scrollHeight = el.scrollHeight
@@ -70,8 +80,8 @@
 			.then((data) => {})
 	}
 	const addScrollPlan = () => {
-		const el = scrollDiv.value?.$el
-		if(el && el.clientHeight == el.scrollHeight){
+		const el = pdfRef.value?.$el
+		if (el && el.clientHeight == el.scrollHeight) {
 			maxStr.value = 100
 		}
 		classCentre
@@ -84,6 +94,9 @@
 			})
 			.then((data) => {})
 	}
+	function renderedHandler(e) {
+		showPdf.value = true
+	}
 	onBeforeUnmount(() => {
 		outNowTimesStr.value = Date.now()
 		addScrollPlan()
@@ -99,4 +112,4 @@
 		justify-content: space-between;
 		align-items: center;
 	}
-</style>
+</style>

+ 43 - 2
src/views/student/classCentre/index.vue

@@ -64,6 +64,25 @@
 							您的浏览器不支持 HTML5 video 标签。
 						</video>
 					</div>
+					<div>
+						<div>
+							<div v-for="(item,idx) in webCon" >
+								<a :href="item.href" target="_blank">{{ item.title }}</a>
+							</div>
+						</div>
+						<div>
+							在小学和初中,我们已经接触过一些集合.例如,自然数的集合,同一平面内到一个定点的距离等于定长的点的集合(即圆)等.为了更有效地使用集合语言,我们需要进一步了解集合的有关知识.下面先从集合的含义开始.
+							看下面的例子:<br/>
+							(1)1~10之间的所有偶数;<br/>
+							(2)立德中学今年人学的全体高一学生;<br/>
+							(3)所有的正方形;<br/>
+							(4)到直线l的距离等于定长d的所有点<br/>
+							(5)方程x’-3x+2=0的所有实数根;<br/>
+							(6)地球上的四大洋.<br/>
+							例(1)中,我们把1~10之间的每一个偶数作为元素,这些元素的全体就是一个集合;同样地,<br/>
+							例(2)中,把立德中学今年人学的每一位高一学生作为元素,这些元素的全体也是一个集合.
+						</div>
+					</div>
 					<rightMenu
 						:idsObj="idsObj"
 						:dataList="classTimeData"
@@ -265,7 +284,7 @@
 	const videoJumpTime = ref(false)
 	const videoSpeed = (e) => {
 		videoJumpTime.value = true
-		currentTimenew.value = e.startTime
+		currentTimenew.value = parseFloat(e.startTime)
 	}
 
 	const forumData = computed(() => {
@@ -292,7 +311,7 @@
 			.theLastDetail({
 				funcType: 1,
 				type: 1,
-				hourld: classHourData.value?.id
+				hourId: classHourData.value?.id
 			})
 			.then((data) => {
 				if (data.endTime) {
@@ -391,6 +410,28 @@
 		videoRef.value.pause()
 		callback && callback(videoRef.value.currentTime)
 	}
+	const webCon = ref([
+		{
+			title:'1.1 集合的概念',
+			href:'/webEmpty'
+		},
+		{
+			title:'1.2 集合间的基本关系',
+			href:'/webEmpty'
+		},
+		{
+			title:'1.3 集合的基本运算',
+			href:'/webEmpty'
+		},
+		{
+			title:'1.4 充分条件与必要条件',
+			href:'/webEmpty'
+		},
+		{
+			title:'1.5 全称量词与存在量词',
+			href:'/webEmpty'
+		},
+	])
 	onMounted(() => {
 		getClassData()
 	})

+ 1 - 1
src/views/student/classCentre/note.vue

@@ -134,7 +134,7 @@
 					return {
 						...r,
 						loading: false,
-						startTime: r.recordTime ?? 0,
+						startTime: parseFloat(r.recordTime)/1000 ?? 0,
 						videoStopTime: formatTime(r.recordTime ?? 0)
 					}
 				})

+ 7 - 7
src/views/student/classCentre/rightMenu.vue

@@ -105,13 +105,13 @@
 			routerUrl: '/student/paper/1',
 			relateId: route.query.id
 		},
-		{
-			title: '网页',
-			key: '9',
-			icon: IeOutlined,
-			type: 4,
-			routerUrl: 'https://www.baidu.com/'
-		}
+		// {
+		// 	title: '网页',
+		// 	key: '9',
+		// 	icon: IeOutlined,
+		// 	type: 4,
+		// 	routerUrl: 'https://www.baidu.com/'
+		// }
 	])
 	const selectBtn = (event) => {
 		switch (event.type) {

+ 8 - 0
src/views/student/classCentre/webEmpty.vue

@@ -0,0 +1,8 @@
+<template>
+	<a-card :bordered="false">
+		<div>第三方网址链接</div>
+	</a-card>
+</template>
+
+<script setup name="classCentre"></script>
+<style scoped lang="less"></style>

+ 1 - 1
src/views/student/forumBtn/index.vue

@@ -82,7 +82,7 @@
 	.redressBox {
 		position: fixed;
 		right: 10px;
-		top: calc(130px + 60px * 8 + 30px);
+		top: calc(130px + 60px * 7 + 30px);
 	}
 	.addBox {
 		display: flex;

+ 16 - 2
src/views/student/learningFootprint/index.vue

@@ -2,6 +2,7 @@
 	<a-card>
 		<s-table ref="table" :columns="columns" :data="loadData" bordered :row-key="(record) => record.id">
 			<template #bodyCell="{ column, record }">
+				<template v-if="column.dataIndex == 'endTime'">{{ classTime(record) }}</template>
 				<template v-if="column.dataIndex == 'funcType'">{{ funcTypeName(record.funcType) }}</template>
 				<template v-if="column.dataIndex == 'type'">{{ typeName(record.type) }}</template>
 				<template v-if="column.dataIndex === 'action'">
@@ -46,8 +47,17 @@
 			label: '讲义'
 		}
 	])
-	const typeName = computed(() => (e) =>typeList.value.find((r) => r.value == e)?.label)
-	const funcTypeName = computed(() => (e) =>funcTypeList.value.find((r) => r.value == e)?.label)
+	const typeName = computed(() => (e) => typeList.value.find((r) => r.value == e)?.label)
+	const funcTypeName = computed(() => (e) => funcTypeList.value.find((r) => r.value == e)?.label)
+	function formatTime(seconds) {
+		let hours = parseInt(seconds / 3600)
+		let minutes = parseInt((seconds % 3600) / 60)
+		let secondsLeft = seconds % 60
+		return `${hours ? hours + '小时' : ''}${minutes ? minutes + '分' : ''}${secondsLeft}秒`
+	}
+	const classTime = computed(() => (e) => {
+		return formatTime(parseFloat(e.endTime ?? 0) / 1000)
+	})
 	const router = useRouter()
 	const columns = [
 		{
@@ -62,6 +72,10 @@
 			title: '课时名',
 			dataIndex: 'hourhlame'
 		},
+		{
+			title: '学习时长',
+			dataIndex: 'endTime'
+		},
 		{
 			title: '文件名',
 			dataIndex: 'fileName'

+ 55 - 12
src/views/student/paper/index.vue

@@ -6,6 +6,14 @@
 				<h3 style="border-left: solid 4px #3651d4; padding-left: 8px; margin-bottom: 12px; font-size: 18px">
 					<div>{{ examName }}</div>
 				</h3>
+				<a-select
+					v-model:value="examTypeSelect"
+					placeholder="所有分类"
+					style="width: 110px"
+					:options="typeOptionsVal"
+					@change="handleChangeVal"
+					allowClear
+				></a-select>
 				<a-spin :spinning="taskLoading">
 					<a-table
 						ref="paperTableRef"
@@ -14,12 +22,12 @@
 						:expand-row-by-click="true"
 						:pagination="pagination"
 					>
-						<template #headerCell="{ column}">
+						<template #headerCell="{ column }">
 							<template v-if="column.dataIndex === 'examName'">
-								{{ examName +  column.title}}
+								{{ examName + column.title }}
 							</template>
 							<template v-if="column.dataIndex === 'examType'">
-								{{ examName +  column.title}}
+								{{ examName + column.title }}
 							</template>
 						</template>
 						<template #bodyCell="{ column, record }">
@@ -108,6 +116,27 @@
 				break
 		}
 	})
+	const typeOptionsVal = ref([
+		{
+			label: '考试',
+			value: '1'
+		},
+		{
+			label: '章节测验',
+			value: '2'
+		},
+		{
+			label: '调查问卷',
+			value: '3'
+		},
+		{
+			label: '作业',
+			value: '4'
+		}
+	])
+	const handleChangeVal = (value) => {
+		getTaskList()
+	}
 	// 任务中心相关
 	const taskList = ref([])
 	const taskLoading = ref(false)
@@ -125,14 +154,23 @@
 			ellipsis: true
 		}
 	]
-	const taskColumns = ref([
-		{ title: '名称', dataIndex: 'examName', key: 'examName' },
-		{ title: '类型', dataIndex: 'examType', key: 'examType', width: 120 },
-		{ title: '开始时间', dataIndex: 'startTime', key: 'startTime', width: 180 },
-		{ title: '结束时间', dataIndex: 'endTime', key: 'endTime', width: 180 },
+	const taskColumns = computed(() =>
+		taskAllColumns.value.filter((r) => r.columnsType.includes(parseFloat(examType.value)))
+	)
+	const taskAllColumns = ref([
+		{ title: '课程名称', dataIndex: 'courseName', key: 'courseName', columnsType: [2, 4] },
+		{ title: '章节名称', dataIndex: 'chapterName', key: 'chapterName', columnsType: [2, 4] },
+		{ title: '课时名称', dataIndex: 'hourName', key: 'hourName', columnsType: [2, 4] },
+		{ title: '作业名称', dataIndex: 'name', key: 'name', columnsType: [2, 4] },
+		{ title: '试卷类型', dataIndex: 'paperType', key: 'paperType', width: 120, columnsType: [2, 4] },
+
+		{ title: '名称', dataIndex: 'examName', key: 'examName', columnsType: [1, 3] },
+		{ title: '类型', dataIndex: 'examType', key: 'examType', width: 120, columnsType: [1, 3] },
+		{ title: '开始时间', dataIndex: 'startTime', key: 'startTime', width: 180, columnsType: [1, 3] },
+		{ title: '结束时间', dataIndex: 'endTime', key: 'endTime', width: 180, columnsType: [1, 3] },
 
-		{ title: '状态', dataIndex: 'status', key: 'status', width: 90 },
-		{ title: '操作', key: 'action', align: 'right', width: 120 }
+		{ title: '状态', dataIndex: 'status', key: 'status', width: 90, columnsType: [1, 2, 3, 4] },
+		{ title: '操作', key: 'action', align: 'right', width: 120, columnsType: [1, 2, 3, 4] }
 	])
 	const statusTextFormatter = (status) => {
 		if (status === 0) return '未答题'
@@ -156,9 +194,13 @@
 				subjectId: pagination.value.subjectId,
 				courseId: route.query.id,
 				paperType: paperType.value,
-				examType: examType.value
+				examType: examTypeSelect.value
+			}
+			if (examType.value == 4 || examType.value == 2) {
+				res = await examPaperApi.newPageList(params)
+			} else {
+				res = await examPaperApi.pageExamList(params)
 			}
-			res = await examPaperApi.pageExamList(params)
 
 			taskList.value = res?.records || []
 			pagination.value.total = res.total
@@ -182,6 +224,7 @@
 	}
 	// lifecycle
 	const examType = ref()
+	const examTypeSelect = ref()
 	const paperType = ref(2)
 
 	// 监听消息

+ 8 - 0
src/views/student/user/index.vue

@@ -57,6 +57,9 @@
 					<a-form-item label="生日:" name="birthday">
 						<a-date-picker v-model:value="formData.birthday" value-format="YYYY-MM-DD" style="width: 100%" />
 					</a-form-item>
+					<a-form-item label="年龄:" name="age">
+						<span>{{ birthdayToAge(formData.birthday) }}</span>
+					</a-form-item>
 					<a-form-item label="邮箱:" name="email">
 						<a-input v-model:value="formData.email" :maxlength="200" placeholder="请输入邮箱" allow-clear />
 					</a-form-item>
@@ -100,6 +103,11 @@
 	const typeOptions = tool.dictList('LEVAL').sort(function (a, b) {
 		return a.value - b.value
 	})
+	const birthdayToAge = computed(()=>(birthday)=>{
+		const ageDifMs = Date.now() - new Date(birthday).getTime()
+		const ageDate = new Date(ageDifMs)
+		return Math.abs(ageDate.getUTCFullYear() - 1970)
+	})
 	const cropUpload = ref()
 	const avatarLoading = ref(false)
 	const uploadLogo = () => {