Browse Source

'优惠卷系统实现'

hfll
hflllll 2 weeks ago
parent
commit
b4d4c2564b
22 changed files with 859 additions and 304 deletions
  1. +22
    -2
      api/model/index.js
  2. +1
    -1
      api/model/order.js
  3. +1
    -1
      components/product/productItem.vue
  4. +2
    -1
      mixins/list.js
  5. +3
    -0
      pages.json
  6. +1
    -1
      pages/index/cart.vue
  7. +16
    -38
      pages/index/category.vue
  8. +1
    -1
      pages/index/center.vue
  9. +66
    -17
      pages/index/index.vue
  10. +2
    -2
      pages/index/oldIndex.vue
  11. +25
    -7
      pages/index/order.vue
  12. +5
    -5
      pages_order/auth/wxLogin.vue
  13. +1
    -1
      pages_order/auth/wxUserInfo.vue
  14. +15
    -12
      pages_order/components/order/placeOrder.vue
  15. +32
    -23
      pages_order/mine/coupon.vue
  16. +2
    -8
      pages_order/mine/share.vue
  17. +18
    -14
      pages_order/mine/unbindTeam.vue
  18. +1
    -1
      pages_order/mine/wallet.vue
  19. +548
    -0
      pages_order/order/cartOrder.vue
  20. +83
    -164
      pages_order/order/newOrderDetail.vue
  21. +13
    -4
      store/store.js
  22. +1
    -1
      utils/utils.js

+ 22
- 2
api/model/index.js View File

@ -11,14 +11,34 @@ const api = {
queryGoodsList: {
url: '/teambuy/goods/queryGoodsList',
method: 'GET',
limit: 500
limit: 100
},
// 商品信息- 查询商品信息详情
// 轮播图-查询轮播图列表
queryGoodsById: {
url: '/teambuy/goods/queryGoodsById',
method: 'GET',
limit: 500
},
// 首页-获取首页轮播图
queryBannerList : {
url: '/teambuy/index/queryBannerList',
method: 'GET',
limit: 500
},
// 展示信息-查询展示列表
queryInfoList : {
url: '/teambuy/index/queryInfoList',
method: 'GET',
limit: 500
},
// 轮播图-查询轮播图列表
rollList: {
url: '/teambuy/index/rollList',
method: 'GET',
limit: 500
}
}
export default api

+ 1
- 1
api/model/order.js View File

@ -25,7 +25,7 @@ const api = {
queryMemberOrderList: {
url: '/teambuy/order/queryMemberOrderList',
method: 'GET',
limit: 500
limit: 200
},
// 订单-查看购物车列表-详情


+ 1
- 1
components/product/productItem.vue View File

@ -113,7 +113,7 @@
</view>
<view @click.stop="addCart(item)" class="buy-btn">
<uv-badge type="error" max="9" :value="getProductCount(item.id)" absolute :offset="[-10, 1]" bg-color="#FF2A2A" />
<!-- <uv-badge type="error" max="9" :value="getProductCount(item.id)" absolute :offset="[-10, 1]" bg-color="#FF2A2A" /> -->
加购物车
</view>
</view>


+ 2
- 1
mixins/list.js View File

@ -51,14 +51,15 @@ export default {
if(!this.mixinsListApi){
return console.error('mixinsListApi 缺失');
}
uni.showLoading({
title: '加载列表中...'
})
console.log('6666', query(this, queryParams));
this.$api(this.mixinsListApi,
query(this, queryParams), res => {
uni.stopPullDownRefresh()
uni.hideLoading()
if(res.code == 200){
success(res.result)


+ 3
- 0
pages.json View File

@ -168,6 +168,9 @@
{
"path": "order/receiveGift"
},
{
"path": "order/cartOrder"
},
{
"path": "location/pickupPoint",
"style": {


+ 1
- 1
pages/index/cart.vue View File

@ -162,7 +162,7 @@ export default {
//
this.$utils.navigateTo({
url: '/pages_order/order/newOrderDetail?status=cart'
url: '/pages_order/order/cartOrder'
});
},
// //


+ 16
- 38
pages/index/category.vue View File

@ -5,16 +5,7 @@ const DEFAULT_OPEN = 1
<!-- 导航栏 -->
<!-- <navbar bgColor="#019245" color="#fff" /> -->
<!-- 搜索栏 -->
<view class="search">
<image src="/static/image/logo.webp" mode="aspectFill" class="search-img" />
<view style="position: relative;">
<uv-search placeholder="陕西苹果" bgColor="#fff" @search="search" @change="search" @custom="search"
:searchIconSize="40" v-model="queryParams.title" height="75rpx" :showAction="false"
actionText=" " />
<text class="search-text" @tap="search">搜索</text>
</view>
</view>
<navbar title="商品" bgColor="#019245" color="#fff" />
<!-- 商品列表 -->
<view style="position: 20rpx;" v-if="queryParams.title">
@ -51,30 +42,22 @@ const DEFAULT_OPEN = 1
<uv-vtabs-item>
<view class="category-item">
<!-- 这里加载更多数据需要你使用scroll-view 因为你的列表在uv-vtabs里面 -->
<scroll-view
scroll-y="true"
@scrolltolower="loadMoreData"
style="height: calc(100vh - 470rpx);"
>
<productItem
:item="pro"
:key="i"
v-for="(pro, i) in list"
@tap="navigateToDetail(pro.id)"
@purchase="navigateToDetail(pro.id, true)"
/>
<view style="padding-top: 100rpx;">
<uv-empty v-if="list.length == 0" text="还没有菜品哦" />
</view>
<scroll-view scroll-y="true" @scrolltolower="loadMoreData"
style="height: calc(100vh - 360rpx);">
<productItem :item="pro" :key="i" v-for="(pro, i) in list" @tap="navigateToDetail(pro.id)"
@purchase="navigateToDetail(pro.id, true)" />
<view style="padding-top: 100rpx;">
<uv-empty v-if="list.length == 0" text="还没有菜品哦" />
</view>
</scroll-view>
</view>
</uv-vtabs-item>
</uv-vtabs>
</view>
<!-- tabbar -->
@ -134,11 +117,7 @@ export default {
this.getData()
},
search() {
// for (let i = 0; i < 10; i++) {
// delete this.queryParams[i]
// }
// this.queryParams.pageSize = 10
this.getData()
},
navigateToDetail(id, open) {
this.$utils.navigateTo(`/pages_order/product/productDetail?id=${id}&open=${open}`);
@ -152,15 +131,15 @@ export default {
// background-color: #f5f5ff;
/deep/ .uv-vtabs {
height: calc(100vh - 470rpx) !important;
height: calc(100vh - 360rpx) !important;
}
/deep/ .uv-vtabs__bar {
height: calc(100vh - 470rpx) !important;
height: calc(100vh - 360rpx) !important;
}
/deep/ .uv-vtabs__content {
height: calc(100vh - 470rpx) !important;
height: calc(100vh - 360rpx) !important;
}
.search {
@ -236,7 +215,6 @@ export default {
/* background-color: green; */
font-size: 30rpx;
color: #333;
.category-title {
position: relative;
display: flex;


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

@ -1,7 +1,7 @@
<template>
<view class="center-page">
<!-- 顶部背景和个人信息 -->
<view class="header" :style="{ backgroundImage: `url(${imageUrl})` }">
<view class="header" :style="{ backgroundImage: `url(${configList.config_bg_image})` }">
<view class="user-info">
<image class="avatar" :src="userInfo.headImage" mode="aspectFill"></image>


+ 66
- 17
pages/index/index.vue View File

@ -14,7 +14,7 @@
<!-- 店铺信息 -->
<view class="restaurant-info">
<div class="restaurant-logo">
<image :src="configList.config_logo" mode="aspectFill" style="width: 100%; height: 100%;" />
<image :src="homeData.restaurant.icon" mode="aspectFill" style="width: 100%; height: 100%;" />
</div>
<view class="restaurant-name">{{homeData.restaurant.name}}</view>
<!-- <view class="service-btns">
@ -35,30 +35,30 @@
<!-- 公告信息 -->
<view class="notice">
<text class="notice-text">{{homeData.restaurant.notice}}</text>
<text class="notice-desc">{{homeData.restaurant.description}}</text>
<text class="notice-text">{{homeData.restaurant.title}}</text>
<!-- <text class="notice-desc">{{homeData.restaurant.tag}}</text> -->
</view>
<!-- 标签列表 -->
<view class="tag-list">
<view class="tag" v-for="(tag, index) in homeData.tags" :key="index">{{tag}}</view>
<view class="tag" v-for="(tag, index) in homeData.restaurant.tag.split('、')" :key="index">{{tag}}</view>
</view>
<!-- 价格区间 -->
<view class="price-range">
<text class="price">{{homeData.priceRange}}</text>
<text class="price">{{homeData.restaurant.price}}</text>
</view>
<!-- 产品展示 -->
<scroll-view scroll-x class="food-scroll">
<view class="food-item" v-for="food in homeData.foods" :key="food.id">
<view class="food-item" v-for="food in homeData.goodsList" :key="food.categoryId" @click="goGoodsDetail">
<image :src="food.image" mode="aspectFill" class="food-image" />
<view class="food-detail">
<view class="food-name">{{food.name}}</view>
<view class="food-desc">{{food.desc}}</view>
<view class="food-name">{{food.title}}</view>
<view class="food-desc">{{food.categoryId_dictText}}</view>
<view class="food-price">
<text class="current-price">¥{{food.price}}</text>
<text class="original-price">¥{{food.originalPrice}}</text>
<text class="original-price">¥{{food.price + 10}}</text>
</view>
</view>
</view>
@ -74,15 +74,21 @@
display-multiple-items="3">
<swiper-item v-for="(order, index) in orderList" :key="index">
<view class="order-item">
<view class="order-id">{{ order.id }}</view>
<view class="order-id">{{ (order.hanHaiMember.id).substring(0, 3) + '****' + (order.hanHaiMember.id).substring(6, 9) }}</view>
<view class="order-user">
<image :src="order.avatar" mode="aspectFill" class="user-avatar" />
<text class="user-name">{{ order.userName }}</text>
<text class="order-time">{{ order.time }}</text>
<image :src="order.hanHaiMember.headImage" mode="aspectFill" class="user-avatar" />
<text class="user-name">{{ order.hanHaiMember.nickName }}</text>
<text class="order-time">
{{
order.updateTime ?
$timeUtils.formatTime($dayjs(order.updateTime).unix()) :
$timeUtils.formatTime($dayjs(order.createTime).unix())
}}
</text>
</view>
<view class="order-content">
<text class="order-desc">{{ order.content }}</text>
<text class="order-count">+{{ order.count }}</text>
<text class="order-desc">{{ order.goodsList[0].goods.title }}</text>
<text class="order-count">+{{ order.goodsList[0].num }}</text>
</view>
</view>
</swiper-item>
@ -151,6 +157,49 @@ export default {
}
]
}
},
onShow() {
this.getBannerList()
this.getInfoList()
this.getGoodsList()
this.getRollList()
},
methods: {
getBannerList() {
this.$api('queryBannerList', {
type: '0'
}, res => {
if (res.code == 200) {
this.homeData.banners = res.result.records
}
})
},
getInfoList() {
this.$api('queryInfoList', {}, res => {
if (res.code == 200) {
this.homeData.restaurant = res.result.records[0]
}
})
},
getGoodsList() {
this.$api('queryGoodsList', { }, res => {
if (res.code == 200) {
this.$set(this.homeData, 'goodsList', res.result.records)
}
})
},
getRollList() {
this.$api('rollList', { }, res => {
if (res.code == 200) {
this.orderList = res.result.records
}
})
},
goGoodsDetail() {
uni.navigateTo({
url: '/pages/index/category'
})
}
}
}
</script>
@ -305,8 +354,8 @@ export default {
}
.food-image {
width: 140rpx;
height: 140rpx;
width: 160rpx;
height: 160rpx;
}
.food-detail {


+ 2
- 2
pages/index/oldIndex.vue View File

@ -83,7 +83,7 @@
<view class="line"></view>
推荐宝贝
</view>
<view @tap="$utils.navigateTo('/pages/index/category')"
<view @tap="$utils.navigateTo('/pages/index/index')"
class="recommend-more">更多</view>
</view>
@ -169,7 +169,7 @@
//
search() {
uni.navigateTo({
url: '/pages/index/category?search=' + this.keyword
url: '/pages/index/index?search=' + this.keyword
})
this.keyword = ''
},


+ 25
- 7
pages/index/order.vue View File

@ -7,7 +7,7 @@
<view style="background-color: #fff; padding: 12rpx 20rpx 0rpx; ">
<uv-search placeholder="搜索商品名" v-model="keyword" :showAction="false" actionText="" height="80rpx" animation
bgColor="#F5F5F5" inputAlign="center" color="#000" placeholderColor="#979797"
searchIconSize="50rpx"></uv-search>
searchIconSize="50rpx" @search="handleSearch"></uv-search>
</view>
<!-- 订单筛选 -->
@ -181,8 +181,31 @@
},
onLoad(args) {
this.getData()
// tabIndextab
if (args.tabIndex !== undefined) {
const index = parseInt(args.tabIndex)
if (!isNaN(index) && index >= 0 && index < this.tabs.length) {
this.current = index
//
// if (index == 0) {
// delete this.queryParams.state
// } else {
// this.queryParams.state = index - 1
// }
}
}
},
methods: {
handleSearch(value) {
this.$api('queryMemberOrderList', {
title: value
}, res => {
if (res.code == 200) {
this.memberOrderList = res.result.records
}
})
},
getData() {
uni.showLoading({
title: '加载中'
@ -209,13 +232,8 @@
clickTabs({
index
}) {
if (index == 0) {
delete this.queryParams.state
} else {
this.queryParams.state = index - 1
}
this.current = index
this.getData()
},
//
goToOrderDetail(order) {


+ 5
- 5
pages_order/auth/wxLogin.vue View File

@ -69,10 +69,8 @@ export default {
return {
checkboxValue : [],
config : {},
serviceAgreement:
'用户服务协议为使用小程序名称的服务,您应当阅读并遵守《用户服务协议》(以下简称"本协议")。请您务必审慎阅读、充分理解各条款内容,特别是免除或者限制责任的条款,所有加粗字体为我方重点提示的内容。如果您未满18周岁,或者不具备完全民事行为能力,请在法定监护人的陪同下阅读本协议,并特别注意未成年人使用条款。否则小程序名称对于该等后续注册、使用网站服务等行为而对您所发生的不利后果不承担责任,并有权在知晓该等情况后解除双方间的服务协议。一、【协议的范围】本协议及《隐私政策》是您与小程序名称经营者之间关于用户使用小程序名称旗下产品相关服务所订立的协议。小程序名称的经营者是指法律认可的经营瀚用户服务协议为使用小程序名称的服务,您应当阅读并遵守《用户服务协议》(以下简称"本协议")。请您务必审慎阅读、充分理解各条款内容,特别是免除或者限制责任的条款,所有加粗字体为我方重点提示的内容。如果您未满18周岁,或者不具备完全民事行为能力,请在法定监护人的陪同下阅读本协议,并特别注意未成年人使用条款。否则小程序名称对于该等后续注册、使用网站服务等行为而对您所发生的不利后果不承担责任,并有权在知晓该等情况后解除双方间的服务协议。一、【协议的范围】本协议及《隐私政策》是您与小程序名称经营者之间关于用户使用小程序名称旗下产品相关服务所订立的协议。小程序名称的经营者是指法律认可的经营瀚',
personalInformationProtectionGuidelines: '用户服务协议为使用小程序名称的服务,您应当阅读并遵守《用户服务协议》(以下简称"本协议")。请您务必审慎阅读、充分理解各条款内容,特别是免除或者限制责任的条款,所有加粗字体为我方重点提示的内容。如果您未满18周岁,或者不具备完全民事行为能力,请在法定监护人的陪同下阅读本协议,并特别注意未成年人使用条款。否则小程序名称对于该等后续注册、使用网站服务等行为而对您所发生的不利后果不承担责任,并有权在知晓该等情况后解除双方间的服务协议。一、【协议的范围】本协议及《隐私政策》是您与小程序名称经营者之间关于用户使用小程序名称旗下产品相关服务所订立的协议。小程序名称的经营者是指法律认可的经营瀚用户服务协议为使用小程序名称的服务,您应当阅读并遵守《用户服务协议》(以下简称"本协议")。请您务必审慎阅读、充分理解各条款内容,特别是免除或者限制责任的条款,所有加粗字体为我方重点提示的内容。如果您未满18周岁,或者不具备完全民事行为能力,请在法定监护人的陪同下阅读本协议,并特别注意未成年人使用条款。否则小程序名称对于该等后续注册、使用网站服务等行为而对您所发生的不利后果不承担责任,并有权在知晓该等情况后解除双方间的服务协议。一、【协议的范围】本协议及《隐私政策》是您与小程序名称经营者之间关于用户使用小程序名称旗下产品相关服务所订立的协议。小程序名称的经营者是指法律认可的经营瀚',
title: '服务协议'
title: '服务协议',
serviceAgreement: '暂未拿到信息'
}
},
onLoad(query) {
@ -88,8 +86,10 @@ export default {
openPrivacyPopup(index){
if (index == 0) {
this.title = '服务协议'
this.serviceAgreement = this.configList.config_privacy_policy
} else {
this.title = '隐私政策'
this.serviceAgreement = this.configList.config_personal_protection
}
this.$refs.privacyPopup.open()
},
@ -113,7 +113,7 @@ export default {
},
qux(){
uni.reLaunch({
url: '/pages/index/category'
url: '/pages/index/index'
})
},
}


+ 1
- 1
pages_order/auth/wxUserInfo.vue View File

@ -145,7 +145,7 @@
if (res.code == 200) {
this.$store.commit('getUserInfo')
uni.reLaunch({
url:'/pages/index/category'
url:'/pages/index/index'
})
}
})


+ 15
- 12
pages_order/components/order/placeOrder.vue View File

@ -71,10 +71,10 @@
<!-- 优惠 -->
<view class="discount">
<text style="font-size: 35rpx;">优惠</text>
<view style="display: flex; align-items: center; gap: 20rpx">
<view style="display: flex; align-items: center; gap: 20rpx" @click="gotoCoupon">
<image src="@/static/image/券.webp" mode="aspectFill" class="discount-image" />
<text>新用户立减</text>
<text style="color: red;">-2</text>
<text>{{ couponData.couponId_dictText || '请选择您的优惠卷' }}</text>
<text style="color: red;">-{{ couponData.discount || 0 }}</text>
</view>
</view>
@ -106,6 +106,7 @@ import { mapState } from 'vuex'
export default {
name: 'placeOrder',
data() {
return {
value: 1,
payMethod: '0',
@ -122,6 +123,7 @@ export default {
computed: {
...mapState(['userInfo']),
...mapState(['couponData']),
priceAll () {
return this.item.price * this.value
},
@ -130,7 +132,10 @@ export default {
}
},
methods: {
//
gotoCoupon() {
this.$utils.navigateTo('/pages_order/mine/coupon?usein=1')
},
// open
open() {
this.$refs.popup.open();
@ -181,10 +186,11 @@ export default {
})
this.$api('createOrder', {
priceAll: this.priceAll,
pricePay: this.priceAll - 0,
pricePreferential: 0,
pricePay: this.priceAll - ( this.couponData.discount || 0 ),
pricePreferential: this.couponData.discount || 0,
payType: this.payMethod,
leaderId: this.pickupPoint.id,
couponId: this.couponData.id || '',
goodss: this.goodss,
remark: this.remark
}, res => {
@ -192,9 +198,9 @@ export default {
if (res.code === 200) {
if (this.payMethod == '0') {
uni.requestPaymentWxPay(res)
.catch(n => {
.then(n => {
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order'
url: '/pages/index/order?tabIndex=1'
})
})
}else {
@ -203,7 +209,7 @@ export default {
icon: 'success'
})
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order'
url: '/pages/index/order?tabIndex=1'
})
}
}
@ -212,9 +218,6 @@ export default {
},
mounted(){
this.listenPickupPoint();
console.log(123123);
console.log('111', this.userInfo.balance);
},
beforeDestroy() {
uni.$off('updatePickupPoint');


+ 32
- 23
pages_order/mine/coupon.vue View File

@ -37,6 +37,7 @@
<script>
import navbar from '@/components/base/navbar.vue'
import CouponItem from '@/components/coupon/CouponItem.vue'
import { mapState } from 'vuex'
export default {
components: {
@ -51,10 +52,12 @@ export default {
{ name: '已过期' }
],
currentTab: 0,
allCoupons: []
allCoupons: [],
usein: false // 使
}
},
computed: {
...mapState(['couponData']),
unusedCoupons() {
return (this.allCoupons || []).filter(coupon => coupon.status === "0")
},
@ -65,8 +68,11 @@ export default {
return (this.allCoupons || []).filter(coupon => coupon.status === "2")
}
},
onLoad() {
onLoad(args) {
this.getCoupon()
if (args.usein === '1') {
this.usein = true
}
},
methods: {
//
@ -76,31 +82,34 @@ export default {
// 使
useCoupon(coupon) {
uni.showModal({
title: '提示',
content: `确定使用面值${coupon.discount}元的优惠券吗?`,
success: (res) => {
// 使
uni.showLoading({
title: '使用中...'
})
setTimeout(() => {
uni.hideLoading()
uni.showToast({
title: '使用成功',
icon: 'success'
if (this.usein) {
uni.showModal({
title: '提示',
content: `确定使用面值${coupon.discount}元的优惠券吗?`,
success: (res) => {
// 使
uni.showLoading({
title: '使用中...'
})
setTimeout(() => {
uni.hideLoading()
if (res.confirm) {
this.$utils.navigateTo('/pages/order/index')
uni.showToast({
title: '使用成功',
icon: 'success'
})
this.$store.commit('setCouponData', coupon)
this.$utils.navigateBack()
}
}, 1000)
}, 1000)
},
fail: (err) => {
console.log('err', err)
}
})
}, 300)
},
fail: (err) => {
console.log('err', err)
}
})
}else {
this.$utils.navigateTo('/pages/index/category')
}
},
//
getCoupon() {


+ 2
- 8
pages_order/mine/share.vue View File

@ -20,12 +20,6 @@
<view class="qrcode-container">
<image :src="shareData.url" class="qrcode-image" mode="aspectFit" />
</view>
<!-- 邀请码 -->
<view class="invite-code">
<!-- 邀请码{{ shareData.inviteCode }} -->
邀请码66666
</view>
</view>
</view>
@ -134,8 +128,8 @@ export default {
//
onShareAppMessage() {
return {
title: `邀请您使用敢为人鲜小程序,邀请码: 666`,
path: `/pages/index/index?inviteCode=666`,
title: `邀请您使用敢为人鲜小程序`,
path: `/pages/index/index`,
imageUrl: this.shareData.url,
success: () => {
uni.showToast({


+ 18
- 14
pages_order/mine/unbindTeam.vue View File

@ -108,12 +108,13 @@ export default {
title: `${res.message}`
})
}
this.getLeaderList()
})
}
}
})
},
updateLeader(point) {
updateLeader(point) {
uni.showModal({
title: '确认选择',
content: '您确定要选择该取餐点吗?需要平台审核通过后才能更换。',
@ -138,22 +139,25 @@ export default {
}
})
},
getLeaderList() {
// this.currentPickupPoint = currentPickupPoint
this.$api('queryLeaderList', {}, res => {
if (res.code == 200) {
this.nearbyPickupPoints = res.result.records
}
})
this.$api('queryMyLeader', {}, res => {
if (res.code == 200) {
this.currentPickupPoint = res.result
} else if (res.code == 500 || !res.result) {
this.isBind = false
}
})
}
},
onLoad() {
// this.currentPickupPoint = currentPickupPoint
this.$api('queryLeaderList', {}, res => {
if (res.code == 200){
this.nearbyPickupPoints = res.result.records
}
})
this.$api('queryMyLeader', {}, res => {
if (res.code == 200){
this.currentPickupPoint = res.result
}else if(res.code == 500 || !res.result){
this.isBind = false
}
})
this.getLeaderList()
}
}
</script>


+ 1
- 1
pages_order/mine/wallet.vue View File

@ -4,7 +4,7 @@
<navbar title="钱包" leftClick @leftClick="$utils.navigateBack" bgColor="#019245" color="#fff" />
<!-- 总余额展示区 -->
<view class="balance-card" :style="{ backgroundImage: 'url(/static/image/红烧肉.webp)' }">
<view class="balance-card" :style="{ backgroundImage: `url(${configList.config_money_image})` }">
<view class="balance-info">
<view class="balance-title">总余额</view>
<view class="balance-amount">{{ userInfo.balance ? userInfo.balance.toFixed(2) : '0.00' }}</view>


+ 548
- 0
pages_order/order/cartOrder.vue View File

@ -0,0 +1,548 @@
<template>
<view class="page">
<!-- 导航栏 -->
<navbar title="购物车支付 " leftClick @leftClick="navigateBack" bgColor="#019245" color="#fff" />
<!-- 店铺信息 -->
<view class="shop-info">
<view class="shop-header">
<image class="shop-logo" :src="teamLeader.spotImage" mode="aspectFill"></image>
<view class="shop-name-container">
<text class="shop-name"> {{ teamLeader.spotName }} </text>
<view class="shop-address">
<view style="padding-top: 7rpx;">
<!-- 需要置顶 -->
<uv-icon name="map-fill" color="#019245" size="28rpx"></uv-icon>
</view>
<text class="address-text">{{ teamLeader.area }} {{ teamLeader.address }}</text>
</view>
<view class="shop-phone">
<view style="padding-top: 7rpx;">
<!-- 需要置顶 -->
<uv-icon name="phone-fill" color="#019245" size="28rpx"></uv-icon>
</view>
<text class="phone-text">{{ teamLeader.phone }}</text>
</view>
</view>
</view>
</view>
<view class="order-status">
<!-- 商品列表 -->
<view class="food-list">
<view class="food-item" v-for="(food, index) in showedFoods" :key="food.id">
<image class="food-image" :src="food.goods.image" mode="aspectFill" />
<view class="food-info">
<text class="food-name">{{ food.goods.title }}</text>
<view class="food-sold">
<uv-icon name="bag" size="28rpx"></uv-icon>
<text>已售出 {{ food.goods.sales }}</text>
</view>
<text class="food-price"> <text style="font-size: 20rpx;"></text> {{ food.goods.price }}</text>
<text class="food-count">×{{ food.num }}</text>
</view>
</view>
<view class="expand-more" @tap="showAllFoods = !showAllFoods" v-if="cartData.sendData.length > 3">
<text>{{ showAllFoods ? '收起' : '展开' }} ({{ cartData.sendData.length }})</text>
<uv-icon :name="showAllFoods ? 'arrow-up' : 'arrow-down'" size="28rpx"></uv-icon>
</view>
</view>
<!-- 订单信息 -->
<view class="order-info">
<view class="info-item">
<text class="info-label">合计:</text>
<!-- <text class="info-value price">{{ thePriceAll.toFixed(2) || 0 }}</text> -->
<text class="info-value price">{{ (cartData.priceAll || 0).toFixed(2) || 0 }}</text>
</view>
</view>
</view>
<view class="discount-info-container">
<!-- 优惠信息 -->
<view class="discount-info">
<view class="discount-header">
<text>优惠</text>
</view>
<view class="discount-item" @click="gotoCoupon">
<view class="discount-left">
<image src="@/static/image/券.webp" mode="aspectFill" class="coupon-icon" v-if="couponData.couponId" />
<view :style="{ color: couponData.couponId ? 'inherit' : '#ccc' }">{{ couponData.couponId_dictText || '点击选择优惠卷->' }}
</view>
<text class="discount-amount">{{ couponData.discount ? ('-' + couponData.discount) : '' }}</text>
</view>
</view>
</view>
<!-- 备注 -->
<view class="remark-section">
<view class="remark-header">
<text>备注</text>
</view>
<view class="remark-content">
<input type="text" v-model="orderDetail.remark"
placeholder="请输入您要备注的内容" placeholder-style="font-size: 28rpx" />
</view>
</view>
<!-- 支付方式 -->
<uv-radio-group v-model="payMethod">
<view class="payment-methods">
<view class="payment-item">
<uv-icon name="weixin-circle-fill" size="70rpx" color="#019245" />
<text class="payment-name">微信支付</text>
<uv-radio activeColor="#019245" size="40rpx" name="0" />
</view>
<view class="payment-item">
<uv-icon name="red-packet" size="70rpx" color="#019245" />
<text class="payment-name">账户余额<text class="balance-text">(余额: {{ userInfo.balance
}})</text></text>
<uv-radio activeColor="#019245" size="40rpx" name="1" />
</view>
</view>
</uv-radio-group>
<!-- 底部支付栏 -->
<view class="bottom-bar">
<view class="total-section">
<text class="total-label">
{{ cartData.sendData.length }}
<text style="color: black;">合计</text>
</text>
<text class="total-price">{{ (pricePay || 0).toFixed(2) || 0 }}</text>
</view>
<view class="pay-button" @tap="handlePay">立即下单</view>
</view>
</view>
</view>
</template>
<script>
import navbar from '@/components/base/navbar.vue'
import { mapState, mapMutations } from 'vuex'
export default {
components: {
navbar
},
data() {
return {
payMethod: '0',
showAllFoods: false,
teamLeader: {},
thePriceAll: 0,
}
},
computed: {
...mapState(['cartData', 'userInfo', 'couponData']),
showedFoods() {
return this.showAllFoods ? this.cartData.sendData : this.cartData.sendData.slice(0, 3)
},
pricePay() {
return this.cartData.priceAll - (this.couponData.discount || 0)
},
// goodId,goodNum;goodId2,goodsNum
goodss() {
return this.cartData.sendData.map(item => {
return `${item.goodsId},${item.num},${item.goods.price * item.num}`
}).join(';')
}
},
onShow() {
this.getLeaderData()
},
onHide() {
this.clearCouponData()
},
methods: {
...mapMutations(['clearCouponData']),
//
navigateBack() {
uni.navigateBack()
},
//
getLeaderData() {
this.$api('queryMyLeader', {}, res => {
if (res.code === 200) {
this.teamLeader = res.result
}else {
uni.showModal({
title: '提示',
content: res.message,
confirmColor: '#019245',
confirmText: '去绑定',
cancelText: '晚点再绑',
success: (result) => {
console.log('弹窗操作结果', result);
if (result.confirm) {
this.$utils.navigateTo({
url: '/pages_order/mine/unbindTeam'
})
} else {
this.$utils.navigateBack()
}
},
fail: (err) => {
console.error('弹窗显示失败', err);
}
})
}
})
},
//
handlePay() {
uni.showLoading({
title: '支付处理中...'
})
this.$api('createOrder', {
priceAll: this.cartData.priceAll,
pricePay: this.pricePay,
pricePreferential: this.couponData.discount || 0,
payType: this.payMethod,
leaderId: this.teamLeader.id,
goodss: this.goodss
}, res => {
uni.hideLoading()
if (res.code === 200) {
if (this.payMethod == '0') {
uni.requestPaymentWxPay(res)
.then(n => {
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order?tabIndex=1'
})
})
} else {
uni.showToast({
title: '下单成功',
icon: 'success'
})
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order?tabIndex=1'
})
}
}
})
},
//
gotoCoupon() {
//
this.$utils.navigateTo({
url: '/pages_order/mine/coupon?usein=1'
})
}
}
}
</script>
<style lang="scss" scoped>
.page {
background-color: #f5f5f5;
min-height: 100vh;
padding-bottom: 120rpx;
}
.status-bar {
background-color: #019245;
padding: 30rpx;
color: #fff;
font-size: 32rpx;
font-weight: 500;
}
.shop-info {
background-color: #fff;
margin: 20rpx;
border-radius: 16rpx;
padding: 20rpx;
.shop-header {
display: flex;
align-items: center;
// background-color: red;
.shop-logo {
width: 150rpx;
height: 150rpx;
// border-radius: 10rpx;
margin-right: 20rpx;
}
.shop-name-container {
flex: 1;
.shop-name {
font-size: 30rpx;
font-weight: 500;
margin-bottom: 10rpx;
display: block;
}
.shop-address,
.shop-phone {
display: flex;
align-items: start;
font-size: 24rpx;
color: $uni-color-third;
margin-top: 8rpx;
.address-text,
.phone-text {
margin-left: 8rpx;
width: 80%;
white-space: wrap;
// overflow: hidden;
// text-overflow: ellipsis;
}
}
.shop-address-top {
display: flex;
align-items: start;
background-color: red;
// gap: 10rpx;
}
}
}
}
.order-status {
background-color: #fff;
margin: 20rpx;
border-radius: 16rpx;
padding: 20rpx;
.food-list {
// gap: 20rpx;
// background-color: #019245;
.food-item {
display: flex;
margin-bottom: 20rpx;
// background-color: red;
.food-image {
width: 120rpx;
height: 120rpx;
// border-radius: 10rpx;
margin-right: 20rpx;
}
.food-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
position: relative;
.food-name {
font-size: 28rpx;
font-weight: 500;
}
.food-sold {
display: flex;
align-items: center;
font-size: 24rpx;
color: $uni-color-third;
}
.food-price {
font-size: 28rpx;
color: #f00;
}
.food-count {
color: black;
position: absolute;
bottom: 50%;
right: 0;
}
}
}
.expand-more {
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx 0 0;
font-size: 24rpx;
color: $uni-color-third;
}
}
.order-info {
padding-top: 20rpx;
.info-item {
display: flex;
justify-content: space-between;
margin-bottom: 15rpx;
font-size: 26rpx;
.info-label {
color: black;
}
.info-value {
color: #333;
&.price {
color: #f00;
font-weight: 500;
}
}
}
}
}
.discount-info-container {
background-color: #fff;
margin: 20rpx;
border-radius: 16rpx;
padding: 20rpx;
display: flex;
flex-direction: column;
gap: 40rpx;
}
.discount-info {
display: flex;
align-items: center;
justify-content: space-between;
.discount-header {
font-size: 28rpx;
}
.discount-item {
display: flex;
justify-content: space-between;
align-items: center;
gap: 20rpx;
.discount-left {
display: flex;
align-items: center;
gap: 10rpx;
.coupon-icon {
width: 36rpx;
height: 36rpx;
margin-top: 6rpx;
}
}
.discount-amount {
color: #f00;
font-weight: 500;
}
.none-discount-amount {
color: gray;
font-weight: 500;
}
}
}
.remark-section {
display: flex;
// flex-direction: column;
gap: 40rpx;
// background-color: red;
align-items: center;
.remark-header {
font-size: 28rpx;
// font-weight: 500;
}
.remark-content {
font-size: 26rpx;
color: black;
min-height: 60rpx;
display: flex;
align-items: center;
}
}
.payment-methods {
background-color: #fff;
width: 100%;
margin: 20rpx;
border-radius: 16rpx;
padding: 20rpx;
display: flex;
flex-direction: column;
gap: 20rpx;
.payment-item {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.payment-name {
flex: 1;
margin-left: 20rpx;
font-size: 28rpx;
.balance-text {
font-size: 24rpx;
color: $uni-color-third;
margin-left: 10rpx;
}
}
}
}
.bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
background-color: #fff;
display: flex;
align-items: center;
padding: 0 30rpx;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
.total-section {
flex: 1;
.total-label {
font-size: 26rpx;
color: $uni-color-third;
}
.total-price {
font-size: 32rpx;
color: #f00;
margin-left: 10rpx;
}
}
.pay-button {
width: 240rpx;
height: 80rpx;
background-color: #019245;
color: #fff;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 40rpx;
}
}
</style>

+ 83
- 164
pages_order/order/newOrderDetail.vue View File

@ -1,8 +1,7 @@
<template>
<view class="page">
<!-- 导航栏 -->
<navbar title="订单详情 " leftClick @leftClick="navigateBack" bgColor="#019245"
color="#fff" />
<navbar title="订单详情 " leftClick @leftClick="navigateBack" bgColor="#019245" color="#fff" />
<!-- 店铺信息 -->
<view class="shop-info">
@ -54,13 +53,13 @@
<view class="order-info">
<view class="info-item">
<text class="info-label">合计:</text>
<text class="info-value price">{{ orderDetail.priceAll.toFixed(2) }}</text>
<text class="info-value price">{{ orderDetail.pricePay }}</text>
</view>
<view class="info-item" v-if="orderStatus != '-1'" >
<view class="info-item">
<text class="info-label">创建时间:</text>
<text class="info-value">{{ orderDetail.createTime }}</text>
</view>
<view class="info-item" v-if="orderStatus != '-1'">
<view class="info-item">
<text class="info-label">订单编号:</text>
<text class="info-value">{{orderDetail.id}}</text>
</view>
@ -68,56 +67,62 @@
</view>
<view class="discount-info-container">
<!-- 优惠信息 -->
<view class="discount-info" @click="gotoCoupon">
<view class="discount-info">
<view class="discount-header">
<text>优惠</text>
</view>
<view class="discount-item">
<view class="discount-left">
<view class="discount-left" v-ifan class="s">="orderDetail.pricePreferential">
<image src="@/static/image/券.webp" mode="aspectFill" class="coupon-icon" />
<view>新用户立减</view>
</view>
<text class="discount-amount">-{{ orderDetail.pricePreferential || 0 }}</text>
<text v-if="orderDetail.pricePreferential" class="discount-amount">{{orderDetail.pricePreferential}}</text>
<text v-else class="none-discount-amount">未使用优惠卷</text>
</view>
</view>
<!-- 备注 -->
<view class="remark-section">
<view class="remark-header">
<text>备注</text>
</view>
<view class="remark-content">
<input v-if="orderStatus === '0' || orderStatus === '-1'" type="text" v-model="orderDetail.remark"
placeholder="请输入您要备注的内容" placeholder-style="font-size: 28rpx" />
<text v-else>{{orderDetail.remark || '无备注信息'}}</text>
</view>
</view>
</view>
<!-- 支付方式 -->
<uv-radio-group v-model="payMethod" v-if="orderStatus === '0' || orderStatus === '-1'">
<view class="payment-methods">
<view class="payment-item">
<uv-icon name="weixin-circle-fill" size="70rpx" color="#019245" />
<text class="payment-name">微信支付</text>
<uv-radio activeColor="#019245" size="40rpx" name="0" />
<!-- 备注 -->
<view class="remark-section">
<view class="remark-header">
<text>备注</text>
</view>
<view class="remark-content">
<input v-if="orderStatus === '0' " type="text" v-model="orderDetail.remark"
placeholder="请输入您要备注的内容" placeholder-style="font-size: 28rpx" />
<text v-else>{{orderDetail.remark || '无备注信息'}}</text>
</view>
</view>
<view class="payment-item">
<uv-icon name="red-packet" size="70rpx" color="#019245" />
<text class="payment-name">账户余额<text class="balance-text">(余额: {{ userInfo.balance }})</text></text>
<uv-radio activeColor="#019245" size="40rpx" name="1" />
<!-- 支付方式 -->
<uv-radio-group v-model="payMethod" v-if="orderStatus === '0' ">
<view class="payment-methods">
<view class="payment-item">
<uv-icon name="weixin-circle-fill" size="70rpx" color="#019245" />
<text class="payment-name">微信支付</text>
<uv-radio activeColor="#019245" size="40rpx" name="0" />
</view>
<view class="payment-item">
<uv-icon name="red-packet" size="70rpx" color="#019245" />
<text class="payment-name">账户余额<text class="balance-text">(余额: {{ userInfo.balance }})</text></text>
<!-- 钱不够就会禁用 -->
<uv-radio activeColor="#019245" size="40rpx" name="1" :disabled="userInfo.balance < orderDetail.pricePay" />
</view>
</view>
</view>
</uv-radio-group>
</uv-radio-group>
<!-- 底部支付栏 -->
<view class="bottom-bar">
<view class="total-section">
<text class="total-label">{{ orderDetail.goodsList.length || 0 }}<text style="color: black;">合计</text> </text>
<text class="total-price">{{ (orderDetail.pricePay || cartPay).toFixed(2) }}</text>
<!-- 底部支付栏 -->
<view class="bottom-bar">
<view class="total-section">
<text class="total-label">
{{ (orderDetail.goodsList || []).length }}
<text style="color: black;">合计</text>
</text>
<text class="total-price">{{ ( orderDetail.pricePay || 0 ).toFixed(2) || 0 }}</text>
</view>
<view class="pay-button" @tap="handlePay" v-if="orderStatus === '0' ">立即下单</view>
<view class="pay-button" @tap="handleTake" v-if="orderStatus === '3'">取餐完成</view>
</view>
<view class="pay-button" @tap="handlePay" v-if="orderStatus === '0' || orderStatus === '-1'">立即下单</view>
<view class="pay-button" @tap="handleTake" v-if="orderStatus === '3'">取餐完成</view>
</view>
</view>
</template>
@ -148,57 +153,26 @@
}
},
computed: {
...mapState(['cartData', 'userInfo']),
...mapState([ 'userInfo']),
showedFoods() {
return this.showAllFoods ? this.orderDetail.goodsList : this.orderDetail.goodsList.slice(0, 3)
},
cartPay() {
return this.orderDetail.priceAll - this.cartDiscount
return this.showAllFoods ? this.orderDetail.goodsList : (this.orderDetail.goodsList.length > 3 ? this.orderDetail.goodsList.slice(0, 3) : this.orderDetail.goodsList)
},
orderStatus() {
return this.orderDetail.status
},
// goodId,goodNum;goodId2,goodsNum
goodss() {
return this.orderDetail.goodsList.map(item => {
return `${item.goodsId},${item.num},${item.goods.price * item.num}`
}).join(';')
}
},
onLoad(options) {
//
if (options.status === 'cart') {
this.showCartData()
//
this.orderDetail.status = '-1'
this.checkBindLeader()
}
else if (options.id) {
if (options.id) {
this.getOrderDetail(options.id)
}
console.log('userInfo', this.userInfo);
},
methods: {
...mapMutations(['checkBindLeader']),
...mapMutations([ 'clearCouponData']),
//
navigateBack() {
uni.navigateBack()
},
//
showCartData() {
this.$api('queryMyLeader', {}, res => {
if (res.code === 200) {
this.teamLeader = res.result
}
})
this.orderDetail.goodsList = this.cartData.sendData
this.orderDetail.priceAll = this.cartData.priceAll
this.orderDetail.status = '-1'
},
//
getOrderDetail(id) {
this.id = id
@ -206,8 +180,6 @@
id: this.id
}, res => {
if (res.code === 200) {
console.log('res', res);
this.orderDetail = res.result.records[0]
this.teamLeader = res.result.records[0].teamLeader
}
@ -220,93 +192,41 @@
title: '支付处理中...'
})
//
if(this.orderStatus === '0'){
this.$api('payOrder',{
payType: this.payMethod,
orderId: this.id,
}, res => {
uni.hideLoading()
if (res.code === 200) {
if (this.payMethod == '0') {
uni.requestPaymentWxPay(res)
.then(( ) => {
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order'
})
this.$api('payOrder',{
payType: this.payMethod,
orderId: this.id,
}, res => {
uni.hideLoading()
if (res.code === 200) {
if (this.payMethod == '0') {
uni.requestPaymentWxPay(res)
.then(( ) => {
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order?tabIndex=1'
})
} else {
uni.showToast({
title: '下单成功',
icon: 'success'
})
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order'
})
}
}
})
}
//
else if(this.orderStatus === '-1'){
console.log('goodss', this.goodss);
this.$api('createOrder',{
priceAll: this.orderDetail.priceAll,
pricePay: this.orderDetail.priceAll - 0,
pricePreferential: 0,
payType: this.payMethod,
leaderId: this.teamLeader.id,
goodss: this.goodss
}, res => {
uni.hideLoading()
console.log('res', res);
if(res.code === 200){
if (this.payMethod == '0') {
uni.requestPaymentWxPay(res)
.then(n => {
} else {
uni.showModal({
title: '提示',
content: '确认使用余额支付吗?',
confirmColor: '#019245',
success: (result) => {
if (result.confirm) {
uni.showToast({
title: '下单成功',
icon: 'success'
})
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order'
url: '/pages/index/order?tabIndex=1'
})
})
} else {
uni.showToast({
title: '下单成功',
icon: 'success'
})
setTimeout(uni.redirectTo, 700, {
url: '/pages/index/order'
})
}
}
}
})
}
})
}
}
})
},
// handlePickOrder(orderId) {
// uni.showModal({
// title: '',
// content: '',
// confirmColor: '#019245',
// success: (res) => {
// if (res.confirm) {
// this.$api('finishMemberOrderById', {
// memberOrderId: orderId
// }, res => {
// if (res.code === 200) {
// uni.showToast({
// title: '',
// icon: 'success',
// duration: 2000
// })
// this.getData()
// }
// })
// }
// }
// })
// }
//
handleTake() {
this.$api('finishMemberOrderById', {
@ -322,12 +242,6 @@
}, 1000)
}
})
},
//
gotoCoupon() {
this.$utils.navigateTo({
url: '/pages_order/mine/coupon?isUseinOrder=true'
})
}
}
}
@ -524,6 +438,11 @@
color: #f00;
font-weight: 500;
}
.none-discount-amount{
color: gray;
font-weight: 500;
}
}
}


+ 13
- 4
store/store.js View File

@ -35,7 +35,7 @@ const store = new Vuex.Store({
res.result.records.forEach(n => {
state.configList[n.paramCode] = n.paramValueText ||
n.paramValue ||
n.paramValueImage
n.paramValueImage || n.paramValueArea
});
console.log('configList', state.configList);
}
@ -164,7 +164,7 @@ const store = new Vuex.Store({
if(reLaunch){
uni.reLaunch({
url: '/pages/index/category'
url: '/pages/index/index'
})
}
@ -212,7 +212,7 @@ const store = new Vuex.Store({
},
// 检查绑定团长与否
checkBindLeader(){
api('queryLeaderInfo', {}, res => {
api('queryMyLeader', {}, res => {
if(res.code == 500 || !res.result) {
uni.showModal({
title: '提示',
@ -227,10 +227,19 @@ const store = new Vuex.Store({
}
}
})
}else {
return res.result
}
})
},
// 设置选中的优惠券数据
setCouponData(state, data){
state.couponData = data
},
// 清除选中的优惠卷数据
clearCouponData(state){
state.couponData = {}
}
},
actions: {},
})


+ 1
- 1
utils/utils.js View File

@ -200,7 +200,7 @@ export function navigateTo(...args){
export function navigateBack(num = -1){
if(getCurrentPages().length == 1){
uni.reLaunch({
url: '/pages/index/category'
url: '/pages/index/index'
})
return
}


Loading…
Cancel
Save