594 lines
12 KiB
Vue
594 lines
12 KiB
Vue
<template>
|
||
<view class="my-coupon">
|
||
<view>
|
||
<!--顶部导航栏-->
|
||
<view class="tabr" :style="{ top: headerTop }">
|
||
<view :class="typeClass == 'valid' ? `text-${themeColor.name} on` : ''" @tap="switchType('valid', 1)"
|
||
>可用
|
||
<text v-if="state === 1">({{ couponList.length }})</text>
|
||
</view>
|
||
<view :class="typeClass == 'used' ? `text-${themeColor.name} on` : ''" @tap="switchType('used', 2)"
|
||
>已使用
|
||
<text v-if="state === 2">({{ couponList.length }})</text>
|
||
</view>
|
||
<view
|
||
:class="typeClass == 'invalid' ? `text-${themeColor.name} on` : ''"
|
||
@tap="switchType('invalid', 3)"
|
||
>已失效
|
||
<text v-if="state === 3">({{ couponList.length }})</text>
|
||
</view>
|
||
<view class="border" :class="[typeClass, 'bg-' + themeColor.name]"></view>
|
||
</view>
|
||
<!--占位符-->
|
||
<view class="place"></view>
|
||
<!--优惠券列表-->
|
||
<view class="coupon-list">
|
||
<view
|
||
v-if="state === 3 && couponList.length > 0 && !loading"
|
||
class="empty-invalid"
|
||
:class="'text-' + themeColor.name"
|
||
@tap.stop="emptyInvalidCoupon"
|
||
>
|
||
清空失效优惠券
|
||
</view>
|
||
<!-- 优惠券列表 -->
|
||
<view
|
||
class="sub-list valid"
|
||
:style="{ marginTop: state === 3 ? '50upx' : 0 }"
|
||
>
|
||
<view class="row" v-for="(row, index) in couponList" :key="index">
|
||
<!-- content -->
|
||
<view class="carrier">
|
||
<view class="left">
|
||
<view class="in1line title">
|
||
<text class="cell-icon" :class="'bg-' + themeColor.name">{{
|
||
parseInt(row.type, 10) === 1 ? '满减' : '直降'
|
||
}}</text>
|
||
{{ row.name }}
|
||
</view>
|
||
<view class="term" v-if="state !== 2">
|
||
{{ row.startTime |filterTime }} ~ {{ row.endTime |filterTime }}
|
||
</view>
|
||
<view class="term" v-else>
|
||
使用时间:{{ row.userTime |filterTime }}
|
||
</view>
|
||
<view class="overdue" v-if="state === 3">
|
||
<text class="iconfont iconyiguoqi2" :class="'text-' + themeColor.name"></text>
|
||
</view>
|
||
<view class="overdue" v-if="state === 2">
|
||
<text class="iconfont iconyishiyong"></text>
|
||
</view>
|
||
|
||
</view>
|
||
<view class="right" :class="state !== 1 ? 'invalid' : 'bg-' + themeColor.name">
|
||
<view class="ticket">
|
||
<view class="num">
|
||
{{ row.fallPrice ? moneySymbol +'直降'+ row.fallPrice : '减'+moneySymbol +row.price }}
|
||
</view>
|
||
</view>
|
||
<view class="criteria" v-if="parseInt(row.type, 10) === 1"> 满{{ row.fullPrice }}使用 </view>
|
||
<view
|
||
class="use view"
|
||
:class="'text-' + themeColor.name"
|
||
@tap="show(row)"
|
||
|
||
>
|
||
商品
|
||
</view>
|
||
<view
|
||
class="use"
|
||
:class="'text-' + themeColor.name"
|
||
v-if="state == 1"
|
||
@tap="navTo('/pages/product/list')"
|
||
>
|
||
去使用
|
||
</view>
|
||
<view
|
||
class="use"
|
||
:class="'text-' + themeColor.name"
|
||
v-if="state == 2"
|
||
@tap="navTo(`/pages/order/detail?id=${row.orderId}`)"
|
||
>
|
||
去查看
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<rf-load-more
|
||
:status="loadingType"
|
||
v-if="couponList.length > 0"
|
||
></rf-load-more>
|
||
</view>
|
||
</view>
|
||
<rf-empty
|
||
class="empty"
|
||
info="暂无优惠券"
|
||
v-if="couponList.length === 0 && !loading"
|
||
></rf-empty>
|
||
<!--显示部分商品的抽屉-->
|
||
<uni-drawer
|
||
class="rf-drawer"
|
||
:visible="showRight"
|
||
mode="right"
|
||
@close="closeDrawer()"
|
||
>
|
||
<view class="rf-drawer-title" :class="'text-' + themeColor.name">可用商品列表</view>
|
||
<view class="rf-drawer-list">
|
||
<view
|
||
class="rf-drawer-item"
|
||
@tap="navTo(`/pages/product/product?id=${item.id}`)"
|
||
v-for="item in currentCoupon.usableProduct"
|
||
:key="item.id"
|
||
>
|
||
<view class="left">
|
||
<view class="title">{{
|
||
item.name
|
||
.split('】')[0]
|
||
.split('【')
|
||
.join('')
|
||
}}</view>
|
||
<view class="desc in2line">{{ item.name.split('】')[1] }}</view>
|
||
</view>
|
||
<text class="iconfont iconyou"></text>
|
||
</view>
|
||
</view>
|
||
<view class="close">
|
||
<view
|
||
class="btn"
|
||
:class="'bg-' + themeColor.name"
|
||
plain="true"
|
||
size="small"
|
||
type="primary"
|
||
@tap="hide"
|
||
>
|
||
关闭
|
||
</view>
|
||
</view>
|
||
</uni-drawer>
|
||
<rfLoading isFullScreen :active="loading"></rfLoading>
|
||
</view>
|
||
</template>
|
||
<script>
|
||
/**
|
||
* @des 优惠券管理
|
||
*
|
||
* @author 237524947@qq.com
|
||
* @date 2019-12-09 10:13
|
||
* @copyright 2019
|
||
*/
|
||
import { couponClear, myCouponList } from '@/api/userInfo';
|
||
import rfLoadMore from '@/components/rf-load-more/rf-load-more';
|
||
import moment from '@/common/moment';
|
||
import uniDrawer from '@/components/uni-drawer/uni-drawer';
|
||
export default {
|
||
components: {
|
||
rfLoadMore,
|
||
uniDrawer
|
||
},
|
||
data() {
|
||
return {
|
||
headerTop: 0,
|
||
// 控制滑动效果
|
||
typeClass: 'valid',
|
||
theIndex: null,
|
||
oldIndex: null,
|
||
state: 1,
|
||
isStop: false,
|
||
couponList: [],
|
||
loadingType: 'more',
|
||
token: null,
|
||
pageNum :0,
|
||
showRight: false,
|
||
moneySymbol: this.moneySymbol,
|
||
currentCoupon: {},
|
||
loading: true
|
||
};
|
||
},
|
||
filters: {
|
||
// 格式化时间
|
||
time(val) {
|
||
return moment(val * 1000).format('YYYY-MM-DD');
|
||
},
|
||
filterTime(val) {
|
||
if(val && val.length>11){
|
||
return val.substring(0, 10);
|
||
}else{
|
||
return val;
|
||
}
|
||
|
||
},
|
||
// 格式化时间
|
||
timeFull(val) {
|
||
return moment(val * 1000).format('YYYY-MM-DD HH:mm:ss');
|
||
}
|
||
},
|
||
// 下拉刷新,需要自己在page.json文件中配置开启页面下拉刷新 "enablePullDownRefresh": true
|
||
onPullDownRefresh() {
|
||
this.pageNum = 0;
|
||
this.couponList = [];
|
||
this.getMyCouponList('refresh');
|
||
},
|
||
// 加载更多
|
||
onReachBottom() {
|
||
if (this.loadingType === 'nomore') return;
|
||
this.pageNum++
|
||
this.getMyCouponList();
|
||
},
|
||
onLoad() {
|
||
// 数据初始化
|
||
this.initData();
|
||
// 兼容H5下排序栏位置
|
||
// #ifdef H5
|
||
// 定时器方式循环获取高度为止,这么写的原因是onLoad中head未必已经渲染出来。
|
||
let Timer = setInterval(() => {
|
||
let uniHead = document.getElementsByTagName('uni-page-head');
|
||
if (uniHead.length > 0) {
|
||
this.headerTop = uniHead[0].offsetHeight + 'px';
|
||
clearInterval(Timer); // 清除定时器
|
||
}
|
||
}, 1);
|
||
// #endif
|
||
},
|
||
methods: {
|
||
// 显示抽屉(可使用商品)
|
||
show(item) {
|
||
if (item.usableProduct.length === 0) return;
|
||
this.currentCoupon = item;
|
||
this.showRight = true;
|
||
},
|
||
// 隐藏抽屉
|
||
hide() {
|
||
this.showRight = false;
|
||
},
|
||
// 关闭抽屉
|
||
closeDrawer() {
|
||
this.showRight = false;
|
||
},
|
||
// 切换顶部优惠券类型
|
||
switchType(type, state) {
|
||
if (this.typeClass === type) {
|
||
return;
|
||
}
|
||
uni.pageScrollTo({
|
||
scrollTop: 0,
|
||
duration: 0
|
||
});
|
||
this.typeClass = type;
|
||
this.state = state;
|
||
this.pageNum = 0;
|
||
this.couponList = [];
|
||
this.loading = true;
|
||
this.getMyCouponList();
|
||
},
|
||
// 清空失效优惠券
|
||
async emptyInvalidCoupon() {
|
||
await this.$http.get(`${couponClear}`).then(() => {
|
||
this.getMyCouponList();
|
||
});
|
||
},
|
||
// 占位方法
|
||
discard() {
|
||
// 丢弃
|
||
},
|
||
// 初始化数据
|
||
initData() {
|
||
this.pageNum = 0;
|
||
this.couponList = [];
|
||
this.getMyCouponList();
|
||
},
|
||
// 统一跳转接口
|
||
navTo(route, type) {
|
||
if (type) {
|
||
this.$mRouter.switchTab({ route });
|
||
} else {
|
||
this.$mRouter.push({ route });
|
||
}
|
||
},
|
||
// 获取我的优惠券列表
|
||
async getMyCouponList(type) {
|
||
await this.$http
|
||
.get(`${myCouponList}`, {
|
||
pageNum: this.pageNum,
|
||
status: this.state
|
||
})
|
||
.then(r => {
|
||
this.loading = false;
|
||
if (type === 'refresh') {
|
||
uni.stopPullDownRefresh();
|
||
}
|
||
if(r.list){
|
||
this.loadingType = r.list.length === 10 ? 'more' : 'nomore';
|
||
this.couponList = [...this.couponList, ...r.list];
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.loading = false;
|
||
if (type === 'refresh') {
|
||
uni.stopPullDownRefresh();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
<style lang="scss">
|
||
view {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
}
|
||
page {
|
||
position: relative;
|
||
background-color: $page-color-base;
|
||
}
|
||
|
||
.my-coupon {
|
||
.place {
|
||
width: 100%;
|
||
height: 95upx;
|
||
}
|
||
.tabr {
|
||
background-color: #fff;
|
||
width: 100%;
|
||
height: 95upx;
|
||
padding: 0 3%;
|
||
border-bottom: solid 1upx #dedede;
|
||
position: fixed;
|
||
top: 0;
|
||
z-index: 10;
|
||
view {
|
||
width: 33.3%;
|
||
height: 90upx;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 32upx;
|
||
}
|
||
.border {
|
||
height: 4upx;
|
||
&.used {
|
||
transform: translate3d(100%, 0, 0);
|
||
}
|
||
&.invalid {
|
||
transform: translate3d(200%, 0, 0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.coupon-list {
|
||
width: 100%;
|
||
display: block;
|
||
position: relative;
|
||
.empty-invalid {
|
||
position: absolute;
|
||
right: 20upx;
|
||
top: 10upx;
|
||
font-size: $font-base;
|
||
}
|
||
}
|
||
@keyframes showValid {
|
||
0% {
|
||
transform: translateX(-100%);
|
||
}
|
||
100% {
|
||
transform: translateX(0);
|
||
}
|
||
}
|
||
@keyframes showInvalid {
|
||
0% {
|
||
transform: translateX(0);
|
||
}
|
||
100% {
|
||
transform: translateX(-100%);
|
||
}
|
||
}
|
||
.sub-list {
|
||
width: 100%;
|
||
&.invalid {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 100%;
|
||
display: none;
|
||
}
|
||
|
||
&.showvalid {
|
||
display: flex;
|
||
animation: showValid 0.2s linear both;
|
||
}
|
||
|
||
&.showinvalid {
|
||
display: flex;
|
||
animation: showInvalid 0.2s linear both;
|
||
}
|
||
|
||
.tis {
|
||
width: 100%;
|
||
height: 60upx;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 32upx;
|
||
}
|
||
|
||
.row {
|
||
width: 92%;
|
||
height: 27vw;
|
||
margin: 20upx auto 10upx auto;
|
||
border-radius: 8upx;
|
||
// box-shadow: 0upx 0 10upx rgba(0,0,0,0.1);
|
||
align-items: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
z-index: 4;
|
||
border: 0;
|
||
.carrier {
|
||
@keyframes showMenu {
|
||
0% {
|
||
transform: translateX(0);
|
||
}
|
||
100% {
|
||
transform: translateX(-28%);
|
||
}
|
||
}
|
||
@keyframes closeMenu {
|
||
0% {
|
||
transform: translateX(-28%);
|
||
}
|
||
100% {
|
||
transform: translateX(0);
|
||
}
|
||
}
|
||
|
||
&.open {
|
||
animation: showMenu 0.25s linear both;
|
||
}
|
||
|
||
&.close {
|
||
animation: closeMenu 0.15s linear both;
|
||
}
|
||
|
||
background-color: #fff;
|
||
position: absolute;
|
||
width: 100%;
|
||
padding: 0 0;
|
||
height: 100%;
|
||
z-index: 3;
|
||
flex-wrap: nowrap;
|
||
|
||
.left {
|
||
width: 100%;
|
||
position: relative;
|
||
|
||
.title {
|
||
padding-top: 3vw;
|
||
width: 90%;
|
||
margin: 0 5%;
|
||
font-size: 36upx;
|
||
|
||
.cell-icon {
|
||
display: inline-block;
|
||
height: 32upx;
|
||
margin-top: 15upx;
|
||
width: 32upx;
|
||
font-size: 22upx;
|
||
text-align: center;
|
||
line-height: 32upx;
|
||
border-radius: 4upx;
|
||
margin-right: 12upx;
|
||
&.hb {
|
||
background: #ffaa0e;
|
||
}
|
||
&.lpk {
|
||
background: #3ab54a;
|
||
}
|
||
}
|
||
}
|
||
|
||
.term {
|
||
width: 90%;
|
||
margin: 0 5%;
|
||
font-size: 26upx;
|
||
color: #999;
|
||
}
|
||
|
||
.usage {
|
||
width: 90%;
|
||
margin: 0 5%;
|
||
font-size: 26upx;
|
||
color: $font-color-light;
|
||
}
|
||
|
||
.gap-top,
|
||
.gap-bottom {
|
||
position: absolute;
|
||
width: 20upx;
|
||
height: 20upx;
|
||
right: -10upx;
|
||
border-radius: 100%;
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.gap-top {
|
||
top: -10upx;
|
||
}
|
||
|
||
.gap-bottom {
|
||
bottom: -10upx;
|
||
}
|
||
|
||
.overdue {
|
||
position: absolute;
|
||
right: 10upx;
|
||
top: 0;
|
||
|
||
.iconyiguoqi2 {
|
||
font-size: $font-lg + 40upx;
|
||
}
|
||
|
||
.iconyishiyong {
|
||
font-size: $font-lg + 40upx;
|
||
color: $font-color-base;
|
||
}
|
||
}
|
||
}
|
||
|
||
.right {
|
||
flex-shrink: 0;
|
||
width: 28%;
|
||
color: #fff;
|
||
&.invalid {
|
||
background: linear-gradient(to right, #aaa, #999);
|
||
.use {
|
||
color: #aaa;
|
||
}
|
||
}
|
||
|
||
justify-content: center;
|
||
|
||
.ticket,
|
||
.criteria {
|
||
width: 100%;
|
||
}
|
||
|
||
.ticket {
|
||
padding-top: 1vw;
|
||
justify-content: center;
|
||
align-items: baseline;
|
||
height: 6vw;
|
||
|
||
.num {
|
||
font-size: 42upx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.unit {
|
||
font-size: 24upx;
|
||
}
|
||
}
|
||
|
||
.criteria {
|
||
justify-content: center;
|
||
|
||
font-size: 28upx;
|
||
}
|
||
|
||
.use {
|
||
width: 45%;
|
||
margin: 0 2.5%;
|
||
height: 40upx;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 24upx;
|
||
background-color: #fff;
|
||
border-radius: 40upx;
|
||
padding: 0 4upx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.empty {
|
||
width: 100vw;
|
||
display: block;
|
||
}
|
||
</style>
|