改进下拉

This commit is contained in:
田岩
2025-09-17 09:42:05 +08:00
parent badfc55df7
commit 6411ea98ff
18 changed files with 493 additions and 831 deletions
+4 -4
View File
@@ -1,17 +1,17 @@
# 开发环境
ENV = 'development'
# 'development'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
# UAT
# VITE_APP_BASE_API_Url = 'http://25.18.122.78:9786'
# DEV
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
# app入口
#VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
#VITE_APP_BASE_API_Url = 'http://25.16.122.65:7001'
#VITE_APP_BASE_API_Url = 'http://25.16.122.91:9786'
# VITE_APP_BASE_API_Url = 'http://25.16.122.92:9786'
#VITE_APP_BASE_API_Url = 'http://25.18.122.66:9786'
# h5专用地址x2
+1
View File
@@ -286,6 +286,7 @@
if (pages.length >= 2) {
const prevPage = pages[pages.length - 2];
if (prevPage.route === 'pages/favorites/index') {
uni.$emit('refresh_favorites_list', {
type: 'course',
state: !!form.value.collectId, // 最终是收藏了还是取消了
@@ -1,68 +1,41 @@
<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>
<z-paging
ref="pagingRef"
v-model="data_list"
@query="queryList"
class="scroll_div"
:auto="false"
empty-view-text="暂无记录"
>
<view class="scroll-Y">
<itemVue :item="item" v-for="item in data_list"></itemVue>
</view>
</z-paging>
</template>
<script setup>
<script setup lang="ts">
import itemVue from './examRecordItem.vue';
import { ref, reactive } from 'vue';
import { ref, reactive, onMounted, watch } from 'vue';
import { queryCrsExamRecordPaging } from '@/api/courseRecord.js';
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 20;
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++;
}
queryCrsExamRecordPaging({
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 = () => {
getData();
};
defineExpose({
getData
import useZpaging from '@/composables/useZpaging';
const { pagingRef, queryList, data_list, reload, total } = useZpaging({
fetchFunction: queryCrsExamRecordPaging
});
const props = defineProps<{
tabIndex: number;
currentIndex: number;
}>();
onMounted(() => {
watch(
() => props.currentIndex,
(v) => v === props.tabIndex && total.value === -1 && reload(),
{ immediate: true }
);
});
</script>
<style scoped lang="scss">
.scroll_div {
background-color: #f1f5fa;
}
.scroll-Y {
height: calc(100vh - var(--status-bar-height) - 88rpx - 88rpx - 30rpx);
background-color: #f1f5fa;
height: 100%;
}
</style>
@@ -1,68 +1,41 @@
<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>
<z-paging
ref="pagingRef"
v-model="data_list"
@query="queryList"
class="scroll_div"
:auto="false"
empty-view-text="暂无记录"
>
<view class="scroll-Y">
<itemVue :item="item" v-for="item in data_list"></itemVue>
</view>
</z-paging>
</template>
<script setup>
<script setup lang="ts">
import itemVue from './practiceRecordItem.vue';
import { ref, reactive } from 'vue';
import { ref, reactive, onMounted, watch } from 'vue';
import useZpaging from '@/composables/useZpaging';
import { queryPracticeRecordPaging } from '@/api/courseRecord.js';
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 20;
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++;
}
queryPracticeRecordPaging({
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 = () => {
getData();
};
defineExpose({
getData
const { pagingRef, queryList, data_list, reload, total } = useZpaging({
fetchFunction: queryPracticeRecordPaging
});
const props = defineProps<{
tabIndex: number;
currentIndex: number;
}>();
onMounted(() => {
watch(
() => props.currentIndex,
(v) => v === props.tabIndex && total.value === -1 && reload(),
{ immediate: true }
);
});
</script>
<style scoped lang="scss">
.scroll_div {
background-color: #f1f5fa;
}
.scroll-Y {
height: calc(100vh - var(--status-bar-height) - 88rpx - 88rpx - 30rpx);
background-color: #f1f5fa;
height: 100%;
}
</style>
@@ -58,6 +58,7 @@
</template>
<script setup>
console.log('学习组件');
import { computed } from 'vue';
import common from '@/common/common';
import { queryStdyBatchByCrsId } from '@/api/courseRecord.js';
@@ -1,70 +1,42 @@
<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>
<z-paging
ref="pagingRef"
v-model="data_list"
@query="queryList"
class="scroll_div"
:auto="false"
empty-view-text="暂无记录"
>
<view class="scroll-Y">
<itemVue :item="item" v-for="item in data_list"></itemVue>
</view>
</z-paging>
</template>
<script setup>
<script setup lang="ts">
import itemVue from './studyRecordItem.vue';
import { ref, reactive} from 'vue';
import { ref, reactive, onMounted, watch } from 'vue';
import { queryStdyRecordPaging } from '@/api/courseRecord.js';
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 20;
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++;
}
queryStdyRecordPaging({
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 = () => {
getData();
};
defineExpose({
getData
import useZpaging from '@/composables/useZpaging';
const { pagingRef, queryList, data_list, reload, total } = useZpaging({
fetchFunction: queryStdyRecordPaging
});
const props = defineProps<{
tabIndex: number;
currentIndex: number;
}>();
onMounted(() => {
watch(
() => props.currentIndex,
(v) => v === props.tabIndex && total.value === -1 && reload(),
{ immediate: true }
);
});
</script>
<style scoped lang="scss">
.scroll_div {
.scroll-Y {
background-color: #f1f5fa;
height: 100%;
}
.scroll-Y {
height: calc(100vh - var(--status-bar-height) - 88rpx - 88rpx - 30rpx);
}
</style>
+51 -71
View File
@@ -1,54 +1,63 @@
<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>
<template #top>
<view class="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="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 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>
<studyRecordList :ref="(el) => (listItemRefs[0] = el)"></studyRecordList>
</swiper-item>
<swiper-item>
<practiceRecordList :ref="(el) => (listItemRefs[1] = el)"></practiceRecordList>
</swiper-item>
<swiper-item>
<examRecordList :ref="(el) => (listItemRefs[2] = el)"></examRecordList>
</swiper-item>
</swiper>
</view>
</view>
</view>
</template>
<swiper class="swiper" :current="tabAct" :indicator-dots="false" @change="swiperChange">
<swiper-item class="swiper-item">
<studyRecordList
:ref="(el) => (listItemRefs[0] = el)"
:tabIndex="0"
:currentIndex="tabAct"
></studyRecordList>
</swiper-item>
<swiper-item class="swiper-item">
<practiceRecordList
:ref="(el) => (listItemRefs[1] = el)"
:tabIndex="1"
:currentIndex="tabAct"
></practiceRecordList>
</swiper-item>
<swiper-item class="swiper-item">
<examRecordList :ref="(el) => (listItemRefs[2] = el)" :tabIndex="2" :currentIndex="tabAct"></examRecordList>
</swiper-item>
</swiper>
</z-paging-swiper>
</template>
<script setup>
import { LineBg } from '@/enum.js';
import studyRecordList from './components/studyRecordList.vue';
import practiceRecordList from './components/practiceRecordList.vue';
import examRecordList from './components/examRecordList.vue';
import { ref, onMounted, watch } from 'vue';
import common from '@/common/common.js';
const listItemRefs = ref([]);
const tabAct = ref(0);
import useIndexList from '@/composables/useIndexList.js';
const { tabAct, listItemRefs, tabChange, swiperChange } = useIndexList();
const tabList = ref([
{
name: '学习记录'
@@ -60,30 +69,10 @@
name: '考试记录'
}
]);
const tabChange = (item) => {
tabAct.value = item.index;
};
const swiperChange = (item) => {
tabAct.value = item.detail.current;
};
onMounted(() => {
watch(
tabAct,
(newValue) => {
typeof listItemRefs.value[newValue]?.getData === 'function' &&
listItemRefs.value[newValue]?.getData('first');
},
{
immediate: true
}
);
});
</script>
<style lang="scss" scoped>
$bg-margin-left: 50rpx;
.my_tabs {
// 解决这个圆角的图片,开穿透
:deep(.uv-tabs__wrapper__nav__line) {
@@ -95,21 +84,12 @@
}
.swiper {
/*
状态栏 var(--status-bar-height)
标题高度88rpx
tab切换栏高度88rpx
下方滑动区域上下边距各10共20rpx
**/
height: calc(100vh - var(--status-bar-height) - 88rpx - 88rpx - 30rpx);
height: 100%;
}
.swiper-item {
display: block;
height: 100%;
line-height: 300rpx;
text-align: center;
background-color: #f1f5fa;
}
.detail-body {
@@ -1,16 +1,13 @@
<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.flagQuery === 'Y'?item.highestGrade:'--' || 0 }}</view>
<view class="top">{{ item.flagQuery === 'Y' ? item.highestGrade : '--' || 0 }}</view>
<view class="bottom">历史最高分</view>
</view>
<view class="prompt_div_line"></view>
@@ -19,7 +16,7 @@
{{ item.examCnt || 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"
@@ -40,7 +37,7 @@
</view>
<view class="list_small_item">
<image src="@/static/images/courseRecord/duration.png" class="icon_img"></image>
<view class="prompt">考试得分{{ item_list.flagQuery === 'Y'?item_list.examGrade:'--' }}</view>
<view class="prompt">考试得分{{ item_list.flagQuery === 'Y' ? item_list.examGrade : '--' }}</view>
</view>
</view>
<view class="fl1"></view>
@@ -225,7 +222,7 @@
/* 添加过渡动画,包含延迟效果 */
transition: transform 0.2s ease;
}
.click_text_icon_action{
.click_text_icon_action {
transform: rotate(90deg);
}
}
@@ -1,68 +0,0 @@
<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 { ref, reactive } from 'vue';
import { queryExamRecordPaging } from '@/api/courseRecord.js';
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 20;
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 = () => {
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>
+29 -44
View File
@@ -1,59 +1,34 @@
<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 ref="pagingRef" v-model="data_list" @query="queryList" class="scroll_div" empty-view-text="暂无记录">
<template #top>
<view class="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>
<view class="title font_pf">考试记录</view>
</template>
<view class="scroll-Y">
<itemVue :item="item" v-for="item in data_list"></itemVue>
</view>
<view class="detail-body">
<examRecordList ref="listItemRef"></examRecordList>
</view>
</view>
</z-paging>
</template>
<script setup>
import examRecordList from './components/examRecordList.vue';
import { ref, onMounted } from 'vue';
import itemVue from './components/examRecordItem.vue';
import { queryExamRecordPaging } from '@/api/courseRecord.js';
import useZpaging from '@/composables/useZpaging.js';
import common from '@/common/common.js';
const listItemRef = ref(null);
onMounted(() => {
listItemRef.value?.getData('first');
const { pagingRef, queryList, data_list, reload, search, total, clear } = useZpaging({
fetchFunction: queryExamRecordPaging
});
</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
tab切换栏高度88rpx
下方滑动区域上下边距各10共20rpx
**/
height: calc(100vh - var(--status-bar-height) - 88rpx - 88rpx - 30rpx);
}
.swiper-item {
display: block;
height: 100%;
line-height: 300rpx;
text-align: center;
}
.detail-body {
background: #ffffff;
border-radius: 15rpx;
@@ -131,4 +106,14 @@
}
}
}
.scroll-Y {
background-color: #f1f5fa;
border-radius: 16rpx;
// padding: 17rpx 12rpx 0 22rpx;
// margin: 17rpx 20rpx;
}
.scroll_div {
background-color: #f1f5fa;
// padding: 22rpx;
}
</style>
@@ -1,52 +1,55 @@
<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" @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>
<z-paging
ref="pagingRef"
v-model="data_list"
@query="queryList"
:auto="false"
empty-view-text="暂无数据"
paging-class="pagingClass"
>
<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" @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>
<view class="right_div">
<view class="title ellipsis-text">
{{ item.crsName }}
</view>
<view class="right_div">
<view class="title ellipsis-text">
{{ item.crsName }}
</view>
<view class="tag_div">
<view class="tag" v-for="tagItem in item?.tagCataList ?? []">
{{ 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="tag_div">
<view class="tag" v-for="tagItem in item?.tagCataList ?? []">
{{ tagItem?.tagName }}
</view>
</view>
<view class="time_and_num">
<view class="mr-10">发布{{ item.issuTm?.substr(0, 10) }}</view>
<view>已学{{ item.accmStdyCnt }}</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>
</view>
</uv-swipe-action-item>
</uv-swipe-action>
</z-paging>
</template>
<script setup>
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 20;
const total = ref(-1);
const page = ref(0);
const data_list = reactive([]);
import { ref, reactive} from 'vue';
import { ref, reactive, onMounted, watch } from 'vue';
import { queryTraPersonalCollectionCrsPaging, deleteTraPersonalCollectionById } from '@/api/favorites.js';
import common from '@/common/common';
import useZpaging from '@/composables/useZpaging';
const { pagingRef, queryList, data_list, reload, total } = useZpaging({
fetchFunction: queryTraPersonalCollectionCrsPaging
});
const options = [
{
text: '删除',
@@ -55,39 +58,7 @@
}
}
];
const getData = (from = '') => {
console.log('status.value', status.value);
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++;
}
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';
}
console.log('status.value', status.value);
});
};
// 进入课程详情页
const click_item = (item) => {
common.navigateTo(`/pages/courseDetail/index?crsId=${item.crsId}&collectId=${item.collectId}`);
@@ -108,52 +79,41 @@
});
});
};
const scrolltolower = () => {
getData();
};
const refreshData = () => {
total.value = -1;
getData('first');
};
const updateData = (item) => {
console.log('收藏的updateData');
};
defineExpose({
getData,
updateData,
refreshData
});
const props = defineProps(['tabIndex', 'currentIndex']);
onMounted(() => {
watch(
() => props.currentIndex,
(v) => v === props.tabIndex && total.value === -1 && reload(),
{ immediate: true }
);
});
</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);
.pagingClass {
width: calc(100% - 44rpx);
margin: 22rpx auto;
background-color: #fff;
border-radius: 16rpx;
}
.item-swipe-action {
margin: 32rpx 22rpx;
overflow: hidden;
:deep(.uv-swipe-action-item__right__button__wrapper) {
border-radius: 20rpx !important;
}
}
.scroll-Y .item {
.item {
height: 170rpx;
display: flex;
// background-color: red;
.img_div {
position: relative;
width: 224rpx;
+95 -122
View File
@@ -1,66 +1,73 @@
<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(item.isFinish)" @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 === '02'">已完成</view>
<view class="subscript" v-else>未完成</view>
<z-paging
ref="pagingRef"
v-model="data_list"
@query="queryList"
:auto="false"
empty-view-text="暂无数据"
paging-class="pagingClass"
>
<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(item.isFinish)" @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 === '02'">已完成</view>
<view class="subscript" v-else>未完成</view>
</view>
<view class="right_div">
<view class="title ellipsis-text">
{{ item.taskName }}
</view>
<view class="right_div">
<view class="title ellipsis-text">
{{ item.taskName }}
<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 class="time_div">
起止时间
<view>
进度
<text class="blod_color">
{{ item.startTm?.substr(0, 10) }}{{ item.endTm?.substr(0, 10) }}
{{ item.finishCrs ?? item.learnedNumber ?? 0 }}/{{
item.sumCrs ?? item.taskNumber ?? 0
}}门课程
</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.finishCrs ?? item.learnedNumber ?? 0 }}/{{ item.sumCrs ?? item.taskNumber ?? 0 }}门课程</text>
</view>
<!-- <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>
</view>
</uv-swipe-action-item>
</uv-swipe-action>
</z-paging>
</template>
<script setup>
import { ref, reactive} from 'vue';
import { queryTraPersonalCollectionTaskPaging,deleteTraPersonalCollectionById } from '@/api/favorites.js';
import { ref, reactive, onMounted, watch } 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 = 20;
const total = ref(-1);
const page = ref(0);
const data_list = reactive([]);
import useZpaging from '@/composables/useZpaging';
const { pagingRef, queryList, data_list, reload, total } = useZpaging({
fetchFunction: queryTraPersonalCollectionTaskPaging
});
const options = [
{
text: '删除',
@@ -69,39 +76,7 @@
}
}
];
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];
@@ -118,13 +93,13 @@
});
});
};
// 跳转到详情
const click_item = (item) => {
if(item.limitTyp === '02') {
if(item.isTimeOut === '01') {
if (item.limitTyp === '02') {
if (item.isTimeOut === '01') {
return common.msg('任务未开始');
} else if(item.isTimeOut === '02') {
} else if (item.isTimeOut === '02') {
return common.msg('任务已结束');
}
}
@@ -132,52 +107,51 @@
common.navigateTo(`/pages/learningTasks/details?collectId=${item.collectionId}`);
};
const getStatusClass = (isFinish) => {
// 01进行中、02已完成、03已超时
// if (isFinish === '00') return 'in_progress';
// if (isFinish === '01') return 'completed';
// return 'expired';
if (isFinish === '02') return 'completed';
return 'expired';
};
const scrolltolower = (item) => {
getData();
};
const refreshData = (params) => {
total.value = -1;
getData('first');
console.log('子组件refreshData');
};
const updateData = (item) => {
console.log('收藏的updateData', item);
console.log('收藏的updatedata_list', data_list);
const index = data_list.findIndex((res) => res.taskId === item.taskId);
console.log('updateData', index, item);
if (index !== -1) {
data_list[index] = item;
}
};
const props = defineProps(['tabIndex', 'currentIndex']);
onMounted(() => {
watch(
() => props.currentIndex,
(v) => v === props.tabIndex && total.value === -1 && reload(),
{ immediate: true }
);
});
// const updateData = (item) => {
// console.log('收藏的updateData', item);
// console.log('收藏的updatedata_list', data_list);
// const index = data_list.findIndex((res) => res.taskId === item.taskId);
// console.log('updateData', index, item);
// if (index !== -1) {
// data_list[index] = item;
// }
// };
defineExpose({
getData,
refreshData,
updateData
// getData,
// refreshData,
// updateData
});
</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);
.pagingClass {
width: calc(100% - 44rpx);
margin: 22rpx auto;
background-color: #fff;
border-radius: 16rpx;
}
.scroll-Y .item.in_progress {
.item-swipe-action {
overflow: hidden;
:deep(.uv-swipe-action-item__right__button__wrapper) {
border-radius: 20rpx !important;
}
}
.item.in_progress {
// 进行中
.subscript {
color: #0066ff;
@@ -189,7 +163,7 @@
}
}
.scroll-Y .item.completed {
.item.completed {
// 已完成
.subscript {
color: #ffffff;
@@ -201,7 +175,7 @@
}
}
.scroll-Y .item.expired {
.item.expired {
// 已超时
.subscript {
color: #ffffff;
@@ -221,9 +195,8 @@
}
}
.scroll-Y .item {
.item {
height: 170rpx;
// margin: 32rpx 22rpx;
display: flex;
.img_div {
+62 -82
View File
@@ -1,57 +1,57 @@
<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>
<template #top>
<view class="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="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 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"
:disable-touch="true"
@change="swiperChange"
>
<swiper-item>
<FavoritesCourse ref="courseRef"></FavoritesCourse>
</swiper-item>
<swiper-item>
<FavoritesTask ref="taskRef"></FavoritesTask>
</swiper-item>
</swiper>
</view>
</view>
</view>
</template>
<swiper class="swiper" :current="tabAct" :indicator-dots="false" :disable-touch="true" @change="swiperChange">
<swiper-item>
<FavoritesCourse
:ref="(el) => (listItemRefs[0] = el)"
:tabIndex="0"
:currentIndex="tabAct"
></FavoritesCourse>
</swiper-item>
<swiper-item>
<FavoritesTask :ref="(el) => (listItemRefs[1] = el)" :tabIndex="1" :currentIndex="tabAct"></FavoritesTask>
</swiper-item>
</swiper>
</z-paging-swiper>
</template>
<script setup>
// 我的收藏
import FavoritesTask from './components/favoritesTask.vue';
import FavoritesCourse from './components/favoritesCourse.vue';
// 我的收藏
import { ref, onMounted, watch } from 'vue';
import { onLoad, onUnload } from '@dcloudio/uni-app';
import { LineBg } from '@/enum.js';
import common from '@/common/common';
const courseRef = ref(null);
const taskRef = ref(null);
const tabAct = ref(0);
import useIndexList from '@/composables/useIndexList.js';
const { tabAct, listItemRefs, tabChange, swiperChange, search } = useIndexList();
const tabList = ref([
{
name: '课程收藏'
@@ -61,49 +61,28 @@
}
]);
const tabChange = (item) => {
tabAct.value = item.index;
};
const swiperChange = (item) => {
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');
}
},
{
immediate: true
}
); // 这里的immediate会在onMounted之后执行
});
onLoad(() => {
// 里面取消收藏后重新刷新列表
uni.$on('refresh_favorites_list', (params) => {
if (params.type === 'course') {
courseRef.value?.refreshData(params);
} else if (params.type === 'task') {
taskRef.value?.refreshData(params);
}
});
// 完成任务后更新列表单条信息
uni.$on('refresh_favorites_data', (res) => {
console.log('列表监听里面学习完成后更新任务历程', res);
if (tabAct.value === 0) {
courseRef.value?.updateData(res);
} else if (tabAct.value === 1) {
taskRef.value?.updateData(res);
}
});
// uni.$on('refresh_favorites_list', (params) => {
// if (params.type === 'course') {
// courseRef.value?.refreshData(params);
// } else if (params.type === 'task') {
// taskRef.value?.refreshData(params);
// }
// });
// // 完成任务后更新列表单条信息
// uni.$on('refresh_favorites_data', (res) => {
// console.log('列表监听里面学习完成后更新任务历程', res);
// if (tabAct.value === 0) {
// courseRef.value?.updateData(res);
// } else if (tabAct.value === 1) {
// taskRef.value?.updateData(res);
// }
// });
});
onUnload(() => {
uni.$off('refresh_favorites_data');
uni.$off('refresh_favorites_list');
// uni.$off('refresh_favorites_data');
// uni.$off('refresh_favorites_list');
});
</script>
@@ -122,6 +101,7 @@
.swiper {
height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 10rpx);
background-color: #f1f5fa;
}
.swiper-item {
+1
View File
@@ -480,6 +480,7 @@
let fileUrl = base_url + '/traask/traFilePreview/' + info.docId;
uni.downloadFile({
url: fileUrl,
success: function (res) {
var filePath = res.tempFilePath;
uni.openDocument({
@@ -1,4 +1,3 @@
<!-- 在这个文件对每个tab对应的列表进行渲染 -->
<template>
<z-paging
ref="pagingRef"
@@ -46,10 +45,7 @@
}
}
});
console.log('aaa', props.state);
const updateData = (item) => {
console.log('未完成专属逻辑,如果未完成列表出现了已完成状态,就重新加载未完成列表', props.tabIndex, item.isFinish);
// 未完成专属逻辑,如果未完成列表出现了已完成状态,就重新加载未完成列表
if(props.tabIndex !== 0 && item.isFinish === '02') {
reload()
} else{
+1 -24
View File
@@ -1,4 +1,3 @@
<!-- 滑动切换选项卡演示(标准写法) -->
<template>
<z-paging-swiper>
<template #top>
@@ -68,23 +67,9 @@
listItemRefs.value[1]?.updateData(res);
listItemRefs.value[2]?.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('update_tasks_item');
// uni.$off('refresh_tasks_data');
});
</script>
@@ -100,7 +85,7 @@
background-repeat: no-repeat !important;
}
}
.swiper {
height: 100%;
}
@@ -191,13 +176,5 @@
.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>
+36 -67
View File
@@ -1,87 +1,56 @@
<template>
<view class="scroll_div">
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
<view class="item" v-for="item in data_list" @click="goto_course_detail(item)">
<view class="img_div">
<image-preview class="img" :imgId="item.imgId" mode="scaleToFill"></image-preview>
</view>
<view class="right_div">
<view class="title ellipsis-text">{{ item.crsName }}</view>
<view class="tag_div">
<view class="tag" v-for="tag in item.tagCataList">{{ tag.tagName }}</view>
</view>
<view class="time_and_num"></view>
</view>
<z-paging
ref="pagingRef"
v-model="data_list"
@query="queryList"
:auto="false"
empty-view-text="暂无数据"
paging-class="pagingClass"
>
<view class="item" v-for="item in data_list" @click="goto_course_detail(item)">
<view class="img_div">
<image-preview class="img" :imgId="item.imgId" mode="scaleToFill"></image-preview>
</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>
<view class="right_div">
<view class="title ellipsis-text">{{ item.crsName }}</view>
<view class="tag_div">
<view class="tag" v-for="tag in item.tagCataList">{{ tag.tagName }}</view>
</view>
<view class="time_and_num"></view>
</view>
</view>
</z-paging>
</template>
<script setup>
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
const limit = 20;
const total = ref(-1);
const page = ref(0);
import common from '@/common/common';
const data_list = reactive([]);
import { ref, reactive, onMounted, nextTick } from 'vue';
import { ref, reactive, onMounted, nextTick, watch } from 'vue';
import { queryTraStdyInfoPreviewPaging } from '@/api/preview.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++;
}
queryTraStdyInfoPreviewPaging({
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();
};
import useZpaging from '@/composables/useZpaging';
const { pagingRef, queryList, data_list, reload, total } = useZpaging({
fetchFunction: queryTraStdyInfoPreviewPaging
});
const props = defineProps(['tabIndex', 'currentIndex']);
const goto_course_detail = (item) => {
common.navigateTo('/pages/courseDetail/index?isPreview=preview&crsId=' + item.crsId);
};
defineExpose({
getData
onMounted(() => {
watch(
() => props.currentIndex,
(v) => v === props.tabIndex && total.value === -1 && reload(),
{ immediate: true }
);
});
</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);
.pagingClass {
width: calc(100% - 44rpx);
margin: 22rpx auto;
background-color: #fff;
border-radius: 16rpx;
}
.scroll-Y .item {
.item {
height: 170rpx;
margin: 32rpx 22rpx;
display: flex;
+59 -67
View File
@@ -1,80 +1,68 @@
<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>
<template #top>
<view class="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="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 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">
<swiper class="swiper" :current="tabAct" :indicator-dots="false" @change="swiperChange">
<swiper-item>
<PreviewCourse ref="courseRef"></PreviewCourse>
</swiper-item>
<swiper-item>
<PreviewAiSparring ref="aiSparringRef"></PreviewAiSparring>
</swiper-item>
</swiper>
</view>
</view>
</view>
</template>
<swiper class="swiper" :current="tabAct" :indicator-dots="false" @change="swiperChange">
<swiper-item>
<PreviewCourse :ref="(el) => (listItemRefs[0] = el)" :tabIndex="0" :currentIndex="tabAct"></PreviewCourse>
</swiper-item>
<swiper-item>
<PreviewAiSparring :ref="(el) => (listItemRefs[1] = el)" :tabIndex="1" :currentIndex="tabAct"></PreviewAiSparring>
</swiper-item>
</swiper>
</z-paging-swiper>
</template>
<script setup>
// 我的预览
import PreviewAiSparring from './components/previewAiSparring.vue'
import PreviewCourse from './components/previewCourse.vue'
import {
ref,
onMounted,
watch
} from 'vue';
import PreviewAiSparring from './components/previewAiSparring.vue';
import PreviewCourse from './components/previewCourse.vue';
import { ref, onMounted, watch } from 'vue';
import common from '@/common/common';
import {
LineBg
} from '@/enum.js'
const courseRef = ref(null);
const aiSparringRef = ref(null);
const tabAct = ref(0);
const tabList = ref([{
name: '预览课程'
}, {
name: '预览AI陪练'
}]);
const tabChange = (item) => {
tabAct.value = item.index;
};
const swiperChange = (item) => {
tabAct.value = item.detail.current;
};
onMounted(() => {
watch(tabAct, (newValue, oldValue) => {
if (newValue === 0) {
courseRef.value?.getData('first')
} else if (newValue === 1) {
}
}, {
immediate: true
})
})
import { LineBg } from '@/enum.js';
import useIndexList from '@/composables/useIndexList.js';
const { tabAct, listItemRefs, tabChange, swiperChange, search } = useIndexList();
const tabList = ref([
{
name: '预览课程'
},
{
name: '预览AI陪练'
}
]);
</script>
<style lang="scss" scoped>
$bg-margin-left: 50rpx;
.my_tabs {
// 解决这个圆角的图片,开穿透
:deep(.uv-tabs__wrapper__nav__line) {
height: 26rpx !important;
@@ -86,6 +74,9 @@
.swiper {
height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 10rpx);
// background-color: red;
// height: 100%;
background-color: #f1f5fa;
}
.swiper-item {
@@ -107,7 +98,7 @@
}
.detail-main {
background-color: #F6F8FF;
background-color: #f6f8ff;
overflow: hidden;
}
@@ -120,7 +111,8 @@
line-height: 34rpx;
}
.swiper {}
.swiper {
}
.fixed_search_div {
padding: calc(20rpx + var(--status-bar-height)) 15rpx 24rpx 30rpx;
@@ -163,4 +155,4 @@
}
}
}
</style>
</style>