<template> <div class="page"> <div class="card"> <div class="row head-row"> <div class="l">商品总额</div> <div class="r">{{ totalPrice }}</div> </div> <!-- 优惠券 --> <div class="row" v-if="discount.show"> <div class="l">折扣</div> <div class="r"> {{ (totalPrice - discount.value) | plusMinus }} <span class="close" @click="removeDiscount"> <my-image class="img" src="/static/icon/close2.png" ></my-image> </span> </div> </div> <!-- 支付方式 --> <div class="row" v-if="curPayType"> <div class="l">{{ curPayType | payStr }}</div> <div class="r"> -{{ payType[curPayType] }} <span class="close" @click="closePayType"> <my-image class="img" src="/static/icon/close2.png" ></my-image> </span> </div> </div> <!-- 信息 --> <div class="info" v-if="surplusPrice > 0 && !payErr"> <div class="tools"> <span @click="discountShow">折扣</span> </div> <div class="money"> <span>应收(元)</span> <span class="price"> {{ surplusPrice }} </span> </div> </div> <div class="success" v-if="surplusPrice <= 0 && !payErr"> <my-image v-if="surplusPrice === 0" class="img" src="/static/icon/ok1.png" ></my-image> <my-image v-if="surplusPrice < 0" class="img" src="/static/icon/ok2.png" ></my-image> <div class="text" :class="{ text2: surplusPrice < 0 }"> {{ successText }} </div> </div> <div class="success" v-if="orderId && payErr"> <my-image class="img" src="/static/icon/error.png"></my-image> <div class="text err-text">结算成功,支付失败,请重新支付</div> </div> </div> <div class="submit-btn" v-if="!payErr && surplusPrice <= 0" @click="submit" > 结算 </div> <div class="submit-btn" v-if="orderId && payErr" @click="payModal"> 继续支付 </div> <ul class="pay-list" v-if="surplusPrice > 0"> <li class="item" @click="showPay('1')">现金</li> <li class="item" @click="showPay('2')">刷卡</li> <li class="item" @click="showPay('3')">扫码</li> </ul> <div class="modal" v-if="cashVisibile"> <div class="bg" @click="cashHide"></div> <div class="modal-body"> <div class="modal-head"> <div>现金</div> <div @click="cashHide"> <my-image class="close" src="/static/icon/close3.png" ></my-image> </div> </div> <div class="modal-main"> <div class="collection"> <section class="l"> <div class="name">实收</div> <!-- <input type="d" class="digit"> --> <div class="input" :class="{ focus: inputType === 3 }" > {{ payType[1] }} </div> <div class="surplus">剩余应收{{ actualPrice }}</div> </section> <section class="r"> <div class="name">找零</div> <div class="input">{{ remnant }}</div> </section> </div> </div> <keyboard-package @onInput="onInput($event, 'cash')" @onDelete="onDelete('cash')" @onConfirm="onConfirm('cash')" ></keyboard-package> </div> </div> <!-- 折扣 --> <div class="modal" v-if="discountVisibile"> <div class="bg" @click="discountVisibile = false"></div> <div class="modal-body"> <div class="modal-head"> <div>折扣</div> <div @click="discountVisibile = false"> <my-image class="close" src="/static/icon/close3.png" ></my-image> </div> </div> <div class="modal-main"> <div class="collection"> <section class="l" @click="inputType = 0"> <div class="name">折后总额</div> <!-- <input type="d" class="digit"> --> <div class="input" :class="{ focus: inputType === 0 }" > {{ discount.value }} </div> </section> <section class="r" @click="inputType = 1"> <div class="name">折扣率</div> <div class="input" :class="{ focus: inputType === 1 }" > {{ discount.ratio }} </div> % </section> </div> <ul class="dis-list" v-if="discountList && discountList.length" > <li v-for="item of discountList" :key="item"> <div class="box" @click="disItemClick(item)"> {{ item }}折 </div> </li> </ul> </div> <keyboard-package :disableDot="inputType === 1" @onInput="onInput($event, 'discount')" @onDelete="onDelete('discount')" @onConfirm="onConfirm('discount')" ></keyboard-package> </div> </div> <uni-popup ref="popup" type="dialog"> <uni-popup-dialog-pay mode="input" :title="'付款码'" :content="false" :inputType="'number'" :beforeClose="true" placeholder="请输入付款码" @confirm="popupConfirm" @scan="seanCode" @close="popupClose" ></uni-popup-dialog-pay> </uni-popup> </div> </template> <script> import MyImage from "../../../components/image/index"; import KeyboardPackage from "../../../components/keyboard-package/keyboard-package"; import uniPopup from "../../../components/uni-popup/uni-popup"; import uniPopupDialogPay from "../../../components/uni-popup/uni-popup-dialog-pay"; export default { name: "", components: { MyImage, KeyboardPackage, uniPopup, uniPopupDialogPay }, filters: { plusMinus(v) { if (v > 0) { return "-" + +v.toFixed(2); } else { v = 0 - v; return "+" + v.toFixed(2); } }, payStr(v) { switch (v) { case "1": return "现金"; case "2": return "刷卡"; case "3": return "扫码"; } }, }, // 数据 data() { return { goods: [], inputType: 0, // 0 折扣总额。 1 折扣率 3 现金 cashVisibile: false, // 输入现金显示 payShow: "", curPayType: "", payType: { 1: "", // 现金 2: "", // 刷卡 3: "", // 扫码 }, // 折扣 discountList: [], // 折扣列表 discountVisibile: false, discount: { show: false, ratio: "", value: "", }, btnLoading: false, orderId: "", payErr: false, }; }, onLoad() { this.goods = this.$store.state.common.cashierGoodList; if (!this.goods) { this.router.back(); } this.getConfig(); }, async onShow() { this.$store.commit("common/update", { closeSelectList: false, }); }, // 函数 methods: { getConfig() { this.api .get("/Store/GetStoreConfig", { id: this.user.storeId, }) .then((res) => { let data = res.data; if (data.orderConfig && data.orderConfig.discountList) { this.discountList = data.orderConfig.discountList; } }); }, showPay(type) { this.curPayType = type; if (type === "1") { // 现金 this.cashVisibile = true; this.cacheCashVal = this.payType[1]; if (!this.payType[1]) { this.payType[1] = this.actualPrice; } } else { this.payType[type] = this.actualPrice; } }, onInput(v, name) { switch (name) { case "discount": this.discount.show = true; // 折扣 if (this.inputType === 0) { this.discount.value += v; this.computeDiscountRatio(); } else { this.discount.ratio += v; this.computeDiscountValue(); } break; case "cash": // 现金 console.log(this.payType[1], v); this.payType[1] = String(this.payType[1]) + v; break; default: break; } }, onDelete(name) { switch (name) { case "discount": // 折扣 if (this.inputType === 0) { this.discount.value = this.discount.value.replace( /.$/, "" ); this.computeDiscountRatio(); if (this.discount.value === "") { this.discount.show = false; } } else { this.discount.ratio = String( this.discount.ratio ).replace(/.$/, ""); if (this.discount.ratio === "") { this.discount.show = false; } this.computeDiscountValue(); } break; case "cash": // 现金 let str = String(this.payType[1]).replace(/.$/, ""); this.payType[1] = str; break; default: break; } }, onConfirm(name) { switch (name) { case "discount": // 折扣 this.discountVisibile = false; break; case "cash": // 现金 if (this.payType[1] < this.actualPrice) { this.fn.showToast("收款金额不能小于应收金额"); return; } this.cashVisibile = false; break; default: break; } }, cashHide() { if (this.cacheCashVal !== this.payType[1]) { this.payType[1] = this.cacheCashVal; } this.cashVisibile = false; }, // 删除折扣 removeDiscount() { this.discount.show = false; this.discount.ratio = ""; this.discount.value = ""; this.orderId = ""; this.payErr = false; }, // 折扣显示 discountShow() { this.discountVisibile = true; this.inputType = 0; }, // 计算折扣后值 computeDiscountValue() { let ratioV = ( (this.totalPrice * this.discount.ratio) / 100 ).toFixed(2); this.discount.value = ratioV; }, // 计算折扣率 computeDiscountRatio() { this.discount.ratio = Math.round( (this.discount.value / this.totalPrice) * 100 ); }, // 打折点击 disItemClick(val) { this.discount.show = true; this.discount.ratio = val; this.computeDiscountValue(); }, closePayType() { this.curPayType = ""; this.payErr = false; }, submit() { if (this.btnLoading) { return; } let sendData = { totalAmount: parseInt(this.totalPrice * 100), payAmount: parseInt(this.payAmount * 100), discount: this.discount.show ? Number(this.discount.ratio) : 100, // 折扣 payMethod: Number(this.curPayType), // 支付方式,1-现金支付,2-刷卡支付,3-扫码 orderItems: [], }; for (let item of this.goods) { sendData.orderItems.push({ productId: item.id, // skuId:item.id, skuId: item._sku ? item._sku.skuId : "", count: item.isWeightGood ? parseInt(item.select_num * 1000) : item.select_num, remark: "", }); } console.log(sendData); this.submitLoading = true; uni.showLoading({ title: "提交中...", mask: true, }); // 扫码失败后的现金支付 if (this.orderId && sendData.payMethod !== 3) { this.api .post( "/Order/CashPay", { orderId: this.orderId, payMethod: sendData.payMethod, query: true, }, { pass: true } ) .then((res) => { this.btnLoading = false; uni.hideLoading(); if (res.success) { this.fn.showToast("保存成功"); this.$store.commit("common/update", { closeSelectList: true, }); this.router.back(); } else { this.fn.showModal({ content: res.message, showCancel: false, }); } }); } else { this.api .post("/Order/Settle", sendData, { pass: true }) .then((res) => { this.btnLoading = false; uni.hideLoading(); if (res.success) { // 微信 支付宝支付 if ( this.curPayType === "4" || this.curPayType === "3" ) { this.orderId = res.data; this.payModal(); } else { this.fn.showToast("保存成功"); this.$store.commit("common/update", { closeSelectList: true, }); this.router.back(); } } else { this.fn.showModal({ content: res.message, showCancel: false, }); } }); } }, payModal() { this.$refs.popup.open({ type: "dialog", }); }, seanCode(done) { let self = this; uni.scanCode({ scanType: "barCode", success(res) { console.log("扫码", res); if ( res.scanType === "CODE_128" || res.scanType === "QR_CODE" ) { uni.showLoading({ title: "支付中...", mask: true, }); self.api .post( "/order/BarcodePay", { query: true, orderId: self.orderId, barcode: res.result, }, { pass: true } ) .then((res) => { uni.hideLoading(); if (res.success) { self.fn.showToast("支付成功"); done(); self.router.back(); self.$store.commit("common/update", { closeSelectList: true, }); } else { self.fn.showToast( "支付失败:" + res.message ); self.payErr = true; } }); } else { self.fn.showToast("扫码失败"); self.payErr = true; } }, fail(res) { self.fn.showToast("扫码失败"); console.log("扫码失败:", res); self.payErr = true; }, }); }, popupConfirm(done, value) { let self = this; uni.showLoading({ title: "支付中...", mask: true, }); self.api .post( "/order/BarcodePay", { query: true, orderId: self.orderId, barcode: value, }, { pass: true } ) .then((res) => { uni.hideLoading(); if (res.success) { self.fn.showToast("支付成功"); self.router.back(); this.$store.commit("common/update", { closeSelectList: true, }); } else { self.fn.showToast("支付失败:" + res.message); self.payErr = true; } }); }, popupClose(done) { this.fn.showToast("扫码支付失败"); this.payErr = true; done(); }, }, // 数据计算 computed: { user() { return this.$store.state.user.user; }, // 总金额 totalPrice() { let n = 0; for (let item of this.goods) { // 是否为称重 if (item.isWeightGood) { let m = (item.price / 100) * item.select_num; m = Number(m.toFixed(2)); n += m; } else { if (item._sku) { n += (item._sku.price / 100) * item.select_num; } else { n += (item.price / 100) * item.select_num; } } } n = n.toFixed(2); return parseFloat(n); // return 100; }, // 打折 优惠 后价格 actualPrice() { let price = this.totalPrice; if (this.discount.show) { price = this.discount.value; } return price; }, // 收款金额 payAmount() { let v = 0; console.log(this.payType, this.curPayType); if (this.payType[this.curPayType]) { v += Number(this.payType[this.curPayType]); } return v; }, // 收款后还差多少 surplusPrice() { let v = this.actualPrice; if (this.payAmount) { v = v - this.payAmount; } return v; }, // 成功显示文字 successText() { if (this.surplusPrice === 0) { return `实收 ¥${this.actualPrice}`; } else { return `实收 ¥${this.actualPrice - this.surplusPrice},找零¥${ 0 - this.surplusPrice }`; } }, // 找零 remnant() { if ( this.payType[1] && Number(this.payType[1]) > Number(this.actualPrice) ) { let num = Number(this.payType[1]) - Number(this.actualPrice); return num.toFixed(2); } else { return 0; } }, }, // 数据监听 watch: {}, }; </script> <style lang="scss" scoped> .page { background-color: #0399ce; min-height: 100vh; display: flex; flex-direction: column; justify-content: flex-end; padding-bottom: px(40); } .card { background-color: #fff; margin: px(35); border-radius: px(8); .row { display: flex; justify-content: space-between; align-items: center; padding: 0 px(30); font-size: px(38); height: px(110); color: #333; .close { width: px(40); height: px(40); border-radius: 50%; background-color: #d1d1d1; display: inline-flex; align-items: center; justify-content: center; margin-left: px(20); .img { width: px(25); height: px(25); /deep/ img { width: px(25); height: px(25); } } } } .head-row { height: px(120); font-size: px(44); border-bottom: 1px solid #f1f1f1; } .row ~ .row { border-top: 1px solid #f1f1f1; } .info { padding: px(50); display: flex; justify-content: space-between; align-items: center; } .tools { display: flex; align-items: center; span { border-radius: px(8); height: px(66); padding: 0 px(20); background-color: #ebdcbb; color: #4f3912; font-size: px(34); display: inline-flex; justify-content: center; align-items: center; & ~ span { margin-left: px(20); } } } .money { display: flex; flex-direction: column; font-size: px(40); .price { font-size: px(74); margin-top: px(15); color: #049dd7; } } } .pay-list { display: flex; justify-content: space-between; align-items: center; padding: 0 px(35); .item { width: 32%; height: px(150); border-radius: px(8); background-color: #fff; font-size: px(40); display: flex; align-items: center; justify-content: center; padding: px(30); box-sizing: border-box; } } .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 100; .bg { width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.3); } .modal-body { position: absolute; bottom: 0; left: 0; width: 100%; z-index: 1; } .modal-head { height: px(130); background-color: #f4f4f4; display: flex; align-items: center; justify-content: space-between; padding: 0 px(35); .close { width: px(40); height: px(40); /deep/ img { width: px(40); height: px(40); } } } .modal-main { padding: px(35); background-color: #fff; } } .collection { display: flex; justify-content: space-between; align-items: flex-start; .l, .r { width: 49%; } .name { font-size: px(38); color: #666; } .input { font-size: px(70); color: #333; margin-top: px(30); min-height: px(80); line-height: px(80); position: relative; display: inline-block; min-width: 2px; max-width: 100%; word-break: break-all; &.focus { &::after { content: ""; position: absolute; right: -3px; height: 1em; bottom: 3px; z-index: 1; width: 1px; background-color: #666; animation: focusLine 0.8s linear alternate infinite; } } } .surplus { font-size: px(38); color: #666; margin-top: px(30); } } @keyframes focusLine { from { opacity: 1; } to { opacity: 0; } } .success { height: px(500); display: flex; align-items: center; justify-content: center; flex-direction: column; .img { width: px(140); height: px(140); /deep/ img { width: px(140); height: px(140); } } .text { margin-top: px(40); font-size: px(50); text-align: center; color: #06cd58; } .text2 { color: #3c9ec5; } } .submit-btn { height: px(120); margin: 0 px(35); border-radius: px(8); background-color: #fff; color: #3c9ec5; font-size: px(40); display: flex; justify-content: center; align-items: center; } .dis-list { display: flex; background-color: #eee; flex-wrap: wrap; padding: px(20) px(10) px(1); margin: px(30) px(-35) 0; li { width: 25%; padding: 0 px(10); margin-bottom: px(20); } .box { display: flex; align-items: center; justify-content: center; height: px(90); border-radius: px(8); background-color: #fff; } } .err-text { color: #f00 !important; } </style>