dedsudiyu 1 week ago
parent
commit
ed56085528
1 changed files with 262 additions and 0 deletions
  1. 262 0
      pages_safetyEducationExamination/views/studyHourTask/index.vue

+ 262 - 0
pages_safetyEducationExamination/views/studyHourTask/index.vue

@@ -0,0 +1,262 @@
+<!-- 学时任务列表 -->
+<template>
+	<view class="safetyEducationExamination-studyHourTask">
+		<!-- 顶部类型标签 -->
+		<scroll-view scroll-x class="tag-scroll">
+			<view class="tag-scroll-inner">
+				<text
+					v-for="(tag, index) in typeTags"
+					:key="index"
+					class="filter-tag"
+					:class="{ 'filter-tag-active': activeTagIndex === index }"
+					@click="onTagChange(index)"
+				>{{ tag.label }}</text>
+			</view>
+		</scroll-view>
+
+		<!-- 课程列表 -->
+		<scroll-view scroll-y class="scroll-content">
+			<view class="panel">
+				<view
+					v-for="(item, index) in courseList"
+					:key="index"
+					class="course-card"
+					@click="goCourseDetail(item)"
+				>
+					<view class="course-cover" :style="'background:' + item.coverGradient">
+						<text 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="status-tag" :class="item.statusClass">{{ item.statusName }}</text>
+						</view>
+						<text class="course-meta">{{ item.courseDuration }}分钟 | {{ item.studyHours }}学时 | {{ item.points }}积分</text>
+					</view>
+				</view>
+				<view v-if="!courseList[0] && !loading" class="empty-tip">暂无学时任务</view>
+				<view v-if="loading" class="loading-tip">加载中...</view>
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	import {
+		examUserCourseLearningList,
+		examUserExamTypeSelectExamType,
+	} from '@/pages_safetyEducationExamination/api/index.js'
+
+	// 封面渐变色池
+	const COVER_GRADIENTS = [
+		'linear-gradient(135deg,#ffd666,#fa8c16)',
+		'linear-gradient(135deg,#b37feb,#722ed1)',
+		'linear-gradient(135deg,#ff9c6e,#f5222d)',
+		'linear-gradient(135deg,#5cdbd3,#13c2c2)',
+		'linear-gradient(135deg,#1857d4,#5b8af0)',
+		'linear-gradient(135deg,#10a37f,#34d399)',
+		'linear-gradient(135deg,#6c63ff,#a78bfa)',
+		'linear-gradient(135deg,#95de64,#237804)',
+	];
+
+	// 学习状态映射
+	function getStatusInfo(status) {
+		const map = {
+			0: { name: '未开始', cls: 'tag-gray' },
+			1: { name: '学习中', cls: 'tag-orange' },
+			2: { name: '已完成', cls: 'tag-green' },
+		};
+		return map[status] || map[0];
+	}
+
+	export default {
+		data() {
+			return {
+				typeTags: [{ label: '全部', value: null }],
+				activeTagIndex: 0,
+				courseList: [],
+				loading: false,
+			}
+		},
+		created() {
+			this.loadTypeTags();
+		},
+		onShow() {
+			this.loadCourseList();
+		},
+		methods: {
+			// 加载考试类型标签
+			async loadTypeTags() {
+				try {
+					const { data } = await examUserExamTypeSelectExamType({});
+					if (data.code === 200 && data.data) {
+						const tags = (data.data || []).map(item => ({
+							label: item.examTypeName,
+							value: item.examTypeId,
+						}));
+						this.$set(this, 'typeTags', [{ label: '全部', value: null }, ...tags]);
+					}
+				} catch (e) {
+					console.error('获取考试类型失败', e);
+				}
+			},
+			onTagChange(index) {
+				this.activeTagIndex = index;
+				this.loadCourseList();
+			},
+			// 学时任务列表(courseType=1)
+			async loadCourseList() {
+				if (this.loading) 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,
+					});
+					if (data.code === 200) {
+						const list = (data.data.records || []).map((item, i) => {
+							const s = getStatusInfo(item.learnStatus);
+							return {
+								...item,
+								coverGradient: COVER_GRADIENTS[i % COVER_GRADIENTS.length],
+								statusName: s.name,
+								statusClass: s.cls,
+							};
+						});
+						this.$set(this, 'courseList', list);
+					}
+				} catch (e) {
+					console.error('获取学时任务失败', e);
+				} finally {
+					this.loading = false;
+				}
+			},
+			goCourseDetail(item) {
+				// 跳转课程详情,传递 courseId
+			},
+		},
+	}
+</script>
+
+<style lang="stylus" scoped>
+	.safetyEducationExamination-studyHourTask
+		height 100%
+		display flex
+		flex-direction column
+		overflow hidden
+		background-color #f0f4fb
+
+	// 类型标签横滚
+	.tag-scroll
+		background #fff
+		white-space nowrap
+		padding 16rpx 24rpx
+		border-bottom 1rpx solid #e8edf3
+		flex-shrink 0
+
+	.tag-scroll-inner
+		display inline-flex
+		gap 16rpx
+
+	.filter-tag
+		display inline-block
+		font-size 22rpx
+		padding 8rpx 20rpx
+		border-radius 30rpx
+		background #eef1f6
+		color #666
+		border 1rpx solid transparent
+		white-space nowrap
+
+	.filter-tag-active
+		background #e6f0ff
+		color #1677ff
+		border-color #91caff
+		font-weight 600
+
+	// 滚动区
+	.scroll-content
+		flex 1
+		overflow hidden
+
+	.panel
+		padding 24rpx
+
+	// 课程卡片
+	.course-card
+		background #fff
+		border-radius 20rpx
+		margin-bottom 20rpx
+		overflow hidden
+		box-shadow 0 2rpx 12rpx rgba(0,0,0,0.04)
+		border 1rpx solid #dde3ed
+
+	.course-cover
+		width 100%
+		height 180rpx
+		display flex
+		align-items center
+		justify-content center
+
+	.cover-icon
+		font-size 64rpx
+
+	.course-info
+		padding 20rpx 24rpx
+
+	.course-info-top
+		display flex
+		justify-content space-between
+		align-items center
+		margin-bottom 8rpx
+
+	.course-name
+		flex 1
+		font-size 28rpx
+		font-weight 600
+		color #222
+		margin-right 12rpx
+
+	.course-meta
+		font-size 22rpx
+		color #999
+
+	// 状态标签
+	.status-tag
+		font-size 20rpx
+		padding 4rpx 12rpx
+		border-radius 8rpx
+		border 1rpx solid transparent
+		flex-shrink 0
+
+	.tag-gray
+		background #f5f5f5
+		color #999
+		border-color #e8e8e8
+
+	.tag-orange
+		background #fff7e6
+		color #d46b08
+		border-color #ffd591
+
+	.tag-green
+		background #f6ffed
+		color #389e0d
+		border-color #b7eb8f
+
+	// 提示
+	.empty-tip
+		text-align center
+		line-height 80rpx
+		color #aaa
+		font-size 24rpx
+
+	.loading-tip
+		text-align center
+		line-height 60rpx
+		color #aaa
+		font-size 22rpx
+</style>