重构学习任务
This commit is contained in:
@@ -54,8 +54,9 @@
|
||||
return common.msg('任务已结束');
|
||||
}
|
||||
}
|
||||
|
||||
setPageCache('learning_tasks_details', item);
|
||||
common.navigateTo('/pages/learningTasks/details');
|
||||
common.navigateTo('/pages/learningTasks/details?taskId='+item.taskId);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -96,8 +97,10 @@
|
||||
}
|
||||
}
|
||||
.item {
|
||||
height: 170rpx;
|
||||
margin-top: 32rpx;
|
||||
// background-color: red;
|
||||
// height: 170rpx;
|
||||
padding-top: 16rpx;
|
||||
padding-bottom: 16rpx;
|
||||
display: flex;
|
||||
|
||||
.img_div {
|
||||
@@ -143,6 +146,7 @@
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 44rpx;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.time_div {
|
||||
|
||||
@@ -1,114 +1,89 @@
|
||||
<!-- 在这个文件对每个tab对应的列表进行渲染 -->
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<z-paging
|
||||
ref="pagingRef"
|
||||
v-model="data_list"
|
||||
@query="queryList"
|
||||
:fixed="false"
|
||||
class="scroll_div"
|
||||
:auto="false"
|
||||
empty-view-text="暂无学习任务"
|
||||
>
|
||||
<view class="scroll-Y">
|
||||
<!-- 如果当前页已经加载过数据或者当前切换到的tab是当前页,才展示当前页数据(懒加载) -->
|
||||
<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>
|
||||
</view>
|
||||
</z-paging>
|
||||
</template>
|
||||
<script setup>
|
||||
import common from '@/common/common';
|
||||
import { ref, reactive, onMounted, nextTick, watch } from 'vue';
|
||||
import itemVue from './content-item.vue';
|
||||
import { queryAllTraTaskInfoByUserId } from '@/api/learningTasks.js';
|
||||
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 20;
|
||||
const total = ref(-1);
|
||||
const page = ref(0);
|
||||
const data_list = reactive([]);
|
||||
<script setup>
|
||||
import itemVue from './content-item.vue';
|
||||
import { ref, onMounted, watch, computed, nextTick } from 'vue';
|
||||
import useZpaging from '@/composables/useZpaging.js';
|
||||
import { queryAllTraTaskInfoByUserId } from '@/api/learningTasks.js';
|
||||
const pagingRef = ref(null);
|
||||
const fetchFunction = (params) => queryAllTraTaskInfoByUserId({ state: props.state, ...params });
|
||||
const { queryList, data_list, reload, search, total, clear } = useZpaging({
|
||||
pagingRef,
|
||||
fetchFunction,
|
||||
searchKey: 'taskName'
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
state: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const getData = (from = '', _searchText = '') => {
|
||||
if (from == 'first') {
|
||||
if (total.value !== -1) {
|
||||
return;
|
||||
},
|
||||
tabIndex: {
|
||||
type: Number,
|
||||
default: function () {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
currentIndex: {
|
||||
type: Number,
|
||||
default: function () {
|
||||
return 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++;
|
||||
}
|
||||
setTimeout(() => {
|
||||
queryAllTraTaskInfoByUserId({
|
||||
state: props.state,
|
||||
page: page.value,
|
||||
limit: limit,
|
||||
taskName: _searchText || searchText.value
|
||||
})
|
||||
.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 scrolltolower = (item) => {
|
||||
getData();
|
||||
};
|
||||
const searchText = ref('');
|
||||
const search = (value, state) => {
|
||||
total.value = -1;
|
||||
searchText.value = value;
|
||||
if (state) {
|
||||
getData('first', value);
|
||||
} else {
|
||||
total.value = -1;
|
||||
page.value = 1;
|
||||
data_list.length = 0;
|
||||
}
|
||||
};
|
||||
const clear = (state) => {
|
||||
total.value = -1;
|
||||
page.value = 1;
|
||||
data_list.length = 0;
|
||||
};
|
||||
|
||||
const updateData = (item) => {
|
||||
const index = data_list.findIndex((res) => res.taskId === item.taskId);
|
||||
|
||||
console.log('updateData', index, item);
|
||||
if (index !== -1) {
|
||||
data_list[index] = item;
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
getData,
|
||||
search,
|
||||
updateData,
|
||||
clear
|
||||
});
|
||||
</script>
|
||||
console.log('aaa', props.state);
|
||||
const updateData = (item) => {
|
||||
console.log('未完成专属逻辑,如果未完成列表出现了已完成状态,就重新加载未完成列表', props.tabIndex, item.isFinish);
|
||||
// 未完成专属逻辑,如果未完成列表出现了已完成状态,就重新加载未完成列表
|
||||
if(props.tabIndex !== 0 && item.isFinish === '02') {
|
||||
reload()
|
||||
} else{
|
||||
const index = data_list.value.findIndex((res) => res.taskId === item.taskId);
|
||||
if (index !== -1) {
|
||||
data_list.value[index] = item;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
watch(
|
||||
() => props.currentIndex,
|
||||
(newVal) => {
|
||||
if (newVal === props.tabIndex && total.value === -1) {
|
||||
reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
defineExpose({ reload, search, updateData });
|
||||
</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);
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 12rpx 0 22rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
+160
-107
@@ -1,12 +1,21 @@
|
||||
<template>
|
||||
<view class="main_div max_page">
|
||||
<view class="my-nav-bar"></view>
|
||||
<view class="body-title">
|
||||
<view class="back_div" @click="common.navigateBack()">
|
||||
<view class="back-icon"></view>
|
||||
<!-- <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>
|
||||
<view>任务详情</view>
|
||||
</view>
|
||||
</template>
|
||||
<view class="detail_div">
|
||||
<view class="left">
|
||||
<image-preview class="img" :src="detailData.ossAddr" mode="scaleToFill"></image-preview>
|
||||
@@ -18,7 +27,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="time">
|
||||
<text class="color_3">起止时间:</text>
|
||||
<text class="color_3">起止时间:</text>
|
||||
<text class="color_class">
|
||||
{{ detailData.startTm?.substr(0, 10) }}至{{ detailData.endTm?.substr(0, 10) }}
|
||||
</text>
|
||||
@@ -40,28 +49,23 @@
|
||||
</view>
|
||||
<view class="num_div">
|
||||
<view class="num_div_item">
|
||||
<text class="color_3">完成人数:</text>
|
||||
<text class="color_3">完成人数:</text>
|
||||
<text class="color_2">{{ detailData.taskFinishSums ?? 0 }}/{{ detailData.taskSums ?? 0 }}</text>
|
||||
</view>
|
||||
<view class="num_div_item">
|
||||
<text class="color_3">我的进度:</text>
|
||||
<text class="color_3">进度:</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"
|
||||
@scrolltolower="scrolltolower"
|
||||
>
|
||||
<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>
|
||||
@@ -94,18 +98,32 @@
|
||||
<template v-if="item.isFinishStudy !== '01'">
|
||||
<image
|
||||
class="img"
|
||||
:src="passTheExamIcon(item.isFinishStudy === '02' ? '#0066FF' : '#999999')"
|
||||
:src="
|
||||
passTheExamIcon(
|
||||
item.isFinishStudy === '02' && item.status !== '03' ? '#0066FF' : '#999999'
|
||||
)
|
||||
"
|
||||
></image>
|
||||
<view class="button_text" :class="item.isFinishStudy === '02' ? 'success' : 'error'">
|
||||
<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' ? '#0066FF' : '#999999')"
|
||||
:src="
|
||||
completeTheExercisesIcon(
|
||||
item.isFinishExam === '02' && item.status !== '03' ? '#0066FF' : '#999999'
|
||||
)
|
||||
"
|
||||
></image>
|
||||
<view class="button_text" :class="item.isFinishExam === '02' ? 'success' : 'error'">
|
||||
<view
|
||||
class="button_text"
|
||||
:class="item.isFinishExam === '02' && item.status !== '03' ? 'success' : 'error'"
|
||||
>
|
||||
通过考试
|
||||
</view>
|
||||
</template>
|
||||
@@ -122,17 +140,82 @@
|
||||
></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</z-paging>
|
||||
<!-- </view> -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||
import { ref, reactive, computed, nextTick } from 'vue';
|
||||
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 useZpaging from '@/composables/useZpaging.js';
|
||||
import common from '@/common/common';
|
||||
import { setPageCache, getPageCache } 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: '',
|
||||
@@ -141,37 +224,16 @@
|
||||
taskFinishSums: '',
|
||||
taskSums: '',
|
||||
finishCrs: '',
|
||||
isFinish: '',
|
||||
sumCrs: ''
|
||||
});
|
||||
|
||||
const total = ref(-1);
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const data_list = reactive([]);
|
||||
const getStatusClass = (isFinish) => {
|
||||
// 00进行中、01已完成、02已超时
|
||||
if (isFinish === '01') return 'unfinished';
|
||||
if (isFinish === '02') return 'completed';
|
||||
return 'not_unlocked';
|
||||
};
|
||||
const getData = () => {
|
||||
status.value = 'loading';
|
||||
queryAllTraTaskCrsInfo({
|
||||
taskId: detailData.taskId
|
||||
})
|
||||
.then((res) => {
|
||||
data_list.length = 0;
|
||||
data_list.push(...res.body);
|
||||
})
|
||||
.finally(() => {
|
||||
total.value = data_list.length;
|
||||
if (total.value === 0) {
|
||||
status.value = 'nomore';
|
||||
} else {
|
||||
status.value = 'loadmore';
|
||||
}
|
||||
});
|
||||
};
|
||||
const scrolltolower = () => {};
|
||||
|
||||
const item_click = (item) => {
|
||||
if (item.status === '03') {
|
||||
@@ -180,66 +242,63 @@
|
||||
}
|
||||
common.navigateTo('/pages/courseDetail/index?crsId=' + item.crsId);
|
||||
};
|
||||
|
||||
const collect_click = async (id) => {
|
||||
const loadingText = id ? '取消收藏中' : '收藏中';
|
||||
try {
|
||||
common.loading(loadingText);
|
||||
if (!id) {
|
||||
common.loading('收藏中');
|
||||
insertTraPersonalCollectionTask({
|
||||
// 收藏操作
|
||||
const res = await insertTraPersonalCollectionTask({
|
||||
collectTyp: '02',
|
||||
collectBusId: detailData.taskId
|
||||
})
|
||||
.then((res) => {
|
||||
detailData.collectionId = res.body;
|
||||
common.msg('收藏成功');
|
||||
})
|
||||
.catch(() => {
|
||||
common.hideLoading();
|
||||
});
|
||||
});
|
||||
detailData.collectionId = res.body;
|
||||
common.msg('收藏成功');
|
||||
} else {
|
||||
common.loading('取消收藏中');
|
||||
deleteTraPersonalCollectionById({
|
||||
// 取消收藏操作
|
||||
await deleteTraPersonalCollectionById({
|
||||
collectId: id
|
||||
})
|
||||
.then(() => {
|
||||
detailData.collectionId = null;
|
||||
common.msg('取消成功');
|
||||
})
|
||||
.catch(() => {
|
||||
common.hideLoading();
|
||||
});
|
||||
});
|
||||
detailData.collectionId = null;
|
||||
common.msg('取消成功');
|
||||
}
|
||||
} catch (e) {
|
||||
common.hideLoading();
|
||||
} 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 || '';
|
||||
getData();
|
||||
const updateFun = () => {
|
||||
setTimeout(() => {
|
||||
console.log('详情监听里面学习完成后更新任务历程');
|
||||
queryTraTaskInfoByTaskId({ taskId: detailData.taskId }).then(({ body }) => {
|
||||
uni.$emit('refresh_tasks_data', body);
|
||||
Object.assign(detailData, {
|
||||
...body
|
||||
});
|
||||
});
|
||||
getData();
|
||||
}, 4000);
|
||||
console.log('监听考试获取结果事件,执行更新函数');
|
||||
pagingRef.value?.reload();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// 监听里面学习完成后更新任务历程,执行更新函数
|
||||
uni.$on('refresh_course_list', () => updateFun());
|
||||
// 监听考试完成事件,执行更新函数
|
||||
uni.$on('exam_completed', () => updateFun());
|
||||
// 监听考试获取结果事件,执行更新函数
|
||||
uni.$on('get_result_completed', () => updateFun());
|
||||
});
|
||||
|
||||
onUnload(() => {
|
||||
uni.$off('refresh_course_list');
|
||||
uni.$off('exam_completed');
|
||||
uni.$off('get_result_completed');
|
||||
// 如果收藏变了,并且上一页是收藏页,更新收藏列表
|
||||
if (detailData.collectionId !== collectId.value) {
|
||||
const pages = getCurrentPages();
|
||||
@@ -256,7 +315,7 @@
|
||||
} else if (prevPage.route === 'pages/learningTasks/index') {
|
||||
// 学习任务页跳入,更新外部列表否则下次列表数据还是老的
|
||||
console.log('学习任务页跳入,更新外部列表否则下次列表数据还是老的');
|
||||
uni.$emit('refresh_tasks_list', detailData);
|
||||
uni.$emit('update_tasks_item', detailData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,37 +512,34 @@
|
||||
height: calc(100vh - var(--status-bar-height) - 120rpx - 250rpx + 20rpx + 20rpx - 20rpx - 42rpx - 50rpx);
|
||||
}
|
||||
|
||||
.main_div {
|
||||
.body-title {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
height: 160rpx;
|
||||
padding-top: var(--status-bar-height);
|
||||
margin-bottom: -20rpx;
|
||||
line-height: calc(160rpx - var(--status-bar-height) - 20rpx);
|
||||
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;
|
||||
}
|
||||
.my-nav-bar {
|
||||
width: 100%;
|
||||
height: calc(var(--status-bar-height) - 10rpx);
|
||||
}
|
||||
.body-title {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
height: 120rpx;
|
||||
line-height: 60rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 600;
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.detail_div {
|
||||
margin-top: -20rpx;
|
||||
height: 250rpx;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
padding: 36rpx 26rpx 20rpx 26rpx;
|
||||
background-color: #ffffff;
|
||||
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
@@ -566,7 +622,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
overflow: hidden;
|
||||
height: 28rpx;
|
||||
.num_div_item {
|
||||
@@ -609,7 +665,6 @@
|
||||
color: #ffffff;
|
||||
background-color: #33c583;
|
||||
}
|
||||
|
||||
.color_class {
|
||||
color: #0066ff;
|
||||
}
|
||||
@@ -618,11 +673,9 @@
|
||||
.back_div {
|
||||
position: absolute;
|
||||
left: 26rpx;
|
||||
height: 100%;
|
||||
top: -30rpx;
|
||||
bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.back-icon {
|
||||
position: relative;
|
||||
width: 50rpx;
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<view class="max_page detail-main">
|
||||
<nav-bar :is_seat="false"></nav-bar>
|
||||
<view class="fixed_search_div">
|
||||
<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>
|
||||
<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>
|
||||
<content :ref="(el) => (listItemRefs[0] = el)" state="01"></content>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<content :ref="(el) => (listItemRefs[1] = el)" state="02"></content>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<content :ref="(el) => (listItemRefs[2] = el)" state="03"></content>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { LineBg } from '@/enum.js';
|
||||
import content from './components/content.vue';
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import common from '@/common/common.js';
|
||||
const listItemRefs = ref([]);
|
||||
const tabAct = ref(0);
|
||||
const searchText = ref('');
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '全 部'
|
||||
},
|
||||
{
|
||||
name: '已完成'
|
||||
},
|
||||
{
|
||||
name: '未完成'
|
||||
}
|
||||
]);
|
||||
|
||||
const tabChange = (item) => {
|
||||
tabAct.value = item.index;
|
||||
};
|
||||
const swiperChange = (item) => {
|
||||
tabAct.value = item.detail.current;
|
||||
};
|
||||
const search = (value) => {
|
||||
listItemRefs.value[0]?.search(value, tabAct.value === 0);
|
||||
listItemRefs.value[1]?.search(value, tabAct.value === 1);
|
||||
listItemRefs.value[2]?.search(value, tabAct.value === 2);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
watch(
|
||||
tabAct,
|
||||
(newValue, oldValue) => {
|
||||
typeof listItemRefs.value[newValue]?.getData === 'function' &&
|
||||
listItemRefs.value[newValue]?.getData('first');
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
onLoad(() => {
|
||||
uni.$on('refresh_tasks_list', (res) => {
|
||||
console.log('refresh_tasks_list');
|
||||
listItemRefs.value[0]?.updateData(res);
|
||||
listItemRefs.value[1]?.updateData(res);
|
||||
listItemRefs.value[2]?.updateData(res);
|
||||
});
|
||||
// 完成任务后更新列表单条信息
|
||||
uni.$on('refresh_tasks_data', (res) => {
|
||||
console.log('refresh_tasks_data');
|
||||
listItemRefs.value[0]?.updateData(res);
|
||||
listItemRefs.value[1]?.clear();
|
||||
listItemRefs.value[2]?.clear();
|
||||
listItemRefs.value[tabAct.value]?.getData('first');
|
||||
if (tabAct.value === 0) {
|
||||
courseRef.value?.updateData(res);
|
||||
} else if (tabAct.value === 1) {
|
||||
taskRef.value?.updateData(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
onUnload(() => {
|
||||
uni.$off('refresh_tasks_list');
|
||||
uni.$off('refresh_tasks_data');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$bg-margin-left: 50rpx;
|
||||
|
||||
.my_tabs {
|
||||
// 解决这个圆角的图片,开穿透
|
||||
:deep(.uv-tabs__wrapper__nav__line) {
|
||||
height: 26rpx !important;
|
||||
left: 60rpx;
|
||||
background-size: 28rpx !important;
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
/*
|
||||
状态栏 var(--status-bar-height)
|
||||
标题高度88rpx
|
||||
搜索栏高度80rpx
|
||||
tab切换栏高度88rpx
|
||||
下方滑动区域上下边距各10共20rpx
|
||||
**/
|
||||
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 80rpx - 88rpx - 20rpx);
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
display: block;
|
||||
height: 100%;
|
||||
line-height: 300rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.detail-body {
|
||||
background: #ffffff;
|
||||
border-radius: 15rpx;
|
||||
z-index: 101;
|
||||
overflow: hidden;
|
||||
|
||||
.body-tab {
|
||||
height: 88rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-main {
|
||||
background-color: #f6f8ff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #000000;
|
||||
font-size: 34rpx;
|
||||
height: 34rpx;
|
||||
font-weight: 600;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
.fixed_search_input_div {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
padding: 0 22rpx;
|
||||
// background-color: red;
|
||||
background-color: #fff;
|
||||
:deep(.uv-input.uv-input--radius) {
|
||||
border-radius: 16rpx !important;
|
||||
}
|
||||
}
|
||||
.fixed_search_div {
|
||||
padding: calc(20rpx + var(--status-bar-height)) 15rpx 34rpx 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
// background-color: red;
|
||||
// height: 180rpx;
|
||||
position: relative;
|
||||
|
||||
.back_div {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: var(--status-bar-height);
|
||||
padding: 10rpx;
|
||||
|
||||
.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>
|
||||
@@ -1,116 +1,95 @@
|
||||
<!-- 滑动切换选项卡演示(标准写法) -->
|
||||
<template>
|
||||
<view class="max_page detail-main">
|
||||
<nav-bar :is_seat="false"></nav-bar>
|
||||
<view class="fixed_search_div">
|
||||
<view class="back_div" @click="common.navigateBack()">
|
||||
<view class="back-icon"></view>
|
||||
<!-- 使用z-paging-swiper为根节点可以免计算高度 -->
|
||||
<z-paging-swiper>
|
||||
<!-- 需要固定在顶部不滚动的view放在slot="top"的view中 -->
|
||||
<!-- 注意!此处的z-tabs为独立的组件,可替换为第三方的tabs,若需要使用z-tabs,请在插件市场搜索z-tabs并引入,否则会报插件找不到的错误 -->
|
||||
<template #top>
|
||||
<nav-bar :is_seat="false"></nav-bar>
|
||||
<view class="fixed_search_div">
|
||||
<view class="back_div" @click="common.navigateBack()">
|
||||
<view class="back-icon"></view>
|
||||
</view>
|
||||
<view class="title font_pf">学习任务</view>
|
||||
</view>
|
||||
<view class="title font_pf">学习任务</view>
|
||||
</view>
|
||||
<view class="fixed_search_input_div">
|
||||
<search-input placeholder="请输入任务名" @search="search"></search-input>
|
||||
</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 class="fixed_search_input_div">
|
||||
<search-input placeholder="请输入任务名" @search="search"></search-input>
|
||||
</view>
|
||||
<view class="uni-margin-wrap no-overflow">
|
||||
<swiper class="swiper" :current="tabAct" :indicator-dots="false" @change="swiperChange">
|
||||
<swiper-item>
|
||||
<content :ref="(el) => (listItemRefs[0] = el)" state="01"></content>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<content :ref="(el) => (listItemRefs[1] = el)" state="02"></content>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<content :ref="(el) => (listItemRefs[2] = el)" state="03"></content>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<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>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<!-- swiper必须设置height:100%,因为swiper有默认的高度,只有设置高度100%才可以铺满页面 -->
|
||||
<swiper class="swiper" :current="tabAct" @change="swiperChange">
|
||||
<swiper-item class="swiper-item" v-for="(item, index) in tabList" :key="index">
|
||||
<content ref="listItemRefs" :state="item.value" :tabIndex="index" :currentIndex="tabAct"></content>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</z-paging-swiper>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { LineBg } from '@/enum.js';
|
||||
import content from './components/content.vue';
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import common from '@/common/common.js';
|
||||
const listItemRefs = ref([]);
|
||||
const tabAct = ref(0);
|
||||
const searchText = ref('');
|
||||
import content from './components/content.vue';
|
||||
import { ref } from 'vue';
|
||||
import { LineBg } from '@/enum.js';
|
||||
import useIndexList from '@/composables/useIndexList.js';
|
||||
const { tabAct, listItemRefs, tabChange, swiperChange, search } = useIndexList();
|
||||
// 定义tab列表数据
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '全 部'
|
||||
name: '全 部',
|
||||
value: '01'
|
||||
},
|
||||
{
|
||||
name: '已完成'
|
||||
name: '已完成',
|
||||
value: '02'
|
||||
},
|
||||
{
|
||||
name: '未完成'
|
||||
name: '未完成',
|
||||
value: '03'
|
||||
}
|
||||
]);
|
||||
|
||||
const tabChange = (item) => {
|
||||
tabAct.value = item.index;
|
||||
// 刷新当前列表
|
||||
const reloadCurrentList = () => {
|
||||
listItemRefs.value && listItemRefs.value[current.value]?.reload();
|
||||
};
|
||||
const swiperChange = (item) => {
|
||||
tabAct.value = item.detail.current;
|
||||
};
|
||||
const search = (value) => {
|
||||
listItemRefs.value[0]?.search(value, tabAct.value === 0);
|
||||
listItemRefs.value[1]?.search(value, tabAct.value === 1);
|
||||
listItemRefs.value[2]?.search(value, tabAct.value === 2);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
watch(
|
||||
tabAct,
|
||||
(newValue, oldValue) => {
|
||||
typeof listItemRefs.value[newValue]?.getData === 'function' &&
|
||||
listItemRefs.value[newValue]?.getData('first');
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
onLoad(() => {
|
||||
uni.$on('refresh_tasks_list', (res) => {
|
||||
console.log('refresh_tasks_list');
|
||||
// 收藏这里更新列表的item的数据
|
||||
uni.$on('update_tasks_item', (res) => {
|
||||
listItemRefs.value[0]?.updateData(res);
|
||||
listItemRefs.value[1]?.updateData(res);
|
||||
listItemRefs.value[2]?.updateData(res);
|
||||
});
|
||||
|
||||
// 完成任务后更新列表单条信息
|
||||
uni.$on('refresh_tasks_data', (res) => {
|
||||
console.log('refresh_tasks_data');
|
||||
listItemRefs.value[0]?.updateData(res);
|
||||
listItemRefs.value[1]?.clear();
|
||||
listItemRefs.value[2]?.clear();
|
||||
listItemRefs.value[tabAct.value]?.getData('first');
|
||||
if (tabAct.value === 0) {
|
||||
courseRef.value?.updateData(res);
|
||||
} else if (tabAct.value === 1) {
|
||||
taskRef.value?.updateData(res);
|
||||
}
|
||||
});
|
||||
// uni.$on('refresh_tasks_data', (res) => {
|
||||
// listItemRefs.value[0]?.updateData(res);
|
||||
// listItemRefs.value[1]?.clear();
|
||||
// listItemRefs.value[2]?.clear();
|
||||
// listItemRefs.value[tabAct.value]?.getData('first');
|
||||
// if (tabAct.value === 0) {
|
||||
// courseRef.value?.updateData(res);
|
||||
// } else if (tabAct.value === 1) {
|
||||
// taskRef.value?.updateData(res);
|
||||
// }
|
||||
// });
|
||||
});
|
||||
onUnload(() => {
|
||||
uni.$off('refresh_tasks_list');
|
||||
uni.$off('refresh_tasks_data');
|
||||
uni.$off('update_tasks_item');
|
||||
// uni.$off('refresh_tasks_data');
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -128,22 +107,13 @@
|
||||
}
|
||||
|
||||
.swiper {
|
||||
/*
|
||||
状态栏 var(--status-bar-height)
|
||||
标题高度88rpx
|
||||
搜索栏高度80rpx
|
||||
tab切换栏高度88rpx
|
||||
下方滑动区域上下边距各10共20rpx
|
||||
**/
|
||||
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 80rpx - 88rpx - 20rpx);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
display: block;
|
||||
height: 100%;
|
||||
line-height: 300rpx;
|
||||
text-align: center;
|
||||
background-color: #f1f5fa;
|
||||
}
|
||||
|
||||
.detail-body {
|
||||
@@ -223,4 +193,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.scroll_div {
|
||||
background-color: #f1f5fa;
|
||||
padding: 22rpx;
|
||||
|
||||
// height: calc(100vh - var(--status-bar-height) - 88rpx - 80rpx - 88rpx - 20rpx - 30rpx);
|
||||
.scroll_item_div {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 12rpx 0 22rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user