Browse Source

feat: 代金券列表、代金券核销页面;

pull/1/head
fox 2 months ago
parent
commit
5f679cacaa
10 changed files with 447 additions and 15 deletions
  1. +6
    -0
      pages.json
  2. +1
    -2
      pages/index/center.vue
  3. +111
    -0
      pages_order/components/voucher/storeCard.vue
  4. +94
    -0
      pages_order/components/voucher/voucherCard.vue
  5. +0
    -13
      pages_order/mine/coupon.vue
  6. +106
    -0
      pages_order/mine/verifyVoucher.vue
  7. +129
    -0
      pages_order/mine/voucher.vue
  8. BIN
      pages_order/static/voucher/icon-address.png
  9. BIN
      pages_order/static/voucher/icon-phone.png
  10. BIN
      pages_order/static/voucher/voucher-bg.png

+ 6
- 0
pages.json View File

@ -82,6 +82,12 @@
{ {
"path": "mine/coupon" "path": "mine/coupon"
}, },
{
"path": "mine/voucher"
},
{
"path": "mine/verifyVoucher"
},
{ {
"path": "mine/verifyRecord" "path": "mine/verifyRecord"
}, },


+ 1
- 2
pages/index/center.vue View File

@ -106,8 +106,7 @@
<image class="fun-common-icon" src="@/static/image/center/icon-coupon.png" mode="widthFix"></image> <image class="fun-common-icon" src="@/static/image/center/icon-coupon.png" mode="widthFix"></image>
<text class="fun-common-label">优惠券</text> <text class="fun-common-label">优惠券</text>
</view> </view>
<!-- todo: navigateTo -->
<view class="flex flex-column" @click="$utils.navigateTo('/pages_order/mine/coupon')">
<view class="flex flex-column" @click="$utils.navigateTo('/pages_order/mine/voucher')">
<image class="fun-common-icon" src="@/static/image/center/icon-voucher.png" mode="widthFix"></image> <image class="fun-common-icon" src="@/static/image/center/icon-voucher.png" mode="widthFix"></image>
<text class="fun-common-label">代金券</text> <text class="fun-common-label">代金券</text>
</view> </view>


+ 111
- 0
pages_order/components/voucher/storeCard.vue View File

@ -0,0 +1,111 @@
<template>
<view class="card flex store">
<image class="store-img" :src="data.imgUrl"></image>
<view class="store-info">
<view class="store-name">{{ data.name }}</view>
<view class="store-desc">{{ `地址:${data.address}` }}</view>
<view class="store-desc">{{ `联系方式:${data.phone}` }}</view>
<view class="store-contact">
<button plain class="flex btn" @click="onCall(data.phone)">
<image class="btn-icon" src="../../static/voucher/icon-phone.png" mode="widthFix"></image>
<text>电话</text>
</button>
<button plain class="flex btn" @click="openLocation(data.latitude, data.longitude)">
<image class="btn-icon" src="../../static/voucher/icon-address.png" mode="widthFix"></image>
<text>导航</text>
</button>
</view>
</view>
</view>
</template>
<script>
const TEST_DATA = {
id: '001',
imgUrl: 'http://gips3.baidu.com/it/u=70459541,3412285454&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280',
name: '推拿馆',
address: '湖南省长沙市岳麓区麓云路268号',
latitude: 0,
longitude: 0,
phone: '13425992900'
}
export default {
props: {
data: {
type: Object,
default() {
return TEST_DATA
}
},
},
methods: {
onCall(phoneNumber) {
uni.makePhoneCall({
phoneNumber,
success() {
console.log('安卓拨打成功');
},
fail() {
console.log('安卓拨打失败');
}
})
},
},
}
</script>
<style lang="scss" scoped>
.store {
padding: 22rpx 38rpx 30rpx 30rpx;
&-img {
width: 155rpx;
height: 155rpx;
margin-right: 23rpx;
}
&-info {
flex: 1;
}
&-name {
color: #3B3B3B;
font-size: 28rpx;
font-weight: 700;
}
&-desc {
color: #999999;
font-size: 22rpx;
margin-top: 13rpx;
}
&-contact {
margin-top: 3rpx;
text-align: right;
}
}
.btn {
display: inline-flex;
border: none;
color: $uni-color-light;
font-size: 22rpx;
line-height: 30rpx;
& + & {
margin-left: 44rpx;
}
&-icon {
width: 23rpx;
height: 23rpx;
margin-right: 6rpx;
}
}
</style>

+ 94
- 0
pages_order/components/voucher/voucherCard.vue View File

@ -0,0 +1,94 @@
<template>
<view class="voucher">
<image class="voucher-bg" src="@/pages_order/static/voucher/voucher-bg.png" ></image>
<view class="voucher-info">
<view class="voucher-row voucher-title">{{ data.name }}</view>
<view class="voucher-row voucher-time">{{ `${data.startTime}-${data.endTime}` }}</view>
<view class="voucher-row voucher-desc">{{ data.desc }}</view>
</view>
<template v-if="!readonly">
<button palin class="btn" @click="onClick">立即使用</button>
</template>
</view>
</template>
<script>
const TEST_DATA = {
id: '001',
name: '【会员礼】50元代金券',
startTime: '2025.03.12',
endTime: '2025.09.12',
desc: '只可在线下门店使用',
}
export default {
props: {
data: {
type: Object,
default() {
return TEST_DATA
}
},
readonly: {
type: Boolean,
default: false,
}
},
methods: {
onClick() {
this.$utils.navigateTo(`/pages_order/mine/verifyVoucher?id=${this.data.id}`)
}
},
}
</script>
<style lang="scss" scoped>
.voucher {
width: 100%;
height: 202rpx;
position: relative;
&-bg {
width: 100%;
height: 100%;
}
&-info {
position: absolute;
top: 49rpx;
left: 253rpx;
color: $uni-color-light;
font-size: 18rpx;
}
&-row {
& + & {
margin-top: 6rpx;
}
}
&-title {
font-size: 28rpx;
font-weight: 900;
}
.btn {
position: absolute;
bottom: 39rpx;
right: 39rpx;
width: auto;
padding: 12rpx 29rpx;
color: $uni-text-color-inverse;
font-size: 18rpx;
line-height: 25rpx;
border-radius: 25rpx;
border: none;
background-image: linear-gradient(to right, #84A73F, #D8FF8F);
}
}
</style>

+ 0
- 13
pages_order/mine/coupon.vue View File

@ -131,7 +131,6 @@
background-image: linear-gradient(#84A73F, #D8FF8F); background-image: linear-gradient(#84A73F, #D8FF8F);
} }
} }
.tabs { .tabs {
/deep/ .uv-tabs__wrapper__nav__line { /deep/ .uv-tabs__wrapper__nav__line {
@ -139,16 +138,4 @@
} }
} }
// //
// .tabs {
// &::v-deep .uv-tabs__wrapper__nav {
// background: white;
// .uv-tabs__wrapper__nav__item {
// width: 33.33%;
// text-align: center;
// box-sizing: border-box;
// }
// }
// }
</style> </style>

+ 106
- 0
pages_order/mine/verifyVoucher.vue View File

@ -0,0 +1,106 @@
<template>
<view class="page">
<navbar title="代金券" leftClick @leftClick="$utils.navigateBack" color="#fff" />
<view class="page-content">
<!-- 代金券详情 -->
<view class="coupon">
<voucherCard :data="voucherDetail" :readonly="true"></voucherCard>
</view>
<view class="card info">
<view class="info-header">代金券核销</view>
<view class="flex flex-column info-content">
<image class="info-qr" :src="voucherDetail.qrCodeImgUrl" mode="widthFix"></image>
<view class="info-desc">{{ `有效时间:${voucherDetail.startTime}${voucherDetail.endTime}` }}</view>
</view>
</view>
</view>
</view>
</template>
<script>
import voucherCard from '../components/voucher/voucherCard.vue'
export default {
components: {
voucherCard,
},
data() {
return {
// todo: fetch
voucherDetail: {
id: '001',
name: '【会员礼】50元代金券',
startTime: '2025.03.12',
endTime: '2025.09.12',
desc: '只可在线下门店使用',
orderNo: 'da123567',
qrCodeImgUrl: '../static/verifyOrder/temp-qrcode.png',
startTime: '2025-03-14',
endTime: '2025-04-14',
rights: ['过期退', '随时退']
},
}
},
onLoad(option) {
const { id } = option
// todo: fetch voucher data by voucher id
},
methods: {
},
}
</script>
<style scoped lang="scss">
$bar-height: 132rpx;
.page {
background-color: #F5F5F5;
/deep/ .nav-bar__view {
background-image: linear-gradient(#84A73F, #D8FF8F);
}
&-header {
color: #000000;
font-size: 28rpx;
margin-top: 24rpx;
}
&-content {
padding: 33rpx 13rpx;
}
}
.coupon {
padding: 0 13rpx;
}
.info {
margin-top: 26rpx;
padding: 25rpx 41rpx 108rpx 41rpx;
&-header {
color: #000000;
padding: 0 0 16rpx 7rpx;
border-bottom: 1rpx dashed #C7C7C7;
}
&-qr {
width: 279rpx;
height: auto;
margin-top: 57rpx;
}
&-desc {
color: #999999;
font-size: 22rpx;
margin-top: 45rpx;
}
}
</style>

+ 129
- 0
pages_order/mine/voucher.vue View File

@ -0,0 +1,129 @@
<template>
<view class="page">
<navbar title="代金券" leftClick @leftClick="$utils.navigateBack" color="#fff" />
<view class="tabs">
<uv-tabs
:list="tabs"
@click="onTabChange"
:customStyle="{
backgroundColor: '#FFFFFF',
}"
:activeStyle="{
color: '#84A73F',
fontSize: '28rpx',
whiteSpace: 'nowrap',
paddingTop: '29rpx',
paddingBottom: '21rpx',
}"
:inactiveStyle="{
color: '#000000',
fontSize: '28rpx',
whiteSpace: 'nowrap',
paddingTop: '29rpx',
paddingBottom: '21rpx',
}"
lineHeight="5rpx"
lineWidth="92rpx"
lineColor="linear-gradient(to right, #84A73F, #D8FF8F)"
:scrollable="false"
></uv-tabs>
</view>
<template v-if="current == 0" >
<view class="list voucher">
<voucherCard class="list-item"
v-for="item in list"
:key="item.id"
:data="data"
></voucherCard>
</view>
</template>
<template v-else-if="current == 1" >
<view class="list store">
<storeCard class="list-item"
v-for="item in list"
:key="item.id"
:data="data"
></storeCard>
</view>
</template>
</view>
</template>
<script>
import mixinsList from '@/mixins/list.js'
import voucherCard from '../components/voucher/voucherCard.vue'
import storeCard from '../components/voucher/storeCard.vue'
const TAB_AND_API_FIELDS_MAPPING = {
// todo:
0: 'fetchVoucher',
1: 'fetchStore',
}
export default {
mixins : [mixinsList],
components: {
voucherCard,
storeCard,
},
data() {
return {
tabs: [{
name: "代金券"
}, {
name: "可使用门店"
}],
current: 0
};
},
computed: {
mixinsListApi() {
// todo
return TAB_AND_API_FIELDS_MAPPING[this.current]
}
},
methods: {
onTabChange(e) {
this.current = e.index
}
},
}
</script>
<style scoped lang="scss">
.page {
background-color: $uni-bg-color;
min-height: 100vh;
/deep/ .nav-bar__view {
background-image: linear-gradient(#84A73F, #D8FF8F);
}
}
.tabs {
/deep/ .uv-tabs__wrapper__nav__line {
bottom: 0;
}
}
.list {
&-item {
& + & {
margin-top: 20rpx;
}
}
&.voucher {
padding: 30rpx 28rpx;
}
&.store {
padding: 29rpx 13rpx;
}
}
</style>

BIN
pages_order/static/voucher/icon-address.png View File

Before After
Width: 19  |  Height: 25  |  Size: 725 B

BIN
pages_order/static/voucher/icon-phone.png View File

Before After
Width: 24  |  Height: 23  |  Size: 1.1 KiB

BIN
pages_order/static/voucher/voucher-bg.png View File

Before After
Width: 698  |  Height: 202  |  Size: 19 KiB

Loading…
Cancel
Save