| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
60dcdc0be2 | 1.7.2 做完团长钱包 | 8 months ago |
|
|
933e306038 | 1.7 还在完善团员个人主页 | 8 months ago |
| @ -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,381 @@ | |||
| <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" v-if="!isRecharge" @tap="navigateToRecharge"> | |||
| <text>去充值</text> | |||
| <text class="arrow">></text> | |||
| </view> | |||
| <view class="action-btn" v-else /> | |||
| <view class="action-btn detail-btn" @tap="navigateToDetail"> | |||
| <text>资产明细</text> | |||
| <text class="arrow">></text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 提现表单 --> | |||
| <view class="withdraw-section"> | |||
| <view class="section-title">{{ isRecharge ? '我要充值' : '我要提现' }}</view> | |||
| <!-- 提现金额输入框 --> | |||
| <view class="input-item"> | |||
| <text class="currency-symbol">¥</text> | |||
| <input v-if="!isRecharge" class="amount-input" type="digit" v-model="withdrawAmount" placeholder="请输入提现金额" | |||
| @blur="validateAmount" /> | |||
| <input v-else class="amount-input" type="digit" v-model="rechargeAmount" placeholder="请输入充值金额" | |||
| @blur="validateAmount" /> | |||
| </view> | |||
| <!-- 真实姓名输入框 --> | |||
| <view class="input-item" v-if="!isRecharge"> | |||
| <input class="name-input" type="nickname" v-model="realName" placeholder="请输入真实姓名" | |||
| @blur="validateName" /> | |||
| </view> | |||
| <!-- 提现说明 --> | |||
| <view class="withdraw-notes" v-if="!isRecharge"> | |||
| <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" @tap="submitWithdraw" :disabled="!isFormValid"> | |||
| {{ isRecharge ? '立即充值' : '立即提现' }} | |||
| </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: '', | |||
| rechargeAmount: '', | |||
| realName: '', | |||
| amountError: '', | |||
| nameError: '', | |||
| isFormValid: true, | |||
| isRecharge: false | |||
| } | |||
| }, | |||
| onLoad() { | |||
| this.walletData = walletData | |||
| }, | |||
| methods: { | |||
| // 导航到充值页面 | |||
| navigateToRecharge() { | |||
| this.isRecharge = true | |||
| }, | |||
| // 导航到资产明细页面 | |||
| navigateToDetail() { | |||
| uni.showToast({ | |||
| title: '资产明细功能暂未开放', | |||
| icon: 'error' | |||
| }) | |||
| }, | |||
| // 验证提现金额 | |||
| 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.isRecharge) { | |||
| return this.recharge() | |||
| } | |||
| // 再次验证表单 | |||
| if (!this.validateAmount() || !this.validateName()) { | |||
| console.log(2); | |||
| // 显示具体错误 | |||
| if (this.amountError) { | |||
| console.log(3); | |||
| uni.showToast({ | |||
| title: this.amountError, | |||
| icon: 'error' | |||
| }) | |||
| return | |||
| } | |||
| if (this.nameError) { | |||
| uni.showToast({ | |||
| title: this.nameError, | |||
| icon: 'error' | |||
| }) | |||
| return | |||
| } | |||
| return | |||
| } | |||
| // 如果在isFormVaild为false的情况下进入函数 则为多次点击 直接返回 | |||
| if (this.isFormValid) { | |||
| this.isFormValid = false | |||
| }else return | |||
| // 显示提交中状态 | |||
| uni.showLoading({ | |||
| title: '提交中...' | |||
| }) | |||
| // 模拟提交过程 | |||
| setTimeout(() => { | |||
| uni.hideLoading() | |||
| uni.showToast({ | |||
| title: '提现申请已提交', | |||
| icon: 'success' | |||
| }) | |||
| // 清空表单 | |||
| this.withdrawAmount = '' | |||
| this.realName = '' | |||
| // 模拟余额变更 | |||
| this.walletData.balance -= parseFloat(this.withdrawAmount) | |||
| this.isFormValid = true | |||
| }, 1500) | |||
| }, | |||
| recharge() { | |||
| uni.showModal({ | |||
| title: '确认充值', | |||
| content: '充值金额为' + this.rechargeAmount + '元', | |||
| confirmColor: '#019245', | |||
| success: (res) => { | |||
| // 这里编写函数逻辑 | |||
| if (res.confirm) { | |||
| uni.showLoading({ | |||
| title: '充值中...' | |||
| }) | |||
| // 执行重置逻辑 | |||
| // 模拟重置时间 | |||
| setTimeout(() => { | |||
| uni.hideLoading() | |||
| uni.showToast({ | |||
| title: '充值成功', | |||
| icon: 'success' | |||
| }) | |||
| // 重置表单 | |||
| this.rechargeAmount = '' | |||
| this.isRecharge = false | |||
| }, 1500) | |||
| } | |||
| }, | |||
| fail: (err) => { | |||
| console.log(err); | |||
| } | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| </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; | |||
| gap: 4rpx; | |||
| // line-height: 1; | |||
| padding: 0 20rpx; | |||
| } | |||
| .detail-btn { | |||
| .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: #e7e7e7; | |||
| 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', | |||
| '直接提现至微信账户,无法提现至支付宝' | |||
| ] | |||
| } | |||