重构学习任务

This commit is contained in:
田岩
2025-09-12 14:27:18 +08:00
parent 3e2f81bbda
commit ca7f9a09a1
61 changed files with 11150 additions and 305 deletions
@@ -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 {
+67 -92
View File
@@ -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
View File
@@ -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;
+226
View File
@@ -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>
+81 -99
View File
@@ -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>