订单详情完善

This commit is contained in:
wwz
2025-03-11 16:42:37 +08:00
parent 5342133cbd
commit cab9f836af
16 changed files with 506 additions and 126 deletions

View File

@@ -0,0 +1,152 @@
<template>
<view class="integral-modal" v-if="visible">
<view class="modal-mask" @click="closeModal"></view>
<view class="modal-content">
<view class="input-wrapper">
<input type="number" v-model="inputValue" :min="minValue" :max="maxValue" @input="handleInput"
placeholder="请输入积分" />
</view>
<view class="instructions">{{ instructions }}</view>
<up-button type="primary" @click="confirmIntegral" text="确定"></up-button>
<button style="margin-top: 20rpx;" @click="IntegralInputclose">取消</button>
</view>
</view>
</template>
<script setup>
import {
ref,
defineProps,
defineEmits
} from 'vue';
// 定义接收的属性
const props = defineProps({
visible: {
type: Boolean,
default: false
},
minValue: {
type: Number,
default: 1
},
maxValue: {
type: Number,
default: 100
},
instructions: {
type: String,
default: '请输入有效积分值'
}
});
// 定义事件发射器
const emits = defineEmits(['confirm', 'close','IntegralInputclose']);
// 定义响应式变量
const inputValue = ref('');
// 处理输入事件,确保输入为整数且在有效范围内
const handleInput = (e) => {
// 兼容不同平台获取输入值的方式
let value = e.detail ? e.detail.value : (e.target ? e.target.value : '');
// if (value > props.maxValue || value < props.minValue) {
// inputValue.value = value > props.maxValue ? props.maxValue : props.minValue
// return false;
// }
// 只允许输入数字,去除非数字字符
value = value.replace(/\D/g, '');
if (value) {
value = parseInt(value, 10);
// 限制输入值在最小和最大值之间
// if (value < props.minValue) {
// value = props.minValue;
// } else if (value > props.maxValue) {
// value = props.maxValue;
// }
inputValue.value = value.toString();
} else {
inputValue.value = '';
}
};
// 确认积分并返回值给父组件
const confirmIntegral = () => {
console.log(inputValue.value, 444)
if (inputValue.value < props.minValue || inputValue.value > props.maxValue) {
uni.showToast({
title: '输入的积分值不在有效范围内',
icon: 'none'
});
return false;
}
if (inputValue.value) {
const value = parseInt(inputValue.value, 10);
if (value >= props.minValue && value <= props.maxValue) {
emits('confirm', value);
emits('close');
} else {
uni.showToast({
title: '输入的积分值不在有效范围内',
icon: 'none'
});
}
} else {
uni.showToast({
title: '请输入有效的积分值',
icon: 'none'
});
}
};
const IntegralInputclose = () => {
emits('IntegralInputclose');
}
// 关闭模态框
const closeModal = () => {
emits('close');
};
</script>
<style scoped>
.integral-modal {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
}
.modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
padding: 20px;
box-sizing: border-box;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
text-align: center;
}
.input-wrapper {
margin-bottom: 15px;
}
.instructions {
margin-bottom: 20px;
color: #666;
}
</style>

View File

@@ -6,7 +6,7 @@
</view>
<!-- 先付款 -->
<view class="tabBox">
<view class="tabBox" v-if="listinfo.status == 'unpaid'">
<view class="tab">
<view v-for="(item,index) in tebtypeList" :key="index"
:class="is_type==index?'tab_item'+(is_type+1)+' tab_item active ':'tab_item'"
@@ -132,8 +132,8 @@
<view class="favorable_right" :class="{column:item.value}" v-if="item.type=='product'">
<view :class="{column:item.value}">
<view class="favorable_right_text" v-if="item.value.uniqueIds">
<text>{{item.value.uniqueIds}}</text>
<text>-{{item.value.Productroll}}</text>
<text>{{item.value.uniqueIds}}</text>
<text>-{{item.value.Productroll}}</text>
</view>
</view>
<up-icon name="arrow-right" color="#575B66" size="16"
@@ -146,25 +146,18 @@
<up-icon name="arrow-right" color="#575B66" size="16"
v-if="listinfo.status == 'unpaid' || listinfo.status == 'paying'"></up-icon>
</view>
<!-- 积分 -->
<view class="favorable_right" v-if="item.type=='points'" @click.stop="pointsChange">
<text class="favorable_right_text" style="color: #666;margin-right: 16rpx;"
v-if="calcUsablePointsData.usable">
使用 {{ calcUsablePointsData.pointsNum}}
积分抵扣{{calcUsablePointsData.pointsNum/calcUsablePointsData.equivalentPoints}}
</text>
<text class="favorable_right_text"
style="color: #666;margin-right: 16rpx;color: #DE4D3A;" v-else>
{{calcUsablePointsData.unusableReason||''}}
</text>
<up-checkbox-group iconPlacement="right" @change="pointsChange">
<up-checkbox v-model="isPointsChecked"
:disabled="freeCheck||!calcUsablePointsData.usable" :checked="isPointsChecked"
activeColor="#E8AD7B" shape="circle" icon-size="18" size="18">
</up-checkbox>
</up-checkbox-group>
<!-- 积分 -->
<view class="favorable_right" v-if="item.type=='points'"
@click.stop="calcUsablePointsData.showModal = true">
<text class="favorable_right_text" style="color: #666;margin-right: 16rpx;"
v-if="calcUsablePointsData.integral">
使用 {{ calcUsablePointsData.integral}}
积分抵扣{{props.listinfo.pointsDiscountAmount}}
</text>
<up-icon v-else name="arrow-right" color="#575B66" size="16"></up-icon>
</view>
</view>
</view>
</block>
@@ -236,6 +229,10 @@
<text class="info">{{ listinfo.seatNum || ""}}</text>
</view>
</view>
<IntegralInput :visible="calcUsablePointsData.showModal" :minValue="calcUsablePointsData.minIntegral"
:maxValue="calcUsablePointsData.maxIntegral" :instructions="calcUsablePointsData.instructionText"
@confirm="handleConfirm" @close="calcUsablePointsData.showModal = false"
@IntegralInputclose="IntegralInputclose" />
</view>
</template>
@@ -252,6 +249,14 @@
defineExpose
} from 'vue'
import IntegralInput from './IntegralInput.vue';
import {
APImemberPointsmyPoints,
APImemberPointscalcUsablePoints,
APImemberPointscalcDeductionAmount
} from '@/common/api/shop/index.js'
// 定义自定义事件
const emits = defineEmits(['customevent', 'istype']);
@@ -315,15 +320,6 @@
}
})
const calcUsablePointsData = reactive({
usable: '',
pointsNum: '',
equivalentPoints: '',
unusableReason: '',
})
const isPointsChecked = ref(false)
const is_type = ref(0)
// 监听送餐/打包切换
const tabClick = (item, index) => {
@@ -342,20 +338,12 @@
}
const childOnShow = () => {}
// * 监听优惠券/商品券选择
const changeCoupon = (data) => {}
const setPayAmount = (cartLists) => {}
// * 积分状态监听
const pointsChange = () => {}
// 跳转
const goUrl = (item) => {
switch (item.type) {
case 'coupon':
// 清空积分
IntegralInputclose()
uni.pro.navigateTo('/pages/order/coupon', {
type: "confirm_order_coupon",
shopId: uni.cache.get('orderVIP').shopId,
@@ -365,6 +353,11 @@
})
break;
case 'product':
// 清空积分
IntegralInputclose()
// 清空优惠卷
props.listinfo.coupondiscountAmount = 0
favorablelist[1].value = ''
uni.pro.navigateTo('/pages/order/coupon', {
type: "confirm_order_product",
shopId: uni.cache.get('orderVIP').shopId,
@@ -373,11 +366,52 @@
shoppingCart: JSON.stringify(props.listinfo.combinedArray)
})
break;
case 'points':
if (calcUsablePointsData.usable == 0) {
uni.showToast({
title: '此次订单不可用积分!'
})
return false;
}
calcUsablePointsData.showModal = true
break;
}
}
// 积分
const calcUsablePointsData = reactive({
minIntegral: 1, //最小
maxIntegral: '', //最多积分
instructionText: '',
unusableReason: '',
showModal: false,
integral: ''
})
const handleConfirm = async (integral) => {
calcUsablePointsData.integral = integral
props.listinfo.pointsDiscountAmount = await APImemberPointscalcDeductionAmount({
points: integral,
userId: props.orderVIP.id,
orderAmount: props.listinfo.totalCost
})
emits('clickPointsamount', props.listinfo.pointsDiscountAmount);
};
// * 获取积分相关信息
const getCalcUsablePoints = async () => {}
const getCalcUsablePoints = async (data) => {
Object.assign(calcUsablePointsData, data);
calcUsablePointsData.minIntegral = data.minDeductionPoints
calcUsablePointsData.maxIntegral = data.maxUsablePoints
calcUsablePointsData.instructionText = `请输入 ${ data.minDeductionPoints} - ${data.maxUsablePoints} 之间的积分`
}
// 积分取消清空
const IntegralInputclose = async () => {
calcUsablePointsData.integral = null
props.listinfo.pointsDiscountAmount = 0
calcUsablePointsData.showModal = false
}
// * 复制订单号
const copyHandle = (e) => {
@@ -394,7 +428,8 @@
// 将方法暴露给父组件
defineExpose({
dataprocessing
dataprocessing,
getCalcUsablePoints
});
</script>