| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- <script lang="ts" setup>
- import { usePagination } from 'alova/client'
- import { reactive, ref, watch } from 'vue'
- import { getCouponIssuerAccountByPageMap } from '@/api/income'
- import { getInviteList } from '@/api/me'
- import CustomNavigationBar from '@/components/CustomNavigationBar.vue'
- import IncomeItem from '@/components/IncomeItem.vue'
- import MescrollUni from '@/components/mescroll.vue'
- import MescrollEmpty from '@/custom-components/custom-mescroll-uni/components/mescroll-empty.vue'
- import { changtime, safeAreaInsets } from '@/utils'
- definePage({
- style: {
- navigationBarTitleText: '收益',
- navigationStyle: 'custom',
- },
- })
- const topSafeAreaHeight = safeAreaInsets?.top || 0
- const activeIndex = ref(0)
- const showLoading = ref(false)
- const pickerDate = ref(Date.now())
- const pickerShow = ref(false)
- const totalAmount = ref(0)
- let mescroll = null
- const inviteType = reactive([
- { name: '已结算', key: 0 },
- { name: '待结算', key: 1 },
- ])
- const { send, data, pageCount, loading, page, pageSize, isLastPage, refresh, reload, onSuccess, onError } = usePagination((page, pageSize) => getCouponIssuerAccountByPageMap({
- pageNo: page,
- pageSize,
- type: 1,
- status: activeIndex.value,
- year: changtime(pickerDate.value, 'YYYY'),
- month: changtime(pickerDate.value, 'MM'),
- }), {
- initialPage: 1,
- initialPageSize: 10,
- append: true,
- preloadNextPage: false,
- preloadPreviousPage: false,
- total: response => response.total,
- data: response => response.detailList,
- immediate: false,
- })
- // ============ mescroll 配置 ============
- const downOption = reactive({
- use: true,
- auto: false,
- bgColor: '#f8f8fa',
- textColor: '#666',
- textInOffset: '下拉刷新',
- textOutOffset: '释放刷新',
- textLoading: '刷新中...',
- offset: 80,
- })
- const upOption = reactive({
- use: true,
- auto: false,
- noMoreSize: 7,
- isBounce: true,
- page: {
- num: page.value,
- size: pageSize.value,
- },
- empty: {
- use: false,
- },
- textNoMore: '--- 已经到底了 ---',
- toTop: {
- src: '/static/images/mescroll-totop.png',
- offset: 1000,
- bottom: 120,
- },
- // 开启虚拟列表优化(大数据量时)
- virtual: {
- use: false,
- rowHeight: 300,
- }
- })
- const emptyOption = reactive({
- use: true,
- tip: '暂无数据',
- btnText: '刷新试试',
- icon: '/static/images/mescroll-empty.png',
- fixed: false,
- top: '200rpx',
- })
- function mescrollInit(ref) {
- mescroll = ref
- }
- async function downCallback() {
- console.log('下拉刷新触发')
- await refresh()
- }
- async function upCallback() {
- console.log('上拉加载触发')
- if (isLastPage.value) {
- console.log(mescroll)
- mescroll.endSuccess(0, false)
- return
- }
- page.value++
- }
- onSuccess((response) => {
- let isNextPage = isLastPage.value
- // 此处处理alova isLastPage默认值为true,首次请求出现的无法加载下一页问题
- if (pageCount.value > page.value && isLastPage.value) {
- isNextPage = false
- }
- totalAmount.value = response.data?.totalAmount || 0
- // mescroll.setPageNum(page.value - 1)
- mescroll.endSuccess(data.value.length, !isNextPage)
- })
- onError(() => {
- console.log('请求失败')
- mescroll.endErr()
- })
- onShow(async () => {
- await send()
- })
- async function tabChange(index) {
- // 切换tab时,重置上拉加载
- // mescroll.resetUpScroll(true)
- // mescroll.showDownScroll()
- mescroll.hideUpScroll()
- mescroll.scrollTo(0, 0)
- showLoading.value = true
- await reload()
- showLoading.value = false
- }
- async function pickerConfirm() {
- pickerShow.value = false
- mescroll.scrollTo(0, 0)
- console.log(mescroll)
- mescroll.hideUpScroll()
- showLoading.value = true
- await reload()
- showLoading.value = false
- }
- </script>
- <template>
- <view class="income-container">
- <custom-navigation-bar :show-back="true" title="收益" />
- <view class="income-content"
- :style="{ marginTop: `calc(${topSafeAreaHeight}px + 88rpx)`, height: `calc(100vh - ${topSafeAreaHeight}px - 88rpx)` }">
- <view class="tabs-container flex">
- <up-tabs v-model:current="activeIndex" :scrollable="false" class="tabs-content" :list="inviteType"
- line-height="0" line-width="0" line-color="transparent"
- :active-style="{ fontWeight: 'bolder', fontSize: '30rpx', color: '#333333' }"
- :inactive-style="{ fontWeight: '400', fontSize: '30rpx', color: '#888888' }"
- item-style="height: 88rpx;" @change="tabChange" />
- </view>
- <view class="income-content-search">
- <view class="income-menu-time-filter-text" @click="pickerShow = true">
- <text>{{ changtime(pickerDate) }}</text>
- <up-icon name="arrow-down" color="#666666" size="14" />
- <up-datetime-picker v-model="pickerDate" :show="pickerShow" mode="year-month" close-on-click-overlay
- @confirm="pickerConfirm" @cancel="pickerShow = false" />
- </view>
- <view class="income-menu-total-amount">
- 合计:¥{{ totalAmount }}
- </view>
- </view>
- <view class="income-content-list"
- :style="{ height: `calc(100vh - ${topSafeAreaHeight}px - 88rpx - 88rpx - 72rpx)` }">
- <mescroll-uni id="mescrollContainer" :down="downOption" :up="upOption" :fixed="false"
- @init="mescrollInit" @down="downCallback" @up="upCallback">
- <view v-for="item in data" :key="item.userId" class="income-content-item">
- <income-item :data="item" :type="activeIndex" />
- </view>
- <mescroll-empty v-if="data.length === 0 && !loading" icon="'none'" tip="暂无数据" :option="emptyOption"
- @emptyclick="reload" />
- <!-- 滚动区域内的loading遮罩 -->
- <view v-if="showLoading && loading" class="loading-mask">
- <view class="loading-spinner" />
- <text class="loading-text">加载中...</text>
- </view>
- </mescroll-uni>
- </view>
- </view>
- </view>
- </template>
- <style lang="scss" scoped>
- .income-container {
- // height: 100vh;
- .income-content {
- display: flex;
- flex-direction: column;
- .income-content-search {
- padding: 27rpx 25rpx;
- padding-bottom: 15rpx;
- background-color: #f8f8fa;
- height: 60rpx;
- display: flex;
- justify-content: space-between;
- align-items: center;
- .income-menu-time-filter-text {
- font-weight: 400;
- font-size: 26rpx;
- color: #000000;
- display: flex;
- align-items: center;
- gap: 12rpx;
- }
- .income-menu-total-amount {
- font-weight: 400;
- font-size: 24rpx;
- color: #333333;
- }
- }
- .tabs-container {
- height: 88rpx;
- display: flex;
- flex-direction: row;
- justify-content: space-around;
- align-items: center;
- .tabs-content {
- width: 100%;
- :deep(.u-tabs__wrapper__nav__item) {
- &:first-child {
- position: relative;
- &:after {
- content: '';
- position: absolute;
- top: 50%;
- right: 0;
- transform: translateY(-50%);
- width: 2rpx;
- height: 40rpx;
- background-color: #9a9b9b;
- }
- }
- }
- }
- }
- .income-content-list {
- background-color: #f8f8fa;
- padding: 0 24rpx;
- display: flex;
- flex-direction: column;
- position: relative;
- #mescrollContainer {
- height: 100%;
- }
- .income-content-item {
- margin-top: 20rpx;
- }
- // loading遮罩样式
- .loading-mask {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: rgba(255, 255, 255, 0.8);
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- z-index: 999;
- }
- .loading-spinner {
- width: 40rpx;
- height: 40rpx;
- border: 4rpx solid #e0e0e0;
- border-top-color: #ed6b66;
- border-radius: 50%;
- animation: spin 1s linear infinite;
- }
- .loading-text {
- margin-top: 16rpx;
- font-size: 24rpx;
- color: #666;
- }
- @keyframes spin {
- to {
- transform: rotate(360deg);
- }
- }
- }
- }
- }
- </style>
|