fix: 代客下单修复先打折后选会员导致结算价格为负数问题。订单退款增加安全密码校验,代客下单修复选择用户手机号未展示问题

This commit is contained in:
YeMingfei666 2025-03-21 16:01:07 +08:00
parent 5891fe6e1f
commit d097d73f12
6 changed files with 409 additions and 92 deletions

View File

@ -233,7 +233,11 @@
<!-- 退款 -->
<div
class="u-p-20 u-flex u-row-right"
v-if="detail.status !== 'refund' && detail.status !== 'unpaid'"
v-if="
detail.status !== 'refund' &&
detail.status !== 'unpaid' &&
detail.status !== 'cancelled'
"
>
<el-checkbox
v-model="allSelected"

View File

@ -0,0 +1,270 @@
<template>
<div class="select_desk">
<el-dialog width="410px" title="安全密码" v-model="show" @close="reset">
<div class="select_desk_dialog u-p-b-20">
<key-board isCanEmpty v-model="number" @clear="clear" :maxLength="6">
<template #input>
<span class="u-font-32" style="transform: translateY(3px)">
{{ returnPwd }}
</span>
</template>
</key-board>
<div class="confirm_btns u-flex u-m-t-20">
<el-button style="width: 100%" type="primary" @click="confirm">确定</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<script setup>
import keyBoard from "@/views/tool/Instead/components/keyboard.vue";
const state = reactive({
number: "",
show: false,
data: {},
});
const { number, show } = toRefs(state);
const min = ref(1);
const returnPwd = computed(() => {
return number.value.replace(/./g, "*");
});
function reset() {}
function clear(e) {
number.value = "";
}
const emits = defineEmits(["confirm"]);
function confirm() {
if (`${number.value}`.length <= 0) {
return ElMessage.error("请输入密码!");
}
emits("confirm", number.value);
close();
}
function open() {
show.value = true;
}
function close() {
show.value = false;
number.value = "";
}
defineExpose({
open,
close,
});
</script>
<style lang="scss" scoped>
:deep(.keybord-box .box_status) {
border: 1px solid #dcdfe6;
}
:deep(.el-button) {
padding: 12px 20px;
}
:deep(.carts .box_status) {
border: none;
}
:deep(.el-input__inner::-webkit-inner-spin-button) {
-webkit-appearance: none;
margin: 0;
}
:deep(.el-input__inner::-webkit-outer-spin-button) {
-webkit-appearance: none;
margin: 0;
}
:deep(.el-button--success) {
border-color: #22bf64;
background-color: #22bf64;
}
.select_desk .btn {
height: 34px;
}
.tags {
font-size: 16px;
&.using {
color: rgb(234, 64, 37);
}
&.wait {
color: rgb(252, 236, 79);
}
&.idle {
color: rgb(137, 234, 71);
}
&.closed {
color: rgb(221, 221, 221);
filter: grayscale(1);
}
}
:deep(.inputs .el-input__inner) {
border-color: transparent !important;
color: rgba(0, 0, 0, 0.8);
letter-spacing: 1.25px;
font-size: 20px;
}
.select_desk .select_desk_dialog {
display: flex;
flex-direction: column;
align-items: center;
}
.select_desk .select_desk_dialog .nav {
width: 286px;
height: 38px;
background: #dcf0e8;
justify-content: space-around;
}
.select_desk .select_desk_dialog .nav .li,
.select_desk .select_desk_dialog .nav {
border-radius: 4px;
display: flex;
align-items: center;
}
.select_desk .select_desk_dialog .nav .li {
width: 140px;
height: 34px;
color: #0fc161;
justify-content: center;
font-size: 14px;
cursor: pointer;
}
.select_desk .select_desk_dialog .nav .lion {
background: #0fc161;
color: #fff;
}
.select_desk .select_desk_dialog .inputs {
width: 370px;
line-height: 54px;
margin-top: 24px;
height: 54px;
margin-bottom: 20px;
background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
color: rgba(0, 0, 0, 0.8);
letter-spacing: 1.25px;
text-align: center;
font-size: 20px;
position: relative;
}
.price {
font-size: 18px;
text-align: left;
color: rgb(255, 81, 82);
font-weight: 600;
}
.select_desk .select_desk_dialog .inputs .close {
color: #aaa;
position: absolute;
right: 10px;
height: 30px;
width: 30px;
line-height: 30px;
top: 50%;
margin-top: -15px;
cursor: pointer;
}
.guazhangren {
padding: 12px 10px;
border: 1px solid #dcdfe6;
border-radius: 4px;
margin-top: 20px;
min-height: 58px;
color: #999;
cursor: pointer;
.name {
color: #3f9eff;
}
}
.select_desk .select_desk_dialog .keyboard {
display: flex;
flex-wrap: wrap;
width: 100%;
margin-top: 20px;
margin-bottom: 10px;
border-right: 1px solid #dcdfe6;
border-bottom: 1px solid #dcdfe6;
}
.select_desk .select_desk_dialog .keyboard .li {
height: 60px;
width: 33.333%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: #212121;
cursor: pointer;
user-select: none;
border-left: 1px solid #dcdfe6;
border-top: 1px solid #dcdfe6;
transition: all 0.1s;
}
.select_desk .select_desk_dialog .keyboard .li:hover {
background: #dcdfe6;
}
.select_desk .select_desk_dialog .keyboard .li .icon {
font-size: 1.3em;
}
.select_desk .select_desk_dialog .keyboard .confirm {
height: 140px;
background: #ff9f2e;
position: absolute;
bottom: 0;
right: 0;
border-right: none;
}
.select_desk .select_desk_dialog .keyboard .confirm:hover {
background: #f88502;
}
.confirm_btns {
display: flex;
justify-content: space-between;
width: 100%;
}
.confirm_btns .el-button {
width: 175px;
}
</style>

View File

@ -1,102 +1,110 @@
<template>
<el-dialog title="修改退款金额" width="410px" v-model="show" @close="reset" :modal="modal">
<div class="u-flex u-col-top" v-if="goodsList && goodsList.length">
<span class="u-m-0">退款商品</span>
<div class="u-p-l-20 goods-list">
<div
class="u-flex u-font-12 goods-list-item"
v-for="(goods, index) in goodsList"
:key="index"
>
<span class="">
{{ goods.productName }}
</span>
<span class="color-999 u-m-l-10">x{{ goods.selNumber || "" }}</span>
<span class="color-333 u-m-l-10 u-font-600">
{{ (goods.selNumber * goods.unitPrice).toFixed(2) }}
</span>
<div>
<el-dialog title="修改退款金额" width="410px" v-model="show" @close="reset" :modal="modal">
<div class="u-flex u-col-top" v-if="goodsList && goodsList.length">
<span class="u-m-0">退款商品</span>
<div class="u-p-l-20 goods-list">
<div
class="u-flex u-font-12 goods-list-item"
v-for="(goods, index) in goodsList"
:key="index"
>
<span class="">
{{ goods.productName }}
</span>
<span class="color-999 u-m-l-10">x{{ goods.selNumber || "" }}</span>
<span class="color-333 u-m-l-10 u-font-600">
{{ (goods.selNumber * goods.unitPrice).toFixed(2) }}
</span>
</div>
</div>
</div>
</div>
<div class="u-flex u-col-top u-m-t-22">
<span class="u-m-0">支付金额</span>
<div class="u-p-l-20">
{{ detail.payAmount }}
</div>
</div>
<div class="u-flex u-col-top u-m-t-22">
<span class="u-m-0">优惠金额</span>
<div class="u-p-l-20">
{{ detail.discountAmount }}
</div>
</div>
<div class="u-p-b-16 u-m-t-22">
<div class="flex u-row-between">
<span class="color-red">退款金额</span>
<div class="u-flex u-flex-1 u-p-l-20">
<el-input-number
type="number"
v-model="number"
:min="min"
:max="canReturnMoney"
></el-input-number>
<span class="u-m-l-10">可退{{ canReturnMoney }}</span>
</div>
</div>
<div class="u-flex u-col-top u-m-t-22" v-if="detail.returnAmount * 1 > 0">
<span class="u-m-0">退款金额</span>
<div class="u-flex u-col-top u-m-t-22">
<span class="u-m-0">支付金额</span>
<div class="u-p-l-20">
<span class="color-red"> {{ detail.returnAmount || 0 }}</span>
<!-- <span class="color-666 u-m-l-4">(退款商品金额)</span> -->
{{ detail.payAmount }}
</div>
</div>
<!-- <div class="u-flex u-col-top u-m-t-22">
<div class="u-flex u-col-top u-m-t-22">
<span class="u-m-0">优惠金额</span>
<div class="u-p-l-20">
{{ detail.discountAmount }}
</div>
</div>
<div class="u-p-b-16 u-m-t-22">
<div class="flex u-row-between">
<span class="color-red">退款金额</span>
<div class="u-flex u-flex-1 u-p-l-20">
<el-input-number
type="number"
v-model="number"
:min="min"
:max="canReturnMoney"
></el-input-number>
<span class="u-m-l-10">可退{{ canReturnMoney }}</span>
</div>
</div>
<div class="u-flex u-col-top u-m-t-22" v-if="detail.returnAmount * 1 > 0">
<span class="u-m-0">退款金额</span>
<div class="u-p-l-20">
<span class="color-red"> {{ detail.returnAmount || 0 }}</span>
<!-- <span class="color-666 u-m-l-4">(退款商品金额)</span> -->
</div>
</div>
<!-- <div class="u-flex u-col-top u-m-t-22">
<span class="u-m-0">退回优惠券</span>
<div class="u-p-l-20">
<span class="color-666 u-m-l-4">该订单未使用优惠券</span>
</div>
</div> -->
</div>
</div>
<div class="u-p-b-16 border-bottom">
<div class="flex">
<span class="u-m-r-12">是否现金</span>
<el-switch v-model="cash"></el-switch>
<div class="u-p-b-16 border-bottom">
<div class="flex">
<span class="u-m-r-12">是否现金</span>
<el-switch v-model="cash"></el-switch>
</div>
</div>
</div>
<div class="u-m-t-26">
<div>
<span>退款原因</span>
<span class="color-red">*</span>
<div class="u-m-t-26">
<div>
<span>退款原因</span>
<span class="color-red">*</span>
</div>
</div>
</div>
<div class="u-flex u-flex-wrap tags">
<div
class="tag"
v-for="(tag, index) in tags"
@click="changeSel(tag)"
:key="index"
:class="{ active: tag.checked }"
>
{{ tag.label }}
<div class="u-flex u-flex-wrap tags">
<div
class="tag"
v-for="(tag, index) in tags"
@click="changeSel(tag)"
:key="index"
:class="{ active: tag.checked }"
>
{{ tag.label }}
</div>
</div>
</div>
<div class="u-m-t-20">
<el-input v-model="note" placeholder="请输入自定义备注"></el-input>
</div>
<template #footer>
<div>
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
<div class="u-m-t-20">
<el-input v-model="note" placeholder="请输入自定义备注"></el-input>
</div>
</template>
</el-dialog>
<template #footer>
<div>
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</div>
</template>
</el-dialog>
<safe-password ref="refPassword" @confirm="pwdConfirm"></safe-password>
</div>
</template>
<script>
import { ElMessage } from "element-plus";
import safePassword from "./password.vue";
import { useUserStore } from "@/store/modules/user";
const shopUser = useUserStore();
export default {
components: {
safePassword,
},
props: {
modal: {
type: Boolean,
@ -178,16 +186,16 @@ export default {
this.show = false;
this.number = 1;
},
confirm() {
pwdConfirm(pwd) {
this.emitTuikuan({ pwd });
},
emitTuikuan(e) {
const selTag = this.tags
.filter((item) => item.checked)
.map((item) => item.label)
.join(",");
const note = selTag + (this.note.length > 0 ? "," + this.note : "");
console.log(note);
if (!note) {
return ElMessage.error("请输入退款原因");
}
this.$emit("confirm", {
refundAmount: this.number,
cash: this.cash,
@ -195,9 +203,25 @@ export default {
refundDetails: this.goodsList.map((v) => {
return { id: v.id, num: v.num };
}),
...e,
});
this.close();
},
confirm() {
const selTag = this.tags
.filter((item) => item.checked)
.map((item) => item.label)
.join(",");
const note = selTag + (this.note.length > 0 ? "," + this.note : "");
if (!note) {
return ElMessage.error("请输入退款原因");
}
if (shopUser.userInfo.isReturnPwd) {
this.$refs.refPassword.open();
return;
}
this.emitTuikuan();
},
},
mounted() {},
};

View File

@ -22,7 +22,10 @@
<el-table-column label="用户" prop="headImg" width="200px">
<template v-slot="scope">
<div class="user_info">
<el-image :src="scope.row.headImg" style="width: 40px; height: 40px; flex-shrink: 0">
<el-image
:src="scope.row.headImg"
style="width: 40px; height: 40px; flex-shrink: 0"
>
<template #error>
<div class="image-slot">
<i class="el-icon-user"></i>
@ -33,7 +36,7 @@
</div>
</template>
</el-table-column>
<el-table-column label="手机号" prop="telephone" width="160"></el-table-column>
<el-table-column label="手机号" prop="phone" width="160"></el-table-column>
<el-table-column label="会员" prop="isVip">
<template v-slot="scope">
@ -52,9 +55,14 @@
</el-table>
</div>
<div class="head-container">
<el-pagination :total="tableData.total" :current-page="tableData.page + 1" :page-size="tableData.size"
@size-change="sizeChange" @current-change="paginationChange"
layout="total, sizes, prev, pager, next, jumper"></el-pagination>
<el-pagination
:total="tableData.total"
:current-page="tableData.page"
:page-size="tableData.size"
@size-change="sizeChange"
@current-change="paginationChange"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
</div>
</div>
</el-dialog>
@ -119,7 +127,7 @@ function toPage(type) {
}
function sizeChange() {
tableData.value.page = 0;
tableData.value.page = 1;
getTableData();
}
//
@ -142,7 +150,7 @@ function resetHandle() {
}
//
function paginationChange(e) {
tableData.value.page = e - 1;
tableData.value.page = e;
getTableData();
}
async function getTableData() {
@ -151,7 +159,7 @@ async function getTableData() {
const res = await shopUserApi.getList({
...query.value,
size: tableData.value.size,
page: tableData.value.page + 1,
page: tableData.value.page,
});
tableData.value.loading = false;
tableData.value.data = res.records;

View File

@ -92,6 +92,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
maxLength: {
type: Number,
default: 14,
},
});
const number = defineModel({
@ -109,6 +113,9 @@ function clearFunction() {
const regex = /^\d+(\.\d{1,2})?$/;
function keyboradAdd(n) {
if (`${number.value}`.length >= props.maxLength) {
return;
}
if (n == "." && `${number.value}`.includes(".")) {
return;
}
@ -315,7 +322,7 @@ function keyboradConfirm() {
height: 58px;
background: #fff;
border-radius: 4px;
overflow: hidden;
display: flex;
justify-content: center;

View File

@ -347,6 +347,10 @@ watch(
() => props.user.id,
(newval) => {
quansSelArr.value = [];
checkOrderPay.discountAmount = 0;
checkOrderPay.discount = 0;
score.sel = -1;
usePointsNumber.value = 0;
if (newval !== "") {
pointsInit();
}