Merge branch 'dev-20250930' of http://25.13.9.101:9000/K17_AITS/tra-app into dev-20250930
This commit is contained in:
@@ -147,6 +147,7 @@
|
||||
const tabsDiv = ref(null);
|
||||
const form = ref({});
|
||||
const crsId = ref('');
|
||||
const collectId = ref(''); // 记录初始的收藏id
|
||||
const tabAct = ref(0);
|
||||
const scrollTop = ref(0);
|
||||
const tabSwitch = (item) => {
|
||||
@@ -230,20 +231,23 @@
|
||||
common.hideLoading();
|
||||
});
|
||||
};
|
||||
|
||||
const collect_click = async (collectId) => {
|
||||
// uni.$emit('refresh_comment_data');
|
||||
const collect_click = async (id) => {
|
||||
try {
|
||||
if (!collectId) {
|
||||
if (!id) {
|
||||
common.loading('收藏中');
|
||||
form.value.collectId = await insertTraPersonalCollectionTask({
|
||||
const result = await insertTraPersonalCollectionTask({
|
||||
collectTyp: '01',
|
||||
collectBusId: crsId.value
|
||||
});
|
||||
console.log('result.body', result.body);
|
||||
form.value.collectId = result.body;
|
||||
|
||||
common.msg('收藏成功');
|
||||
} else {
|
||||
common.loading('取消收藏中');
|
||||
await deleteTraPersonalCollectionById({
|
||||
collectId: collectId
|
||||
collectId: id
|
||||
});
|
||||
form.value.collectId = null;
|
||||
|
||||
@@ -255,20 +259,35 @@
|
||||
};
|
||||
onMounted(async () => {
|
||||
uni.$on('refresh_comment_data', () => {
|
||||
console.log('发评论了刷新');
|
||||
// console.log('发评论了刷新');
|
||||
commentRef.value?.getData('submit');
|
||||
|
||||
tabAct.value = 2;
|
||||
});
|
||||
});
|
||||
onLoad((params) => {
|
||||
crsId.value = params.crsId;
|
||||
collectId.value = params.collectId || '';
|
||||
});
|
||||
onShow(() => {
|
||||
getData();
|
||||
});
|
||||
onUnload(() => {
|
||||
uni.$off('refresh_comment_data');
|
||||
if (form.value.collectId !== collectId.value) {
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length >= 2) {
|
||||
const prevPage = pages[pages.length - 2];
|
||||
if (prevPage.route === 'pages/favorites/index') {
|
||||
// 更新
|
||||
uni.$emit('refresh_favorites_data', {
|
||||
type: 'course',
|
||||
state: !!form.value.collectId, // 最终是收藏了还是取消了
|
||||
old: collectId.value, // 进入时候的收藏id
|
||||
new: form.value.collectId // 新的收藏id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<view class="item">
|
||||
<view class="details_div">
|
||||
<view class="img_div" v-if="props.mode === 'testingHall'">
|
||||
<view class="img_div">
|
||||
<image-preview class="img" :src="item.ossAddr" mode="scaleToFill"></image-preview>
|
||||
</view>
|
||||
<view class="right_div">
|
||||
@@ -58,26 +58,15 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, reactive, nextTick } from 'vue';
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { queryCrsExamHisByExamId } from '@/api/courseRecord.js';
|
||||
const status = ref('loadmore'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'testingHall',
|
||||
validator: (value) => {
|
||||
// 考试: examination
|
||||
// 考试中心 testingHall
|
||||
return ['examination', 'testingHall'].includes(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
import { queryCrsExamHisByExamId } from '@/api/courseRecord.js';
|
||||
const item = computed(() => props.item);
|
||||
const data_list = reactive([]);
|
||||
const total = ref(-1);
|
||||
|
||||
@@ -9,12 +9,9 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import itemVue from './examRecordItem.vue';
|
||||
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
import { queryCrsExamRecordPaging } from '@/api/courseRecord.js';
|
||||
import { studyDurationIcon, studyTimeIcon } from '@/common/imgSvg';
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
const total = ref(-1);
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
</view>
|
||||
<view class="prompt_div">
|
||||
<view class="prompt_div_left">
|
||||
<view class="top">{{ item.correctRate || '' }}</view>
|
||||
<view class="top">{{ item.correctRate || '0' }}%</view>
|
||||
<view class="bottom">答题正确率</view>
|
||||
</view>
|
||||
<view class="prompt_div_line"></view>
|
||||
<view class="prompt_div_right" @click="show_list_click">
|
||||
<view class="click_text">
|
||||
{{ item.exrCnt || 0 }}
|
||||
{{ item.exrCnt || '0' }}
|
||||
<uv-icon
|
||||
class="click_text_icon"
|
||||
:class="{click_text_icon_action:show_list_state}"
|
||||
:class="{ click_text_icon_action: show_list_state }"
|
||||
name="arrow-right"
|
||||
color="#0066FF"
|
||||
size="12"
|
||||
@@ -58,8 +58,8 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, reactive, nextTick } from 'vue';
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { queryPracticeHis } from '@/api/courseRecord.js';
|
||||
const status = ref('loadmore'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const props = defineProps({
|
||||
item: {
|
||||
@@ -67,11 +67,10 @@
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
|
||||
import { queryPracticeHis } from '@/api/courseRecord.js';
|
||||
const item = computed(() => props.item);
|
||||
const data_list = reactive([]);
|
||||
const total = ref(-1);
|
||||
|
||||
const show_list_state = ref(false);
|
||||
const list_div_height = computed(() => {
|
||||
if (!show_list_state.value) {
|
||||
@@ -97,6 +96,7 @@
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 跳转到详情
|
||||
const click_list_item = (list_item) => {
|
||||
common.navigateTo(`/pages/courseRecord/coursePracticeRecordDetail?exrId=${list_item.exrId}`);
|
||||
@@ -267,10 +267,9 @@
|
||||
/* 添加过渡动画,包含延迟效果 */
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.click_text_icon_action{
|
||||
.click_text_icon_action {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import itemVue from './practiceRecordItem.vue';
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { queryPracticeRecordPaging } from '@/api/courseRecord.js';
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
@@ -49,7 +48,7 @@
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const scrolltolower = (item) => {
|
||||
getData();
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</view>
|
||||
<view class="prompt_div">
|
||||
<view class="prompt_div_left">
|
||||
<view class="top">{{ item.stdyTm || '' }}</view>
|
||||
<view class="top">{{ formatSeconds(item.stdyTm) || '' }}</view>
|
||||
<view class="bottom">学习时长</view>
|
||||
</view>
|
||||
<view class="prompt_div_line"></view>
|
||||
@@ -31,7 +31,7 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list_div" :style="{ height: list_div_height}">
|
||||
<view class="list_div" :style="{ height: list_div_height }">
|
||||
<view class="list_item" v-for="item_list in data_list" @click="click_list_item(item_list)">
|
||||
<view class="list_content">
|
||||
<view class="list_small_item">
|
||||
@@ -57,9 +57,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, reactive, nextTick } from 'vue';
|
||||
import { setPageCache } from '@/common/common';
|
||||
import { computed, ref, reactive } from 'vue';
|
||||
import { formatSeconds } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { queryStdyBatchByCrsId } from '@/api/courseRecord.js';
|
||||
const status = ref('loadmore'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const props = defineProps({
|
||||
item: {
|
||||
@@ -67,8 +68,6 @@
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
|
||||
import { queryStdyBatchByCrsId } from '@/api/courseRecord.js';
|
||||
const item = computed(() => props.item);
|
||||
const data_list = reactive([]);
|
||||
const total = ref(-1);
|
||||
@@ -82,7 +81,7 @@
|
||||
return data_list.length * 136 + 'rpx';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 点击获取详情
|
||||
const show_list_click = () => {
|
||||
show_list_state.value = !show_list_state.value;
|
||||
@@ -99,9 +98,12 @@
|
||||
};
|
||||
// 跳转到详情
|
||||
const click_list_item = (list_item) => {
|
||||
common.navigateTo(`/pages/courseRecord/courseStudyRecordDetail?stdyId=${list_item.stdyBatch}`);
|
||||
common.navigateTo(
|
||||
`/pages/courseRecord/courseStudyRecordDetail?stdyId=${list_item.stdyBatch}&crsName=${item.value.crsName}`
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// 计算两个标准时间的时间差值
|
||||
const formatDuration = (startTm, endTm) => {
|
||||
// 解析时间字符串为时间戳(毫秒)
|
||||
@@ -131,7 +133,6 @@
|
||||
}
|
||||
|
||||
.list_div {
|
||||
|
||||
overflow: hidden; /* 确保内容不会溢出容器 */
|
||||
transition: height 0.3s ease-out; /* 高度动画 */
|
||||
.list_item {
|
||||
|
||||
@@ -9,12 +9,9 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import itemVue from './studyRecordItem.vue';
|
||||
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
import { queryStdyRecordPaging } from '@/api/courseRecord.js';
|
||||
import { studyDurationIcon, studyTimeIcon } from '@/common/imgSvg';
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
const total = ref(-1);
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
$bg-margin-left: 30rpx;
|
||||
|
||||
.scroll-Y {
|
||||
height: calc(100vh - var(--status-bar-height) - 70rpx - 10rpx);
|
||||
height: calc(100vh - var(--status-bar-height) - 70rpx);
|
||||
}
|
||||
.content {
|
||||
position: relative;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
import studyRecordList from './components/studyRecordList.vue';
|
||||
import practiceRecordList from './components/practiceRecordList.vue';
|
||||
import examRecordList from './components/examRecordList.vue';
|
||||
|
||||
import { reactive, ref, computed, nextTick, onMounted, watch } from 'vue';
|
||||
import common from '@/common/common.js';
|
||||
const listItemRefs = ref([]);
|
||||
@@ -82,7 +83,7 @@
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
); // 这里的immediate会在onMounted之后执行
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -92,8 +92,10 @@
|
||||
@submit="touchBtnSubmit"
|
||||
loadingText="问题回答中,请在问题回答结束后重试!"
|
||||
:isLoading="!answerIsOver"
|
||||
:isDisabled="false"
|
||||
:isDisabled="touchIsDisabled"
|
||||
/>
|
||||
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -159,6 +161,7 @@
|
||||
const feedbackRef = ref(null);
|
||||
const dialogRef = ref(null);
|
||||
const popupRef = ref(null);
|
||||
let examinationStartTime = 0; // 考试开始时间
|
||||
|
||||
const mode = ref('examination'); // 考试 examination 练习practice
|
||||
const paperData = reactive({
|
||||
@@ -172,12 +175,21 @@
|
||||
const popup_input_bottom = ref('0px');
|
||||
const questionNumber = ref(0); // 题号
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
|
||||
const topic = computed({
|
||||
get: () => topicList[questionNumber.value],
|
||||
set: (val) => (topicList[questionNumber.value] = val)
|
||||
});
|
||||
const showTouchBtn = computed(() => {
|
||||
return topicList[questionNumber.value]['qnsTyp'] === 'ES';
|
||||
});
|
||||
const completedList = computed(() => {
|
||||
return [];
|
||||
});
|
||||
// 下面语音组件的禁用状态判断
|
||||
const touchIsDisabled = computed(() => {
|
||||
return topic.value?.es_status !== '' && topic.value?.es_status !== undefined;
|
||||
});
|
||||
|
||||
const markList = computed(() => topicList.filter((res) => !!res.mark).map((res) => res.qnsId)); // 标记列表
|
||||
// 下一题按钮状态
|
||||
@@ -265,6 +277,9 @@
|
||||
common.navigateBack();
|
||||
return;
|
||||
}
|
||||
// 记录起始时间
|
||||
examinationStartTime = new Date().getTime();
|
||||
|
||||
paperData.execId = examination.execId;
|
||||
paperData.examId = examination.examId;
|
||||
paperData.papersId = examination.papersId;
|
||||
@@ -395,7 +410,8 @@
|
||||
common.loading('正在提交');
|
||||
// 这里通过是否存在examId来判断是考试中心的考试还是课程的考试
|
||||
let func;
|
||||
if (paperData.examId) { // 这里是考试中心考试
|
||||
if (paperData.examId) {
|
||||
// 这里是考试中心考试
|
||||
func = commitPaperExam({
|
||||
papersId: paperData.papersId,
|
||||
examId: paperData.examId,
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
<template>
|
||||
<view class="item">
|
||||
<view class="details_div">
|
||||
<!-- <view class="img_div"> -->
|
||||
<!-- <image-preview class="img" :src="item.ossAddr" mode="scaleToFill"></image-preview> -->
|
||||
<!-- </view> -->
|
||||
<view class="right_div">
|
||||
<view class="title ellipsis-text">
|
||||
{{ item.examName }}
|
||||
</view>
|
||||
<view class="prompt_div">
|
||||
<view class="prompt_div_left">
|
||||
<view class="top">{{ item.highestGrade || 0 }}</view>
|
||||
<view class="bottom">历史最高分</view>
|
||||
</view>
|
||||
<view class="prompt_div_line"></view>
|
||||
<view class="prompt_div_right" @click="show_list_click">
|
||||
<view class="click_text">
|
||||
{{ item.examCnt || 0 }}
|
||||
<uv-icon
|
||||
class="click_text_icon"
|
||||
:class="{click_text_icon_action:show_list_state}"
|
||||
name="arrow-right"
|
||||
color="#0066FF"
|
||||
size="12"
|
||||
:bold="true"
|
||||
></uv-icon>
|
||||
</view>
|
||||
<view class="bottom">考试次数</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list_div" :style="{ height: list_div_height }">
|
||||
<view class="list_item" v-for="item_list in data_list" @click="click_list_item(item_list)">
|
||||
<view class="list_content">
|
||||
<view class="list_small_item">
|
||||
<image src="@/static/images/courseRecord/time.png" class="icon_img"></image>
|
||||
<view class="prompt">考试时间:{{ item_list.examStartTm }}</view>
|
||||
</view>
|
||||
<view class="list_small_item">
|
||||
<image src="@/static/images/courseRecord/duration.png" class="icon_img"></image>
|
||||
<view class="prompt">考试得分:{{ item_list.examGrade }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fl1"></view>
|
||||
<uv-icon name="arrow-right" color="#979797" size="17" :bold="true"></uv-icon>
|
||||
</view>
|
||||
<uv-load-more
|
||||
v-if="status === 'loading'"
|
||||
:status="status"
|
||||
loadmore-text="轻轻上拉加载"
|
||||
:height="30"
|
||||
></uv-load-more>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, reactive, nextTick } from 'vue';
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
const status = ref('loadmore'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
|
||||
import { queryExamHisByExamId } from '@/api/courseRecord.js';
|
||||
const item = computed(() => props.item);
|
||||
const data_list = reactive([]);
|
||||
const total = ref(-1);
|
||||
const show_list_state = ref(false);
|
||||
const list_div_height = computed(() => {
|
||||
if (!show_list_state.value) {
|
||||
return '0';
|
||||
} else if (status.value === 'loading') {
|
||||
return '100rpx';
|
||||
} else {
|
||||
return data_list.length * 136 + 'rpx';
|
||||
}
|
||||
});
|
||||
|
||||
// 点击获取考试详情
|
||||
const show_list_click = () => {
|
||||
show_list_state.value = !show_list_state.value;
|
||||
if (total.value === -1) {
|
||||
//加载数据
|
||||
status.value = 'loading';
|
||||
data_list.length = 0;
|
||||
queryExamHisByExamId({ examId: item.value.examId }).then((res) => {
|
||||
data_list.push(...res.body);
|
||||
total.value = data_list.length;
|
||||
status.value = 'loadmore';
|
||||
});
|
||||
}
|
||||
};
|
||||
// 跳转到详情
|
||||
const click_list_item = (list_item) => {
|
||||
const examLenTm = 666;
|
||||
const papersName = item.value.examName;
|
||||
common.navigateTo(
|
||||
`/pages/examination/result?execId=${list_item.execId}&examLenTm=${examLenTm}&papersName=${papersName}`
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.icon_img {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
}
|
||||
|
||||
.list_div {
|
||||
overflow: hidden; /* 确保内容不会溢出容器 */
|
||||
transition: height 0.2s ease-out; /* 高度动画 */
|
||||
.list_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 18rpx 32rpx 18rpx 28rpx;
|
||||
background-color: #f9fbff;
|
||||
border-radius: 8rpx;
|
||||
margin: 20rpx 0 0 0;
|
||||
.list_content {
|
||||
.list_small_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 40rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
.prompt {
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.item {
|
||||
margin: 17rpx 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx 22rpx;
|
||||
.details_div {
|
||||
display: flex;
|
||||
|
||||
.img_div {
|
||||
position: relative;
|
||||
width: 226rpx;
|
||||
height: 168rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 22rpx;
|
||||
|
||||
.img {
|
||||
width: 226rpx;
|
||||
height: 168rpx;
|
||||
}
|
||||
|
||||
.subscript {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 92rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 0px 0px 0px 22rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
line-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.right_div {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.title {
|
||||
font-family: PingFangSC;
|
||||
color: #333333;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 28rpx; /* 字体大小30rpx */
|
||||
overflow: hidden; /* 超出部分隐藏 */
|
||||
margin-bottom: 8rpx;
|
||||
min-height: 40rpx;
|
||||
}
|
||||
|
||||
.prompt_div {
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #666;
|
||||
line-height: 34rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
height: 116rpx;
|
||||
background-color: #f9fbff;
|
||||
border-radius: 8rpx;
|
||||
justify-content: space-around;
|
||||
.prompt_div_line {
|
||||
width: 4rpx;
|
||||
height: 30rpx;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
RGBA(242, 244, 248, 1) 0%,
|
||||
RGBA(230, 232, 238, 1) 30%,
|
||||
RGBA(230, 232, 238, 1) 70%,
|
||||
RGBA(242, 244, 248, 1) 100%
|
||||
);
|
||||
}
|
||||
.prompt_div_left,
|
||||
.prompt_div_right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.top,
|
||||
.click_text {
|
||||
font-family: Arial;
|
||||
font-weight: 700;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
line-height: 34rpx;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
}
|
||||
.bottom {
|
||||
}
|
||||
.click_text {
|
||||
position: relative;
|
||||
.click_text_icon {
|
||||
position: absolute;
|
||||
margin-left: 18rpx;
|
||||
top: calc(50% - 12rpx);
|
||||
left: calc(100% - 14rpx);
|
||||
/* 添加过渡动画,包含延迟效果 */
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.click_text_icon_action{
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.people_progress_div {
|
||||
display: flex;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
margin-bottom: 23rpx;
|
||||
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<itemVue :item="item" v-for="(item, index) in data_list"></itemVue>
|
||||
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
|
||||
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import itemVue from './examRecordItem.vue';
|
||||
import common from '@/common/common';
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
import { queryExamRecordPaging } from '@/api/courseRecord.js';
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
const total = ref(-1);
|
||||
const page = ref(0);
|
||||
const data_list = reactive([]);
|
||||
|
||||
const getData = (from = '') => {
|
||||
if (from == 'first') {
|
||||
if (total.value !== -1) {
|
||||
return;
|
||||
}
|
||||
status.value = 'loading';
|
||||
total.value = -1;
|
||||
page.value = 1;
|
||||
data_list.length = 0;
|
||||
} else {
|
||||
if (status.value !== 'loadmore' && status.value !== '') return;
|
||||
status.value = 'loading';
|
||||
page.value++;
|
||||
}
|
||||
queryExamRecordPaging({
|
||||
page: page.value,
|
||||
limit: limit
|
||||
})
|
||||
.then((res) => {
|
||||
total.value = res.total;
|
||||
data_list.push(...res.body);
|
||||
})
|
||||
.finally(() => {
|
||||
if (data_list.length >= total.value) {
|
||||
status.value = 'nomore';
|
||||
} else {
|
||||
status.value = 'loadmore';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const scrolltolower = (item) => {
|
||||
getData();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
getData
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scroll_div {
|
||||
background-color: #f1f5fa;
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 88rpx - 30rpx);
|
||||
}
|
||||
</style>
|
||||
@@ -1,249 +0,0 @@
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<view
|
||||
class="item"
|
||||
:class="getStatusClass(item.isFinish)"
|
||||
v-for="(item, index) in data_list"
|
||||
@click="click_item(item)"
|
||||
>
|
||||
<view class="img_div">
|
||||
<image-preview class="img" :src="item.ossAddr" mode="scaleToFill"></image-preview>
|
||||
<view class="subscript" v-if="item.isFinish === '00'">未完成</view>
|
||||
<view class="subscript" v-if="item.isFinish === '01'">已完成</view>
|
||||
</view>
|
||||
<view class="right_div">
|
||||
<view class="title ellipsis-text">
|
||||
{{ item.taskName }}
|
||||
</view>
|
||||
<view class="time_div" v-if="item.limitTyp === '02'">
|
||||
起止时间:
|
||||
<text class="blod_color">{{ item.startTm?.substr(0, 10) }}至{{ item.endTm?.substr(0, 10) }}</text>
|
||||
</view>
|
||||
<view class="people_progress_div">
|
||||
<view class="mr-10">
|
||||
完成人数:
|
||||
<text class="">{{ item.taskFinishSums ?? 0 }}/{{ item.taskSums ?? 0 }}</text>
|
||||
</view>
|
||||
<view>
|
||||
进度:
|
||||
<text class="">{{ item.finishCrs ?? 0 }}/{{ item.sumCrs ?? 0 }}门课程</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
|
||||
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
const total = ref(-1);
|
||||
const page = ref(0);
|
||||
const data_list = reactive([]);
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
|
||||
import { queryAllTraTaskInfoByUserId } from '@/api/learningTasks.js';
|
||||
const props = defineProps({
|
||||
state: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const getData = (from = '', searchText = '') => {
|
||||
if (from == 'first') {
|
||||
if (total.value !== -1) {
|
||||
return;
|
||||
}
|
||||
status.value = 'loading';
|
||||
total.value = -1;
|
||||
page.value = 1;
|
||||
data_list.length = 0;
|
||||
} else {
|
||||
if (status.value !== 'loadmore' && status.value !== '') return;
|
||||
status.value = 'loading';
|
||||
page.value++;
|
||||
}
|
||||
setTimeout(() => {
|
||||
queryAllTraTaskInfoByUserId({
|
||||
state: props.state,
|
||||
page: page.value,
|
||||
limit: limit,
|
||||
taskName: searchText
|
||||
})
|
||||
.then((res) => {
|
||||
total.value = res.total;
|
||||
data_list.push(...res.body);
|
||||
})
|
||||
.finally(() => {
|
||||
if (data_list.length >= total.value) {
|
||||
status.value = 'nomore';
|
||||
} else {
|
||||
status.value = 'loadmore';
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
const getStatusClass = (isFinish) => {
|
||||
// 00进行中、01已完成、02已超时
|
||||
if (isFinish === '00') return 'in_progress';
|
||||
if (isFinish === '01') return 'completed';
|
||||
return 'expired';
|
||||
};
|
||||
|
||||
// 跳转到详情
|
||||
const click_item = (item) => {
|
||||
if(item.isTimeOut === '00') {
|
||||
common.msg('任务已结束')
|
||||
return ;
|
||||
}
|
||||
setPageCache('learning_tasks_details', item);
|
||||
common.navigateTo('/pages/learningTasks/details');
|
||||
};
|
||||
const scrolltolower = (item) => {
|
||||
getData();
|
||||
};
|
||||
const search = (value) => {
|
||||
total.value = -1;
|
||||
console.log('value', value);
|
||||
getData('first', value);
|
||||
};
|
||||
defineExpose({
|
||||
getData,
|
||||
search
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scroll_div {
|
||||
background-color: #f1f5fa;
|
||||
padding: 22rpx;
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 80rpx - 88rpx - 20rpx - 30rpx);
|
||||
// height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 44rpx);
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
.item.in_progress {
|
||||
// 进行中
|
||||
.subscript {
|
||||
color: #0066ff;
|
||||
background-color: #daf0ff;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #0066ff;
|
||||
}
|
||||
}
|
||||
|
||||
.item.completed {
|
||||
// 已完成
|
||||
.subscript {
|
||||
color: #ffffff;
|
||||
background-color: #33c583 !important;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.item.expired {
|
||||
// 已超时
|
||||
.subscript {
|
||||
color: #ffffff;
|
||||
background-color: #ef5705;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #d70c18;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item {
|
||||
height: 170rpx;
|
||||
margin: 32rpx 22rpx;
|
||||
display: flex;
|
||||
|
||||
.img_div {
|
||||
position: relative;
|
||||
width: 224rpx;
|
||||
height: 168rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 22rpx;
|
||||
|
||||
.img {
|
||||
width: 226rpx;
|
||||
height: 168rpx;
|
||||
}
|
||||
|
||||
.subscript {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 92rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 0px 0px 0px 22rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
line-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.right_div {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.title {
|
||||
font-family: PingFangSC;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
|
||||
.time_div {
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.people_progress_div {
|
||||
display: flex;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
margin-bottom: 23rpx;
|
||||
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -5,59 +5,34 @@
|
||||
<view class="back_div" @click="common.navigateBack()">
|
||||
<view class="back-icon"></view>
|
||||
</view>
|
||||
<view class="title font_pf">学习任务</view>
|
||||
</view>
|
||||
<view class="fixed_search_input_div">
|
||||
<search-input placeholder="请输入任务名" @search="search"></search-input>
|
||||
<view class="title font_pf">考试记录</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-body">
|
||||
<view class="body-tab">
|
||||
<uv-tabs
|
||||
class="font_pf my_tabs"
|
||||
:current="tabAct"
|
||||
:list="tabList"
|
||||
@change="tabChange"
|
||||
:scrollable="false"
|
||||
line-color="#0066FF"
|
||||
:inactive-style="{ color: '#333333', fontSize: '30rpx', fontWeight: '600' }"
|
||||
:activeStyle="{ color: '#0066FF', fontSize: '30rpx', fontWeight: '600' }"
|
||||
:lineColor="`url(${LineBg}) 10% 10%`"
|
||||
></uv-tabs>
|
||||
</view>
|
||||
<view class="uni-margin-wrap no-overflow">
|
||||
<swiper class="swiper" :current="tabAct" :indicator-dots="false" @change="swiperChange">
|
||||
<swiper-item>
|
||||
<listItem :ref="(el) => (listItemRefs[0] = el)" state="01"></listItem>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<listItem :ref="(el) => (listItemRefs[1] = el)" state="02"></listItem>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<listItem :ref="(el) => (listItemRefs[2] = el)" state="03"></listItem>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<examRecordList ref="listItemRef"></examRecordList>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { LineBg } from '@/enum.js';
|
||||
import listItem from './components/list-item.vue';
|
||||
|
||||
import examRecordList from './components/examRecordList.vue';
|
||||
|
||||
import { reactive, ref, computed, nextTick, onMounted, watch } from 'vue';
|
||||
import common from '@/common/common.js';
|
||||
const listItemRefs = ref([]);
|
||||
const listItemRef = ref(null);
|
||||
const taskRef = ref(null);
|
||||
const tabAct = ref(0);
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '全 部'
|
||||
name: '学习记录'
|
||||
},
|
||||
{
|
||||
name: '已完成'
|
||||
name: '练习记录'
|
||||
},
|
||||
{
|
||||
name: '未完成'
|
||||
name: '考试记录'
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -67,21 +42,10 @@
|
||||
const swiperChange = (item) => {
|
||||
tabAct.value = item.detail.current;
|
||||
};
|
||||
const search = (value) => {
|
||||
listItemRefs.value[tabAct.value]?.search(value);
|
||||
};
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
watch(
|
||||
tabAct,
|
||||
(newValue, oldValue) => {
|
||||
typeof listItemRefs.value[newValue]?.getData === 'function' &&
|
||||
listItemRefs.value[newValue]?.getData('first');
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
); // 这里的immediate会在onMounted之后执行
|
||||
listItemRef.value?.getData('first');
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -102,12 +66,11 @@
|
||||
/*
|
||||
状态栏 var(--status-bar-height)
|
||||
标题高度88rpx
|
||||
搜索栏高度80rpx
|
||||
tab切换栏高度88rpx
|
||||
下方滑动区域上下边距各10共20rpx
|
||||
**/
|
||||
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 80rpx - 88rpx - 20rpx);
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 88rpx - 30rpx);
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<view class="item" :class="getStatusClass(index)" v-for="(item,index) in data_list" @click="click_item(item)" >
|
||||
<view class="img_div">
|
||||
<image-preview class="img" :src="item?.ossAddr" mode="scaleToFill"></image-preview>
|
||||
<view class="subscript" v-if="item.isFinish === '00'">未完成</view>
|
||||
<view class="subscript" v-if="item.isFinish === '01'">已完成</view>
|
||||
</view>
|
||||
<view class="right_div">
|
||||
<view class="title ellipsis-text">
|
||||
{{item.taskName}}
|
||||
</view>
|
||||
<view class="time_div">
|
||||
起止时间:<text class="blod_color">{{item.startTm?.substr(0, 10)}}至{{item.endTm?.substr(0, 10)}}</text>
|
||||
</view>
|
||||
<view class="people_progress_div">
|
||||
<view class="mr-10">
|
||||
完成人数:<text class="blod_color">{{item.taskFinishSums ?? 0}}/{{item.taskSums ?? 0}}</text>
|
||||
</view>
|
||||
<view>
|
||||
我的进度:<text class="blod_color">{{item.myProcess ?? 0}}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<list-no-data v-if="total == 0 && status=='nomore'"></list-no-data>
|
||||
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
const status = ref('loading') // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15
|
||||
const total = ref(-1)
|
||||
const page = ref(0)
|
||||
const data_list = reactive([])
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
onMounted,
|
||||
nextTick
|
||||
} from 'vue'
|
||||
import {
|
||||
queryTraPersonalCollectionTaskPaging
|
||||
} from '@/api/favorites.js';
|
||||
const getData = (from = '') => {
|
||||
if (from == 'first') {
|
||||
if (total.value !== -1) {
|
||||
return
|
||||
}
|
||||
status.value = 'loading'
|
||||
total.value = -1
|
||||
page.value = 1
|
||||
data_list.length = 0
|
||||
} else {
|
||||
if (status.value !== 'loadmore' && status.value !== '') return
|
||||
status.value = 'loading'
|
||||
page.value++
|
||||
}
|
||||
console.log(status.value, '阿斯顿撒');
|
||||
|
||||
setTimeout(() => {
|
||||
queryTraPersonalCollectionTaskPaging({
|
||||
page: page.value,
|
||||
limit: limit
|
||||
}).then(res => {
|
||||
total.value = res.total
|
||||
data_list.push(...res.body)
|
||||
}).finally(() => {
|
||||
if (data_list.length >= total.value) {
|
||||
status.value = 'nomore'
|
||||
} else {
|
||||
status.value = 'loadmore'
|
||||
}
|
||||
})
|
||||
}, 200)
|
||||
}
|
||||
|
||||
// 跳转到详情
|
||||
const click_item = (item) => {
|
||||
|
||||
// tudo
|
||||
|
||||
// if(item.isTimeOut === '00') {
|
||||
// common.msg('任务已结束')
|
||||
// return ;
|
||||
// }
|
||||
|
||||
// setPageCache('learning_tasks_details', item);
|
||||
// common.navigateTo('/pages/learningTasks/details');
|
||||
};
|
||||
const getStatusClass = (index) => {
|
||||
const remainder = index % 3;
|
||||
if (remainder === 0) return 'in_progress';
|
||||
if (remainder === 1) return 'completed';
|
||||
return 'expired';
|
||||
};
|
||||
const scrolltolower = (item) => {
|
||||
getData()
|
||||
};
|
||||
defineExpose({
|
||||
getData
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scroll_div {
|
||||
background-color: #F1F5FA;
|
||||
padding: 22rpx;
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 44rpx);
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.scroll-Y .item.in_progress {
|
||||
|
||||
// 进行中
|
||||
.subscript {
|
||||
|
||||
color: #0066FF;
|
||||
background-color: #DAF0FF;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item.completed {
|
||||
|
||||
// 已完成
|
||||
.subscript {
|
||||
color: #FFFFFF;
|
||||
background-color: #33C583;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item.expired {
|
||||
|
||||
// 已超时
|
||||
.subscript {
|
||||
color: #FFFFFF;
|
||||
background-color: #EF5705;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #D70C18;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item {
|
||||
height: 170rpx;
|
||||
margin: 32rpx 22rpx;
|
||||
display: flex;
|
||||
|
||||
.img_div {
|
||||
position: relative;
|
||||
width: 224rpx;
|
||||
height: 168rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 22rpx;
|
||||
|
||||
.img {
|
||||
width: 226rpx;
|
||||
height: 168rpx;
|
||||
}
|
||||
|
||||
.subscript {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 92rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 0px 0px 0px 22rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
line-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.right_div {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.title {
|
||||
font-family: PingFangSC;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
|
||||
.time_div {
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.people_progress_div {
|
||||
display: flex;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
margin-bottom: 23rpx;
|
||||
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+85
-84
@@ -2,127 +2,129 @@
|
||||
<view class="scroll_div">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<uv-swipe-action :autoClose="true">
|
||||
<uv-swipe-action-item class="item-swipe-action" :options="options" :threshold="40" :index="index"
|
||||
:name="index" v-for="(item,index) in data_list" @click="swipeActionClick" >
|
||||
<uv-swipe-action-item
|
||||
class="item-swipe-action"
|
||||
:options="options"
|
||||
:threshold="40"
|
||||
:index="index"
|
||||
:name="index"
|
||||
v-for="(item, index) in data_list"
|
||||
@click="swipeActionClick"
|
||||
>
|
||||
<view class="item" @touchmove.stop @click="click_item(item)">
|
||||
<view class="img_div">
|
||||
<image-preview class="img" :src="item?.ossAddr" mode="scaleToFill"></image-preview>
|
||||
<view class="subscript">
|
||||
{{item.evalGrade ?? 0}}分
|
||||
</view>
|
||||
<view class="subscript">{{ item.evalGrade ?? 0 }}分</view>
|
||||
</view>
|
||||
<view class="right_div">
|
||||
<view class="title ellipsis-text">
|
||||
{{item.crsName}}
|
||||
{{ item.crsName }}
|
||||
</view>
|
||||
<view class="tag_div">
|
||||
<view class="tag" v-for="tagItem in item?.tagCataList ?? []">
|
||||
{{tagItem?.tagName}}
|
||||
{{ tagItem?.tagName }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="time_and_num">
|
||||
<view class="mr-10">
|
||||
发布:{{item.issuTm?.substr(0, 10)}}
|
||||
</view>
|
||||
<view>
|
||||
已学:{{item.accmStdyCnt}}次
|
||||
</view>
|
||||
<view class="mr-10">发布:{{ item.issuTm?.substr(0, 10) }}</view>
|
||||
<view>已学:{{ item.accmStdyCnt }}次</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uv-swipe-action-item>
|
||||
</uv-swipe-action>
|
||||
<list-no-data v-if="total == 0 && status=='nomore'"></list-no-data>
|
||||
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
|
||||
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
const status = ref('loading') // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15
|
||||
const total = ref(-1)
|
||||
const page = ref(0)
|
||||
const data_list = reactive([])
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
onMounted,
|
||||
nextTick
|
||||
} from 'vue'
|
||||
import {
|
||||
queryTraPersonalCollectionCrsPaging,
|
||||
deleteTraPersonalCollectionById
|
||||
} from '@/api/favorites.js';
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
const total = ref(-1);
|
||||
const page = ref(0);
|
||||
const data_list = reactive([]);
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
import { queryTraPersonalCollectionCrsPaging, deleteTraPersonalCollectionById } from '@/api/favorites.js';
|
||||
import common from '@/common/common';
|
||||
const options = [{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#f56c6c'
|
||||
const options = [
|
||||
{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#f56c6c'
|
||||
}
|
||||
}
|
||||
}]
|
||||
];
|
||||
const getData = (from = '') => {
|
||||
console.log('status.value', status.value);
|
||||
if (from == 'first') {
|
||||
if (total.value !== -1) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
status.value = 'loading'
|
||||
total.value = -1
|
||||
page.value = 1
|
||||
data_list.length = 0
|
||||
status.value = 'loading';
|
||||
total.value = -1;
|
||||
page.value = 1;
|
||||
data_list.length = 0;
|
||||
} else {
|
||||
if (status.value !== 'loadmore' && status.value !== '') return
|
||||
status.value = 'loading'
|
||||
page.value++
|
||||
if (status.value !== 'loadmore' && status.value !== '') return;
|
||||
status.value = 'loading';
|
||||
page.value++;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
queryTraPersonalCollectionCrsPaging({
|
||||
page: page.value,
|
||||
limit: limit
|
||||
}).then(res => {
|
||||
total.value = res.total
|
||||
data_list.push(...res.body)
|
||||
}).finally(() => {
|
||||
if (data_list.length >= total.value) {
|
||||
status.value = 'nomore'
|
||||
} else {
|
||||
status.value = 'loadmore'
|
||||
}
|
||||
queryTraPersonalCollectionCrsPaging({
|
||||
page: page.value,
|
||||
limit: limit
|
||||
})
|
||||
.then((res) => {
|
||||
total.value = res.total;
|
||||
data_list.push(...res.body);
|
||||
})
|
||||
}, 200)
|
||||
}
|
||||
.finally(() => {
|
||||
if (data_list.length >= total.value) {
|
||||
status.value = 'nomore';
|
||||
} else {
|
||||
status.value = 'loadmore';
|
||||
}
|
||||
console.log('status.value', status.value);
|
||||
});
|
||||
};
|
||||
// 进入课程详情页
|
||||
const click_item = (item) => {
|
||||
common.navigateTo('/pages/courseDetail/index?crsId=' + item.crsId)
|
||||
common.navigateTo(`/pages/courseDetail/index?crsId=${item.crsId}&collectId=${item.collectId}`);
|
||||
};
|
||||
const swipeActionClick = (click_item) => {
|
||||
const index = click_item['name']
|
||||
const item = data_list[index]
|
||||
common.show('提示', '确认删除吗?').then(res => {
|
||||
const index = click_item['name'];
|
||||
const item = data_list[index];
|
||||
common.show('提示', '确认删除吗?').then((res) => {
|
||||
if (!res) return;
|
||||
common.loading()
|
||||
const collectId = '11'
|
||||
deleteTraPersonalCollectionById({collectId:item.collectId}).then(()=>{
|
||||
data_list.splice(index, 1); // 从列表移除
|
||||
total.value -= 1 // 更新下总数
|
||||
}).finally(() => {
|
||||
common.hideLoading()
|
||||
})
|
||||
})
|
||||
}
|
||||
const scrolltolower = (item) => {
|
||||
getData()
|
||||
common.loading();
|
||||
deleteTraPersonalCollectionById({ collectId: item.collectId })
|
||||
.then(() => {
|
||||
data_list.splice(index, 1); // 从列表移除
|
||||
total.value -= 1; // 更新下总数
|
||||
})
|
||||
.finally(() => {
|
||||
common.hideLoading();
|
||||
});
|
||||
});
|
||||
};
|
||||
const scrolltolower = (item) => {
|
||||
getData();
|
||||
};
|
||||
const refreshData = (params) => {
|
||||
total.value = -1;
|
||||
getData('first');
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
getData
|
||||
})
|
||||
getData,
|
||||
refreshData
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
|
||||
.scroll_div {
|
||||
background-color: #F1F5FA;
|
||||
background-color: #f1f5fa;
|
||||
padding: 22rpx;
|
||||
}
|
||||
|
||||
@@ -171,8 +173,8 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #EF5705;
|
||||
color: #FFFFFF;
|
||||
background-color: #ef5705;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,16 +205,15 @@
|
||||
padding: 0 10rpx;
|
||||
margin-right: 14rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #FFA150;
|
||||
border: 2rpx solid #ffa150;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 500;
|
||||
font-size: 23rpx;
|
||||
color: #FFA150;
|
||||
color: #ffa150;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.time_and_num {
|
||||
@@ -229,4 +230,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -0,0 +1,282 @@
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<uv-swipe-action :autoClose="true">
|
||||
<uv-swipe-action-item
|
||||
class="item-swipe-action"
|
||||
:options="options"
|
||||
:threshold="40"
|
||||
:index="index"
|
||||
:name="index"
|
||||
v-for="(item, index) in data_list"
|
||||
@click="swipeActionClick"
|
||||
>
|
||||
<view class="item" :class="getStatusClass(index)" @touchmove.stop @click="click_item(item)">
|
||||
<view class="img_div">
|
||||
<image-preview class="img" :src="item?.ossAddr" mode="scaleToFill"></image-preview>
|
||||
<view class="subscript" v-if="item.isFinish === '00'">未完成</view>
|
||||
<view class="subscript" v-if="item.isFinish === '01'">已完成</view>
|
||||
</view>
|
||||
<view class="right_div">
|
||||
<view class="title ellipsis-text">
|
||||
{{ item.taskName }}
|
||||
</view>
|
||||
<view class="time_div">
|
||||
起止时间:
|
||||
<text class="blod_color">
|
||||
{{ item.startTm?.substr(0, 10) }}至{{ item.endTm?.substr(0, 10) }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="people_progress_div">
|
||||
<view class="mr-10">
|
||||
完成人数:
|
||||
<text class="blod_color">{{ item.taskFinishSums ?? 0 }}/{{ item.taskSums ?? 0 }}</text>
|
||||
</view>
|
||||
<view>
|
||||
我的进度:
|
||||
<text class="blod_color">{{ item.myProcess ?? 0 }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uv-swipe-action-item>
|
||||
</uv-swipe-action>
|
||||
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
|
||||
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
import { queryTraPersonalCollectionTaskPaging,deleteTraPersonalCollectionById } from '@/api/favorites.js';
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
const total = ref(-1);
|
||||
const page = ref(0);
|
||||
const data_list = reactive([]);
|
||||
const options = [
|
||||
{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#f56c6c'
|
||||
}
|
||||
}
|
||||
];
|
||||
const getData = (from = '') => {
|
||||
if (from == 'first') {
|
||||
if (total.value !== -1) {
|
||||
return;
|
||||
}
|
||||
status.value = 'loading';
|
||||
total.value = -1;
|
||||
page.value = 1;
|
||||
data_list.length = 0;
|
||||
} else {
|
||||
if (status.value !== 'loadmore' && status.value !== '') return;
|
||||
status.value = 'loading';
|
||||
page.value++;
|
||||
}
|
||||
setTimeout(() => {
|
||||
queryTraPersonalCollectionTaskPaging({
|
||||
page: page.value,
|
||||
limit: limit
|
||||
})
|
||||
.then((res) => {
|
||||
total.value = res.total;
|
||||
data_list.push(...res.body);
|
||||
})
|
||||
.finally(() => {
|
||||
if (data_list.length >= total.value) {
|
||||
status.value = 'nomore';
|
||||
} else {
|
||||
status.value = 'loadmore';
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
|
||||
const swipeActionClick = (click_item) => {
|
||||
const index = click_item['name'];
|
||||
const item = data_list[index];
|
||||
common.show('提示', '确认删除吗?').then((res) => {
|
||||
if (!res) return;
|
||||
common.loading();
|
||||
const collectId = '11';
|
||||
deleteTraPersonalCollectionById({ collectId: item.collectionId })
|
||||
.then(() => {
|
||||
data_list.splice(index, 1); // 从列表移除
|
||||
total.value -= 1; // 更新下总数
|
||||
})
|
||||
.finally(() => {
|
||||
common.hideLoading();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 跳转到详情
|
||||
const click_item = (item) => {
|
||||
// tudo
|
||||
if (item.isTimeOut === '00') {
|
||||
common.msg('任务已结束');
|
||||
return;
|
||||
}
|
||||
setPageCache('learning_tasks_details', item);
|
||||
common.navigateTo(`/pages/learningTasks/details?collectId=${item.collectionId}`);
|
||||
};
|
||||
const getStatusClass = (index) => {
|
||||
const remainder = index % 3;
|
||||
if (remainder === 0) return 'in_progress';
|
||||
if (remainder === 1) return 'completed';
|
||||
return 'expired';
|
||||
};
|
||||
const scrolltolower = (item) => {
|
||||
getData();
|
||||
};
|
||||
const refreshData = (params) => {
|
||||
total.value = -1;
|
||||
getData('first');
|
||||
console.log('子组件refreshData');
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
getData,
|
||||
refreshData
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scroll_div {
|
||||
background-color: #f1f5fa;
|
||||
padding: 22rpx;
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 44rpx);
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.scroll-Y .item.in_progress {
|
||||
// 进行中
|
||||
.subscript {
|
||||
color: #0066ff;
|
||||
background-color: #daf0ff;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item.completed {
|
||||
// 已完成
|
||||
.subscript {
|
||||
color: #ffffff;
|
||||
background-color: #33c583;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item.expired {
|
||||
// 已超时
|
||||
.subscript {
|
||||
color: #ffffff;
|
||||
background-color: #ef5705;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #d70c18;
|
||||
}
|
||||
}
|
||||
.item-swipe-action {
|
||||
margin: 32rpx 22rpx;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.uv-swipe-action-item__right__button__wrapper) {
|
||||
border-radius: 20rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item {
|
||||
height: 170rpx;
|
||||
// margin: 32rpx 22rpx;
|
||||
display: flex;
|
||||
|
||||
.img_div {
|
||||
position: relative;
|
||||
width: 224rpx;
|
||||
height: 168rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 22rpx;
|
||||
|
||||
.img {
|
||||
width: 226rpx;
|
||||
height: 168rpx;
|
||||
}
|
||||
|
||||
.subscript {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 92rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 0px 0px 0px 22rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
line-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.right_div {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.title {
|
||||
font-family: PingFangSC;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
|
||||
.time_div {
|
||||
font-family: Arial;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.people_progress_div {
|
||||
display: flex;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
margin-bottom: 23rpx;
|
||||
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -9,14 +9,26 @@
|
||||
</view>
|
||||
<view class="detail-body">
|
||||
<view class="body-tab">
|
||||
<uv-tabs class="font_pf my_tabs" :current="tabAct" :list="tabList" @change="tabChange"
|
||||
:scrollable="false" line-color="#0066FF"
|
||||
:inactive-style="{ color: '#333333', fontSize: '30rpx', fontWeight:'600'}"
|
||||
:activeStyle="{color:'#0066FF',fontSize:'30rpx', fontWeight:'600'}"
|
||||
:lineColor="`url(${LineBg}) 10% 10%`"></uv-tabs>
|
||||
<uv-tabs
|
||||
class="font_pf my_tabs"
|
||||
:current="tabAct"
|
||||
:list="tabList"
|
||||
@change="tabChange"
|
||||
:scrollable="false"
|
||||
line-color="#0066FF"
|
||||
:inactive-style="{ color: '#333333', fontSize: '30rpx', fontWeight: '600' }"
|
||||
:activeStyle="{ color: '#0066FF', fontSize: '30rpx', fontWeight: '600' }"
|
||||
:lineColor="`url(${LineBg}) 10% 10%`"
|
||||
></uv-tabs>
|
||||
</view>
|
||||
<view class="uni-margin-wrap no-overflow">
|
||||
<swiper class="swiper" :current="tabAct" :indicator-dots="false" :disable-touch="true" @change="swiperChange">
|
||||
<swiper
|
||||
class="swiper"
|
||||
:current="tabAct"
|
||||
:indicator-dots="false"
|
||||
:disable-touch="true"
|
||||
@change="swiperChange"
|
||||
>
|
||||
<swiper-item>
|
||||
<FavoritesCourse ref="courseRef"></FavoritesCourse>
|
||||
</swiper-item>
|
||||
@@ -30,30 +42,25 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import FavoritesTask from './components/favorites-task.vue'
|
||||
import FavoritesCourse from './components/favorites-course.vue'
|
||||
import FavoritesTask from './components/favoritesTask.vue';
|
||||
import FavoritesCourse from './components/favoritesCourse.vue';
|
||||
// 我的收藏
|
||||
import {
|
||||
reactive,
|
||||
ref,
|
||||
computed,
|
||||
nextTick,
|
||||
onMounted,
|
||||
watch
|
||||
} from 'vue';
|
||||
import {
|
||||
LineBg
|
||||
} from '@/enum.js'
|
||||
import { reactive, ref, computed, nextTick, onMounted, watch } from 'vue';
|
||||
import { onShow, onLoad, onUnload } from '@dcloudio/uni-app';
|
||||
import { LineBg } from '@/enum.js';
|
||||
import common from '@/common/common';
|
||||
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
|
||||
const courseRef = ref(null);
|
||||
const taskRef = ref(null);
|
||||
const tabAct = ref(0);
|
||||
const tabList = ref([{
|
||||
name: '课程收藏'
|
||||
}, {
|
||||
name: '任务收藏'
|
||||
}]);
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '课程收藏'
|
||||
},
|
||||
{
|
||||
name: '任务收藏'
|
||||
}
|
||||
]);
|
||||
|
||||
const tabChange = (item) => {
|
||||
tabAct.value = item.index;
|
||||
@@ -62,23 +69,38 @@
|
||||
tabAct.value = item.detail.current;
|
||||
};
|
||||
onMounted(() => {
|
||||
watch(tabAct, (newValue, oldValue) => {
|
||||
if (newValue === 0) {
|
||||
courseRef.value?.getData('first')
|
||||
} else if (newValue === 1) {
|
||||
taskRef.value?.getData('first')
|
||||
watch(
|
||||
tabAct,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue === 0) {
|
||||
courseRef.value?.getData('first');
|
||||
} else if (newValue === 1) {
|
||||
taskRef.value?.getData('first');
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
}, {
|
||||
immediate: true
|
||||
}) // 这里的immediate会在onMounted之后执行
|
||||
})
|
||||
); // 这里的immediate会在onMounted之后执行
|
||||
});
|
||||
onLoad(async () => {
|
||||
uni.$on('refresh_favorites_data', (params) => {
|
||||
if (params.type === 'course') {
|
||||
courseRef.value?.refreshData(params);
|
||||
} else if (params.type === 'task') {
|
||||
taskRef.value?.refreshData(params);
|
||||
}
|
||||
});
|
||||
});
|
||||
onUnload(() => {
|
||||
uni.$off('refresh_favorites_data');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$bg-margin-left: 50rpx;
|
||||
|
||||
.my_tabs {
|
||||
|
||||
// 解决这个圆角的图片,开穿透
|
||||
:deep(.uv-tabs__wrapper__nav__line) {
|
||||
height: 26rpx !important;
|
||||
@@ -111,7 +133,7 @@
|
||||
}
|
||||
|
||||
.detail-main {
|
||||
background-color: #F6F8FF;
|
||||
background-color: #f6f8ff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -164,4 +186,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -79,21 +79,35 @@
|
||||
{{ item.crsName }}
|
||||
</view>
|
||||
<view class="button_div">
|
||||
<template v-if="item.isFinishStudy === '01' && item.isFinishExam === '01' && item.status !== '02'">
|
||||
<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'">
|
||||
<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'?'#0066FF':'#999999')"></image>
|
||||
<view class="button_text" :class="item.isFinishStudy==='02'?'success':'error'">完成练习</view>
|
||||
<image
|
||||
class="img"
|
||||
:src="passTheExamIcon(item.isFinishStudy === '02' ? '#0066FF' : '#999999')"
|
||||
></image>
|
||||
<view class="button_text" :class="item.isFinishStudy === '02' ? 'success' : 'error'">
|
||||
完成练习
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.isFinishExam !== '01'">
|
||||
<image class="img" :src="completeTheExercisesIcon(item.isFinishExam==='02'?'#0066FF':'#999999')"></image>
|
||||
<view class="button_text" :class="item.isFinishExam==='02'?'success':'error'">通过考试</view>
|
||||
<image
|
||||
class="img"
|
||||
:src="completeTheExercisesIcon(item.isFinishExam === '02' ? '#0066FF' : '#999999')"
|
||||
></image>
|
||||
<view class="button_text" :class="item.isFinishExam === '02' ? 'success' : 'error'">
|
||||
通过考试
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
@@ -112,13 +126,14 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||
import { ref, reactive, computed, nextTick } from 'vue';
|
||||
import { queryAllTraTaskCrsInfo } from '@/api/learningTasks.js';
|
||||
import { passTheExamIcon, completeTheExercisesIcon, lockIcon } from '@/common/imgSvg';
|
||||
import { insertTraPersonalCollectionTask, deleteTraPersonalCollectionById } from '@/api/favorites.js';
|
||||
import common from '@/common/common';
|
||||
import { setPageCache, getPageCache } from '@/common/common';
|
||||
const collectId = ref(''); // 记录初始的收藏id
|
||||
const detailData = reactive({
|
||||
taskId: '',
|
||||
taskName: '',
|
||||
@@ -140,10 +155,8 @@
|
||||
};
|
||||
const getData = () => {
|
||||
status.value = 'loading';
|
||||
|
||||
queryAllTraTaskCrsInfo({
|
||||
taskId: detailData.taskId
|
||||
// taskId: 'TASKINFO02506401613920250820161715000008095'
|
||||
})
|
||||
.then((res) => {
|
||||
data_list.push(...res.body);
|
||||
@@ -166,12 +179,11 @@
|
||||
}
|
||||
common.navigateTo('/pages/courseDetail/index?crsId=' + item.crsId);
|
||||
};
|
||||
const collect_click = async (collectId) => {
|
||||
console.log('学习', collectId);
|
||||
const collect_click = async (id) => {
|
||||
console.log('学习', id);
|
||||
try {
|
||||
if (!collectId) {
|
||||
if (!id) {
|
||||
common.loading('收藏中');
|
||||
|
||||
const res = await insertTraPersonalCollectionTask({
|
||||
collectTyp: '02',
|
||||
collectBusId: detailData.taskId
|
||||
@@ -181,7 +193,7 @@
|
||||
} else {
|
||||
common.loading('取消收藏中');
|
||||
await deleteTraPersonalCollectionById({
|
||||
collectId: collectId
|
||||
collectId: id
|
||||
});
|
||||
detailData.collectionId = null;
|
||||
|
||||
@@ -192,14 +204,29 @@
|
||||
}
|
||||
};
|
||||
onLoad((e) => {
|
||||
collectId.value = e.collectId || '';
|
||||
const learning_tasks_details = getPageCache('learning_tasks_details');
|
||||
Object.assign(detailData, {
|
||||
...learning_tasks_details
|
||||
});
|
||||
nextTick(() => {
|
||||
getData();
|
||||
});
|
||||
console.log('detailData', detailData);
|
||||
getData();
|
||||
});
|
||||
onUnload(() => {
|
||||
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('refresh_favorites_data', {
|
||||
type: 'task',
|
||||
state: !!detailData.collectionId, // 最终是收藏了还是取消了
|
||||
old: collectId.value, // 进入时候的收藏id
|
||||
new: detailData.collectionId // 新的收藏id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -221,59 +248,58 @@
|
||||
}
|
||||
.status_div {
|
||||
color: #adb4c3;
|
||||
background-color: #F3F5F5;
|
||||
background-color: #f3f5f5;
|
||||
}
|
||||
.plug{
|
||||
.plug {
|
||||
border-top: 4rpx solid #e1e8f0;
|
||||
}
|
||||
}
|
||||
//未完成
|
||||
&.unfinished {
|
||||
.circle_div {
|
||||
border: 4rpx solid #0066FF;
|
||||
border: 4rpx solid #0066ff;
|
||||
// background-color: #bdc7e6;
|
||||
}
|
||||
.line_div {
|
||||
border-left: 4rpx solid #0066FF;
|
||||
border-left: 4rpx solid #0066ff;
|
||||
}
|
||||
.status_div {
|
||||
color: #FFFFFF;
|
||||
background-color: #4C93FF;
|
||||
color: #ffffff;
|
||||
background-color: #4c93ff;
|
||||
}
|
||||
.plug{
|
||||
border-top: 4rpx solid #0066FF;
|
||||
.plug {
|
||||
border-top: 4rpx solid #0066ff;
|
||||
}
|
||||
}
|
||||
|
||||
// 未解锁
|
||||
&.not_unlocked {
|
||||
.circle_div {
|
||||
border: 4rpx solid #ADB4C3;
|
||||
border: 4rpx solid #adb4c3;
|
||||
}
|
||||
.line_div {
|
||||
border-left: 4rpx dashed #ADB4C3;
|
||||
border-left: 4rpx dashed #adb4c3;
|
||||
}
|
||||
.status_div {
|
||||
color: #6C9CE4;
|
||||
background-color: #EFF6FF;
|
||||
color: #6c9ce4;
|
||||
background-color: #eff6ff;
|
||||
}
|
||||
.plug{
|
||||
border-top: 4rpx solid #ADB4C3;
|
||||
.plug {
|
||||
border-top: 4rpx solid #adb4c3;
|
||||
}
|
||||
}
|
||||
// 最后一项
|
||||
&:last-child .plug{
|
||||
&: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;
|
||||
@@ -338,18 +364,16 @@
|
||||
.button_text {
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
|
||||
|
||||
text-align: left;
|
||||
margin-right: 50rpx;
|
||||
&.success{
|
||||
color: #0066FF;
|
||||
&.success {
|
||||
color: #0066ff;
|
||||
}
|
||||
&.error{
|
||||
&.error {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+599
-588
File diff suppressed because it is too large
Load Diff
+63
-100
@@ -15,8 +15,10 @@
|
||||
<text class="grey">/{{ storageTopicList.length }}</text>
|
||||
</view>
|
||||
<view class="question">
|
||||
<view class="grey">剩余时间</view>
|
||||
<uv-count-down :time="100 * 1000" format="HH:mm:ss"></uv-count-down>
|
||||
<view class="grey">练习时长</view>
|
||||
<view class="">
|
||||
{{ formatSeconds(practiceTime) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="progress">
|
||||
@@ -49,10 +51,6 @@
|
||||
@subject_click="subject_click"
|
||||
v-model="item.my_answer"
|
||||
></Subject>
|
||||
<!-- <CharactersSubject :item="item" v-if="item.qnsTyp === 'ES'" :mode="mode"
|
||||
:activeVoiceId="activeVoiceId" :voicePathValue="voicePathValue"
|
||||
@subject_click="subject_click">
|
||||
</CharactersSubject> -->
|
||||
</scroll-view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
@@ -84,10 +82,10 @@
|
||||
import Subject from '@/components/examination/subject.vue';
|
||||
import CharactersSubject from '@/components/examination/characters-subject.vue';
|
||||
import TouchBtn from '@/components/examination/touchBtn.vue';
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref, reactive, computed, onMounted, nextTick, onUnmounted } from 'vue';
|
||||
import { onLoad, onHide, onShow, onUnload } from '@dcloudio/uni-app';
|
||||
import common from '@/common/common';
|
||||
import { getPageCache } from '@/common/common';
|
||||
import { setPageCache, formatSeconds, getPageCache } from '@/common/common';
|
||||
import { commonUploadVoiceFile } from '@/api/common.js';
|
||||
import { optionErrorIcon, examinationSheetIcon } from '@/common/imgSvg';
|
||||
import { practiceAnswer, practiceCommit, queryCrsPracticeAnswerResult } from '@/api/practice.js';
|
||||
@@ -95,7 +93,11 @@
|
||||
const feedbackRef = ref(null);
|
||||
const dialogRef = ref(null);
|
||||
const touchBtnRef = ref(null);
|
||||
|
||||
const practiceTime = ref(0); // 当前练习时间
|
||||
let practiceStartTime = 0; // 练习开始时间
|
||||
let practiceTimeTimer = null; // 练习计时器
|
||||
let leaveDuration = 0; // 当前总计离开时间
|
||||
let leaveStartTime = 0; // 离开开始时间
|
||||
const mode = ref('practice'); // 考试 examination 练习practice
|
||||
const paperData = reactive({
|
||||
exrId: '',
|
||||
@@ -109,20 +111,19 @@
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const topic = computed({
|
||||
get: () => topicList[questionNumber.value],
|
||||
set: (val) => topicList[questionNumber.value] = val
|
||||
set: (val) => (topicList[questionNumber.value] = val)
|
||||
});
|
||||
const showTouchBtn = computed(() => {
|
||||
return topic.value?.qnsTyp === 'ES';
|
||||
});
|
||||
|
||||
// 下面语音组件的禁用状态判断
|
||||
const touchIsDisabled = computed(() => {
|
||||
|
||||
return topic.value?.es_status !== '' && topic.value?.es_status !== undefined
|
||||
})
|
||||
const touchIsDisabled = computed(() => {
|
||||
console.log('下面语音组件的禁用状态判断', topic.value?.es_status !== '' && topic.value?.es_status !== undefined);
|
||||
return topic.value?.es_status !== '' && topic.value?.es_status !== undefined;
|
||||
});
|
||||
|
||||
|
||||
const progress = computed(() => {
|
||||
const progress = computed(() => {
|
||||
// 计算进度百分比(保留两位小数)
|
||||
const total = storageTopicList.value.length;
|
||||
if (total === 0) return 0;
|
||||
@@ -132,8 +133,6 @@
|
||||
// 弹出框配置
|
||||
const dialogConfiguration = reactive({});
|
||||
|
||||
const activeVoiceId = ref('');
|
||||
|
||||
const swiperChange = (item) => {
|
||||
questionNumber.value = item.detail.current;
|
||||
};
|
||||
@@ -280,7 +279,7 @@
|
||||
touchBtnRef.value?.clearinputText(old_text); // 清除发送框数据
|
||||
// 处理失败情况
|
||||
});
|
||||
|
||||
|
||||
// const traQnsInfoVo = body.traQnsInfoVo;
|
||||
// topic.analyContent = traQnsInfoVo.analyContent; // 答案解析
|
||||
// console.log('答题结果', traQnsInfoVo);
|
||||
@@ -294,41 +293,26 @@
|
||||
})
|
||||
.catch(() => {
|
||||
topic.es_status = ''; // 取消转圈
|
||||
|
||||
});
|
||||
};
|
||||
// 录音组件提交
|
||||
const touchBtnSubmit = (type, submitObj) => {
|
||||
|
||||
const old_text = touchBtnRef.value?.clearinputText(); // 清除发送框数据
|
||||
|
||||
|
||||
if (type === 'voice') {
|
||||
topic.value.es_status = '00'; // 00转圈
|
||||
const voicePath = submitObj;
|
||||
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
|
||||
.then((res) => {
|
||||
let _res = JSON.parse(res.data);
|
||||
console.log('res小行星', _res);
|
||||
if (_res.rtnCode === '0000') {
|
||||
topic.value.es_status = '02'
|
||||
topic.value.es_status = '02';
|
||||
topic.value.my_answer = {
|
||||
anserResult: _res.body.transContent,
|
||||
ossKey: _res.body.fileId,
|
||||
ossAddr: _res.body.ossFileAddr,
|
||||
voicePath: voicePath
|
||||
}
|
||||
// {
|
||||
// "chatId":"CHAT025018122068202508232000590000000000000000000000000000000060",
|
||||
// "fileId":"S3F0250181220722025082320005900000676612",
|
||||
// "ossFileAddr":"http://25.18.122.66::9786/traoss/show//S3F0250181220722025082320005900000676612",
|
||||
// "transContent":"一二三四。"
|
||||
// }
|
||||
// submitProblemEssayQuestion({
|
||||
// anserResult: _res.body.transContent,
|
||||
// ossKey: _res.body.fileId,
|
||||
// ossAddr: _res.body.ossFileAddr,
|
||||
// voicePath: voicePath
|
||||
// });
|
||||
};
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -372,6 +356,8 @@
|
||||
my_answer: []
|
||||
}));
|
||||
addProblem();
|
||||
// 记录起始时间
|
||||
practiceStartTime = new Date().getTime();
|
||||
// #ifdef APP-PLUS
|
||||
// 安全区域底部到屏幕底部的高度(即底部安全区域高度)
|
||||
const safeAreaBottomHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom;
|
||||
@@ -386,7 +372,7 @@
|
||||
});
|
||||
// #endif
|
||||
});
|
||||
|
||||
|
||||
const result_click = ({ key }) => {
|
||||
console.log('res', key);
|
||||
if (key === 'hand_in_paper') {
|
||||
@@ -401,8 +387,6 @@
|
||||
// 交卷按钮点击,打开交卷确认框
|
||||
const hand_in_paper_button_click = () => {
|
||||
console.log('点击交卷', paperData);
|
||||
// console.log('点击交卷topicList', topicList);
|
||||
// return;
|
||||
// 判断是否完成所有题目
|
||||
const completeList = topicList
|
||||
.filter((res) => !!(Array.isArray(res.my_answer) ? res.my_answer.length : res.my_answer))
|
||||
@@ -461,59 +445,42 @@
|
||||
};
|
||||
// 执行交卷
|
||||
const hand_in_paper = () => {
|
||||
const answerDtoList = topicList.map((res) => {
|
||||
let answerItem = {
|
||||
examId: paperData.examId,
|
||||
papersId: paperData.papersId,
|
||||
qnsId: res.qnsId,
|
||||
ossKey: '',
|
||||
anserResult: ''
|
||||
};
|
||||
if (res.qnsTyp === 'ES') {
|
||||
// 问答题特殊处理
|
||||
return {
|
||||
...answerItem,
|
||||
anserResult: ''
|
||||
};
|
||||
} else {
|
||||
//其他题
|
||||
return {
|
||||
...answerItem,
|
||||
anserResult: res.my_answer.join(',')
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
console.log('answerDtoList', answerDtoList);
|
||||
dialogRef.value.close();
|
||||
common.loading('正在提交');
|
||||
commitPaperExam({
|
||||
examId: paperData.examId,
|
||||
execId: paperData.execId || '1',
|
||||
examLenTm: 1200,
|
||||
answerDtoStr: JSON.stringify(answerDtoList)
|
||||
})
|
||||
.then((res) => {
|
||||
console.log('提交成功', res);
|
||||
// 判断是否需要查分
|
||||
if (res.body.flagQuery === 'Y') {
|
||||
// 需要查分
|
||||
const examLenTm = 678;
|
||||
common.redirectTo(
|
||||
`/pages/examination/result?execId=${res.body.execId}&examLenTm=${examLenTm}&papersName=${paperData.papersName}`
|
||||
);
|
||||
} else {
|
||||
// todo 此处应该有个弹窗交代下结果
|
||||
common.navigateBack();
|
||||
}
|
||||
})
|
||||
.catch((res) => {
|
||||
console.log('error', res);
|
||||
})
|
||||
.finally(() => {
|
||||
common.hideLoading().body;
|
||||
});
|
||||
|
||||
};
|
||||
// 启动定时器
|
||||
const startTimer = () => {
|
||||
if (practiceTimeTimer) {
|
||||
clearInterval(practiceTimeTimer);
|
||||
}
|
||||
practiceTimeTimer = setInterval(() => {
|
||||
const currentTime = Date.now();
|
||||
const elapsedSeconds = Math.floor((currentTime - practiceStartTime - leaveDuration) / 1000);
|
||||
practiceTime.value = elapsedSeconds;
|
||||
}, 1000);
|
||||
};
|
||||
// 暂停定时器
|
||||
const stopTimer = () => {
|
||||
if (practiceTimeTimer) {
|
||||
clearInterval(practiceTimeTimer);
|
||||
practiceTimeTimer = null;
|
||||
}
|
||||
};
|
||||
onShow(() => {
|
||||
if (leaveStartTime) {
|
||||
const time = Date.now() - leaveStartTime;
|
||||
leaveDuration += time;
|
||||
leaveStartTime = 0; // 重置离开开始时间
|
||||
}
|
||||
startTimer(); // 启动/恢复定时器
|
||||
});
|
||||
|
||||
onHide(() => {
|
||||
leaveStartTime = new Date().getTime();
|
||||
stopTimer();
|
||||
});
|
||||
onUnload(() => {
|
||||
stopTimer();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -744,17 +711,13 @@
|
||||
align-items: center;
|
||||
// background-color: red;
|
||||
width: 242rpx;
|
||||
color: red;
|
||||
|
||||
.grey {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
:deep(.uv-count-down__text) {
|
||||
color: #ffffff !important;
|
||||
font-weight: 600;
|
||||
font-size: 26rpx !important;
|
||||
}
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.grey {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<view class="scroll_div content">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower">
|
||||
<view class="item" :class="getStatusClass(index)" v-for="(item,index) in data_list">
|
||||
<view class="top">
|
||||
@@ -90,6 +90,7 @@
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.scroll_div {
|
||||
background-color: #F1F5FA;
|
||||
padding: 22rpx;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<scroll-view :scroll-y="true" class="scroll-Y" :show-scrollbar="false" @scrolltolower="scrolltolower">
|
||||
<!-- <view class="item" :class="getStatusClass(index)" v-for="(item, index) in data_list">
|
||||
|
||||
</view> -->
|
||||
<subject v-for="(item, index) in data_list" :item="item" mode="mistake"></subject>
|
||||
<scroll-view :scroll-y="true" class="scroll-Y " :show-scrollbar="false" @scrolltolower="scrolltolower">
|
||||
<view class="content" v-for="(item, index) in data_list">
|
||||
<subject :item="item" mode="mistake" :isPreview="true" :clearResult="false"></subject>
|
||||
</view>
|
||||
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
|
||||
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@@ -67,14 +67,17 @@
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scroll_div {
|
||||
background-color: #f1f5fa;
|
||||
padding: 22rpx;
|
||||
$bg-margin-left: 30rpx;
|
||||
.content {
|
||||
position: relative;
|
||||
margin: 32rpx $bg-margin-left;
|
||||
border-radius: 16rpx;
|
||||
padding: 34rpx 30rpx 34rpx 36rpx;
|
||||
background-color: #fff;
|
||||
// min-height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 44rpx - 156rpx);
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 44rpx - 156rpx);
|
||||
// background-color: #fff;
|
||||
background-color: #f1f5fa;
|
||||
min-height: calc(100vh - var(--status-bar-height) - 78rpx - 88rpx - 156rpx);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
}
|
||||
|
||||
.swiper {
|
||||
height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 10rpx - 156rpx);
|
||||
height: calc(100vh - var(--status-bar-height) - 78rpx - 88rpx - 156rpx);
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
|
||||
Reference in New Issue
Block a user