Files
tra-app/src/pages/learningTasks/details.vue
T

700 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<!-- <view class="main_div max_page"> -->
<z-paging
ref="pagingRef"
@query="queryList"
v-model="data_list"
:loading-more-enabled="false"
:refresher-only="true"
:aoto="false"
>
<template #top>
<view class="body-title">
<view class="back_div" @click="common.navigateBack()">
<view class="back-icon"></view>
</view>
<view>任务详情</view>
</view>
</template>
<view class="detail_div">
<view class="left">
<image-preview class="img" :src="detailData.ossAddr"></image-preview>
</view>
<view class="right">
<view class="title_div">
<view class="title">
{{ detailData.taskName }}
</view>
</view>
<view class="time">
<text class="color_3">起止时间<text class="maoh">:</text></text>
<text class="color_class">
{{ detailData.startTm?.substr(0, 10) }}{{ detailData.endTm?.substr(0, 10) }}
</text>
<view class="fl1"></view>
<view class="num-item" @click="collect_click(detailData.collectionId)">
<image
v-if="detailData.collectionId"
class="collect-icon"
src="@/static/images/courseDetail/out_collect.png"
mode="widthFix"
></image>
<image
v-else
class="collect-icon"
src="@/static/images/courseDetail/in_collect.png"
mode="widthFix"
></image>
</view>
</view>
<view class="num_div">
<view class="num_div_item">
<text class="color_3">完成人数<text class="maoh">:</text></text>
<text class="color_2">{{ detailData.taskFinishSums ?? 0 }}/{{ detailData.taskSums ?? 0 }}</text>
</view>
<view class="num_div_item">
<text class="color_3">进度<text class="maoh">:</text></text>
<text class="color_2">{{ detailData.finishCrs ?? 0 }}/{{ detailData.sumCrs ?? 0 }}门课程</text>
</view>
</view>
</view>
</view>
<view class="scroll-div">
<view class="paper_title_div">
<image src="@/static/images/testingHall/testing.png" class="img" mode="aspectFit"></image>
<view class="title">任务历程</view>
</view>
<scroll-view ref="scrollRef" :scroll-y="true" class="scroll-Y" :show-scrollbar="false">
<view class="item" v-for="item in data_list" @click="item_click(item)" :class="getStatusClass(item.status)">
<view class="progress_div">
<view class="circle_div"></view>
<view class="line_div"></view>
<view class="plug"></view>
</view>
<view class="content_div">
<view class="status_div">
<text v-if="item.status === '01'">进行中</text>
<text v-if="item.status === '02'">已完成</text>
<text v-if="item.status === '03'">未解锁</text>
</view>
<view class="main_body_div">
<view class="title">
{{ item.crsName }}
</view>
<view class="button_div">
<template
v-if="item.isFinishStudy === '01' && item.isFinishExam === '01' && item.status !== '02'"
>
<image class="img" :src="lockIcon('#999999')"></image>
<view class="button_text error">暂无通过条件可自动解锁</view>
</template>
<template
v-if="item.isFinishStudy === '01' && item.isFinishExam === '01' && item.status === '02'"
>
<image class="img" :src="lockIcon('#0066FF')"></image>
<view class="button_text success">已自动解锁</view>
</template>
<template v-if="item.isFinishStudy !== '01'">
<image
class="img"
:src="
passTheExamIcon(
item.isFinishStudy === '02' && item.status !== '03' ? '#0066FF' : '#999999'
)
"
></image>
<view
class="button_text"
:class="item.isFinishStudy === '02' && item.status !== '03' ? 'success' : 'error'"
>
完成学习
</view>
</template>
<template v-if="item.isFinishExam !== '01'">
<image
class="img"
:src="
completeTheExercisesIcon(
item.isFinishExam === '02' && item.status !== '03' ? '#0066FF' : '#999999'
)
"
></image>
<view
class="button_text"
:class="item.isFinishExam === '02' && item.status !== '03' ? 'success' : 'error'"
>
通过考试
</view>
</template>
</view>
</view>
</view>
</view>
<list-no-data v-if="total === 0 && status === 'nomore'">暂无数据</list-no-data>
<uv-load-more
v-if="status === 'loading'"
:status="status"
loadmore-text="轻轻上拉加载"
:height="30"
></uv-load-more>
</scroll-view>
</view>
</z-paging>
<!-- </view> -->
</template>
<script setup>
import { onLoad, onUnload, onShow } from '@dcloudio/uni-app';
import { ref, reactive, computed, nextTick, onMounted } from 'vue';
import { queryAllTraTaskCrsInfo, queryTraTaskInfoByTaskId } from '@/api/learningTasks.js';
import { passTheExamIcon, completeTheExercisesIcon, lockIcon } from '@/common/imgSvg';
import { insertTraPersonalCollectionTask, deleteTraPersonalCollectionById } from '@/api/favorites.js';
import common from '@/common/common';
import { getPageCache } from '@/common/common';
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const pagingRef = ref(null);
const data_list = ref([]);
const total = ref(-1);
const taskId = ref('');
const queryList = async (pageNo, pageSize, from) => {
const requests = [queryAllTraTaskCrsInfo({ taskId: taskId.value })];
// 如果不是第一次请求,才添加第二个请求
if (total.value === -1 && detailData.taskName !== '') {
status.value = 'loading';
} else {
requests.push(queryTraTaskInfoByTaskId({ taskId: taskId.value }));
}
Promise.all(requests)
.then((res) => {
if (res.length === 2) {
const TaskDetailsData = res[1].body;
// 需要比较的属性列表
const compareKeys = [
'taskId',
'taskName',
'collectionId',
'taskFinishSums',
'taskSums',
'finishCrs',
'sumCrs',
'isFinish'
];
// 检查是否需要更新
const needUpdate = compareKeys.some((key) => {
return detailData[key] !== TaskDetailsData[key];
});
console.log('检查是否需要更新', needUpdate);
if (needUpdate) {
Object.assign(detailData, {
...TaskDetailsData
});
uni.$emit('update_tasks_item', detailData);
}
}
const list = res[0].body;
pagingRef.value.complete(list);
total.value = list.length;
if (total.value === 0) {
status.value = 'nomore';
} else {
status.value = 'loadmore';
}
})
.catch((error) => {
pagingRef.value?.complete(false);
total.value = data_list.value.length;
if (total.value === 0) {
status.value = 'nomore';
} else {
status.value = 'loadmore';
}
})
.finally(() => {});
};
const collectId = ref(''); // 记录初始的收藏id
const detailData = reactive({
taskId: '',
taskName: '',
collectionId: '',
taskFinishSums: '',
taskSums: '',
finishCrs: '',
isFinish: '',
sumCrs: ''
});
const getStatusClass = (isFinish) => {
// 00进行中、01已完成、02已超时
if (isFinish === '01') return 'unfinished';
if (isFinish === '02') return 'completed';
return 'not_unlocked';
};
const item_click = (item) => {
if (item.status === '03') {
common.msg('任务未解锁');
return;
}
common.navigateTo('/pages/courseDetail/index?crsId=' + item.crsId);
};
const collect_click = async (id) => {
const loadingText = id ? '取消收藏中' : '收藏中';
try {
common.loading(loadingText);
if (!id) {
// 收藏操作
const res = await insertTraPersonalCollectionTask({
collectTyp: '02',
collectBusId: detailData.taskId
});
detailData.collectionId = res.body;
common.msg('收藏成功');
} else {
// 取消收藏操作
await deleteTraPersonalCollectionById({
collectId: id
});
detailData.collectionId = null;
common.msg('取消成功');
}
} catch (error) {
// 错误提示可以更具体
common.msg(id ? '取消收藏失败' : '收藏失败');
console.error('收藏操作失败:', error);
} finally {
// 无论成功失败,最终都关闭加载提示
// common.hideLoading();
}
};
onMounted(() => {
pagingRef.value.reload();
});
onShow(() => {});
onLoad((e) => {
taskId.value = e.taskId;
const learning_tasks_details = getPageCache('learning_tasks_details');
Object.assign(detailData, {
...learning_tasks_details
});
collectId.value = learning_tasks_details.collectionId || null;
const updateFun = () => {
setTimeout(() => {
console.log('监听考试获取结果事件,执行更新函数');
pagingRef.value?.reload();
}, 1000);
};
// 监听里面学习完成后更新任务历程,执行更新函数
uni.$on('refresh_course_list', () => updateFun());
// 监听考试获取结果事件,执行更新函数
uni.$on('get_result_completed', () => updateFun());
});
onUnload(() => {
uni.$off('refresh_course_list');
uni.$off('get_result_completed');
// 如果收藏变了,并且上一页是收藏页,更新收藏列表
console.log('detailData.collectionId', detailData.collectionId);
console.log('collectId', collectId.value);
if (detailData.collectionId !== collectId.value) {
const pages = getCurrentPages();
if (pages.length >= 2) {
const prevPage = pages[pages.length - 2];
if (prevPage.route === 'pages/favorites/index') {
// 收藏页跳入
uni.$emit('update_tasks_item', detailData);
} else if (prevPage.route === 'pages/learningTasks/index') {
// 学习任务页跳入,更新外部列表否则下次列表数据还是老的
console.log('学习任务页跳入,更新外部列表否则下次列表数据还是老的(作废)');
// uni.$emit('update_tasks_item', detailData);
}
}
}
});
</script>
<style scoped lang="scss">
$bg-margin-left: 30rpx;
.scroll-Y .item {
margin: 0 $bg-margin-left 0 $bg-margin-left;
display: flex;
justify-content: space-between;
// 已完成
&.completed {
.circle_div {
border: 4rpx solid #bdc7e6;
background-color: #bdc7e6;
}
.line_div {
border-left: 4rpx solid #e1e8f0;
}
.status_div {
color: #adb4c3;
background-color: #f3f5f5;
}
.plug {
border-top: 4rpx solid #e1e8f0;
}
}
//未完成
&.unfinished {
.circle_div {
border: 4rpx solid #0066ff;
// background-color: #bdc7e6;
}
.line_div {
border-left: 4rpx solid #0066ff;
}
.status_div {
color: #ffffff;
background-color: #4c93ff;
}
.plug {
border-top: 4rpx solid #0066ff;
}
}
// 未解锁
&.not_unlocked {
.circle_div {
border: 4rpx solid #adb4c3;
}
.line_div {
border-left: 4rpx dashed #adb4c3;
}
.status_div {
color: #6c9ce4;
background-color: #eff6ff;
}
.plug {
border-top: 4rpx solid #adb4c3;
}
}
// 最后一项
&:last-child .plug {
width: 80%;
height: 40rpx;
margin-top: -6rpx;
}
.progress_div {
width: 30rpx;
display: flex;
align-items: center;
flex-direction: column;
.circle_div {
width: 20rpx;
height: 20rpx;
border-radius: 50%;
overflow: hidden;
box-sizing: border-box;
}
.line_div {
height: calc(100% - 20rpx);
width: 4rpx;
margin: 6rpx 0;
}
}
.content_div {
flex: 1;
display: flex;
min-height: 140rpx;
background-color: #fff;
margin-bottom: 34rpx;
padding: 4rpx 4rpx 4rpx 4rpx;
// background-color: red;
border-radius: 16rpx;
overflow: hidden;
.status_div {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 30rpx;
writing-mode: vertical-rl;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 4rpx 4rpx;
}
.main_body_div {
margin-left: 34rpx;
flex: 1;
display: flex;
flex-direction: column;
padding-right: 10rpx;
.title {
// background-color: red;
margin-top: 10rpx;
min-height: 30rpx;
flex: 1;
font-weight: 500;
font-size: 30rpx;
color: #333333;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
.button_div {
// background-color: red;
height: 60rpx;
display: flex;
align-items: center;
flex-wrap: nowrap;
.img {
width: 30rpx;
height: 30rpx;
}
.button_text {
font-weight: 400;
font-size: 24rpx;
text-align: left;
margin-right: 50rpx;
&.success {
color: #0066ff;
}
&.error {
color: #999999;
}
}
}
}
}
}
.paper_title_div {
display: flex;
align-items: center;
margin: 20rpx 0 20rpx $bg-margin-left;
height: 42rpx;
.img {
width: 32rpx;
height: 28rpx;
}
.title {
font-weight: 600;
font-family: PingFangTC;
font-weight: 600;
font-size: 30rpx;
color: #333333;
font-style: normal;
margin-left: 12rpx;
}
}
.scroll-div {
background: linear-gradient(180deg, #ebf2fe 0%, #f3f7fe 6%, #f9fbff 12%, #f4f6f8 100%);
border-radius: 16rpx;
margin-top: -20rpx;
z-index: 2;
box-shadow: 0 0 10rpx #f9fbff;
border: 2rpx solid #f9f9fa;
margin: 0 auto;
width: calc(100% - 52rpx);
}
.scroll-Y {
position: relative;
overflow: hidden;
height: calc(100vh - var(--status-bar-height) - 120rpx - 250rpx + 20rpx + 20rpx - 20rpx - 42rpx - 50rpx);
}
.body-title {
width: 100%;
position: relative;
text-align: center;
height: 180rpx;
padding-top: var(--status-bar-height);
margin-bottom: -10rpx;
line-height: calc(180rpx - var(--status-bar-height) - 10rpx);
font-family: PingFangSC;
font-weight: 600;
font-size: 32rpx;
color: #000000;
font-style: normal;
background-image: url('@/static/images/learningTasks/learningTasksBg.png');
background-repeat: no-repeat;
background-size: 100% calc(420rpx + var(--status-bar-height)); /* 宽度充满,高度自适应比例 */
background-position: top;
background-color: #fff;
}
.detail_div {
height: 210rpx;
z-index: 2;
width: 100%;
padding: 36rpx 26rpx 20rpx 26rpx;
background-color: #ffffff;
border-radius: 16rpx 16rpx 0 0;
position: relative;
overflow: hidden;
display: flex;
.subscript {
position: absolute;
top: 0;
right: 0;
width: 102rpx;
height: 42rpx;
font-family: PingFangSC;
font-weight: 400;
font-size: 24rpx;
line-height: 42rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 0 0 0 28rpx;
}
.left > .img {
// width: 224rpx;
// height: 168rpx;
width: 256rpx;
height: 144rpx;
border-radius: 16rpx;
overflow: hidden;
}
.right {
overflow: hidden;
margin-left: 24rpx;
width: 100%;
.title_div {
display: flex;
justify-content: space-between;
flex: 1;
.title {
font-family: PingFangSC;
font-weight: 600;
color: #000000;
text-align: left;
font-style: normal;
font-size: 28rpx; /* 字体大小30rpx */
display: -webkit-box; /* 启用弹性盒模型 */
-webkit-box-orient: vertical; /* 设置盒子内子元素的排列方向为垂直 */
-webkit-line-clamp: 2; /* 限制最多显示2行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出部分显示省略号(多行时可能不显示,但建议保留) */
line-height: 1.5; /* 可选:设置行高,优化多行显示效果 */
}
}
.time {
font-size: 22rpx;
color: #999999;
line-height: 30rpx;
font-family: Arial;
font-weight: 400;
color: #666666;
height: 54rpx;
display: flex;
align-items: center;
.num-item {
display: flex;
align-items: center;
font-size: 30rpx;
color: #666666;
.collect-icon {
width: 36rpx;
height: 36rpx;
}
}
}
.num_div {
font-family: PingFangSC;
font-weight: 400;
font-size: 22rpx;
display: flex;
align-items: center;
justify-content: space-between;
overflow: hidden;
height: 28rpx;
.num_div_item {
display: flex;
flex-wrap: nowrap;
line-height: 28rpx;
height: 28rpx;
}
}
.color_1 {
color: #d70c18;
}
.color_2 {
color: #111111;
}
.color_3 {
color: #666666;
}
}
}
.incomplete {
// 进行中
.subscript {
color: #ffffff;
background-color: #ef5705;
}
.color_class {
color: #d70c18;
}
}
.completed {
// 已完成
.subscript {
color: #ffffff;
background-color: #33c583;
}
.color_class {
color: #0066ff;
}
}
.back_div {
position: absolute;
left: 26rpx;
bottom: 20rpx;
display: flex;
align-items: center;
.back-icon {
position: relative;
width: 50rpx;
height: 50rpx;
cursor: pointer;
display: flex;
align-items: center;
}
.back-icon::before,
.back-icon::after {
content: '';
position: absolute;
transition: all 0.3s ease;
}
.back-icon::after {
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #000000;
border-left: 4rpx solid #000000;
transform: rotate(-45deg);
}
}
</style>