mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2026-04-08 22:10:05 +00:00
238 lines
9.3 KiB
Vue
238 lines
9.3 KiB
Vue
<template>
|
|
<view class="bg-[var(--page-bg-color)] min-h-[100vh]" :style="themeColor()">
|
|
<view class="fixed left-0 right-0 top-0 z-10085 container">
|
|
<view class="bg-[#f6f6f6] px-[30rpx] h-[88rpx] pt-[10rpx] flex-center relative z-10084">
|
|
<view class="search-input bg-[#fff]">
|
|
<view class="from-type-name" :class="{'selected':from_type}" @click="typePopup = true">{{ from_type_name || '请选择来源用途' }}</view>
|
|
<text class="nc-iconfont nc-icon-shangV6xx-1 !text-[26rpx] ml-[18rpx] !text-[var(--text-color-light6)]" v-if="typePopup" @click="typePopup = false"></text>
|
|
<text class="nc-iconfont nc-icon-xiaV6xx !text-[26rpx] ml-[18rpx] !text-[var(--text-color-light6)]" v-else @click="typePopup = true"></text>
|
|
</view>
|
|
</view>
|
|
<view class="type-class">
|
|
<u-popup :show="typePopup" mode="top" @close="typePopup = false">
|
|
<view @touchmove.prevent.stop class="py-[22rpx]">
|
|
<view class="type-item-wrap" :class="{'selected' : from_type == ''}" @click="searchTypeFn()">全部</view>
|
|
<view class="type-item-wrap" :class="{'selected' : from_type == index}"
|
|
v-for="(item,index) in pointType" @click="searchTypeFn(index,item)">{{ item.name }}</view>
|
|
</view>
|
|
</u-popup>
|
|
</view>
|
|
<view class="px-[var(--sidebar-m)] pb-[20rpx] pt-[20rpx] bg-[#f6f6f6] flex items-center justify-between">
|
|
<view class="flex items-center">
|
|
<view class="amount-type-item-wrap" :class="{'selected':amount_type == item.status}"
|
|
v-for="(item,index) in typeList" :key="index" @click="loadTypeFn(item.status)">{{ item.name }}</view>
|
|
</view>
|
|
<view class="flex items-center" @click="handleSelect">
|
|
<view class="text-[26rpx] text-[#333] mr-[10rpx]">日期</view>
|
|
<view class="nc-iconfont nc-icon-a-riliV6xx-36 !text-[28rpx] leading-[36rpx]"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getPointListFn" :top="mescrollTop">
|
|
<view v-for="(item,index) in pointList" :key="index"
|
|
class="sidebar-margin card-template mt-[var(--top-m)]">
|
|
<view class="flex justify-between items-center">
|
|
<view class="text-[#333]">
|
|
<text class="text-[26rpx]">{{ item.month_info.year }}年</text>
|
|
<text class="text-[36rpx] font-500 ml-[10rpx] mr-[4rpx]">{{ item.month_info.month }}</text>
|
|
<text class="text-[26rpx]">月</text>
|
|
</view>
|
|
<view>
|
|
<text class="nc-iconfont nc-icon-xiaV6xx !text-[26rpx] text-[var(--text-color-light6)]" v-if="item.flag" @click="item.flag = false"></text>
|
|
<text class="nc-iconfont nc-icon-shangV6xx-1 !text-[26rpx] text-[var(--text-color-light6)]" v-else @click="item.flag = true"></text>
|
|
</view>
|
|
</view>
|
|
<view v-show="item.flag">
|
|
<template v-for="(subItem,subIndex) in item.month_data" :key="subItem.id">
|
|
<view class="flex items-center ">
|
|
<view class="w-[60rpx] h-[60rpx]">
|
|
<image v-if="subItem.account_data > 0" :src="img('static/resource/images/member/point/detail/point_add.png')" class="w-[60rpx] h-[60rpx]"/>
|
|
<image v-else :src="img('static/resource/images/member/point/detail/point_min.png')" class="w-[60rpx] h-[60rpx]"/>
|
|
</view>
|
|
<view class="from-type-name-wrap" :class="{'border-style' : subIndex}">
|
|
<view class="flex-1">
|
|
<view class="text-[26rpx] text-[#333]">{{ subItem.from_type_name }}</view>
|
|
<view class="text-[24rpx] text-[var(--text-color-light9)] mt-[16rpx]">{{ subItem.create_time }}</view>
|
|
</view>
|
|
<view class="account-data-wrap price-font" :class="{ '!text-primary' : subItem.account_data > 0 }">{{ subItem.account_data > 0 ? '+' + subItem.account_data : subItem.account_data }}</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
</view>
|
|
</view>
|
|
<mescroll-empty :option="{tip : '暂无积分明细'}" v-if="!pointList.length && loading"></mescroll-empty>
|
|
</mescroll-body>
|
|
<!-- 时间选择 -->
|
|
<select-date ref="selectDateRef" @confirm="confirmFn" />
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { reactive, ref } from 'vue'
|
|
import { t } from '@/locale'
|
|
import { redirect, img ,pxToRpx} from '@/utils/common';
|
|
import { getPointList, getPointType } from '@/app/api/member';
|
|
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
|
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
|
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
|
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
|
import selectDate from '@/components/select-date/select-date.vue';
|
|
|
|
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
|
|
|
const from_type = ref('');
|
|
const from_type_name = ref('')
|
|
const amount_type = ref('all');
|
|
const create_time = ref([])
|
|
const pointList = ref<Array<any>>([]);
|
|
const mescrollRef = ref(null);
|
|
const loading = ref<boolean>(false);
|
|
const typeList = ref([
|
|
{ name: '全部', status: 'all' },
|
|
{ name: '收入', status: 'income' },
|
|
{ name: '支出', status: 'disburse' }
|
|
])
|
|
|
|
const mescrollTop = ref('0rpx');
|
|
// 仅在页面渲染完成后计算一次高度
|
|
const calculateMescrollTop = () => {
|
|
const query = uni.createSelectorQuery()
|
|
query.select('.container').boundingClientRect(rect => {
|
|
if (rect) {
|
|
// 直接用头部实际高度
|
|
const topVal = pxToRpx(rect.height)
|
|
mescrollTop.value = topVal + 'rpx';
|
|
} else {
|
|
// 兜底用原有固定值
|
|
mescrollTop.value = '185rpx';
|
|
}
|
|
}).exec();
|
|
};
|
|
const getPointListFn = (mescroll: any) => {
|
|
let data = {
|
|
page: mescroll.num,
|
|
page_size: mescroll.size,
|
|
from_type: from_type.value,
|
|
amount_type: amount_type.value,
|
|
create_time: create_time.value
|
|
};
|
|
loading.value = false;
|
|
getPointList(data).then((res: any) => {
|
|
let newArr = res.data.data;
|
|
mescroll.endSuccess(newArr.length);
|
|
//设置列表数据
|
|
if (mescroll.num == 1) {
|
|
pointList.value = []; //如果是第一页需手动制空列表
|
|
}
|
|
pointList.value = pointList.value.concat(newArr);
|
|
pointList.value = pointList.value.map(item => {
|
|
item.flag = true
|
|
return item
|
|
})
|
|
loading.value = true;
|
|
}).catch(() => {
|
|
loading.value = true;
|
|
mescroll.endErr(); // 请求失败, 结束加载
|
|
})
|
|
}
|
|
|
|
const pointType = ref({})
|
|
const getPointTypeFn = () => {
|
|
getPointType('point').then((res: any) => {
|
|
pointType.value = res.data
|
|
})
|
|
setTimeout(() => calculateMescrollTop(), 200);
|
|
}
|
|
getPointTypeFn()
|
|
// 关键词搜索条件搜索
|
|
const typePopup = ref(false)
|
|
const searchTypeFn = (index: string = '', item: any = {}) => {
|
|
from_type.value = index
|
|
from_type_name.value = item.name
|
|
typePopup.value = false
|
|
pointList.value = [];
|
|
getMescroll().resetUpScroll();
|
|
}
|
|
// 类型搜索
|
|
const loadTypeFn = (type: string) => {
|
|
amount_type.value = type;
|
|
pointList.value = [];
|
|
getMescroll().resetUpScroll();
|
|
}
|
|
|
|
//日期筛选
|
|
const selectDateRef = ref()
|
|
const handleSelect = () => {
|
|
selectDateRef.value.show = true
|
|
}
|
|
// 确定时间筛选
|
|
const confirmFn = (data: any) => {
|
|
create_time.value = data;
|
|
pointList.value = []
|
|
getMescroll().resetUpScroll();
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
:deep(.type-class .u-popup .u-transition) {
|
|
top: 86rpx !important;
|
|
}
|
|
.from-type-name {
|
|
flex: 1;
|
|
font-size: 24rpx;
|
|
line-height: 60rpx;
|
|
color: var(--text-color-light9);
|
|
|
|
&.selected {
|
|
color: #333 !important;
|
|
}
|
|
}
|
|
.type-item-wrap {
|
|
line-height: 80rpx;
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
padding-left: 50rpx;
|
|
padding-right: 50rpx;
|
|
|
|
&.selected {
|
|
background-color: var(--primary-color-light);
|
|
color: var(--primary-color) !important;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
.amount-type-item-wrap {
|
|
padding-left: 30rpx;
|
|
padding-right: 30rpx;
|
|
background-color: #fff;
|
|
border-radius: 30rpx;
|
|
font-size: 24rpx;
|
|
line-height: 54rpx;
|
|
margin-right: 20rpx;
|
|
color: #333;
|
|
|
|
&.selected {
|
|
color: var(--primary-color) !important;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
.from-type-name-wrap {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
margin-left: 20rpx;
|
|
box-sizing: border-box;
|
|
padding-top: 30rpx;
|
|
padding-bottom: 30rpx;
|
|
border: none;
|
|
|
|
&.border-style {
|
|
border: 2px solid #F0F2F8;
|
|
}
|
|
}
|
|
.account-data-wrap{
|
|
font-size: 36rpx;
|
|
font-weight: 500;
|
|
color: #03B521;
|
|
}
|
|
</style>
|