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

437 lines
11 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="noise-bg">
<view class="is-bg"></view>
<view class="div-max">
<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="interior">
<!-- 详情盒子 -->
<view class="details-div">
<view class="img-div">
<image-preview class="img_100" :src="detailData.ossAddr"></image-preview>
</view>
<view class="right-div">
<view class="title-div">{{ detailData.taskName }}</view>
<view class="other-div-1">
<!-- 时间盒子 -->
<view class="time-div">
起止时间{{ detailData.startTm?.substr(0, 10) }}{{ detailData.endTm?.substr(0, 10) }}
</view>
<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="other-div-2">
<!-- 完成人数盒子 -->
<view class="progress-text-div">
<text class="color_3">
完成人数
<text class="maoh">:</text>
</text>
<text class="color_2">
{{ detailData.taskFinishSums ?? 0 }}/{{ detailData.taskSums ?? 0 }}
</text>
</view>
<!-- 进度条 -->
<view class="line-progress-div">
<view class="progress-div">
<view class="progress-line"></view>
</view>
<view class="progress-text">{{progress}}</view>
</view>
</view>
</view>
</view>
</view>
<!-- 步骤 -->
<view class="step-list-div">
<detailsItem v-for="(item, index) in data_list" :item="item" :index="index" @item_click="item_click"></detailsItem>
</view>
</z-paging>
</view>
</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 detailsItem from './components/details-item';
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 progress = computed(() => '30%');
const progress = computed(() => {
// 计算进度百分比(保留两位小数)
const total = detailData.sumCrs ?? detailData.taskNumber ?? 0;
if (total === 0) return '0%';
const completed = detailData.finishCrs ?? detailData.learnedNumber ?? 0;
return Math.min(Math.round((completed / total) * 10000) / 100, 100) + '%';
});
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">
// 步骤
.step-list-div {
margin: 50rpx 0;
}
// 详情
.details-div {
display: flex;
margin: 50rpx auto 30rpx auto;
width: calc(100% - 60rpx);
.img-div {
width: 224rpx;
height: 126rpx;
border-radius: 18rpx;
overflow: hidden;
}
.right-div {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
margin-left: 24rpx;
.title-div {
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 30rpx;
color: #ffffff;
line-height: 43rpx;
text-align: left;
font-style: normal;
max-height: 86rpx;
}
.other-div-1 {
margin-top: 6rpx;
display: flex;
align-items: center;
.time-div {
font-weight: 400;
font-size: 22rpx;
color: #f2f5fa;
line-height: 33rpx;
font-family: Arial, Helvetica, sans-serif;
}
.num-item {
display: flex;
align-items: center;
font-size: 30rpx;
color: #666666;
.collect-icon {
width: 36rpx;
height: 36rpx;
}
}
}
.other-div-2 {
width: 100%;
margin-top: 6rpx;
display: flex;
align-items: center;
justify-content: space-between;
.progress-text-div {
font-weight: 400;
font-size: 22rpx;
color: #f2f5fa;
line-height: 33rpx;
text-align: left;
font-style: normal;
}
.line-progress-div {
margin-left: 20rpx;
flex: 1;
display: flex;
align-items: center;
.progress-div {
position: relative;
background-color: rgba(255, 255, 255, 0.5);
width: 100%;
height: 16rpx;
border-radius: 10rpx;
overflow: hidden;
.progress-line {
position: absolute;
top: 0;
left: 0;
border-radius: 10rpx;
background-color: #ffffff;
width: v-bind(progress);
height: 100%;
}
}
.progress-text {
color: #ffffff;
font-size: 22rpx;
margin-left: 10rpx;
}
}
}
}
}
.div-max {
width: 100vw;
height: 100vh;
z-index: 10;
opacity: 1;
// background-color: red;
}
.interior {
z-index: 1;
}
.noise-bg {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
background: linear-gradient(358deg, #1848a1 0%, #3772e1 100%);
// opacity: .4;
}
.is-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* 噪点图配置 */
background-image: url('@/static/images/learningTasks/bg.png');
background-repeat: repeat;
background-size: 200px; /* 控制噪点大小,可按需改 */
/* 核心:模糊噪点(1px=轻微,2px=中度,3px=更糊) */
// filter: blur(1px);
opacity: 0.3;
/* 混合模式:让噪点和渐变自然融合(multiply/overlay二选一) */
background-blend-mode: multiply;
/* 不影响容器内元素点击 */
pointer-events: none;
/* 确保噪点在内容之下,渐变之上 */
z-index: 0;
}
.body-title {
width: 100%;
position: relative;
padding-top: var(--status-bar-height);
font-weight: 500;
font-size: 38rpx;
color: #ffffff;
text-align: center;
margin: 34rpx 0;
}
.back_div {
position: absolute;
left: 26rpx;
.back-icon {
position: relative;
width: 50rpx;
height: 50rpx;
}
.back-icon::after {
content: '';
position: absolute;
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #ffffff;
border-left: 4rpx solid #ffffff;
transform: rotate(-45deg);
}
}
</style>