@ -0,0 +1,192 @@ | |||
<template> | |||
<view class="coupon-item" :class="{ 'used': coupon.status === 1, 'expired': coupon.status === 2 }"> | |||
<!-- 左侧金额 --> | |||
<view class="coupon-left"> | |||
<view class="coupon-amount"> | |||
<text class="currency">¥</text> | |||
<text class="number">{{ coupon.amount }}</text> | |||
</view> | |||
</view> | |||
<!-- 中间信息 --> | |||
<view class="coupon-middle"> | |||
<view class="coupon-type">{{ coupon.title }}</view> | |||
<view class="coupon-validity">{{ coupon.validTime }} 前有效</view> | |||
</view> | |||
<!-- 右侧使用按钮 --> | |||
<view class="coupon-right"> | |||
<view class="use-btn" @click="useCoupon" v-if="coupon.status === 0"> | |||
<text>立即</text> | |||
<text>使用</text> | |||
</view> | |||
<view class="use-btn" v-if="coupon.status ===1"> | |||
<text>已使用</text> | |||
</view> | |||
<view class="use-btn" v-if="coupon.status === 2"> | |||
<text>已过期</text> | |||
</view> | |||
</view> | |||
<!-- 装饰元素 --> | |||
<view class="coupon-left-dot"></view> | |||
<view class="coupon-right-dot"></view> | |||
<!-- Logo --> | |||
<!-- <image src="/static/image/logo.png" class="logo-image"></image> --> | |||
</view> | |||
</template> | |||
<script> | |||
export default { | |||
name: 'CouponItem', | |||
props: { | |||
coupon: { | |||
type: Object, | |||
default: () => ({ | |||
id: '', | |||
amount: 0, | |||
title: '新人专享优惠券', | |||
validTime: '2025/4/12 23:59', | |||
status: 0 // 0-未使用 1-已使用 2-已过期 | |||
}) | |||
} | |||
}, | |||
methods: { | |||
useCoupon() { | |||
this.$emit('use', this.coupon) | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.coupon-item { | |||
position: relative; | |||
width: 100%; | |||
height: 160rpx; | |||
background-color: #fff; | |||
display: flex; | |||
border-radius: 16rpx; | |||
margin-bottom: 30rpx; | |||
overflow: hidden; | |||
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.05); | |||
&::before { | |||
content: ''; | |||
position: absolute; | |||
left: 0; | |||
top: 0; | |||
width: 20rpx; | |||
height: 100%; | |||
background-color: $uni-color; | |||
border-radius: 16rpx 0 0 16rpx; | |||
} | |||
&.used, | |||
&.expired { | |||
opacity: 0.6; | |||
} | |||
.coupon-left { | |||
width: 200rpx; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
background-color: #f9f9f9; | |||
position: relative; | |||
.coupon-amount { | |||
display: flex; | |||
align-items: baseline; | |||
color: $uni-color; | |||
.currency { | |||
font-size: 36rpx; | |||
font-weight: bold; | |||
} | |||
.number { | |||
font-size: 80rpx; | |||
font-weight: bold; | |||
line-height: 1; | |||
} | |||
} | |||
} | |||
.coupon-middle { | |||
flex: 1; | |||
padding: 20rpx 20rpx 20rpx 30rpx; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: center; | |||
.coupon-type { | |||
font-size: 28rpx; | |||
color: #333; | |||
margin-bottom: 16rpx; | |||
font-weight: bold; | |||
} | |||
.coupon-validity { | |||
font-size: 24rpx; | |||
color: #999; | |||
} | |||
} | |||
.coupon-right { | |||
width: 120rpx; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
.use-btn { | |||
width: 80rpx; | |||
height: 80rpx; | |||
background-color: $uni-color; | |||
border-radius: 50%; | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
justify-content: center; | |||
color: #fff; | |||
font-size: 24rpx; | |||
font-weight: bold; | |||
} | |||
.status-image { | |||
width: 80rpx; | |||
height: 80rpx; | |||
} | |||
} | |||
.coupon-left-dot, | |||
.coupon-right-dot { | |||
position: absolute; | |||
width: 30rpx; | |||
height: 30rpx; | |||
background-color: #f5f5f5; | |||
border-radius: 50%; | |||
z-index: 1; | |||
} | |||
.coupon-left-dot { | |||
left: 185rpx; | |||
top: -15rpx; | |||
} | |||
.coupon-right-dot { | |||
left: 185rpx; | |||
bottom: -15rpx; | |||
} | |||
.logo-image { | |||
position: absolute; | |||
width: 60rpx; | |||
height: 60rpx; | |||
right: 30rpx; | |||
top: 10rpx; | |||
opacity: 0.2; | |||
} | |||
} | |||
</style> |
@ -1,114 +1,119 @@ | |||
<template> | |||
<view class="coupon"> | |||
<view class="page"> | |||
<!-- 导航栏 --> | |||
<navbar title="优惠券" leftClick @leftClick="$utils.navigateBack" bgColor="#E3441A" color="#fff" /> | |||
<navbar title="优惠券" leftClick @leftClick="$utils.navigateBack" bgColor="#019245" color="#fff" /> | |||
<!-- 优惠券筛选 --> | |||
<view class="tabs"> | |||
<uv-tabs :list="filtrationMenu" @click="hadleFiltrationMenuEvent" lineColor="#E3441A" | |||
:activeStyle="{ color : '#E3441A' }"></uv-tabs> | |||
</view> | |||
<!-- 标签页 --> | |||
<uv-sticky bgColor="#fff"> | |||
<uv-tabs :list="tabs" @change="changeTab" :scrollable="false" lineColor="#019245" | |||
:activeStyle="{color: '#019245' }" lineWidth="80" lineHeight="6" :inactiveStyle="{color: '#333'}" | |||
:itemStyle="{height: '90rpx'}" /> | |||
</uv-sticky> | |||
<couponList ref="couponList" :list="list" :state="state"></couponList> | |||
</view> | |||
</template> | |||
<script> | |||
import couponList from "@/components/couponList/couponList.vue" | |||
<!-- 优惠券列表 --> | |||
<view class="coupon-list"> | |||
<template v-if="currentTab === 0"> | |||
<coupon-item v-for="coupon in unusedCoupons" :key="coupon.id" :coupon="coupon" @use="useCoupon" /> | |||
<uv-empty v-if="unusedCoupons.length == 0" text="暂无优惠卷" textSize="30rpx" iconSize="200rpx" | |||
style="padding-top: 100rpx;" icon="list" /> | |||
export default { | |||
name: "coupon", | |||
components: { | |||
couponList | |||
}, | |||
props: { | |||
height: { | |||
default: 'auto' | |||
// default : 'calc(90vh - 180rpx)' | |||
}, | |||
// 押金 | |||
depositPrice: {}, | |||
washPrice: { //水洗费 | |||
}, | |||
rentPrice: { //租金 | |||
}, | |||
}, | |||
onShow() { | |||
this.getCouponList() | |||
}, | |||
data() { | |||
return { | |||
filtrationMenu: [{ | |||
name: "全部优惠券" | |||
}, { | |||
name: "已使用优惠券" | |||
}, { | |||
name: "已过期优惠券" | |||
}], | |||
state: 0 | |||
}; | |||
}, | |||
methods: { | |||
//获取优惠券数据 | |||
getCouponList() { | |||
this.$refs.couponList.getCouponList() | |||
}, | |||
</template> | |||
select(item) { | |||
if (this.isSelect(item)) { | |||
return | |||
} | |||
this.$emit('select', item) | |||
}, | |||
isSelect(item) { | |||
<template v-if="currentTab === 1"> | |||
<coupon-item v-for="coupon in usedCoupons" :key="coupon.id" :coupon="coupon" /> | |||
<uv-empty v-if="usedCoupons.length == 0" text="暂无优惠卷" textSize="30rpx" iconSize="200rpx" | |||
style="padding-top: 100rpx;" icon="list" /> | |||
</template> | |||
if (!this.depositPrice && !this.rentPrice && !this.washPrice) { | |||
return false | |||
} | |||
<template v-if="currentTab === 2"> | |||
<coupon-item v-for="coupon in expiredCoupons" :key="coupon.id" :coupon="coupon" /> | |||
<uv-empty v-if="expiredCoupons.length == 0" text="暂无优惠卷" textSize="30rpx" iconSize="200rpx" | |||
style="padding-top: 100rpx;" icon="list" /> | |||
</template> | |||
</view> | |||
</view> | |||
</template> | |||
// 押金 | |||
if (this.depositPrice && | |||
item.useType == 0 && | |||
this.depositPrice >= item.conditionPrice) { | |||
return false | |||
} | |||
<script> | |||
import navbar from '@/components/base/navbar.vue' | |||
import CouponItem from '@/components/coupon/CouponItem.vue' | |||
import { unusedCoupons, usedCoupons, expiredCoupons } from '@/static/js/mockCoupon.js' | |||
// 租金 | |||
if (this.rentPrice && | |||
item.useType == 1 && | |||
this.rentPrice >= item.conditionPrice) { | |||
return false | |||
} | |||
export default { | |||
components: { | |||
navbar, | |||
CouponItem | |||
}, | |||
data() { | |||
return { | |||
tabs: [ | |||
{ name: '未使用' }, | |||
{ name: '已使用' }, | |||
{ name: '已过期' } | |||
], | |||
currentTab: 0, | |||
unusedCoupons: [], | |||
usedCoupons: [], | |||
expiredCoupons: [] | |||
} | |||
}, | |||
onLoad() { | |||
// 从mock数据获取优惠券列表 | |||
this.unusedCoupons = unusedCoupons | |||
this.usedCoupons = usedCoupons | |||
// 暂时 没有已过期的优惠卷 | |||
// this.expiredCoupons = expiredCoupons | |||
}, | |||
methods: { | |||
// 切换标签页 | |||
changeTab(item) { | |||
this.currentTab = item.index | |||
}, | |||
// 水洗 | |||
if (this.washPrice && | |||
item.useType == 2 && | |||
this.washPrice >= item.conditionPrice) { | |||
return false | |||
// 使用优惠券 | |||
useCoupon(coupon) { | |||
uni.showModal({ | |||
title: '提示', | |||
content: `确定使用面值${coupon.amount}元的优惠券吗?`, | |||
success: (res) => { | |||
// 模拟使用优惠券 | |||
uni.showLoading({ | |||
title: '使用中...' | |||
}) | |||
setTimeout(() => { | |||
uni.hideLoading() | |||
uni.showToast({ | |||
title: '使用成功', | |||
icon: 'success' | |||
}) | |||
setTimeout(() => { | |||
if (res.confirm) { | |||
this.$utils.navigateTo('/pages/order/index') | |||
} | |||
}, 1000) | |||
}, 1000) | |||
} | |||
return true | |||
}, | |||
//点击过滤菜单 | |||
hadleFiltrationMenuEvent(event) { | |||
this.state = event.index | |||
} | |||
}) | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
// 优惠券筛选 | |||
.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 lang="scss" scoped> | |||
.page { | |||
.tabs-container { | |||
.coupon-list { | |||
padding: 30rpx; | |||
} | |||
.empty-tip { | |||
text-align: center; | |||
color: $uni-color-third; | |||
padding: 100rpx 0; | |||
font-size: 28rpx; | |||
} | |||
} | |||
} | |||
</style> |
@ -0,0 +1 @@ | |||
@ -0,0 +1,114 @@ | |||
<template> | |||
<view class="coupon"> | |||
<!-- 导航栏 --> | |||
<navbar title="优惠券" leftClick @leftClick="$utils.navigateBack" bgColor="#E3441A" color="#fff" /> | |||
<!-- 优惠券筛选 --> | |||
<view class="tabs"> | |||
<uv-tabs :list="filtrationMenu" @click="hadleFiltrationMenuEvent" lineColor="#E3441A" | |||
:activeStyle="{ color: '#E3441A' }"></uv-tabs> | |||
</view> | |||
<couponList ref="couponList" :list="list" :state="state"></couponList> | |||
</view> | |||
</template> | |||
<script> | |||
import couponList from "@/components/couponList/couponList.vue" | |||
export default { | |||
name: "coupon", | |||
components: { | |||
couponList | |||
}, | |||
props: { | |||
height: { | |||
default: 'auto' | |||
// default : 'calc(90vh - 180rpx)' | |||
}, | |||
// 押金 | |||
depositPrice: {}, | |||
washPrice: { //水洗费 | |||
}, | |||
rentPrice: { //租金 | |||
}, | |||
}, | |||
onShow() { | |||
this.getCouponList() | |||
}, | |||
data() { | |||
return { | |||
filtrationMenu: [{ | |||
name: "全部优惠券" | |||
}, { | |||
name: "已使用优惠券" | |||
}, { | |||
name: "已过期优惠券" | |||
}], | |||
state: 0 | |||
}; | |||
}, | |||
methods: { | |||
//获取优惠券数据 | |||
getCouponList() { | |||
this.$refs.couponList.getCouponList() | |||
}, | |||
select(item) { | |||
if (this.isSelect(item)) { | |||
return | |||
} | |||
this.$emit('select', item) | |||
}, | |||
isSelect(item) { | |||
if (!this.depositPrice && !this.rentPrice && !this.washPrice) { | |||
return false | |||
} | |||
// 押金 | |||
if (this.depositPrice && | |||
item.useType == 0 && | |||
this.depositPrice >= item.conditionPrice) { | |||
return false | |||
} | |||
// 租金 | |||
if (this.rentPrice && | |||
item.useType == 1 && | |||
this.rentPrice >= item.conditionPrice) { | |||
return false | |||
} | |||
// 水洗 | |||
if (this.washPrice && | |||
item.useType == 2 && | |||
this.washPrice >= item.conditionPrice) { | |||
return false | |||
} | |||
return true | |||
}, | |||
//点击过滤菜单 | |||
hadleFiltrationMenuEvent(event) { | |||
this.state = event.index | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
// 优惠券筛选 | |||
.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> |
@ -0,0 +1,269 @@ | |||
<template> | |||
<!-- 导航栏 --> | |||
<view class="share-page"> | |||
<navbar title="推广链接" leftClick @leftClick="$utils.navigateBack" bgColor="#019245" color="#fff" /> | |||
<!-- 名片展示区域 --> | |||
<view class="card-container"> | |||
<!-- 用户头像 - 放在卡片容器外,使其一半在卡片之上 --> | |||
<view class="avatar-container"> | |||
<image :src="shareData.userInfo.avatar" class="avatar" mode="aspectFill" /> | |||
</view> | |||
<view class="share-card"> | |||
<!-- 用户信息 --> | |||
<view class="user-info"> | |||
<view class="nickname">{{ shareData.userInfo.nickname }} {{ shareData.userInfo.role }}</view> | |||
</view> | |||
<!-- 小程序码 --> | |||
<view class="qrcode-container"> | |||
<image :src="shareData.qrCodeImage" class="qrcode-image" mode="aspectFit" /> | |||
</view> | |||
<!-- 邀请码 --> | |||
<view class="invite-code"> | |||
邀请码:{{ shareData.inviteCode }} | |||
</view> | |||
</view> | |||
</view> | |||
<!-- 底部按钮区域 --> | |||
<view class="action-buttons"> | |||
<button class="action-btn share-btn" @click="shareToFriend"> | |||
分享给好友 | |||
</button> | |||
<button class="action-btn save-btn" @click="saveToLocal"> | |||
保存到本地 | |||
</button> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
import navbar from '@/components/base/navbar.vue' | |||
import { shareData } from '@/static/js/mockShare.js' | |||
export default { | |||
components: { | |||
navbar | |||
}, | |||
data() { | |||
return { | |||
shareData: null | |||
} | |||
}, | |||
onLoad() { | |||
this.shareData = shareData | |||
}, | |||
methods: { | |||
// 分享给好友 - 微信小程序特有功能 | |||
shareToFriend() { | |||
// 触发按钮形式的分享,提示用户使用右上角的分享 | |||
uni.showModal({ | |||
title: '分享提示', | |||
content: '点击右上角"..."按钮,选择"转发"即可分享给好友', | |||
confirmText: '我知道了', | |||
confirmColor: '#019245', | |||
showCancel: false | |||
}) | |||
}, | |||
// 保存到本地 | |||
saveToLocal() { | |||
// 微信小程序保存图片需要用户授权 | |||
uni.getSetting({ | |||
success: (res) => { | |||
if (!res.authSetting['scope.writePhotosAlbum']) { | |||
uni.authorize({ | |||
scope: 'scope.writePhotosAlbum', // 判断的是相册权限 | |||
success: () => { | |||
this.saveImage() | |||
}, | |||
fail: () => { | |||
// 授权失败 | |||
uni.showModal({ | |||
title: '提示', | |||
content: '需要您授权保存图片', | |||
confirmText: '去设置', | |||
confirmColor: '#019245', | |||
success: (res) => { | |||
if (res.confirm) { | |||
uni.openSetting() | |||
} | |||
}, | |||
fail: () => { | |||
uni.showToast({ | |||
title: '授权失败', | |||
icon: 'none' | |||
}) | |||
} | |||
}) | |||
} | |||
}) | |||
} else { | |||
this.saveImage() | |||
} | |||
} | |||
}) | |||
}, | |||
// 保存图片的具体实现 | |||
saveImage() { | |||
uni.showLoading({ | |||
title: '保存中...' | |||
}) | |||
// 直接保存小程序码图片 | |||
uni.getImageInfo({ | |||
// 获取图片信息 | |||
src: this.shareData.qrCodeImage, // 图片的本地路径 | |||
success: (res) => { | |||
uni.saveImageToPhotosAlbum({ | |||
// 保存图片到系统相册 | |||
filePath: res.path, // 返回的图片 | |||
success: () => { | |||
uni.hideLoading() | |||
uni.showToast({ | |||
title: '已保存到相册', | |||
icon: 'success' | |||
}) | |||
}, | |||
fail: () => { | |||
uni.hideLoading() | |||
uni.showToast({ | |||
title: '保存失败', | |||
icon: 'error' | |||
}) | |||
} | |||
}) | |||
}, | |||
fail: () => { | |||
uni.hideLoading() | |||
uni.showToast({ | |||
title: '图片获取失败', | |||
icon: 'exception' | |||
}) | |||
} | |||
}) | |||
} | |||
}, | |||
// 微信小程序的分享功能 | |||
onShareAppMessage() { | |||
return { | |||
title: `邀请您使用敢为人鲜小程序,邀请码: ${this.shareData.inviteCode}`, | |||
path: `/pages/index/index?inviteCode=${this.shareData.inviteCode}`, | |||
imageUrl: this.shareData.qrCodeImage, | |||
success: () => { | |||
uni.showToast({ | |||
title: '分享成功', | |||
icon: 'success' | |||
}) | |||
}, | |||
fail: () => { | |||
uni.showToast({ | |||
title: '分享失败', | |||
icon: 'fail' | |||
}) | |||
} | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.share-page { | |||
min-height: 100vh; | |||
background-color: $uni-color; | |||
display: flex; | |||
flex-direction: column; | |||
// padding-top: 30rpx; | |||
} | |||
.card-container { | |||
position: relative; | |||
display: flex; | |||
justify-content: center; | |||
margin: auto; | |||
// margin-bottom: 30rpx; | |||
width: 96%; | |||
padding-top: 80rpx; | |||
/* 为头像腾出空间 */ | |||
} | |||
.avatar-container { | |||
position: absolute; | |||
top: 0; | |||
left: 50%; | |||
transform: translateX(-50%); | |||
z-index: 10; | |||
.avatar { | |||
width: 140rpx; | |||
height: 140rpx; | |||
border-radius: 50%; | |||
// border: 4rpx solid #fff; | |||
} | |||
} | |||
.share-card { | |||
width: 100%; | |||
/* 卡片占屏幕宽度的80% */ | |||
background-color: #fff; | |||
border-radius: 16rpx; | |||
padding: 80rpx 20rpx 40rpx; | |||
/* 顶部padding增加,给头像留空间 */ | |||
text-align: center; | |||
} | |||
.user-info { | |||
margin-bottom: 20rpx; | |||
.nickname { | |||
font-size: 26rpx; | |||
font-weight: bold; | |||
color: #333; | |||
} | |||
} | |||
.qrcode-container { | |||
width: 100%; | |||
display: flex; | |||
justify-content: center; | |||
margin: 20rpx 0; | |||
.qrcode-image { | |||
width: 440rpx; | |||
/* 稍微缩小二维码图片 */ | |||
height: 440rpx; | |||
} | |||
} | |||
.invite-code { | |||
font-size: 26rpx; | |||
color: #333; | |||
margin: 20rpx 0; | |||
font-weight: 500; | |||
} | |||
.action-buttons { | |||
width: 100%; | |||
padding: 0 30rpx; | |||
display: flex; | |||
justify-content: space-between; | |||
margin-top: auto; | |||
margin-bottom: 60rpx; | |||
box-sizing: border-box; | |||
.action-btn { | |||
width: 45%; | |||
height: 110rpx; | |||
line-height: 110rpx; | |||
background-color: #fff; | |||
color: $uni-color; | |||
font-size: 32rpx; | |||
border-radius: 15rpx; | |||
border: none; | |||
} | |||
} | |||
</style> |
@ -0,0 +1,238 @@ | |||
<template> | |||
<view class="page"> | |||
<!-- 导航栏 --> | |||
<navbar title="解绑团长" leftClick @leftClick="$utils.navigateBack" bgColor="#019245" color="#fff" /> | |||
<!-- 当前取餐点 --> | |||
<view class="section"> | |||
<view class="section-title">当前取餐点</view> | |||
<view class="pickup-item" v-if="currentPickupPoint"> | |||
<view class="pickup-image"> | |||
<image :src="currentPickupPoint.image" mode="aspectFill"></image> | |||
</view> | |||
<view class="pickup-info"> | |||
<view class="pickup-name">{{ currentPickupPoint.name }}</view> | |||
<view class="pickup-address"> | |||
<view class="pickup-address-icon"> | |||
<uv-icon name="map-fill" color="#019245" size="24"></uv-icon> | |||
</view> | |||
<text>{{ currentPickupPoint.address }}</text> | |||
</view> | |||
<view class="pickup-phone"> | |||
<uv-icon name="phone-fill" color="#019245" size="24"></uv-icon> | |||
<text>{{ currentPickupPoint.phone }}</text> | |||
</view> | |||
</view> | |||
<view class="status-icon"> | |||
<uv-icon name="checkmark-circle-fill" color="#019245" size="40"></uv-icon> | |||
</view> | |||
</view> | |||
</view> | |||
<!-- 附近取餐点 --> | |||
<view class="section"> | |||
<view class="section-title">附近取餐点</view> | |||
<!-- 提示信息 --> | |||
<view class="warning-tip"> | |||
<uv-icon name="info-circle" color="#FF5722" size="36"></uv-icon> | |||
<text>更换取餐地址和团长,需通过平台审核方可更换!</text> | |||
</view> | |||
<!-- 取餐点列表 --> | |||
<view class="pickup-list"> | |||
<view class="pickup-item" v-for="(item, index) in nearbyPickupPoints" :key="index"> | |||
<view class="pickup-image"> | |||
<image :src="item.image" mode="aspectFill"></image> | |||
</view> | |||
<view class="pickup-info"> | |||
<view class="pickup-name">{{ item.name }}</view> | |||
<view class="pickup-address"> | |||
<view class="pickup-address-icon"> | |||
<uv-icon name="map-fill" color="#019245" size="24"></uv-icon> | |||
</view> | |||
<text>{{ item.address }}</text> | |||
</view> | |||
<view class="pickup-phone"> | |||
<uv-icon name="phone-fill" color="#019245" size="24"></uv-icon> | |||
<text>{{ item.phone }}</text> | |||
</view> | |||
</view> | |||
<view class="select-btn" @click="selectPickupPoint(item)"> | |||
<text>选择</text> | |||
</view> | |||
</view> | |||
</view> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
import navbar from '@/components/base/navbar.vue' | |||
import { currentPickupPoint, nearbyPickupPoints } from '@/static/js/mockTeam.js' | |||
export default { | |||
components: { | |||
navbar | |||
}, | |||
data() { | |||
return { | |||
// 当前取餐点 | |||
currentPickupPoint:{}, | |||
// 附近取餐点列表 | |||
nearbyPickupPoints:[] | |||
} | |||
}, | |||
methods: { | |||
// 选择取餐点 | |||
selectPickupPoint(point) { | |||
uni.showModal({ | |||
title: '确认选择', | |||
content: '您确定要选择该取餐点吗?需要平台审核通过后才能更换。', | |||
confirmColor: '#019245', | |||
success: (res) => { | |||
if (res.confirm) { | |||
uni.showLoading({ | |||
title: '提交中...' | |||
}) | |||
setTimeout(() => { | |||
uni.hideLoading() | |||
uni.showToast({ | |||
title: '申请已提交,等待平台审核', | |||
icon: 'none', | |||
}) | |||
setTimeout(() => { | |||
this.$utils.navigateBack() | |||
}, 1400) | |||
}, 1000) | |||
// 返回上一页 | |||
} | |||
} | |||
}) | |||
} | |||
}, | |||
onLoad() { | |||
this.currentPickupPoint = currentPickupPoint | |||
this.nearbyPickupPoints = nearbyPickupPoints | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.page { | |||
// background-color: #f5f5f5; | |||
// min-height: 100vh; | |||
} | |||
.section { | |||
width: 96%; | |||
margin: 0 auto; | |||
margin-bottom: 20rpx; | |||
// border-radius: 10rpx; | |||
&-title { | |||
font-size: 32rpx; | |||
font-weight: bold; | |||
color: #333; | |||
padding: 30rpx 30rpx 20rpx; | |||
} | |||
} | |||
.pickup { | |||
&-item { | |||
background-color: #fff; | |||
padding: 20rpx 20rpx; | |||
display: flex; | |||
position: relative; | |||
margin-bottom: 2rpx; | |||
border-radius: 20rpx; | |||
} | |||
&-image { | |||
width: 170rpx; | |||
height: 170rpx; | |||
margin: auto 20rpx auto 0; | |||
overflow: hidden; | |||
image { | |||
width: 100%; | |||
height: 100%; | |||
} | |||
} | |||
&-info { | |||
flex: 1; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-between; | |||
} | |||
&-name { | |||
font-size: 30rpx; | |||
font-weight: bold; | |||
color: #3B3B3B; | |||
margin-bottom: 10rpx; | |||
} | |||
&-address, &-phone { | |||
font-size: 26rpx; | |||
color: $uni-color-third; | |||
display: flex; | |||
align-items: center; | |||
margin-bottom: 8rpx; | |||
width: 85%; | |||
text { | |||
margin-left: 8rpx; | |||
} | |||
&-icon { | |||
height: 100%; | |||
padding-top: 20rpx; | |||
} | |||
} | |||
} | |||
.status-icon { | |||
position: absolute; | |||
right: 30rpx; | |||
top: 50%; | |||
transform: translateY(-50%); | |||
} | |||
.select-btn { | |||
background-color: $uni-color; | |||
color: #fff; | |||
width: 100rpx; | |||
height: 60rpx; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
border-radius: 10rpx; | |||
align-self: center; | |||
font-size: 24rpx; | |||
} | |||
.warning-tip { | |||
background-color: #FFDBDB; | |||
// width: 90%; | |||
margin: 0rpx 40rpx 20rpx 30rpx; | |||
border-radius: 10rpx; | |||
padding: 15rpx 15rpx; | |||
display: flex; | |||
align-items: center; | |||
margin-bottom: 20rpx; | |||
text { | |||
font-size: 26rpx; | |||
color: $uni-color-second; | |||
margin-left: 10rpx; | |||
} | |||
} | |||
.pickup-list { | |||
gap: 20rpx; | |||
.pickup-item { | |||
margin-bottom: 20rpx; | |||
} | |||
} | |||
</style> |
@ -0,0 +1,337 @@ | |||
<template> | |||
<view class="wallet-page"> | |||
<!-- 导航栏 --> | |||
<navbar title="钱包" leftClick @leftClick="$utils.navigateBack" bgColor="#019245" color="#fff" /> | |||
<!-- 总余额展示区 --> | |||
<view class="balance-card" :style="{ backgroundImage: 'url(/static/image/红烧肉.png)' }"> | |||
<view class="balance-info"> | |||
<view class="balance-title">总余额(元)</view> | |||
<view class="balance-amount">{{ walletData.balance.toFixed(2) }}</view> | |||
<view class="balance-actions"> | |||
<view class="action-btn recharge-btn" @click="navigateToRecharge"> | |||
<text>去充值</text> | |||
</view> | |||
<view class="action-btn detail-btn" @click="navigateToDetail"> | |||
<text>资产明细</text> | |||
<text class="arrow">></text> | |||
</view> | |||
</view> | |||
</view> | |||
</view> | |||
<!-- 提现表单 --> | |||
<view class="withdraw-section"> | |||
<view class="section-title">我要提现</view> | |||
<!-- 提现金额输入框 --> | |||
<view class="input-item"> | |||
<text class="currency-symbol">¥</text> | |||
<input class="amount-input" type="digit" v-model="withdrawAmount" placeholder="请输入提现金额" | |||
@blur="validateAmount" /> | |||
</view> | |||
<!-- 真实姓名输入框 --> | |||
<view class="input-item"> | |||
<input class="name-input" type="nickname" v-model="realName" placeholder="请输入真实姓名" | |||
@blur="validateName" /> | |||
</view> | |||
<!-- 提现说明 --> | |||
<view class="withdraw-notes"> | |||
<view class="notes-title">提现说明</view> | |||
<view class="notes-list"> | |||
<view class="note-item" v-for="(rule, index) in walletData.withdrawRules" :key="index"> | |||
<text>{{ index + 1 }}、{{ rule }}</text> | |||
</view> | |||
</view> | |||
</view> | |||
</view> | |||
<!-- 提现按钮 --> | |||
<view class="submit-btn-wrapper"> | |||
<button class="submit-btn" @click="submitWithdraw" :disabled="!isFormValid"> | |||
立即提现 | |||
</button> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
import navbar from '@/components/base/navbar.vue' | |||
import { walletData } from '@/static/js/mockWallet.js' | |||
export default { | |||
components: { | |||
navbar | |||
}, | |||
data() { | |||
return { | |||
walletData: null, | |||
withdrawAmount: '', | |||
realName: '', | |||
amountError: '', | |||
nameError: '' | |||
} | |||
}, | |||
computed: { | |||
isFormValid() { | |||
return this.withdrawAmount && this.realName && !this.amountError && !this.nameError | |||
} | |||
}, | |||
onLoad() { | |||
this.walletData = walletData | |||
}, | |||
methods: { | |||
// 导航到充值页面 | |||
navigateToRecharge() { | |||
uni.showToast({ | |||
title: '充值功能暂未开放', | |||
icon: 'none' | |||
}) | |||
}, | |||
// 导航到资产明细页面 | |||
navigateToDetail() { | |||
uni.showToast({ | |||
title: '资产明细功能暂未开放', | |||
icon: 'none' | |||
}) | |||
}, | |||
// 验证提现金额 | |||
validateAmount() { | |||
if (!this.withdrawAmount) { | |||
this.amountError = '请输入提现金额' | |||
return false | |||
} | |||
const amount = parseFloat(this.withdrawAmount) | |||
if (isNaN(amount) || amount <= 0) { | |||
this.amountError = '请输入有效的提现金额' | |||
return false | |||
} | |||
if (amount > this.walletData.balance) { | |||
this.amountError = '提现金额不能大于余额' | |||
return false | |||
} | |||
if (amount > 200) { | |||
this.amountError = '单笔提现不能超过200元' | |||
return false | |||
} | |||
this.amountError = '' | |||
return true | |||
}, | |||
// 验证真实姓名 | |||
validateName() { | |||
if (!this.realName) { | |||
this.nameError = '请输入真实姓名' | |||
return false | |||
} | |||
if (this.realName.length < 2) { | |||
this.nameError = '请输入有效的姓名' | |||
return false | |||
} | |||
this.nameError = '' | |||
return true | |||
}, | |||
// 提交提现申请 | |||
submitWithdraw() { | |||
// 再次验证表单 | |||
if (!this.validateAmount() || !this.validateName()) { | |||
// 显示具体错误 | |||
if (this.amountError) { | |||
uni.showToast({ | |||
title: this.amountError, | |||
icon: 'none' | |||
}) | |||
return | |||
} | |||
if (this.nameError) { | |||
uni.showToast({ | |||
title: this.nameError, | |||
icon: 'none' | |||
}) | |||
return | |||
} | |||
return | |||
} | |||
// 显示提交中状态 | |||
uni.showLoading({ | |||
title: '提交中...' | |||
}) | |||
// 模拟提交过程 | |||
setTimeout(() => { | |||
uni.hideLoading() | |||
uni.showToast({ | |||
title: '提现申请已提交', | |||
icon: 'success' | |||
}) | |||
// 清空表单 | |||
this.withdrawAmount = '' | |||
this.realName = '' | |||
// 模拟余额变更 | |||
this.walletData.balance -= parseFloat(this.withdrawAmount) | |||
}, 1500) | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.wallet-page { | |||
} | |||
.balance-card { | |||
width: 96%; | |||
height: 280rpx; | |||
background-size: cover; | |||
background-position: center; | |||
padding: 30rpx; | |||
box-sizing: border-box; | |||
position: relative; | |||
margin: 20rpx auto; | |||
border-radius: 20rpx; | |||
.balance-info { | |||
position: relative; | |||
z-index: 2; | |||
color: #fff; | |||
} | |||
.balance-title { | |||
font-size: 28rpx; | |||
margin-bottom: 10rpx; | |||
} | |||
.balance-amount { | |||
font-size: 56rpx; | |||
font-weight: bold; | |||
margin-bottom: 20rpx; | |||
} | |||
.balance-actions { | |||
display: flex; | |||
justify-content: space-between; | |||
// justify-content: center; | |||
align-items: center; | |||
.action-btn { | |||
padding: 10rpx 24rpx; | |||
font-size: 24rpx; | |||
border-radius: 30rpx; | |||
display: flex; | |||
align-items: center; | |||
} | |||
.recharge-btn { | |||
background-color: #fff; | |||
color: $uni-color; | |||
border: none; | |||
min-width: 120rpx; | |||
height: 60rpx; | |||
justify-content: center; | |||
font-size: 24rpx; | |||
font-weight: normal; | |||
// line-height: 1; | |||
padding: 0 20rpx; | |||
} | |||
.detail-btn { | |||
// border: 1px solid rgba(255, 255, 255, 0.6); | |||
.arrow { | |||
margin-left: 10rpx; | |||
} | |||
} | |||
} | |||
} | |||
.withdraw-section { | |||
padding: 30rpx; | |||
// background-color: #fff; | |||
.section-title { | |||
font-size: 32rpx; | |||
color: #333; | |||
margin-bottom: 30rpx; | |||
font-weight: bold; | |||
} | |||
.input-item { | |||
display: flex; | |||
align-items: center; | |||
padding: 24rpx 20rpx; | |||
margin-bottom: 20rpx; | |||
// background-color: red; | |||
border-radius: 20rpx; | |||
.currency-symbol { | |||
color: #FF0000; | |||
margin-right: 20rpx; | |||
} | |||
.amount-input, | |||
.name-input { | |||
flex: 1; | |||
font-size: 28rpx; | |||
height: 60rpx; | |||
} | |||
.name-input { | |||
padding-left: 40rpx; | |||
} | |||
} | |||
.withdraw-notes { | |||
margin-top: 40rpx; | |||
.notes-title { | |||
font-size: 28rpx; | |||
color: #333; | |||
margin-bottom: 20rpx; | |||
} | |||
.notes-list { | |||
.note-item { | |||
font-size: 26rpx; | |||
color: #666; | |||
line-height: 1.6; | |||
margin-bottom: 10rpx; | |||
} | |||
} | |||
} | |||
} | |||
.submit-btn-wrapper { | |||
padding: 40rpx 30rpx; | |||
.submit-btn { | |||
width: 100%; | |||
height: 88rpx; | |||
background-color: $uni-color; | |||
color: #fff; | |||
font-size: 32rpx; | |||
border-radius: 44rpx; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
border: none; | |||
&:disabled { | |||
background-color: #ccc; | |||
color: rgba(255, 255, 255, 0.6); | |||
} | |||
} | |||
} | |||
</style> |
@ -0,0 +1,60 @@ | |||
// 未使用优惠券 | |||
export const unusedCoupons = [ | |||
{ | |||
id: '001', | |||
amount: 2, | |||
title: '新人专享优惠券', | |||
validTime: '2025/4/12 23:59', | |||
status: 0 // 0-未使用 | |||
}, | |||
{ | |||
id: '002', | |||
amount: 2, | |||
title: '新人专享优惠券', | |||
validTime: '2025/4/12 23:59', | |||
status: 0 | |||
}, | |||
{ | |||
id: '003', | |||
amount: 2, | |||
title: '新人专享优惠券', | |||
validTime: '2025/4/12 23:59', | |||
status: 0 | |||
} | |||
] | |||
// 已使用优惠券 | |||
export const usedCoupons = [ | |||
{ | |||
id: '004', | |||
amount: 5, | |||
title: '周末特惠券', | |||
validTime: '2025/3/30 23:59', | |||
status: 1 // 1-已使用 | |||
}, | |||
{ | |||
id: '005', | |||
amount: 10, | |||
title: '满100减10元', | |||
validTime: '2025/3/15 23:59', | |||
status: 1 | |||
} | |||
] | |||
// 已过期优惠券 | |||
export const expiredCoupons = [ | |||
{ | |||
id: '006', | |||
amount: 3, | |||
title: '节日优惠券', | |||
validTime: '2023/12/31 23:59', | |||
status: 2 // 2-已过期 | |||
}, | |||
{ | |||
id: '007', | |||
amount: 8, | |||
title: '店庆活动券', | |||
validTime: '2024/1/15 23:59', | |||
status: 2 | |||
} | |||
] |
@ -0,0 +1,14 @@ | |||
// 推广链接相关数据 | |||
export const shareData = { | |||
// 用户信息 | |||
userInfo: { | |||
avatar: '/static/image/中森明菜.webp', | |||
nickname: '辣妈Citti"', | |||
role: '首席' | |||
}, | |||
// 推广码 | |||
inviteCode: '888888', | |||
// 小程序码图片,应当使用标准微信小程序码样式的图片 | |||
// qrCodeImage: '/static/image/miniprogram-qrcode.png' // 替换为标准微信小程序码图片 | |||
qrCodeImage: '/static/image/红烧肉.png' | |||
} |
@ -0,0 +1,24 @@ | |||
export const currentPickupPoint = { | |||
id: 1, | |||
name: '轻奢时代茶香兴盛', | |||
address: '长沙市雨花区时代阳光大道轻奢时代茶香兴盛', | |||
phone: '15070023168', | |||
image: '/static/image/古茗店面.webp' | |||
} | |||
// 附近取餐点列表 | |||
export const nearbyPickupPoints = [ | |||
{ | |||
id: 2, | |||
name: '古茗中山街店', | |||
address: '长沙市雨花区中山街100号第二个店面', | |||
phone: '15070023168', | |||
image: '/static/image/古茗店面.webp' | |||
}, | |||
{ | |||
id: 3, | |||
name: '茶香兴盛小文轩便利店', | |||
address: '长沙市芙蓉区牛津街7栋', | |||
phone: '15070023168', | |||
image: '/static/image/古茗店面.webp' | |||
} | |||
] |
@ -0,0 +1,36 @@ | |||
// 钱包相关mock数据 | |||
export const walletData = { | |||
// 钱包余额 | |||
balance: 1500.00, | |||
// 交易记录 | |||
transactions: [ | |||
{ | |||
id: 1, | |||
type: 'income', | |||
amount: 500.00, | |||
date: '2023-12-10', | |||
desc: '团购分佣' | |||
}, | |||
{ | |||
id: 2, | |||
type: 'income', | |||
amount: 1000.00, | |||
date: '2023-12-05', | |||
desc: '推广奖励' | |||
}, | |||
{ | |||
id: 3, | |||
type: 'withdraw', | |||
amount: -200.00, | |||
date: '2023-11-28', | |||
desc: '提现' | |||
} | |||
], | |||
// 提现说明 | |||
withdrawRules: [ | |||
'单日提现次数上限为5次,单笔提现上限200', | |||
'直接提现至微信账户,无法提现至支付宝' | |||
] | |||
} |