You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

739 lines
16 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="page" v-if="diningRoomInfo.table_info">
<div class="shop">
<div class="head">
<u-icon name="shopping-cart" color="#fff" size="16"></u-icon>
下单中
</div>
<div class="body">
<view class="floor-1">
<view class="left">
<view @click="toUrl('/subPackages/stores/restaurantList/index')"
style="margin-bottom: 20rpx;display: flex;">
<u-icon name="arrow-right" :label="diningRoomInfo.name" labelPos="left" color="#262626"
size="15"></u-icon>
</view>
<u-icon name="map" @click="openLocation(diningRoomInfo)"
:label="diningRoomInfo.detail || diningRoomInfo.name" labelColor="#a8a8a8" color="#a8a8a8"
size="12" label-size="12"></u-icon>
</view>
<view class="right">
<view class="item active">桌号:{{ diningRoomInfo.table_info.number }}</view>
</view>
</view>
</div>
</div>
<view class="settlementGoods" v-show="!openinglod">
<view class="list" @click.stop>
<view class="item" v-for="(item, index1) of goodsArr" :key="item.key">
<view class="item-menu-image" v-if="item.goods">
<u--image width="160rpx" height="160rpx" radius="10" class=""
:src="item.activeGoodsInfo.pic_url || item.goods.pic_url || item.goods.pic_url"></u--image>
</view>
<view class="info" v-if="item.goods">
<view class="item-menu-name text_line">{{ item.goods.name }}</view>
<view class="item-desc">
<view class="goods_sky">
<text v-for="(sku, _index) of item.activeGoodsInfo.attr_list" :key="_index">{{
sku.group_name
}}{{ sku.name }}
</text>
</view>
</view>
<view class="list-smallMaterialAttr mb">
<view class="smallitem" v-for="small of item.small_goods">
<view class="tags">
<view class="tag" v-for="sitem of small.group_item">
<view>
{{ sitem.name }}
</view>
<view v-if="sitem.price" class="price">
{{ sitem.price }} 元
</view>
</view>
</view>
</view>
</view>
<view class="sku" v-if="item.activeGoodsInfo">
<view class="price">
¥ {{ (item.activeGoodsInfo.price * item.num).toFixed(2) }}
</view>
<u-number-box :min="1" v-model="item.num"></u-number-box>
</view>
</view>
</view>
</view>
<view
style="padding: 20rpx;margin-top: 20rpx;background-color: white; border-radius:10rpx 10rpx 0 0; display: grid;grid-template-columns: auto 1fr;align-items: center;grid-gap: 14rpx;gap: 14rpx;">
备注 <u--input placeholder="请输入点餐备注" border="surround" v-model="value"></u--input>
</view>
<view class="settlement">
<view class="submit">
<view class="shop">
<view class="box">
<view class="price">总价:¥ {{ totalPrice }}</view>
<!-- <view class="table">桌号:{{ number }}</view> -->
</view>
</view>
<view class="btn" @click="submit" v-if="opening">
<view class="loading" v-if="loading">
<u-loading-icon size="18" color="#fff" textColor="#fff" mode="semicircle"></u-loading-icon>
</view>
<view class="text">
{{ loading ? "下单中" : "下单" }}
</view>
</view>
<view class="btn no_opening" v-else>
<view class="text">
...
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
// #ifndef MP
import wxConfig from '@/utils/wxConfig'
// #endif
export default {
components: {},
data() {
return {
mch: {},
goodsArr: [],
value: "",
n_id: "",
mch_id: "",
loading: false,
number: "",
opening: true,
openinglod: true,
discount: {
type: 1, // 1 折扣
amount: 0
},
diningRoomInfo: {},
pay_type: 0,
table_num: 0
}
},
async onLoad({
n_id,
mch_id,
number,
table_num
}) {
this.n_id = n_id
this.mch_id = mch_id
this.number = number
this.table_num = table_num
const res = await this.$api.common.getIsBusinessHours({
shop_id: mch_id
})
this.openinglod = false
if (res.code == 0) {
this.opening = res.data
}
const res1 = await this.$api.common.DiningRoom({
table_number: this.n_id,
mch_id: this.mch_id
});
this.diningRoomInfo = res1.data || {};
if (this.$utils.isInWeChatBrowser()) {
this.pay_type = 2
}
if (this.$utils.isInAliBrowser()) {
this.pay_type = 1
}
},
async onShow() {
if (!this.$utils.isInWeChatBrowser() && !this.$utils.isInAliBrowser()) {
uni.showModal({
title: '提示',
content: '请使用微信或支付宝扫码',
showCancel: false,
success() {
uni.switchTab({
url: '/pages/index/index'
})
}
})
} else {
this.goodsArr = uni.getStorageSync("take_n_id_" + this.n_id)
const res = await this.$api.common.FoodOrderPreview({
'mch_list': JSON.stringify([{
"mch_id": this.mch_id,
"shop_id": this.mch_id,
'table_num': this.table_num,
"delivery_type": 1,
"good_list": this.goodsArr.map(item => {
return {
"num": item.num,
"goods_id": item.goods.id,
"goods_sku_id": item.goods_sku_id,
"small_goods": item.small_goods,
"small_goods_json": item.small_goods_json,
}
})
}]),
table_number: this.n_id,
});
if (res.code) {
return
}
this.mch = res.data.mch_list[0]
}
},
onHide() {},
computed: {
totalPrice() {
return (this.goodsArr.reduce((pre, cur) => {
let price = cur.activeGoodsInfo.price * cur.num
// 计算小料
let smallMaterialPrice = 0
if (cur.small_goods) {
smallMaterialPrice = cur.small_goods.reduce((price, item) => {
return price + item.group_item.reduce((price, item) =>
price + item.price, 0)
}, 0)
}
smallMaterialPrice = cur.num * (Number(smallMaterialPrice))
return pre + Number(price) + smallMaterialPrice;
}, 0)).toFixed(2)
}
},
methods: {
/**
* 异步提交订单并处理结果。
*/
async submit() {
// 如果正在加载中,则直接返回,避免重复提交
if (this.loading) {
return;
}
// 开始加载
this.loading = true;
// 构建商品列表信息
const good_list = this.goodsArr.map(item => ({
"num": item.num,
"goods_id": item.goods.id,
"goods_sku_id": item.goods_sku_id,
"small_goods": item.small_goods,
}));
// 发起订单提交请求
try {
const res1 = await this.$api.common.FoodPlaceOrder({
'mch_list': JSON.stringify([{
"mch_id": this.mch_id,
"shop_id": this.mch_id,
"delivery_type": 4,
"good_list": good_list,
}]),
delivery_type: 4,
table_num: this.table_num,
table_number: this.n_id,
mark: this.value,
});
this.loading = false;
// 如果请求返回的 code 存在(可能表示请求出错),则显示相应的提示信息并返回
if (res1.code) {
return uni.$u.toast(res1.message);
}
if (res1.data.is_online && res1.data.is_online > 0) {
return this.successSubmit();
} else {
// 构建跳转链接
const order_no = res1.data && res1.data.order_merge_no ? res1.data.order_merge_no : res1.data.order_no;
this.payType(this.pay_type, order_no, 4)
}
} catch (error) {
console.error("Error occurred while submitting order:", error);
this.loading = false;
}
},
async payType(payType, order_no, order_type) {
switch (payType) {
case 1:
await this.payTreasureToPay({
payType,
order_no,
order_type
})
break;
case 2:
await this.wechatPayNow({
payType,
order_no,
order_type
})
break;
default:
break;
}
},
// H5 微信支付
async wechatPayNow({
payType,
order_no,
order_type
}) {
wxConfig.init(["chooseWXPay"]).then((wx) => {
console.log(wx.chooseWXPay);
})
try {
uni.showLoading({
title: '支付中'
})
const res = await this.$api.pay.OrderPayment({
pay_type: payType,
order_no: order_no,
order_type
});
uni.hideLoading()
if (res.code) return this.$u.toast(res.message)
if (res.data == -1) {
return this.successSubmit();
}
let that = this
wxConfig.init(["chooseWXPay"]).then(wx => {
wx.chooseWXPay({
// 支付签名时间戳注意微信jssdk中的所有使用timestamp字段均为小写。
// 但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
timestamp: res.data.timeStamp, // 时间戳
nonceStr: res.data.nonceStr, // 支付签名随机串,不长于 32 位
package: res.data.package, // 统一支付接口返回的prepay_id参数值提交格式如prepay_id=\*\*\*
signType: res.data.signType, // 签名算法
paySign: res.data.paySign, // 签名
success: function(res) {
console.log(res, 'success')
if (res.err_msg == "get_brand_wcpay_request:ok" || res.err_Info ==
"success" || res.errMsg == "chooseWXPay:ok") {
that.successSubmit();
} else {
that.failSubmit();
}
},
complete: function(err) {
console.log(res, 'complete')
if (res.err_msg == "get_brand_wcpay_request:ok" || res.err_Info ==
"success" || res.errMsg == "chooseWXPay:ok" || res.errMsg ==
"getBrandWCPayRequest:ok") {
that.successSubmit();
} else {
that.failSubmit();
}
},
})
})
} catch (error) {
this.$u.toast(error.message)
}
},
// 支付宝支付
async payTreasureToPay({
payType,
order_no,
order_type
}) {
try {
let that = this
uni.showLoading({
title: '支付中'
})
const res = await this.$api.pay.OrderPayment({
pay_type: payType,
order_no: order_no,
order_type,
});
uni.hideLoading()
if (res.code) return this.$u.toast(res.message)
if (this.$utils.isInAliBrowser()) {
AlipayJSBridge.call("tradePay", {
tradeNO: res.data.trade_no
}, function(data) {
if ("9000" == data.resultCode) {
that.successSubmit(res)
} else {
throw new Error('支付失败,状态码:' + data.resultCode)
}
});
} else {
return uni.showToast({
icon: 'none',
title: '请到支付宝或微信环境中支付'
})
}
} catch (error) {
this.$u.toast(error.message)
}
},
failSubmit() {
this.$u.toast("支付失败")
},
successSubmit() {
this.$u.toast("操作成功")
setTimeout(() => {
uni.reLaunch({
url: '/pages/takeaway/orderAndSettlement/edit?store_id=' + this.store_id + '&mch_id=' + this.mch_id + '&n_id=' + this.n_id
})
}, 1500)
},
}
}
</script>
<style lang="scss" scoped>
* {
box-sizing: border-box;
}
.shop {
padding: 24rpx;
padding-bottom: 0px;
.head {
background: linear-gradient(45deg, #cecece 38%, #ebebeb 38%, );
font-size: 24rpx;
color: white;
padding: 14rpx;
border-radius: 10rpx 10rpx 0 0;
margin: 0 10rpx;
display: flex;
align-items: center;
grid-gap: 10rpx;
gap: 10rpx;
}
.body {
border-radius: 10rpx 10rpx 10rpx 10rpx;
overflow: hidden;
}
.floor-1 {
padding: 30rpx;
display: flex;
justify-content: space-between;
align-items: center;
background: white;
.right {
padding: 12rpx 8rpx;
border-radius: 100px;
position: relative;
font-size: 18px;
font-weight: 600;
flex: 1 0 auto;
text-align: end;
.item {
padding: 12rpx 16rpx;
background-color: transparent;
}
}
}
}
.coupons {
padding: 0 20rpx;
background-color: white;
border-radius: 0 0 10rpx 10rpx;
}
.settlement {
position: fixed;
height: 122rpx;
// #ifdef MP-ALIPAY
height: 192rpx;
// #endif
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
display: flex;
flex-direction: column;
box-shadow: 0 0.3125rem 1.25rem rgba(166, 199, 251, 0.12);
z-index: 999999999999 !important;
.submit {
flex: 1;
display: flex;
align-items: center;
background-color: white;
box-shadow: 0 0.3125rem 1.25rem 20px rgba(166, 199, 251, 0.12);
// background: linear-gradient(90deg, #313233 80%, #f84d17);
}
.shop {
display: flex;
flex-direction: column;
justify-content: space-evenly;
height: 100%;
padding: 10rpx 24rpx;
.box {
// color: white;
margin-left: 11px;
font-weight: 600;
display: flex;
flex-direction: column;
justify-content: space-evenly;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-evenly;
.price {
font-size: 32rpx;
}
.table {
font-size: 28rpx;
color: rgb(168, 168, 168);
}
}
}
.btn {
background: linear-gradient(90deg, #ff1e00 0%, #ff5927 100%);
margin-left: auto;
font-size: 36rpx;
border-radius: 20rpx;
display: grid;
align-items: center;
margin: auto 0px;
margin-left: auto;
margin-right: 20rpx;
padding: 20rpx 40rpx;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.4;
box-sizing: border-box;
.loading {
margin-right: 22rpx;
}
.text {
font-weight: 600;
}
}
.no_opening {
background: linear-gradient(90deg, #e4e4e4 0%, #e4e4e4 100%);
color: #5f5f5f;
}
}
.page {
height: 100vh;
overflow: auto;
}
.settlementGoods {
overflow: hidden;
z-index: 1;
background-clip: content-box;
display: flex;
flex-direction: column;
margin: 20rpx;
border-radius: 10rpx;
margin-bottom: 220rpx;
}
.item-menu-image {
width: 160rpx;
height: 160rpx;
background: #f6f6f6;
border-radius: 20rpx;
margin-right: 24rpx;
}
.settlementGoods {
overflow: hidden;
.list {
background-color: white;
padding: 28rpx;
padding-bottom: 0;
}
.item {
display: flex;
margin-bottom: 24rpx;
.item-menu-name {
font-weight: normal;
font-size: 28rpx;
color: $u-main-color;
margin-bottom: 10rpx;
margin-top: 10rpx;
}
.info {
flex: 1;
}
.item-tag {
margin-bottom: 16rpx;
}
.item-desc {
color: rgb(168, 168, 168);
font-size: 24rpx;
margin: 0px 0px 16rpx 3px;
}
.sku {
.price {
font-weight: 600;
font-size: 14px;
}
display: flex;
justify-content: space-between;
align-items: center;
color: #ff553f;
.s-sku {
background: linear-gradient(90deg, #ff1e00 0%, #ff5927 100%);
color: white;
display: inline-flex;
padding: 6rpx 12rpx;
font-size: 12px;
font-weight: 600;
border-radius: 100px;
}
}
}
}
.list-smallMaterialAttr {
.price {
color: #f0250e;
}
font-size: 22rpx;
color: #8c8c8c;
flex: 1;
display: flex;
align-items: center;
width: 100%;
grid-gap: 8px;
gap: 8px;
flex-wrap: wrap;
margin-top: 14rpx;
margin: 0px 0px 8px 3px;
.smallitem {
display: flex;
align-items: center;
}
.tags {
display: flex;
grid-gap: 12px;
gap: 12px;
align-items: center;
flex-wrap: wrap;
.tag {
background-color: rgb(245, 245, 245);
border-radius: 100px;
display: flex;
align-items: center;
padding: 12rpx 20rpx;
.price {
// background-color: red;
margin-left: 12rpx;
border-left: 2px solid #ffffff;
// margin: -14rpx -18rpx;
padding-left: 12rpx;
}
}
}
}
.half_price_count {
font-size: 22rpx;
color: #8c8c8c;
margin-top: 6rpx;
}
/deep/ {
.u-input {
border: 1px solid rgb(236, 236, 236) !important;
border-radius: 14rpx !important;
}
}
.remarks {
padding: 14rpx 20rpx;
display: flex;
align-items: center;
font-size: 14px;
font-weight: 600;
background-color: white;
}
.minus {
border: 1px solid #e5e5e5;
border-right: none;
border-radius: 20px 0 0 20px;
padding: 6px;
}
.plus {
border: 1px solid #e5e5e5;
border-left: none;
border-radius: 0 20px 20px 0;
padding: 6px;
}
.numInput {
width: 35px;
text-align: center;
border: 1px solid #e5e5e5;
padding: 3px 0;
height: 20px;
line-height: 20px;
font-size: 12px;
color: #000;
}
</style>