|
|
@@ -2,7 +2,7 @@
|
|
|
<template>
|
|
|
<view class="safetyEducationExamination-studyHourTask">
|
|
|
<!-- 顶部类型标签 -->
|
|
|
- <scroll-view scroll-x class="tag-scroll">
|
|
|
+ <scroll-view scroll-x class="tag-scroll" enable-flex>
|
|
|
<view class="tag-scroll-inner">
|
|
|
<text
|
|
|
v-for="(tag, index) in typeTags"
|
|
|
@@ -15,7 +15,7 @@
|
|
|
</scroll-view>
|
|
|
|
|
|
<!-- 课程列表 -->
|
|
|
- <scroll-view scroll-y class="scroll-content">
|
|
|
+ <scroll-view scroll-y class="scroll-content" @scrolltolower="onScrollToLower">
|
|
|
<view class="panel">
|
|
|
<view
|
|
|
v-for="(item, index) in courseList"
|
|
|
@@ -24,18 +24,20 @@
|
|
|
@click="goCourseDetail(item)"
|
|
|
>
|
|
|
<view class="course-cover" :style="'background:' + item.coverGradient">
|
|
|
- <text class="cover-icon">{{ item.coverIcon || '📖' }}</text>
|
|
|
+ <image v-if="item.materialType == 1 && item.exampleImg" :src="baseUrl + item.exampleImg" class="cover-image" mode="aspectFill" />
|
|
|
+ <text v-else class="cover-icon">{{ item.coverIcon || '📖' }}</text>
|
|
|
</view>
|
|
|
<view class="course-info">
|
|
|
<view class="course-info-top">
|
|
|
- <text class="course-name">{{ item.courseName }}</text>
|
|
|
+ <text class="course-name">{{ item.coursewareName }}</text>
|
|
|
<text class="status-tag" :class="item.statusClass">{{ item.statusName }}</text>
|
|
|
</view>
|
|
|
- <text class="course-meta">{{ item.courseDuration }}分钟 | {{ item.studyHours }}学时 | {{ item.points }}积分</text>
|
|
|
+ <text class="course-meta">{{ formatDuration(item.minLearningDuration) }}分钟 | {{ item.creditHours }}学时 | {{ item.points }}积分</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
<view v-if="!courseList[0] && !loading" class="empty-tip">暂无学时任务</view>
|
|
|
<view v-if="loading" class="loading-tip">加载中...</view>
|
|
|
+ <view v-if="noMore && courseList[0]" class="loading-tip">没有更多了</view>
|
|
|
</view>
|
|
|
</scroll-view>
|
|
|
</view>
|
|
|
@@ -43,8 +45,11 @@
|
|
|
|
|
|
<script>
|
|
|
import {
|
|
|
- examUserCourseLearningList,
|
|
|
- examUserExamTypeSelectExamType,
|
|
|
+ config
|
|
|
+ } from '@/api/request/config.js'
|
|
|
+ import {
|
|
|
+ examUserCoursewareLearningList,
|
|
|
+ examElKnowledgePointTreeList,
|
|
|
} from '@/pages_safetyEducationExamination/api/index.js'
|
|
|
|
|
|
// 封面渐变色池
|
|
|
@@ -72,61 +77,122 @@
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
- typeTags: [{ label: '全部', value: null }],
|
|
|
+ baseUrl: config.base_url,
|
|
|
+ typeTags: [],
|
|
|
activeTagIndex: 0,
|
|
|
courseList: [],
|
|
|
loading: false,
|
|
|
+ page: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0,
|
|
|
+ noMore: false,
|
|
|
+ knowledgePointIds: null, // 从上个页面传来的知识点ID数组
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad(options) {
|
|
|
+ console.log('options',options);
|
|
|
+ // 接收知识点ID参数
|
|
|
+ if (options.knowledgePointId) {
|
|
|
+ this.knowledgePointIds = options.knowledgePointId;
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
- this.loadTypeTags();
|
|
|
+
|
|
|
},
|
|
|
- onShow() {
|
|
|
- this.loadCourseList();
|
|
|
+ async onShow() {
|
|
|
+ await this.loadTypeTags();
|
|
|
+ this.resetList();
|
|
|
},
|
|
|
methods: {
|
|
|
- // 加载考试类型标签
|
|
|
+ // 递归扁平化树形结构,提取所有节点
|
|
|
+ flattenTree(nodes, result = []) {
|
|
|
+ if (!nodes || !Array.isArray(nodes)) return result;
|
|
|
+
|
|
|
+ nodes.forEach(node => {
|
|
|
+ result.push(node);
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ this.flattenTree(node.children, result);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return result;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 加载知识点标签(根据传入的knowledgePointIds过滤)
|
|
|
async loadTypeTags() {
|
|
|
try {
|
|
|
- const { data } = await examUserExamTypeSelectExamType({});
|
|
|
+ const { data } = await examElKnowledgePointTreeList({ dataScope: 1 });
|
|
|
if (data.code === 200 && data.data) {
|
|
|
- const tags = (data.data || []).map(item => ({
|
|
|
- label: item.examTypeName,
|
|
|
- value: item.examTypeId,
|
|
|
+ // 扁平化树形结构,获取所有节点
|
|
|
+ const allNodes = this.flattenTree(data.data);
|
|
|
+
|
|
|
+ let tags = allNodes;
|
|
|
+
|
|
|
+ // 如果有传入的知识点ID,则过滤标签
|
|
|
+ if (this.knowledgePointIds) {
|
|
|
+ const idsArray = this.knowledgePointIds.split(',').map(id => id.trim());
|
|
|
+ tags = allNodes.filter(item => idsArray.includes(String(item.id)));
|
|
|
+ }
|
|
|
+
|
|
|
+ const typeTags = tags.map(item => ({
|
|
|
+ label: item.knowledgePointName,
|
|
|
+ value: item.id,
|
|
|
}));
|
|
|
- this.$set(this, 'typeTags', [{ label: '全部', value: null }, ...tags]);
|
|
|
+
|
|
|
+ this.$set(this, 'typeTags', typeTags);
|
|
|
+
|
|
|
+ // 默认选中第一个
|
|
|
+ if (typeTags.length > 0) {
|
|
|
+ this.activeTagIndex = 0;
|
|
|
+ }
|
|
|
}
|
|
|
} catch (e) {
|
|
|
- console.error('获取考试类型失败', e);
|
|
|
+ console.error('获取知识点类型失败', e);
|
|
|
}
|
|
|
},
|
|
|
onTagChange(index) {
|
|
|
- this.activeTagIndex = index;
|
|
|
+ if (this.activeTagIndex !== index) {
|
|
|
+ this.activeTagIndex = index;
|
|
|
+ this.resetList();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ resetList() {
|
|
|
+ this.page = 1;
|
|
|
+ this.noMore = false;
|
|
|
+ this.courseList = [];
|
|
|
this.loadCourseList();
|
|
|
},
|
|
|
- // 学时任务列表(courseType=1)
|
|
|
+ // 学时任务列表(materialType为空,查询全部类型)
|
|
|
async loadCourseList() {
|
|
|
- if (this.loading) return;
|
|
|
+ if (this.loading || this.noMore) return;
|
|
|
this.loading = true;
|
|
|
try {
|
|
|
const tag = this.typeTags[this.activeTagIndex];
|
|
|
- const { data } = await examUserCourseLearningList({
|
|
|
- page: 1,
|
|
|
- pageSize: 50,
|
|
|
- courseType: 1,
|
|
|
- examTypeId: tag.value || undefined,
|
|
|
+ const { data } = await examUserCoursewareLearningList({
|
|
|
+ page: this.page,
|
|
|
+ pageSize: this.pageSize,
|
|
|
+ materialType: '', // 空字符串,查询全部类型
|
|
|
+ knowledgePointId: tag ? tag.value : undefined,
|
|
|
});
|
|
|
if (data.code === 200) {
|
|
|
- const list = (data.data.records || []).map((item, i) => {
|
|
|
+ const records = (data.data.records || []).map((item, i) => {
|
|
|
const s = getStatusInfo(item.learnStatus);
|
|
|
+ const colorIndex = (this.courseList.length + i) % COVER_GRADIENTS.length;
|
|
|
return {
|
|
|
...item,
|
|
|
- coverGradient: COVER_GRADIENTS[i % COVER_GRADIENTS.length],
|
|
|
+ coverGradient: COVER_GRADIENTS[colorIndex],
|
|
|
statusName: s.name,
|
|
|
statusClass: s.cls,
|
|
|
};
|
|
|
});
|
|
|
- this.$set(this, 'courseList', list);
|
|
|
+ const newList = this.page === 1 ? records : [...this.courseList, ...records];
|
|
|
+ this.$set(this, 'courseList', newList);
|
|
|
+ this.total = data.data.total;
|
|
|
+ if (newList.length >= this.total) {
|
|
|
+ this.noMore = true;
|
|
|
+ } else {
|
|
|
+ this.page++;
|
|
|
+ }
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('获取学时任务失败', e);
|
|
|
@@ -134,8 +200,15 @@
|
|
|
this.loading = false;
|
|
|
}
|
|
|
},
|
|
|
+ onScrollToLower() {
|
|
|
+ this.loadCourseList();
|
|
|
+ },
|
|
|
+ // 秒数转分钟
|
|
|
+ formatDuration(seconds) {
|
|
|
+ return seconds ? Math.ceil(seconds / 60) : 0;
|
|
|
+ },
|
|
|
goCourseDetail(item) {
|
|
|
- // 跳转课程详情,传递 courseId
|
|
|
+ // 跳转课程详情,传递 coursewareId
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
@@ -204,6 +277,10 @@
|
|
|
.cover-icon
|
|
|
font-size 64rpx
|
|
|
|
|
|
+ .cover-image
|
|
|
+ width 100%
|
|
|
+ height 100%
|
|
|
+
|
|
|
.course-info
|
|
|
padding 20rpx 24rpx
|
|
|
|