优惠劵列表:接入完成

pull/29/head^2
YunaiV 2023-12-16 10:40:04 +08:00
parent 77e2719837
commit 894f57a551
5 changed files with 428 additions and 431 deletions

View File

@ -1,265 +1,231 @@
<!-- 优惠券中心 --> <!-- 优惠券中心 -->
<template> <template>
<s-layout title="优惠券" :bgStyle="{ color: '#f2f2f2' }"> <s-layout title="优惠券" :bgStyle="{ color: '#f2f2f2' }">
<su-sticky bgColor="#fff"> <su-sticky bgColor="#fff">
<su-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab"></su-tabs> <su-tabs
</su-sticky> :list="tabMaps"
<s-empty v-if="state.pagination.total === 0" icon="/static/coupon-empty.png" text="暂无优惠券"></s-empty> :scrollable="false"
<template v-if="state.currentTab == '0'"> @change="onTabsChange"
<view v-for="item in state.pagination.list" :key="item.id"> :current="state.currentTab"
<s-coupon-list :data="item" @tap=" />
sheep.$router.go('/pages/coupon/detail', { </su-sticky>
data: JSON.stringify(item), <s-empty
})"> v-if="state.pagination.total === 0"
icon="/static/coupon-empty.png"
<template #default> text="暂无优惠券"
<button class="ss-reset-button card-btn ss-flex ss-row-center ss-col-center" />
:class="item.get_status != 'can_get' ? 'border-btn' : ''" @click.stop="getBuy(item.id)" <!-- 情况一领劵中心 -->
:disabled="item.get_status != 'can_get'"> <template v-if="state.currentTab == '0'">
<!-- {{ item.status_text }} --> <view v-for="item in state.pagination.list" :key="item.id">
{{item.status_text|| '立即使用' }} <s-coupon-list
</button> :data="item"
</template> @tap="
</s-coupon-list> sheep.$router.go('/pages/coupon/detail', {
</view> data: JSON.stringify(item),
</template> })
<template v-else> "
<view v-for="item in state.pagination.list" :key="item.id"> >
<s-coupon-list :data="item" type="user" @tap=" <template #default>
sheep.$router.go('/pages/coupon/detail', { <button
data: JSON.stringify(item), class="ss-reset-button card-btn ss-flex ss-row-center ss-col-center"
}) :class="!item.canTake ? 'border-btn' : ''"
"> @click.stop="getBuy(item.id)"
:disabled="!item.canTake"
<template #default> >
<button class="ss-reset-button card-btn ss-flex ss-row-center ss-col-center" :class=" {{ item.canTake ? '立即领取' : '已领取' }}
item.status == 'can_get' || item.status == 'can_use' </button>
? '' </template>
: item.status == 'used' || item.status == 'expired' </s-coupon-list>
? 'disabled-btn' </view>
: 'border-btn' </template>
" :disabled="item.status != 'can_get' && item.status != 'can_use'" @click.stop=" <!-- 情况二我的优惠劵 -->
<template v-else>
<view v-for="item in state.pagination.list" :key="item.id">
<s-coupon-list
:data="item"
type="user"
@tap="
sheep.$router.go('/pages/coupon/detail', {
data: JSON.stringify(item),
})
"
>
<template #default>
<button
class="ss-reset-button card-btn ss-flex ss-row-center ss-col-center"
:class=" item.status !== 1 ? 'disabled-btn': ''"
:disabled="item.status !== 1"
@click.stop="
sheep.$router.go('/pages/coupon/detail', { sheep.$router.go('/pages/coupon/detail', {
id: item.coupon_id, id: item.coupon_id,
user_coupon_id: item.id, user_coupon_id: item.id,
}) })
"> "
<!-- {{ item.status_text }} --> >
{{item.status_text|| '立即使用' }} {{ item.status === 1 ? '立即使用' : item.status === 2 ? '已使用' : '已过期' }}
</button> </button>
</template> </template>
</s-coupon-list> </s-coupon-list>
</view> </view>
</template> </template>
<!-- <uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{ <uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
contentdown: '上拉加载更多', contentdown: '上拉加载更多',
}" @tap="loadmore" /> --> }" @tap="loadMore" />
</s-layout> </s-layout>
</template> </template>
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import { import { onLoad, onReachBottom } from '@dcloudio/uni-app';
onLoad, import { reactive } from 'vue';
onReachBottom import _ from 'lodash';
} from '@dcloudio/uni-app'; import { resetPagination } from '@/sheep/util';
import { import CouponApi from '@/sheep/api/promotion/coupon';
computed,
reactive
} from 'vue';
import _ from 'lodash';
const pagination = { //
data: [], const state = reactive({
current_page: 1, currentTab: 0, // tab
total: 1, type: '1',
last_page: 1, pagination: {
}; list: [],
// total: 0,
const state = reactive({ pageNo: 1,
currentTab: 0, pageSize: 5
pagination: { },
data: [], loadStatus: '',
current_page: 1, });
total: 1,
last_page: 1,
},
loadStatus: '',
type: '1',
});
const tabMaps = [ const tabMaps = [
// { {
// name: '', name: '领券中心',
// value: 'all', value: 'all',
// }, },
{ {
name: '已领取', name: '已领取',
value: '1', value: '1',
}, },
{ {
name: '已使用', name: '已使用',
value: '2', value: '2',
}, },
{ {
name: '已失效', name: '已失效',
value: '3', value: '3',
}, },
]; ];
function onTabsChange(e) { // TODO yunai:
state.pagination = pagination function onTabsChange(e) {
state.currentTab = e.index; state.currentTab = e.index;
state.type = e.value; state.type = e.value;
// if (state.currentTab == 0) { resetPagination(state.pagination)
// getData(); if (state.currentTab == 0) {
// } else { getData();
getCoupon(); } else {
// } getCoupon();
} }
async function getData(page = 1, list_rows = 5) { }
state.loadStatus = 'loading';
const res = await sheep.$api.coupon.list({
list_rows,
page
});
if (res.error === 0) {
let couponlist = _.concat(state.pagination.data, res.data.data);
state.pagination = {
...res.data,
data: couponlist,
};
if (state.pagination.current_page < state.pagination.last_page) {
state.loadStatus = 'more';
} else {
state.loadStatus = 'noMore';
}
}
}
async function getCoupon(page = 1, list_rows = 5) { //
state.loadStatus = 'loading'; async function getData() {
let res = await sheep.$api.coupon.userCoupon({ state.loadStatus = 'loading';
status: state.type, const { data, code } = await CouponApi.getCouponTemplatePage({
pageSize: list_rows, pageNo: state.pagination.pageNo,
pageNo: page pageSize: state.pagination.pageSize,
}); });
if (res.code === 0) { if (code !== 0) {
// return;
let obj = { }
1: '可用', state.pagination.list = _.concat(state.pagination.list, data.list);
2: '已用', state.pagination.total = data.total;
3: '过期' state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
} }
let obj2 = {
1: '满减',
2: '折扣'
}
res.data.list = res.data.list.map(item => {
return {
...item,
enough: (item.usePrice / 100).toFixed(2),
amount: (item.discountPrice / 100).toFixed(2),
use_start_time: sheep.$helper.timeFormat(item.validStartTime, 'yyyy-mm-dd hh:MM:ss'),
use_end_time: sheep.$helper.timeFormat(item.validEndTime, 'yyyy-mm-dd hh:MM:ss'),
status_text: obj[item.status],
type_text: obj2[item.discountType]
}
});
if (page >= 2) {
let couponlist = _.concat(state.pagination.data, res.data.list);
state.pagination = { //
...res.data, async function getCoupon() {
data: couponlist, state.loadStatus = 'loading';
}; const { data, code } = await CouponApi.getCouponPage({
console.log(state.pagination, '拿到的优惠券数据'); pageNo: state.pagination.pageNo,
} else { pageSize: state.pagination.pageSize,
state.pagination = res.data; status: state.type
console.log(state.pagination, '拿到的优惠券数据'); });
} if (code !== 0) {
// if (state.pagination.current_page < state.pagination.last_page) { return;
// state.loadStatus = 'more'; }
// } else { state.pagination.list = _.concat(state.pagination.list, data.list);
// state.loadStatus = 'noMore'; state.pagination.total = data.total;
// } state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
} }
}
async function getBuy(id) {
const {
error,
msg
} = await sheep.$api.coupon.get(id);
if (error === 0) {
uni.showToast({
title: msg,
});
setTimeout(() => {
state.pagination = pagination
getData();
}, 1000);
}
}
// //
function loadmore() { async function getBuy(id) {
if (state.loadStatus !== 'noMore') { const { code } = await CouponApi.takeCoupon(id);
if (state.currentTab == 0) { if (code !== 0) {
getData(state.pagination.current_page + 1); return;
} else { }
getCoupon(state.pagination.current_page + 1); uni.showToast({
} title: '领取成功',
} });
} setTimeout(() => {
onLoad((Option) => { resetPagination(state.pagination);
// if (Option.type === 'all' || !Option.type) { getData();
// getData(); }, 1000);
// } else { }
// state.type = Option.type;
// Option.type === 'geted' ?
// () :
// Option.type === 'used' ?
// (state.currentTab = 1 && state.type = 2) :
// (state.currentTab = 2 && state.type = 3);
if (Option.type == 'geted') { //
state.currentTab = 0 function loadMore() {
state.type = 1 if (state.loadStatus === 'noMore') {
} else if (Option.type == 'used') { return;
state.currentTab = 1 }
state.type = 2 state.pagination.pageNo++;
} else { if (state.currentTab === 0) {
state.currentTab = 2 getData();
state.type = 3 } else {
} getCoupon();
getCoupon(); }
// } }
});
onReachBottom(() => { onLoad((Option) => {
loadmore(); //
}); if (Option.type === 'all' || !Option.type) {
getData();
//
} else {
state.type = Option.type;
Option.type === 'geted'
? (state.currentTab = 1)
: Option.type === 'used'
? (state.currentTab = 2)
: (state.currentTab = 3);
getCoupon();
}
});
onReachBottom(() => {
loadMore();
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.card-btn { .card-btn {
// width: 144rpx; // width: 144rpx;
padding: 0 16rpx; padding: 0 16rpx;
height: 50rpx; height: 50rpx;
border-radius: 40rpx; border-radius: 40rpx;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient)); background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: #ffffff; color: #ffffff;
font-size: 24rpx; font-size: 24rpx;
font-weight: 400; font-weight: 400;
} }
.border-btn { .border-btn {
background: linear-gradient(90deg, var(--ui-BG-Main-opacity-4), var(--ui-BG-Main-light)); background: linear-gradient(90deg, var(--ui-BG-Main-opacity-4), var(--ui-BG-Main-light));
color: #fff !important; color: #fff !important;
} }
.disabled-btn { .disabled-btn {
background: #cccccc; background: #cccccc;
background-color: #cccccc !important; background-color: #cccccc !important;
color: #fff !important; color: #fff !important;
} }
</style> </style>

View File

@ -1,3 +1,4 @@
<!-- 搜索界面 -->
<template> <template>
<s-layout class="set-wrap" title="搜索" :bgStyle="{ color: '#FFF' }"> <s-layout class="set-wrap" title="搜索" :bgStyle="{ color: '#FFF' }">
<view class="ss-p-x-24"> <view class="ss-p-x-24">
@ -33,14 +34,18 @@
import { reactive } from 'vue'; import { reactive } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
const state = reactive({ const state = reactive({
historyList: [], historyList: [],
}); });
// //
function onSearch(keyword) { function onSearch(keyword) {
if (!keyword) return; if (!keyword) {
return;
}
saveSearchHistory(keyword); saveSearchHistory(keyword);
//
sheep.$router.go('/pages/goods/list', { keyword }); sheep.$router.go('/pages/goods/list', { keyword });
} }
@ -53,7 +58,7 @@
// //
state.historyList.unshift(keyword); state.historyList.unshift(keyword);
// 10 // 10
if (state.historyList.length >= 10) { if (state.historyList.length >= 10) {
state.historyList.length = 10; state.historyList.length = 10;
} }
@ -72,6 +77,7 @@
}, },
}); });
} }
onLoad(() => { onLoad(() => {
state.historyList = uni.getStorageSync('searchHistory') || []; state.historyList = uni.getStorageSync('searchHistory') || [];
}); });

View File

@ -12,18 +12,7 @@ export default {
showLoading: false, showLoading: false,
}, },
}), }),
userCoupon: (params) =>
request2({
url: 'promotion/coupon/page',
method: 'GET',
params,
}),
// userCoupon: (params) =>
// request({
// url: 'user/coupon',
// method: 'GET',
// params,
// }),
detail: (id, user_coupon_id) => detail: (id, user_coupon_id) =>
request({ request({
url: 'coupon/' + id, url: 'coupon/' + id,
@ -37,9 +26,4 @@ export default {
url: 'coupon/get/' + id, url: 'coupon/get/' + id,
method: 'POST', method: 'POST',
}), }),
listByGoods: (id) =>
request({
url: 'coupon/listByGoods/' + id,
method: 'GET',
}),
}; };

View File

@ -1,6 +1,6 @@
import request from '@/sheep/request'; import request from '@/sheep/request';
export default { const CouponApi = {
// 获得优惠劵模板列表 // 获得优惠劵模板列表
getCouponTemplateListByIds: (ids) => { getCouponTemplateListByIds: (ids) => {
return request({ return request({
@ -17,4 +17,30 @@ export default {
params: { spuId, productScope, count }, params: { spuId, productScope, count },
}); });
}, },
// 获得优惠劵模版分页
getCouponTemplatePage: (params) => {
return request({
url: '/app-api/promotion/coupon-template/page',
method: 'GET',
params,
});
},
// 我的优惠劵列表
getCouponPage: (params) => {
return request({
url: '/app-api/promotion/coupon/page',
method: 'GET',
params,
});
},
// 领取优惠券
takeCoupon: (templateId) => {
return request({
url: '/app-api/promotion/coupon/take',
method: 'POST',
data: { templateId },
});
},
}; };
export default CouponApi;

View File

@ -1,195 +1,210 @@
<template> <template>
<view class="ss-m-20" :style="{ opacity: disabled ? '0.5' : '1' }"> <view class="ss-m-20" :style="{ opacity: disabled ? '0.5' : '1' }">
<view class="content"> <view class="content">
<!-- <view <view
class="tag ss-flex ss-row-center" class="tag ss-flex ss-row-center"
:class=" :class="isDisable ? 'disabled-bg-color' : 'info-bg-color'"
data.status == 'expired' || data.status == 'used' ? 'disabled-bg-color' : 'info-bg-color' >
" {{ data.discountType === 1 ? '满减券' : '折扣券' }}
>{{ data.type_text }}</view </view>
> --> <view class="title ss-m-x-30 ss-p-t-18">
<view class="title ss-m-x-30 ss-p-t-18"> <view class="ss-flex ss-row-between">
<view class="ss-flex ss-row-between"> <view
<view class="value-text ss-flex-1 ss-m-r-10" :class=" class="value-text ss-flex-1 ss-m-r-10"
data.status == 'expired' || data.status == 'used' ? 'disabled-color' : 'info-color' :class="isDisable ? 'disabled-color' : 'info-color'"
">{{ data.name }}</view> >
<view> {{ data.name }}
<view class="ss-flex ss-col-bottom" :class=" </view>
data.status != 'expired' && data.status != 'used' ? 'price-text' : 'disabled-color' <view>
"> <view
<view class="value-reduce ss-m-b-10" v-if="data.type === 'reduce'"></view> class="ss-flex ss-col-bottom"
<view class="value-price">{{ data.amount }}</view> :class="isDisable ? 'disabled-color' : 'price-text'"
<view class="value-discount ss-m-b-10 ss-m-l-4" v-if="data.type === 'discount'"></view> >
</view> <view class="value-reduce ss-m-b-10" v-if="data.discountType === 1"></view>
</view> <view class="value-price">
</view> {{
<view class="ss-flex ss-row-between ss-m-t-16"> data.discountType === 1
<view class="sellby-text" :class=" ? fen2yuan(data.discountPrice)
data.status == 'expired' || data.status == 'used' : data.discountPercent / 10.0
? 'disabled-color' }}
: 'subtitle-color' </view>
"> <view class="value-discount ss-m-b-10 ss-m-l-4" v-if="data.discountType === 2"
{{'有效期:' + data.use_start_time.substring(0, 11) }} ></view
{{ data.use_end_time.substring(0, 11) }} >
<!-- {{ </view>
type === 'user' </view>
? '有效期:' + data.use_start_time.substring(0, 11) </view>
: '领取时间:' + data.get_start_time.substring(0, 11) <view class="ss-flex ss-row-between ss-m-t-16">
}} <view
{{ class="sellby-text"
type === 'user' :class=" isDisable ? 'disabled-color' : 'subtitle-color'"
? data.use_end_time.substring(0, 11) v-if="data.validityType === 2"
: data.get_end_time.substring(0, 11) >
}} --> 有效期领取后 {{ data.fixedEndTerm }} 天内可用
</view> </view>
<view class="value-enough" :class=" <view
data.status == 'expired' || data.status == 'used' class="sellby-text"
? 'disabled-color' :class=" isDisable ? 'disabled-color' : 'subtitle-color'"
: 'subtitle-color' v-else
">{{ data.enough }}可用</view> >
</view> 有效期: {{ sheep.$helper.timeFormat(data.validStartTime, 'yyyy-mm-dd') }}
</view> {{ sheep.$helper.timeFormat(data.validEndTime, 'yyyy-mm-dd') }}
</view> </view>
<view
class="value-enough"
:class="isDisable ? 'disabled-color' : 'subtitle-color'"
>
{{ fen2yuan(data.usePrice) }} 可用
</view>
</view>
</view>
</view>
<view class="desc ss-flex ss-row-between"> <!-- TODO 芋艿可优化增加优惠劵的描述 -->
<view> <view class="desc ss-flex ss-row-between">
<view class="desc-title"> <view>
{{ data.description }} <view class="desc-title">{{ data.description }}</view>
</view> <view>
<view> <slot name="reason" />
<slot name="reason"> </view>
</slot> </view>
</view> <view>
</view> <slot />
<view> </view>
<slot></slot> </view>
</view> </view>
</view>
</view>
</template> </template>
<script setup> <script setup>
import { import { computed, reactive } from 'vue';
reactive import { fen2yuan } from '../../hooks/useGoods';
} from 'vue'; import sheep from '../../index';
import sheep from '@/sheep';
const state = reactive({ const state = reactive({
stateMap: { stateMap: {
0: '立即领取', 0: '立即领取',
1: '去使用', 1: '去使用',
}, },
}); });
//
const props = defineProps({ const isDisable = computed(() => {
data: { if (props.type === 'coupon') {
type: Object, return false;
default: {}, }
}, return props.data.status !== 1;
disabled: { });
type: Boolean,
default: false, //
}, const props = defineProps({
type: { data: {
type: String, type: Object,
default: 'coupon', default: {},
}, },
}); disabled: {
type: Boolean,
default: false,
},
type: {
type: String,
default: 'coupon', // coupon user
},
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.info-bg-color { .info-bg-color {
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient)); background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
} }
.disabled-bg-color { .disabled-bg-color {
background: #999; background: #999;
} }
.info-color { .info-color {
color: #333; color: #333;
} }
.subtitle-color { .subtitle-color {
color: #666; color: #666;
} }
.disabled-color { .disabled-color {
color: #999; color: #999;
} }
.content { .content {
width: 100%; width: 100%;
background: #fff; background: #fff;
border-radius: 20rpx 20rpx 0 0; border-radius: 20rpx 20rpx 0 0;
-webkit-mask: radial-gradient(circle at 12rpx 100%, #0000 12rpx, red 0) -12rpx; -webkit-mask: radial-gradient(circle at 12rpx 100%, #0000 12rpx, red 0) -12rpx;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.04); box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.04);
.tag { .tag {
width: 100rpx; width: 100rpx;
color: #fff; color: #fff;
height: 40rpx; height: 40rpx;
font-size: 24rpx; font-size: 24rpx;
border-radius: 20rpx 0 20rpx 0; border-radius: 20rpx 0 20rpx 0;
} }
.title { .title {
padding-bottom: 22rpx; padding-bottom: 22rpx;
border-bottom: 2rpx dashed #d3d3d3; border-bottom: 2rpx dashed #d3d3d3;
.value-text { .value-text {
font-size: 32rpx; font-size: 32rpx;
font-weight: 600; font-weight: 600;
} }
.sellby-text { .sellby-text {
font-size: 24rpx; font-size: 24rpx;
font-weight: 400; font-weight: 400;
} }
.value-price { .value-price {
font-size: 64rpx; font-size: 64rpx;
font-weight: 500; font-weight: 500;
line-height: normal; line-height: normal;
font-family: OPPOSANS; font-family: OPPOSANS;
} }
.value-reduce { .value-reduce {
line-height: normal; line-height: normal;
font-size: 32rpx; font-size: 32rpx;
} }
.value-discount { .value-discount {
line-height: normal; line-height: normal;
font-size: 28rpx; font-size: 28rpx;
} }
.value-enough { .value-enough {
font-size: 24rpx; font-size: 24rpx;
font-weight: 400; font-weight: 400;
font-family: OPPOSANS; font-family: OPPOSANS;
} }
} }
} }
.desc { .desc {
width: 100%; width: 100%;
background: #fff; background: #fff;
-webkit-mask: radial-gradient(circle at 12rpx 0%, #0000 12rpx, red 0) -12rpx; -webkit-mask: radial-gradient(circle at 12rpx 0%, #0000 12rpx, red 0) -12rpx;
box-shadow: rgba(#000, 0.1); box-shadow: rgba(#000, 0.1);
box-sizing: border-box; box-sizing: border-box;
padding: 24rpx 30rpx; padding: 24rpx 30rpx;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.04); box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.04);
border-radius: 0 0 20rpx 20rpx; border-radius: 0 0 20rpx 20rpx;
.desc-title { .desc-title {
font-size: 24rpx; font-size: 24rpx;
color: #999; color: #999;
font-weight: 400; font-weight: 400;
} }
} }
.price-text { .price-text {
color: #ff0000; color: #ff0000;
} }
</style> </style>