Merge branch 'wwz' of gitee.com:shaanxi-super-shopkeeper_1/cashierdesktop into gyq

This commit is contained in:
gyq 2024-03-11 14:34:22 +08:00
commit 8339506c93
5 changed files with 627 additions and 13 deletions

View File

@ -0,0 +1,315 @@
<template>
<div class="card">
<div class="header">
<div class="t1">
<span class="title">应收:</span>
<span class="num">{{ props.amount }}</span>
</div>
<div class="t2">
<span>已付:0.00</span>
<span>优惠:0.00</span>
</div>
</div>
<div class="number_wrap">
<div class="menus">
<div class="item" :class="{ active: payActive == index }" v-for="(item, index) in payList"
:key="item.id" @click="payTypeChange(index, item)">
<div class="icon">
<el-image :src="item.icon" class="img"></el-image>
</div>
<span class="title">{{ item.payName }}</span>
</div>
</div>
<div class="input_wrap">
<div class="input" style="flex: 1;">储值:{{ money }}</div>
<div class="input" v-if="waitPayMoney > 0">待支付:{{ waitPayMoney }}</div>
</div>
<div class="blance">
<!-- 可用余额0.00 -->
</div>
<div class="keybord_wrap">
<div class="left">
<div class="item" v-for="item in 9" :key="item" @click="amountInput(`${item}`)">{{ item }}</div>
<div class="item" @click="amountInput('.')">.</div>
<div class="item" @click="amountInput('0')">0</div>
<div class="item" @click="delHandle">
<el-icon>
<CloseBold />
</el-icon>
</div>
</div>
<div class="pay_btn" v-loading="payLoading" @click="confirmOrder">
<span></span>
<span></span>
</div>
</div>
</div>
</div>
<scanModal ref="scanModalRef" :amount="props.amount" :orderId="props.orderId" @success="scanCodeSuccess" />
</template>
<script setup>
import { onMounted, ref, computed, watch } from 'vue'
import { queryPayType, accountPay, cashPay } from '@/api/pay'
import { useUser } from "@/store/user.js"
import { clearNoNum } from '@/utils'
import scanModal from '@/components/payCard/scanModal.vue'
import { ElMessage } from "element-plus";
const store = useUser()
const props = defineProps({
amount: {
type: Number,
default: 0
},
orderId: {
type: [String, Number],
default: ''
}
})
const emit = defineEmits(['paySuccess'])
const money = ref('0')
const scanModalRef = ref(null)
watch(props, (value) => {
money.value = `${props.amount}`
})
const waitPayMoney = computed(() => {
let num = JSON.stringify(props.amount - money.value)
num = Math.floor(num * 100) / 100
return num
})
const payActive = ref(0)
const payList = ref([])
const payLoading = ref(false)
//
function scanCodeSuccess() {
emit('paySuccess')
}
//
function payTypeChange(index, item) {
payActive.value = index
if (item.payType == 'scanCode') {
scanModalRef.value.show()
}
}
//
async function confirmOrder() {
try {
if (payList.value[payActive.value].payType == 'scanCode') {
scanModalRef.value.show()
} else {
if (money.value < props.amount) return
payLoading.value = true
switch (payList.value[payActive.value].payType) {
case 'deposit':
await accountPay({
orderId: props.orderId,
memberId: 1
})
break;
case 'cash':
await cashPay({
orderId: props.orderId
})
break;
default:
break;
}
payLoading.value = false
ElMessage.success('支付成功')
emit('paySuccess')
}
} catch (error) {
console.log(error)
payLoading.value = false
scanModalRef.value.loading = false
}
}
//
function amountInput(num) {
if (money.value + num <= props.amount) {
money.value = clearNoNum({ value: (money.value += num) })
} else {
money.value = clearNoNum({ value: `${props.amount}` })
}
}
//
function delHandle() {
if (!money.value) return
money.value = money.value.substring(0, money.value.length - 1)
if (!money.value) {
money.value = '0'
}
}
//
async function queryPayTypeAjax() {
try {
const res = await queryPayType({
shopId: store.userInfo.shopId
})
payList.value = res
} catch (error) {
console.log(error)
}
}
onMounted(() => {
money.value = `${props.amount}`
queryPayTypeAjax()
})
</script>
<style scoped lang="scss">
.card {
padding: var(--el-font-size-base);
height: 100%;
}
.header {
padding-bottom: var(--el-font-size-base);
border-bottom: 1px solid #ececec;
.t1 {
display: flex;
color: var(--el-color-danger);
font-weight: bold;
.title {
font-size: var(--el-font-size-base);
position: relative;
top: 14px;
}
.num {
font-size: 30px;
}
}
.t2 {
display: flex;
gap: var(--el-font-size-base);
color: #999;
padding-top: 10px;
}
}
.number_wrap {
padding: var(--el-font-size-base) 0;
.menus {
display: flex;
gap: var(--el-font-size-base);
.item {
height: 130px;
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #efefef;
padding: 10px 0;
border-radius: 10px;
position: relative;
$lineHeight: 4px;
&.active {
&::after {
content: "";
width: 50%;
height: $lineHeight;
background-color: var(--primary-color);
position: absolute;
bottom: 0;
left: 25%;
border-radius: $lineHeight;
}
}
.img {
$size: 40px;
width: $size;
height: $size;
}
.title {
padding-top: 10px;
}
}
}
.input_wrap {
display: flex;
gap: var(--el-font-size-base);
padding: var(--el-font-size-base) 0;
.input {
display: flex;
align-items: center;
height: 60px;
border-radius: 6px;
border: 1px solid var(--primary-color);
font-size: calc(var(--el-font-size-base) + 6px);
padding: 0 var(--el-font-size-base);
}
}
.blance {
color: var(--el-color-danger);
font-size: calc(var(--el-font-size-base) + 10px);
}
}
.keybord_wrap {
display: flex;
.left {
--item-height: calc((100vh - 440px) / 4);
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: var(--item-height) var(--item-height) var(--item-height) var(--item-height);
gap: var(--el-font-size-base);
.item {
background-color: #efefef;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
font-size: calc(var(--el-font-size-base) + 10px);
&:active {
background-color: #dbdbdb;
}
}
}
.pay_btn {
flex: 0.3;
border-radius: 6px;
color: #fff;
background-color: var(--el-color-warning);
margin-left: var(--el-font-size-base);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(var(--el-font-size-base) + 10px);
}
}
</style>

View File

@ -0,0 +1,278 @@
<!-- 扫码弹窗 -->
<template>
<div class="dialog">
<el-dialog title="扫码支付" width="600" v-model="dialogVisible" @open="reset">
<div class="content">
<div class="left">
<el-image :src="icon" style="width: 60px;height: 60px;"></el-image>
</div>
<div class="right" v-if="!userPayWait">
<div class="amount">
<span class="t">扫码支付</span>
<span class="n">{{ props.amount }}</span>
</div>
<div class="input">
<el-input ref="inputRef" v-model="scanCode"
style="height: calc(var(--el-component-size-large) + 20px);" placeholder="请扫描付款码"
@keydown.enter="enterHandle" clearable></el-input>
</div>
<div class="number_warp">
<div class="item" v-for="item in 9" :key="item" @click="inputHandle(item)">{{ item }}</div>
<div class="item disabled">.</div>
<div class="item" @click="inputHandle(0)">0</div>
<div class="item" @click="delHandle">
<el-icon>
<CloseBold />
</el-icon>
</div>
</div>
<div class="btn">
<el-button type="primary" style="width: 100%;" v-loading="loading"
@click="submitHandle">立即支付</el-button>
</div>
</div>
<div class="pay_wait" v-else>
<div class="loading" v-loading="loading" element-loading-text="用户支付中..."></div>
<div class="btn">
<el-button type="primary" style="width: 100%;" v-loading="checkPayStatusLoading"
@click="checkPayStauts">
<span v-if="!checkPayStatusLoading">查询用户支付状态</span>
<span v-else>查询中...</span>
</el-button>
</div>
<div class="btn">
<el-button style="width: 100%;" @click="resetScanCode">重新扫码</el-button>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script setup>
import _ from 'lodash'
import { ref } from 'vue'
import icon from '@/assets/icon_scan.png'
import { scanpay, queryOrder } from '@/api/pay'
import { ElMessage } from "element-plus";
const emits = defineEmits(['success'])
const props = defineProps({
amount: {
type: [Number, String],
default: 0
},
orderId: {
type: [Number, String],
default: ''
}
})
const dialogVisible = ref(false)
const scanCode = ref('')
const inputRef = ref(null)
const loading = ref(false)
const userPayWait = ref(false)
const checkPayStatusLoading = ref(false)
//
async function submitHandle() {
try {
if (!scanCode.value) return
loading.value = true
await scanpay({
orderId: props.orderId,
authCode: scanCode.value
})
loading.value = false
scanCode.value = ''
emits('success')
} catch (error) {
if (error.code === '100015') {
userPayWait.value = true
} else {
loading.value = false
console.log(error)
}
}
}
//
async function checkPayStauts() {
try {
const res = await queryOrder({ orderId: props.orderId })
loading.value = false
if (res.status == 'closed') {
emits('success')
scanModalRef.value.close()
} else {
checkPayStatusLoading.value = false
ElMessage.error(res.payRemark || '支付失败!')
scanModalRef.value.loading = false
}
} catch (error) {
console.log(error)
}
}
//
function resetScanCode() {
userPayWait.value = false
loading.value = false
scanCode.value = ''
inputRef.value.focus()
}
//
function inputHandle(n) {
scanCode.value += n
inputRef.value.focus()
}
//
function delHandle() {
if (!scanCode.value) return
scanCode.value = scanCode.value.substring(0, scanCode.value.length - 1)
inputRef.value.focus()
}
//
function enterHandle() {
inputRef.value.focus()
}
// const inputChange = _.debounce(function (e) {
// console.log(e);
// }, 300)
function show() {
dialogVisible.value = true
setTimeout(() => {
inputRef.value.focus()
}, 500)
}
function close() {
dialogVisible.value = false
}
function reset() {
loading.value = false
scanCode.value = ''
}
defineExpose({
show,
close,
loading
})
</script>
<style scoped lang="scss">
.dialog :deep(.el-dialog__body) {
padding: 0 !important;
}
.content {
display: flex;
.left {
width: 200px;
display: flex;
align-items: center;
justify-content: center;
background-color: #efefef;
}
.right {
flex: 1;
padding: var(--el-font-size-base);
.amount {
display: flex;
height: calc(var(--el-component-size-large) + 20px);
display: flex;
align-items: center;
justify-content: space-between;
color: var(--primary-color);
background-color: #555;
border-radius: 6px;
padding: 0 var(--el-font-size-base);
font-size: calc(var(--el-font-size-base) + 10px);
}
.input {
padding: var(--el-font-size-base) 0;
:deep(.el-input__inner) {
font-size: calc(var(--el-font-size-base) + 10px);
}
}
.number_warp {
--h: 50px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: var(--h) var(--h) var(--h) var(--h);
gap: 8px;
.item {
background-color: #dddddd;
display: flex;
align-items: center;
justify-content: center;
font-size: calc(var(--el-font-size-base) + 10px);
border-radius: 4px;
&.disabled {
color: #999;
background-color: #efefef;
&:active {
background-color: #efefef;
}
}
&:active {
background-color: #b9b9b9;
}
}
}
.btn {
padding-top: 20px;
}
}
.pay_wait {
flex: 1;
padding: 0 var(--el-font-size-base);
height: 600px;
padding-bottom: 100px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.loading {
width: 200px;
height: 200px;
--el-loading-spinner-size: 100px;
:deep(.el-loading-text) {
font-size: 20px;
}
}
.btn {
width: 200px;
padding-top: var(--el-font-size-base);
}
}
}
</style>

View File

@ -82,7 +82,7 @@
<keyboard v-if="props.membershow == '1'" @consumeFees="consumeFees"></keyboard>
<div class="orderbox_right_button" v-if="props.membershow == '0'">
<router-link to="/" style="width: 35%;">
<el-button style="width: 100%;" >创建订单</el-button>
<el-button style="width: 100%;">创建订单</el-button>
</router-link>
<el-button style="width: 60%;" type="primary" @click="recharge = true">账户充值</el-button>
</div>
@ -152,11 +152,14 @@
</cwxeyboard>
</div>
</div>
</div>
</el-dialog>
</div>
<el-dialog width="500" v-model="payCarddialogVisible" style="padding: 0; " title="会员充值" :close-on-click-modal="false">
<payCard :amount="moneys" :orderId="props.orderId" @paySuccess="paySuccess" />
</el-dialog>
</template>
<script setup>
@ -168,6 +171,8 @@ import lodash from 'lodash'
import add from '@/views/member/components/add.vue'
import cwxeyboard from '@/components/cwx-keyboard/cwx-keyboard.vue'
import keyboard from '@/views/home/components/keyboard.vue'
import payCard from '@/views/member/components/payCard/payCard.vue'
const store = useUser()
const stored = ref(false)//
@ -184,6 +189,14 @@ const props = defineProps({//首页传值
placeholder: {
type: String,
default: '提示'
},
amount: {
type: [Number, String],
default: 0
},
orderId: {
type: [String, Number],
default: ''
}
})
@ -200,7 +213,10 @@ const consumeFees = (e) => {
tableData.phone = e
}
const payCarddialogVisible = ref(false)
const confirmEvent = async () => {//
// payCarddialogVisible.value = true
try {
let res = await accountPaymember({
shopId: store.userInfo.shopId,

View File

@ -7,7 +7,7 @@
<el-input v-model="ordereData.orderNo" placeholder="请输入订单号查询" @input="inputChange" clearable />
<!-- <el-button style="margin-left: 10px;" type="primary" @click="onSubmit">搜索</el-button> -->
</div>
<add :ordereData="ordereData" @emititemboxshow="emititemboxshow" v-if="ordereData.list.length">
<add :loading="loadingboxshow" :ordereData="ordereData" @emititemboxshow="emititemboxshow" v-if="ordereData.list.length">
</add>
<div v-else style="width: 100%; text-align: center; margin: 30px 0;">暂无数据</div>
<el-pagination v-if="ordereData.list.length" layout="prev, pager, next, jumper"
@ -30,7 +30,7 @@
</el-tab-pane>
</el-tabs>
</div>
<div class="orderbox_right" v-if="itemboxshow" v-loading="orderDetaildata.loading">
<div class="orderbox_right" v-if="itemboxshow" v-loading="orderDetaildata.loading" :loading="loadingboxshow">
<div class="orderbox_right_top">
<span>堂食订单</span>
<el-icon :size="32" style="color: var(--primary-color) ;" @click="itemboxshow = false">
@ -250,7 +250,7 @@ const payreturnOrderclick = async () => {
changechecked.value = false
recharge.value = false
asyncorderfindOrder()
}else{
} else {
ElMessage.error('以没有退款项目!')
}
@ -260,18 +260,23 @@ const payreturnOrderclick = async () => {
}
const loadingboxshow = ref(false);
const emititemboxshow = async (e) => { //
loadingboxshow.value = true
try {
let res = await orderorderDetail({
shopId: store.userInfo.shopId,
id: e.id
})
itemboxshow.value = true
loadingboxshow.value = false
orderDetaildata.value = res
orderDetaildata.value.detailList.forEach((e) => {
e.checked = false
})
} catch (error) {
loadingboxshow.value = false
}
}

View File

@ -18,7 +18,7 @@
<div class="box_content_left_top_item">
<div class="box_content_left_top_item_top">
<div style="color:#ff5252; font-size: 30px;">
{{ infoData.orderNum }}
{{ infoData.orderNum || 0}}
</div>
<div style="margin-top: 6px; color: #666;">
总订单
@ -26,7 +26,7 @@
</div>
<div class="box_content_left_top_item_top">
<div style="color:#ff5252; font-size: 30px;">
{{ infoData.amount }}
{{ infoData.amount || 0}}
</div>
<div style="margin-top: 6px; color: #666;">
营业额
@ -36,7 +36,7 @@
<div class="box_content_left_top_item">
<div class="box_content_left_top_item_botton">
<div style=" font-size: 20px;">
{{ infoData.cashAmount }}
{{ infoData.cashAmount|| 0}}
</div>
<div style="margin-top: 6px;">
现金支付
@ -47,7 +47,7 @@
</div>
<div class="box_content_left_top_item_botton">
<div style=" font-size: 20px;">
{{ infoData.returnAmount }}
{{ infoData.returnAmount || 0}}
</div>
<div style="margin-top: 6px;">
退款金额
@ -89,7 +89,7 @@
终端名称
</div>
<div class="box_content_right_tiemright">
{{ infoData.equipment }}
{{ infoData.equipment || '无'}}
</div>
</div>
<div class="box_content_right_tiem">
@ -97,7 +97,7 @@
备用金
</div>
<div class="box_content_right_tiemright">
{{ infoData.pettyCash }}
{{ infoData.pettyCash || '无'}}
</div>
</div>
<div class="box_content_right_tiem">
@ -105,7 +105,7 @@
收营员
</div>
<div class="box_content_right_tiemright">
{{ infoData.userName }}
{{ infoData.userName || '无'}}
</div>
</div>
<div class="box_content_right_tiembutton" :loading="loading" @click="exit">