对接智慧停车模块接口

This commit is contained in:
赵毅 2025-09-01 11:36:01 +08:00
parent 671c24b654
commit 567af67ef1
14 changed files with 1008 additions and 370 deletions

20
api/park.js Normal file
View File

@ -0,0 +1,20 @@
export const apiArr = {
carList: '/api/v2/wechat/smart-parking/car/list', // 车辆列表
carAdd: '/api/v2/wechat/smart-parking/car/add', // 车辆添加
monthCardCreate: '/api/v2/wechat/smart-parking/month-card/create', // 月卡订单创建
monthCardOrderList: '/api/v2/wechat/smart-parking/month-card/order/list', // 包月订单列表
monthCardOrderPreorder: '/api/v2/wechat/smart-parking/month-card/order/preorder', // 月卡充值预下单
monthCardOrderQuery: '/api/v2/wechat/smart-parking/month-card/order/trade_query', // 月卡充值订单交易查询
billingRulesList: '/api/v2/wechat/smart-parking/billing-rules/list', // 月卡计费规则列表
tempParkingCreate: '/api/v2/wechat/smart-parking/temp-parking/create', // 临时车缴费订单创建
tempParkingInfo: '/api/v2/wechat/smart-parking/temp-parking/info', // 临时车缴费信息
tempParkingOrderDelete: '/api/v2/wechat/smart-parking/temp-parking/order/delete', // 临时车停车订单删除
tempParkingOrderInfo: '/api/v2/wechat/smart-parking/temp-parking/order/info', // 临时车停车订单信息
tempParkingOrderList: '/api/v2/wechat/smart-parking/temp-parking/order/list', // 临时车停车订单列表
tempParkingOrderPreorder: '/api/v2/wechat/smart-parking/temp-parking/preorder', // 临时车缴费订单预下单
tempParkingOrderQuery: '/api/v2/wechat/smart-parking/temp-parking/trade_query', // 临时车缴费订单交易查询
parkList: '/api/v2/wechat/smart-parking/parking/list', // 停车场列表
}

View File

@ -2,7 +2,7 @@
<view> <view>
<view class="container"> <view class="container">
<view class="title">请输入车牌号码</view> <view class="title">请输入车牌号码</view>
<car-number-input @numberInputResult="numberInputResult" :defaultStr="defaultNum" /> <car-number-input @numberInputResult="numberInputResult" :defaultStr="defaultNum" ref="carNumberInput" />
<view class="selectColorBox" @click="show = true"> <view class="selectColorBox" @click="show = true">
<view>车牌颜色</view> <view>车牌颜色</view>
<view class="selectColor"> <view class="selectColor">
@ -19,13 +19,8 @@
<view class="tit">选择车牌颜色</view> <view class="tit">选择车牌颜色</view>
<!-- 颜色选择列表 --> <!-- 颜色选择列表 -->
<scroll-view class="color-list" scroll-y> <scroll-view class="color-list" scroll-y>
<view <view class="color-item" :class="{ 'active': selectedColorIndex === index }"
class="color-item" v-for="(item, index) in colorOptions" :key="index" @click="selectColor(index)">
:class="{ 'active': selectedColorIndex === index }"
v-for="(item, index) in colorOptions"
:key="index"
@click="selectColor(index)"
>
{{ item }} {{ item }}
</view> </view>
</scroll-view> </scroll-view>
@ -40,6 +35,15 @@
</template> </template>
<script> <script>
import {
isPhone,
picUrl,
request,
upload,
NavgateTo
} from '../../../utils';
import { apiArr } from '@/api/park.js'
export default { export default {
data() { data() {
return { return {
@ -57,7 +61,7 @@ export default {
}, },
methods: { methods: {
numberInputResult(e) { numberInputResult(e) {
console.log('结果--' + e) this.defaultNum = e;
}, },
onClose() { onClose() {
this.show = false; this.show = false;
@ -75,8 +79,44 @@ export default {
}, },
// //
submit() { submit() {
// const actualNumber = this.defaultNum.replace(/\s/g, '');
console.log('车牌号码:', this.defaultNum, '车牌颜色:', this.color); if (this.defaultNum == '' || actualNumber.length < 7) {
uni.showToast({
title: '请输入正确的车牌号',
icon: 'none',
duration: 2000
})
return;
}
if (this.color == '请选择') {
uni.showToast({
title: '请选择车牌颜色',
icon: 'none',
duration: 2000
})
return;
}
const params = {
user_id: uni.getStorageSync('userId'),
car_number: this.defaultNum,
car_number_color: this.color
}
request(apiArr.carAdd, "POST", params).then((res) => {
uni.showToast({
title: '添加成功',
icon: 'success',
duration: 2000
})
if (this.$refs.carNumberInput) {
// inputList
for (let i = 0; i < 8; i++) {
this.$refs.carNumberInput.inputList[i] = ' ';
}
this.$refs.carNumberInput.$forceUpdate();
}
this.color = '请选择';
this.selectedColorIndex = -1;
});
} }
} }
} }

View File

@ -9,7 +9,7 @@ page {
width: 100%; width: 100%;
background-color: #ffffff; background-color: #ffffff;
padding: 30rpx; padding: 30rpx;
margin-bottom: 30rpx; border-bottom: 1rpx solid #eeeeee;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
} }

View File

@ -1,12 +1,12 @@
<template> <template>
<view class="container"> <view class="container">
<!-- 车辆信息区域 --> <!-- 车辆信息区域 -->
<view class="car-info-container"> <view class="car-info-container" v-for="(item, index) in carList" :key="index">
<view class="license-plate"> <view class="license-plate">
<view class="plate-type-box"> <view class="plate-type-box">
<text class="plate-type">蓝牌</text> <text class="plate-type">{{ item.car_number_color }}</text>
</view> </view>
<text class="plate-number">冀T11855</text> <text class="plate-number">{{ item.car_number }}</text>
</view> </view>
</view> </view>
@ -16,18 +16,39 @@
</template> </template>
<script> <script>
import {
isPhone,
picUrl,
request,
upload,
NavgateTo
} from '../../../utils';
import { apiArr } from '@/api/park.js'
export default { export default {
data() { data() {
return { return {
carList: []
} }
}, },
methods: { methods: {
getCarList() {
const params = {
user_id: uni.getStorageSync('userId')
}
request(apiArr.carList, "POST", params).then((res) => {
this.carList = res.car_list;
})
},
addCar() { addCar() {
// //
uni.navigateTo({ uni.navigateTo({
url: '/packages/park/addCar/index' url: '/packages/park/addCar/index'
}) })
} }
},
onShow() {
this.getCarList();
} }
} }
</script> </script>

View File

@ -293,3 +293,102 @@ page {
font-size: 28rpx; font-size: 28rpx;
color: #ff3f11; color: #ff3f11;
} }
/* 弹窗通用样式 */
.car-plate-popup {
padding: 30rpx;
box-sizing: border-box;
background-color: #ffffff;
border-radius: 30rpx 30rpx 0 0;
max-height: 80vh; /* 限制弹窗最大高度 */
}
.popup-header {
text-align: center;
margin-bottom: 30rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.popup-title {
font-size: 36rpx;
font-weight: bold;
color: #333333;
}
.car-plate-list {
max-height: 600rpx;
overflow-y: auto;
padding-right: 10rpx; /* 为滚动条留出空间 */
}
/* 美化滚动条样式 */
.car-plate-list::-webkit-scrollbar {
width: 8rpx;
}
.car-plate-list::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4rpx;
}
.car-plate-list::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 4rpx;
}
.car-plate-list::-webkit-scrollbar-thumb:hover {
background: #999;
}
.car-plate-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
margin-bottom: 20rpx;
background-color: #f5f7fb;
border-radius: 20rpx;
transition: all 0.3s ease;
}
.car-plate-item.selected {
background-color: #ff431923;
border: 2rpx solid #ff4219;
}
.plate-number {
font-size: 28rpx;
font-weight: 500;
color: #333333;
flex: 1;
}
.rule-price {
font-size: 32rpx;
font-weight: bold;
color: #ff4219;
margin-right: 20rpx;
}
.popup-footer {
margin-top: 30rpx;
padding-top: 20rpx;
border-top: 1rpx solid #f0f0f0;
}
.close-btn {
width: 100%;
height: 90rpx;
line-height: 90rpx;
background-color: #ff4219;
color: #ffffff;
border: none;
border-radius: 45rpx;
font-size: 32rpx;
font-weight: 500;
}
.close-btn:active {
background-color: #e03a16;
}

View File

@ -19,14 +19,14 @@
<view class="parking-item" v-for="(park, index) in parkingLots" :key="index" <view class="parking-item" v-for="(park, index) in parkingLots" :key="index"
@tap="selectParkingLot(park)"> @tap="selectParkingLot(park)">
<view class="parking-item-left"> <view class="parking-item-left">
<view class="parking-spaces" v-if="park.remainingSpaces > 0"> <view class="parking-spaces">
<text class="spaces-label">剩余车位</text> <text class="spaces-label">剩余车位</text>
<text class="spaces-number">{{ park.remainingSpaces }}</text> <text class="spaces-number">{{ park.space_count }}</text>
</view> </view>
</view> </view>
<view class="parking-item-right"> <view class="parking-item-right">
<text class="parking-name">{{ park.name }}</text> <text class="parking-name">{{ park.parking_name }}</text>
<text class="parking-distance">{{ park.distance }}km</text> <text class="parking-distance">{{ getParkDistance(park.lng, park.lat) }}km</text>
<text class="parking-address">{{ park.address }}</text> <text class="parking-address">{{ park.address }}</text>
</view> </view>
<view class="parking-selected" v-if="park.isSelected"></view> <view class="parking-selected" v-if="park.isSelected"></view>
@ -43,9 +43,9 @@
</view> </view>
<!-- 停车场信息 --> <!-- 停车场信息 -->
<view class="park-info"> <view class="park-info" v-if="headerTitle != '请选择停车场'">
<text class="park-name">衡水市市民服务中心地下停车场</text> <text class="park-name">{{ headerTitle }}</text>
<text class="park-type">地下</text> <text class="park-type">{{ selectedParkType == 1 ? '地上' : '地下' }}</text>
</view> </view>
<!-- 支付金额 --> <!-- 支付金额 -->
@ -76,7 +76,7 @@
<!-- 计费规则 --> <!-- 计费规则 -->
<view class="option-item" @tap="showPriceRule"> <view class="option-item" @tap="showPriceRule">
<view v-if="monthPrice" class="option-box"> <view v-if="monthPrice !== ''" class="option-box">
<view class="option-label option-val2">{{ monthPrice + '元/月' }}</view> <view class="option-label option-val2">{{ monthPrice + '元/月' }}</view>
</view> </view>
<view v-else class="option-box"> <view v-else class="option-box">
@ -105,7 +105,7 @@
</view> </view>
<!-- 开始时间 --> <!-- 开始时间 -->
<view class="option-item" @tap="selectStartTime"> <view class="option-item">
<view class="option-box"> <view class="option-box">
<text class="option-label">开始时间</text> <text class="option-label">开始时间</text>
<text class="option-value">{{ startTime }}</text> <text class="option-value">{{ startTime }}</text>
@ -113,7 +113,7 @@
</view> </view>
<!-- 结束时间 --> <!-- 结束时间 -->
<view class="option-item" @tap="selectEndTime"> <view class="option-item">
<view class="option-box"> <view class="option-box">
<text class="option-label">结束时间</text> <text class="option-label">结束时间</text>
<text class="option-value">{{ endTime || '--年--月--日' }}</text> <text class="option-value">{{ endTime || '--年--月--日' }}</text>
@ -130,6 +130,61 @@
<view class="order-record" @tap="viewOrderRecords"> <view class="order-record" @tap="viewOrderRecords">
<text class="order-record-text">订单记录>></text> <text class="order-record-text">订单记录>></text>
</view> </view>
<!-- 车牌选择弹窗 -->
<u-popup :show="showCarPlatePopup" :round="30" mode="bottom" :closeable="true" close-icon-position="top-right"
@close="onCloseCarPlatePopup">
<view class="car-plate-popup">
<view class="popup-header">
<text class="popup-title">选择车牌</text>
</view>
<view class="car-plate-list">
<view class="car-plate-item" v-for="(plate, index) in carPlateList" :key="index"
@tap="onSelectCarPlate(plate)" :class="{ 'selected': selectedCarPlate === plate }">
<text class="plate-number">{{ plate.car_number }}</text>
<u-icon v-if="selectedCarPlate === plate" name="checkmark-circle" size="28"
color="#ff4219"></u-icon>
</view>
</view>
</view>
</u-popup>
<!-- 计费规则弹窗 -->
<u-popup :show="billingRulesPopup" :round="30" mode="bottom" :closeable="true" close-icon-position="top-right"
@close="onCloseBillingRulesPopup">
<view class="car-plate-popup">
<view class="popup-header">
<text class="popup-title">计费规则</text>
</view>
<view class="car-plate-list">
<view class="car-plate-item" v-for="(rule, index) in billingRulesList" :key="index"
@tap="onSelectBillingRule(rule)" :class="{ 'selected': monthPrice === rule.price }">
<text class="plate-number">{{ rule.billing_rule_name }}</text>
<text class="rule-price">¥{{ rule.month_price }}/</text>
<u-icon v-if="monthPrice === rule.month_price" name="checkmark-circle" size="28"
color="#ff4219"></u-icon>
</view>
</view>
</view>
</u-popup>
<!-- 包月月数选择弹窗 -->
<u-popup :show="showMonthCountPopup" :round="30" mode="bottom" :closeable="true" close-icon-position="top-right"
@close="onCloseMonthCountPopup">
<view class="car-plate-popup">
<view class="popup-header">
<text class="popup-title">选择包月月数</text>
</view>
<view class="car-plate-list">
<view class="car-plate-item" v-for="(month, index) in monthList" :key="index"
@tap="onSelectMonthCount(month)" :class="{ 'selected': monthCount === month.value }">
<text class="plate-number">{{ month.label }}</text>
<u-icon v-if="monthCount === month.value" name="checkmark-circle" size="28"
color="#ff4219"></u-icon>
</view>
</view>
</view>
</u-popup>
</view> </view>
</template> </template>
@ -141,60 +196,43 @@ import {
upload, upload,
NavgateTo NavgateTo
} from '../../../utils'; } from '../../../utils';
import { apiArr } from '@/api/park.js'
export default { export default {
data() { data() {
return { return {
// //
selectedCarPlate: '鄂FW3337', selectedCarPlate: '',
monthCount: 8, monthCount: '',
startTime: '2025-08-05 00:00:00', startTime: '',
endTime: '', endTime: '',
paymentAmount: 2400.00, paymentAmount: 2400.00,
monthPrice: 300.00, monthPrice: '',
// //
isDropdownOpen: false, isDropdownOpen: false,
headerTitle: '衡水市民服务中心地下停车场', headerTitle: '请选择停车场',
parkingLots: [ selectedParkType: '',
{ selectedParkId: '',//id
id: 1, parkingLots: [],
name: '衡水市民服务中心地下停车场', //
distance: '0.45', showCarPlatePopup: false,
address: '衡水市中心街123号', carPlateList: [],
remainingSpaces: 124, selectedCarPlateId: '',//id
isSelected: true //
}, billingRulesPopup: false,
{ billingRulesList: [],
id: 2, selectedBillingRule: '',//
name: '衡水市民服务中心地下停车场', //
distance: '0.45', showMonthCountPopup: false,
address: '衡水市中心街123号', monthList: Array.from({ length: 12 }, (_, i) => ({
remainingSpaces: 124, value: i + 1,
isSelected: false label: (i + 1) + '个月'
}, }))
{
id: 3,
name: '衡水市民服务中心地下停车场',
distance: '0.45',
address: '衡水市中心街123号',
remainingSpaces: 124,
isSelected: false
},
{
id: 4,
name: '衡水市民服务中心地下停车场',
distance: '0.45',
address: '衡水市中心街123号',
remainingSpaces: 124,
isSelected: false
}
]
} }
}, },
computed: { computed: {
//
isAllFilled() { isAllFilled() {
return this.selectedCarPlate && this.monthCount > 0 && this.startTime; return this.selectedParkId && this.selectedCarPlateId && this.monthCount > 0 && this.startTime;
} }
}, },
methods: { methods: {
@ -205,61 +243,196 @@ export default {
// //
selectParkingLot(park) { selectParkingLot(park) {
// //
this.parkingLots.forEach(item => { this.parkingLots.forEach(item => {
item.isSelected = false; item.isSelected = false;
}); });
// //
park.isSelected = true; park.isSelected = true;
// this.$set(this, 'headerTitle', park.parking_name);
this.$set(this, 'headerTitle', park.name); this.$set(this, 'selectedParkType', park.space_type);
// this.selectedParkId = park.id;
this.isDropdownOpen = false; this.isDropdownOpen = false;
}, },
//
selectCarPlate() { selectCarPlate() {
console.log('选择车牌'); this.showCarPlatePopup = true;
},
onCloseCarPlatePopup() {
this.showCarPlatePopup = false;
},
//
onSelectCarPlate(plate) {
this.selectedCarPlate = plate.car_number;
this.selectedCarPlateId = plate.id;
this.showCarPlatePopup = false;
}, },
// //
showPriceRule() { showPriceRule() {
console.log('显示计费规则'); if (!this.selectedParkId) {
uni.showToast({
title: '请选择停车场',
icon: 'none'
})
return;
}
this.getBillingRulesList();
this.billingRulesPopup = true;
},
//
onCloseBillingRulesPopup() {
this.billingRulesPopup = false;
},
//
onSelectBillingRule(rule) {
this.selectedBillingRule = rule.billing_rule_name;
this.monthPrice = rule.month_price;
this.paymentAmount = this.monthCount * this.monthPrice;
this.billingRulesPopup = false;
}, },
// //
selectMonthCount() { selectMonthCount() {
console.log('选择包月月数'); this.showMonthCountPopup = true;
}, },
// //
selectStartTime() { onCloseMonthCountPopup() {
console.log('选择开始时间'); this.showMonthCountPopup = false;
}, },
// //
selectEndTime() { onSelectMonthCount(month) {
console.log('选择结束时间'); this.monthCount = month.value;
if (this.startTime) {
const startDate = new Date(this.startTime);
//
const endDate = new Date(startDate);
endDate.setMonth(endDate.getMonth() + this.monthCount);
//
endDate.setDate(endDate.getDate() - 1);
// 23:59:59
endDate.setHours(23, 59, 59, 999);
// 使
const endYear = endDate.getFullYear();
const endMonth = String(endDate.getMonth() + 1).padStart(2, '0');
const endDay = String(endDate.getDate()).padStart(2, '0');
const endHours = String(endDate.getHours()).padStart(2, '0');
const endMinutes = String(endDate.getMinutes()).padStart(2, '0');
const endSeconds = String(endDate.getSeconds()).padStart(2, '0');
this.endTime = `${endYear}-${endMonth}-${endDay} ${endHours}:${endMinutes}:${endSeconds}`;
}
this.paymentAmount = this.monthCount * this.monthPrice;
this.showMonthCountPopup = false;
}, },
// //
goToNextStep() { goToNextStep() {
if (!this.isAllFilled) { if (!this.isAllFilled) {
uni.showModal({
title: "提示",
content: "请填写完整信息",
showCancel: false,
});
return; return;
} }
NavgateTo('../parkOrderDetail/index'); //
const params = {
headerTitle: this.headerTitle,
selectedParkType: this.selectedParkType,
selectedParkId: this.selectedParkId,
selectedCarPlateId: this.selectedCarPlateId,
selectedCarPlate: this.selectedCarPlate,
monthPrice: this.monthPrice,
monthCount: this.monthCount,
startTime: this.startTime,
endTime: this.endTime,
paymentAmount: this.paymentAmount,
selectedBillingRule: this.selectedBillingRule,
};
NavgateTo(`../parkOrderDetail/index?item=${encodeURIComponent(JSON.stringify(params))}`);
}, },
// //
viewOrderRecords() { viewOrderRecords() {
NavgateTo('../monthlyPaymentOrder/index'); NavgateTo('../monthlyPaymentOrder/index');
} },
//
getParkList() {
request(apiArr.parkList, "POST", {}).then((res) => {
this.parkingLots = res.parking_list;
})
},
//
getCarPlateList() {
request(apiArr.carList, "POST", {}).then((res) => {
this.carPlateList = res.car_list;
})
},
//
getBillingRulesList() {
const params = {
parking_id: this.selectedParkId,
}
request(apiArr.billingRulesList, "POST", params).then((res) => {
this.billingRulesList = res.billing_rules_list;
})
},
//
getParkDistance(parkLng, parkLat) {
try {
let locationData = uni.getStorageSync('location');
if (!locationData) {
return '未知';
}
let location= locationData;
const userLat = location.lat;
const userLng = location.lng;
// 使Haversine
const R = 6371; //
const dLat = (parkLat - userLat) * Math.PI / 180;
const dLng = (parkLng - userLng) * Math.PI / 180;
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(userLat * Math.PI / 180) * Math.cos(parkLat * Math.PI / 180) *
Math.sin(dLng / 2) * Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c;
//
return distance.toFixed(1);
} catch (error) {
console.error('计算距离时出错:', error);
return '未知';
}
},
}, },
onLoad() { onLoad() {
// // 0:00:00
console.log('包月支付页面加载'); const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0'); // 0+1
const day = String(today.getDate()).padStart(2, '0');
// 'YYYY-MM-DD HH:mm:ss'
this.startTime = `${year}-${month}-${day} 00:00:00`;
// //
this.paymentAmount = this.monthCount * this.monthPrice; this.paymentAmount = this.monthCount * this.monthPrice;
this.getParkList();
this.getCarPlateList();
} }
} }
</script> </script>

View File

@ -9,57 +9,51 @@
<!-- 订单列表 --> <!-- 订单列表 -->
<view class="order-list"> <view class="order-list">
<view <view v-for="(order, index) in orders" :key="index" class="order-card">
v-for="(order, index) in filteredOrders"
:key="index"
class="order-card"
>
<view class="order-header"> <view class="order-header">
<text class="order-number">订单编号{{ order.orderNumber }}</text> <text class="order-number">订单编号{{ order.order_no }}</text>
<text <text class="order-status" :class="{
class="order-status" 'pending': order.order_status == '1',
:class="{ 'using': order.order_status == '2',
'pending': order.status === 'pending', 'expired': order.order_status == '3'
'using': order.status === 'using', }">
'expired': order.status === 'expired' {{ order.order_status == '1' ? '待支付' : order.order_status == '2' ? '使用中' : order.order_status ==
}" '3' ? '已过期' : '' }}
>
{{ order.statusText }}
</text> </text>
</view> </view>
<view class="order-content"> <view class="order-content">
<view class="order-item"> <view class="order-item">
<text class="order-label">车场名称</text> <text class="order-label">车场名称</text>
<text class="order-value">{{ order.parkName }}</text> <text class="order-value">{{ order.Parking.parking_name }}</text>
</view> </view>
<view class="order-item"> <view class="order-item">
<text class="order-label">车牌号</text> <text class="order-label">车牌号</text>
<text class="order-value">{{ order.carPlate }}</text> <text class="order-value">{{ order.community_car.car_number }}</text>
</view> </view>
<view class="order-item"> <view class="order-item">
<text class="order-label">包月月数</text> <text class="order-label">包月月数</text>
<text class="order-value">{{ order.monthCount }}个月</text> <text class="order-value">{{ order.month_count }}个月</text>
</view> </view>
<view class="order-item"> <view class="order-item">
<text class="order-label">开始时间</text> <text class="order-label">开始时间</text>
<text class="order-value">{{ order.startTime }}</text> <text class="order-value">{{ order.start_time }}</text>
</view> </view>
<view class="order-item"> <view class="order-item">
<text class="order-label">到期时间</text> <text class="order-label">到期时间</text>
<text class="order-value">{{ order.endTime }}</text> <text class="order-value">{{ order.end_time }}</text>
</view> </view>
<view class="order-item amount"> <view class="order-item amount">
<text class="order-label">订单金额</text> <text class="order-label">订单金额</text>
<text class="order-value amount-value">¥{{ order.amount }}</text> <text class="order-value amount-value">¥{{ order.total_amount }}</text>
</view> </view>
<!-- 根据订单状态显示不同内容 --> <!-- 根据订单状态显示不同内容 -->
<view v-if="order.status === 'using' || order.status === 'expired'" class="order-item"> <view v-if="order.order_status == '2' || order.order_status === '3'" class="order-item">
<text class="order-label">付款时间</text> <text class="order-label">付款时间</text>
<text class="order-value">{{ order.payTime }}</text> <text class="order-value">{{ order.pay_time }}</text>
</view> </view>
<view v-if="order.status === 'using'" class="order-item"> <view v-if="order.order_status == '2'" class="order-item">
<text class="order-label">支付状态</text> <text class="order-label">支付状态</text>
<text class="order-value paid">已支付</text> <text class="order-value paid">已支付</text>
</view> </view>
@ -83,6 +77,7 @@ import {
upload, upload,
NavgateTo NavgateTo
} from '../../../utils'; } from '../../../utils';
import { apiArr } from '@/api/park.js'
export default { export default {
data() { data() {
@ -106,73 +101,13 @@ export default {
}, },
], ],
selectedTab: 0, selectedTab: 0,
orders: [ orders: []
//
{
id: 1,
orderNumber: '123456789145',
status: 'pending',
statusText: '待支付',
parkName: '智行光彩生态停车场',
carPlate: '冀T11033',
monthCount: 1,
startTime: '2025-06-04 00:00:00',
endTime: '2025-06-04 23:59:59',
amount: '360.00'
},
// 使
{
id: 2,
orderNumber: '123456789145',
status: 'using',
statusText: '使用中',
parkName: '智行光彩生态停车场',
carPlate: '冀T11033',
monthCount: 1,
startTime: '2025-06-04 00:00:00',
endTime: '2025-06-04 23:59:59',
amount: '360.00',
payTime: '2025-06-04 23:59:59'
},
//
{
id: 3,
orderNumber: '123456789145',
status: 'expired',
statusText: '已过期',
parkName: '智行光彩生态停车场',
carPlate: '冀T11033',
monthCount: 1,
startTime: '2025-06-04 00:00:00',
endTime: '2025-06-04 23:59:59',
amount: '360.00',
payTime: '2025-06-04 23:59:59'
}
]
}
},
computed: {
// tab
filteredOrders() {
if (this.selectedTab === 0) {
//
return this.orders;
} else if (this.selectedTab === 1) {
//
return this.orders.filter(order => order.status === 'pending');
} else if (this.selectedTab === 2) {
// 使
return this.orders.filter(order => order.status === 'using');
} else if (this.selectedTab === 3) {
//
return this.orders.filter(order => order.status === 'expired');
}
return this.orders;
} }
}, },
methods: { methods: {
selectTab(index, item) { selectTab(index, item) {
this.selectedTab = index; this.selectedTab = index;
this.getOrderList()
}, },
// //
cancelOrder(order) { cancelOrder(order) {
@ -181,8 +116,24 @@ export default {
// //
goToPayment(order) { goToPayment(order) {
NavgateTo('../parkOrderDetail/index'); NavgateTo('../parkOrderDetail/index');
},
//
getOrderList() {
const params = {
user_id: uni.getStorageSync('userId'),
order_status: this.selectedTab,
}
if (params.order_status == 0) {
params.order_status = ''
}
request(apiArr.monthCardOrderList, "POST", params).then(res => {
this.orders = res.month_card_order_list;
})
},
onLoad() {
this.getOrderList()
} }
} },
} }
</script> </script>

View File

@ -4,7 +4,7 @@
<view class="order-status-section"> <view class="order-status-section">
<view class="status-left"> <view class="status-left">
<text class="status-title">订单已支付</text> <text class="status-title">订单已支付</text>
<text class="park-name">上海公馆停车场</text> <text class="park-name">{{ orderDetail.parking.parking_name }}</text>
</view> </view>
<view class="status-right"> <view class="status-right">
<image class="success-icon" src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/park/park_orderOk.png" <image class="success-icon" src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/park/park_orderOk.png"
@ -17,14 +17,14 @@
<view class="amount-item" @tap="toggleAmountExpand"> <view class="amount-item" @tap="toggleAmountExpand">
<text class="amount-label">实付金额</text> <text class="amount-label">实付金额</text>
<view class="amount-value"> <view class="amount-value">
<text>¥{{ orderDetail.actualAmount }}</text> <text>¥{{ orderDetail.pay_method }}</text>
<u-icon :name="amountExpanded ? 'arrow-up' : 'arrow-down'" size="28"></u-icon> <u-icon :name="amountExpanded ? 'arrow-up' : 'arrow-down'" size="28"></u-icon>
</view> </view>
</view> </view>
<view class="amount-item" v-show="amountExpanded"> <view class="amount-item" v-show="amountExpanded">
<text class="amount-label2">订单金额</text> <text class="amount-label2">订单金额</text>
<text>¥{{ orderDetail.orderAmount }}</text> <text>¥{{ orderDetail.pay_method }}</text>
</view> </view>
</view> </view>
@ -34,33 +34,33 @@
<view class="info-item"> <view class="info-item">
<text class="info-label">车牌号码</text> <text class="info-label">车牌号码</text>
<text>{{ orderDetail.carNumber }}</text> <text>{{ orderDetail.parking_record.car_number }}</text>
</view> </view>
<view class="info-item"> <view class="info-item">
<text class="info-label">交易时间</text> <text class="info-label">交易时间</text>
<text>{{ orderDetail.transactionTime }}</text> <text>{{ orderDetail.pay_time }}</text>
</view> </view>
<view class="info-item"> <view class="info-item">
<text class="info-label">停车时长</text> <text class="info-label">停车时长</text>
<text>{{ orderDetail.parkingDuration }}</text> <text>{{ calculateParkingDuration() }}</text>
</view> </view>
<view class="info-item"> <view class="info-item">
<text class="info-label">订单类型</text> <text class="info-label">订单类型</text>
<text>{{ orderDetail.orderType }}</text> <text>停车</text>
</view> </view>
<view class="info-item"> <view class="info-item">
<text class="info-label">支付方式</text> <text class="info-label">支付方式</text>
<text>{{ orderDetail.paymentMethod }}</text> <text>{{ orderDetail.pay_method == 1 ? '微信' : orderDetail.pay_method == 2 ? '支付宝' : '其他' }}</text>
</view> </view>
<view class="info-item"> <view class="info-item">
<text class="info-label">订单号</text> <text class="info-label">订单号</text>
<view class="order-number-container"> <view class="order-number-container">
<text>{{ orderDetail.orderNumber }}</text> <text>{{ orderDetail.order_no }}</text>
<image class="copy-icon" src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/myOrder/copy.png" <image class="copy-icon" src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/myOrder/copy.png"
mode="aspectFit" @tap="copyOrderNumber"></image> mode="aspectFit" @tap="copyOrderNumber"></image>
</view> </view>
@ -70,22 +70,22 @@
</template> </template>
<script> <script>
import {
isPhone,
picUrl,
request,
upload,
NavgateTo
} from '../../../utils';
import { apiArr } from '@/api/park.js'
export default { export default {
data() { data() {
return { return {
// //
amountExpanded: false, amountExpanded: false,
// //
orderDetail: { orderDetail: {}
actualAmount: '8.00',
orderAmount: '8.00',
carNumber: '冀TQ2F09',
transactionTime: '2025-08-04 18:41:06',
parkingDuration: '4时16分53秒',
orderType: '停车',
paymentMethod: '微信',
orderNumber: 'BK250804184038818'
}
} }
}, },
methods: { methods: {
@ -98,7 +98,7 @@ export default {
copyOrderNumber() { copyOrderNumber() {
// 使uni.setClipboardData API // 使uni.setClipboardData API
uni.setClipboardData({ uni.setClipboardData({
data: this.orderDetail.orderNumber, data: this.orderDetail.order_no,
success: () => { success: () => {
uni.showToast({ uni.showToast({
title: '复制成功', title: '复制成功',
@ -114,12 +114,41 @@ export default {
}); });
} }
}); });
},
//
calculateParkingDuration() {
if (!this.orderDetail || !this.orderDetail.parking_record) {
return '0分钟';
}
const inTime = new Date(this.orderDetail.parking_record.in_time);
const outTime = new Date(this.orderDetail.parking_record.out_time);
//
const diffMs = outTime - inTime;
//
const diffMinutes = Math.floor(diffMs / (1000 * 60));
if (diffMinutes < 60) {
return `${diffMinutes}分钟`;
} else {
const hours = Math.floor(diffMinutes / 60);
const minutes = diffMinutes % 60;
if (minutes === 0) {
return `${hours}小时`;
} else {
return `${hours}小时${minutes}分钟`;
}
}
} }
}, },
onLoad() { onLoad(options) {
// API const order = options.order;
// 使 if (order) {
console.log('订单详情页面加载'); this.orderDetail = JSON.parse(order);
}
} }
} }
</script> </script>

View File

@ -3,8 +3,8 @@
<!-- 订单按月分组显示 --> <!-- 订单按月分组显示 -->
<view class="month-group" v-for="monthGroup in orderData" :key="monthGroup.month"> <view class="month-group" v-for="monthGroup in orderData" :key="monthGroup.month">
<view class="month-header"> <view class="month-header">
<text class="month-title">{{ monthGroup.month }}</text> <text class="month-title">{{ monthGroup.pay_time }}</text>
<text class="month-expense">支出¥{{ monthGroup.totalExpense }}</text> <text class="month-expense">支出¥{{ monthGroup.amount }}</text>
</view> </view>
<!-- 订单列表 --> <!-- 订单列表 -->
@ -17,20 +17,21 @@
mode="aspectFit"></image> mode="aspectFit"></image>
<text class="order-type-text">停车</text> <text class="order-type-text">停车</text>
</view> </view>
<text class="order-status">{{ order.statusText }}</text> <text class="order-status">{{ order.status == 1 ? '待支付' : '已支付' }}</text>
</view> </view>
<view class="order-park-info"> <view class="order-park-info">
<text class="order-park-name">{{ order.parkName }}</text> <text class="order-park-name">{{ order.parking.parking_name }}</text>
<text class="order-amount">¥{{ order.amount }}</text> <text class="order-amount">¥{{ order.amount }}</text>
</view> </view>
<view class="order-car-info"> <view class="order-car-info">
<text class="order-car-number">{{ order.carNumber }}</text> <text class="order-car-number">{{ order.parking_record.car_number }}</text>
<text class="order-car-type">{{ order.carType }}</text> <text class="order-car-type">{{ order.parking_record.car_billing_type == 1 ? '贵宾车' :
(order.parking_record.car_billing_type == 2) ? '月租车' : '临时车' }}</text>
</view> </view>
<text class="order-time">{{ order.time }}</text> <text class="order-time">{{ order.pay_time }}</text>
</view> </view>
<view class="delete-button" @tap.stop="deleteOrder(order)"> <view class="delete-button" @tap.stop="deleteOrder(order)">
<u-icon name="trash" size="45rpx"></u-icon> <u-icon name="trash" size="45rpx"></u-icon>
@ -55,89 +56,99 @@ import {
upload, upload,
NavgateTo NavgateTo
} from '../../../utils'; } from '../../../utils';
import { apiArr } from '@/api/park.js'
export default { export default {
data() { data() {
return { return {
// API orderData: []
orderData: [
{
month: '2025年08月',
totalExpense: '16.00',
orders: [
{
id: 1,
parkName: '上海公馆停车场',
amount: '8.00',
carNumber: '冀TQ2F09',
carType: '临时车',
carTypeClass: 'temporary',
time: '2025-08-04 18:46',
status: 'paid',
statusText: '已支付'
},
{
id: 2,
parkName: '上海公馆停车场',
amount: '8.00',
carNumber: '冀TQ2F09',
carType: '临时车',
carTypeClass: 'temporary',
time: '2025-08-04 18:46',
status: 'paid',
statusText: '已支付'
}
]
},
{
month: '2025年08月',
totalExpense: '16.00',
orders: [
{
id: 3,
parkName: '上海公馆停车场',
amount: '8.00',
carNumber: '冀TQ2F09',
carType: '月租卡',
carTypeClass: 'monthly',
time: '2025-08-04 18:46',
status: 'paid',
statusText: '已支付'
}
]
}
]
} }
}, },
methods: { methods: {
// //
viewOrderDetail(order) { viewOrderDetail(order) {
NavgateTo('../orderDetail/index') NavgateTo('../orderDetail/index?order=' + JSON.stringify(order))
}, },
// //
deleteOrder(order) { deleteOrder(order) {
console.log("🚀 ~ deleteOrder ~ order:", order) const that = this;
uni.showModal({ uni.showModal({
title: '确认删除订单', title: '确认删除订单',
content: '你确定删除订单吗?删除之后你将无法再找回该订单', content: '你确定删除订单吗?删除之后你将无法再找回该订单',
success: function (res) { success: function (res) {
if (res.confirm) { if (res.confirm) {
// const params = {
uni.showToast({ order_id: order.id
title: '删除成功', }
icon: 'success', request(apiArr.tempParkingOrderDelete, "POST", params).then((res) => {
duration: 2000 uni.showToast({
}); title: '删除成功',
} else if (res.cancel) { icon: 'success',
// duration: 2000
});
setTimeout(() => {
that.getOrderData();
}, 1000);
})
} }
} }
}); });
}, },
//
groupOrdersByMonth(orderList) {
const monthMap = new Map();
orderList.forEach(order => {
let payTime;
try {
payTime = new Date(order.pay_time);
} catch (error) {
payTime = new Date(order.pay_time.replace(/T/, ' ').replace(/\+.*$/, ''));
}
//
const year = payTime.getFullYear();
const month = payTime.getMonth() + 1;
const monthKey = `${year}-${month.toString().padStart(2, '0')}`;
//
if (!monthMap.has(monthKey)) {
monthMap.set(monthKey, {
month: monthKey,
pay_time: `${year}${month}`,
amount: 0,
orders: []
});
}
//
const monthGroup = monthMap.get(monthKey);
monthGroup.orders.push(order);
monthGroup.amount += parseFloat(order.amount || 0);
});
// Map
const groupedArray = Array.from(monthMap.values());
groupedArray.sort((a, b) => b.month.localeCompare(a.month));
//
groupedArray.forEach(group => {
group.amount = group.amount.toFixed(2);
});
return groupedArray;
},
// //
getOrderData() { getOrderData() {
const params = {
user_id: uni.getStorageSync('userId')
}
request(apiArr.tempParkingOrderList, "POST", params).then((res) => {
this.orderData = this.groupOrdersByMonth(res.order_list);
})
} }
}, },
onLoad() { onLoad() {

View File

@ -4,7 +4,7 @@
<view class="payment-header"> <view class="payment-header">
<view class="amount-info"> <view class="amount-info">
<text class="amount-symbol">¥</text> <text class="amount-symbol">¥</text>
<text class="amount-value">4704.00</text> <text class="amount-value">{{ itemObj.paymentAmount }}</text>
<text class="payment-status">待付款</text> <text class="payment-status">待付款</text>
</view> </view>
</view> </view>
@ -15,27 +15,27 @@
<view class="detail-item"> <view class="detail-item">
<text class="detail-label">停车场</text> <text class="detail-label">停车场</text>
<view class="detail-value"> <view class="detail-value">
<text class="park-type">地下</text> <text class="park-type">{{ itemObj.selectedParkType == 1 ? '地上' : '地下' }}</text>
<text class="park-name">衡水市民服务中心地下停车场</text> <text class="park-name">{{ itemObj.headerTitle }}</text>
</view> </view>
</view> </view>
<!-- 车牌号 --> <!-- 车牌号 -->
<view class="detail-item"> <view class="detail-item">
<text class="detail-label">车牌号</text> <text class="detail-label">车牌号</text>
<text class="detail-value">冀T11855</text> <text class="detail-value">{{ itemObj.selectedCarPlate }}</text>
</view> </view>
<!-- 开始时间 --> <!-- 开始时间 -->
<view class="detail-item"> <view class="detail-item">
<text class="detail-label">开始时间</text> <text class="detail-label">开始时间</text>
<text class="detail-value">2025-03-08 00:00:00</text> <text class="detail-value">{{ itemObj.startTime }}</text>
</view> </view>
<!-- 结束时间 --> <!-- 结束时间 -->
<view class="detail-item"> <view class="detail-item">
<text class="detail-label">结束时间</text> <text class="detail-label">结束时间</text>
<text class="detail-value">2025-03-08 23:59:59</text> <text class="detail-value">{{ itemObj.endTime }}</text>
</view> </view>
</view> </view>
@ -56,7 +56,7 @@
mode="aspectFit" style="width: 40rpx; height: 40rpx;"></image> mode="aspectFit" style="width: 40rpx; height: 40rpx;"></image>
</view> --> </view> -->
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/com_check2.png" <image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/com_check2.png"
mode="aspectFit" style="width: 30rpx; height: 30rpx;"></image> mode="aspectFit" style="width: 30rpx; height: 30rpx;"></image>
</view> </view>
</view> </view>
@ -64,7 +64,7 @@
<view class="bottom-payment"> <view class="bottom-payment">
<view class="total-amount"> <view class="total-amount">
<text class="total-label">合计¥</text> <text class="total-label">合计¥</text>
<text class="total-value">4900.00</text> <text class="total-value">{{ itemObj.paymentAmount }}</text>
</view> </view>
<view class="pay-button" @tap="submitPayment"> <view class="pay-button" @tap="submitPayment">
<text class="pay-text">立即支付</text> <text class="pay-text">立即支付</text>
@ -74,20 +74,101 @@
</template> </template>
<script> <script>
import {
isPhone,
picUrl,
request,
upload,
NavgateTo
} from '../../../utils';
import { apiArr } from '@/api/park.js'
export default { export default {
data() { data() {
return { return {
// itemObj: {}
} }
}, },
methods: { methods: {
// //
submitPayment() { submitPayment() {
console.log('提交支付'); const params = {
user_id: uni.getStorageSync('userId'),
parking_id: this.itemObj.selectedParkId,
car_id: this.itemObj.selectedCarPlateId,
billing_rules: this.itemObj.selectedBillingRule,
month_count: this.itemObj.monthCount,
total_amount: this.itemObj.paymentAmount,
start_time: this.itemObj.startTime,
end_time: this.itemObj.endTime,
}
request(apiArr.monthCardCreate, "POST", params).then((resVal) => {
// trans_type
// : 71, App: 51
const systemInfo = uni.getSystemInfoSync();
let trans_type = 51; // App
//
if (systemInfo.platform === 'devtools' || systemInfo.platform === 'unknown') {
trans_type = 71; //
}
//
// #ifdef MP
trans_type = 71; //
// #endif
// #ifdef APP-PLUS
trans_type = 51; // App
// #endif
const param = {
order_id: resVal.order_id,
user_id: uni.getStorageSync('userId'),
trans_type: trans_type
}
request(apiArr.monthCardOrderPreorder, "POST", param).then(res => {
if (res && res.timeStamp && res.nonceStr && res.package && res.signType && res.paySign) {
//
uni.requestPayment({
timeStamp: res.timeStamp,
nonceStr: res.nonceStr,
package: res.package,
signType: res.signType,
paySign: res.paySign,
success: (payRes) => {
const params = {
order_id: resVal.order_id,
}
request(apiArr.monthCardOrderQuery, "POST", params).then(res => {
this.boxshadow1 = true
})
},
fail: (payErr) => {
console.log("支付失败", payErr)
uni.showToast({
title: payErr.errMsg || '支付失败',
icon: 'none'
})
},
complete: () => {
//
}
})
} else {
console.error("获取支付参数失败,缺少必要参数")
uni.showToast({
title: '获取支付信息失败',
icon: 'none'
})
}
})
})
} }
}, },
onLoad() { onLoad(options) {
console.log('订单详情页面加载'); this.itemObj = JSON.parse(decodeURIComponent(options.item));
} }
} }
</script> </script>

View File

@ -18,14 +18,14 @@
<view class="parking-item" v-for="(park, index) in parkingLots" :key="index" <view class="parking-item" v-for="(park, index) in parkingLots" :key="index"
@tap="selectParkingLot(park)"> @tap="selectParkingLot(park)">
<view class="parking-item-left"> <view class="parking-item-left">
<view class="parking-spaces" v-if="park.remainingSpaces > 0"> <view class="parking-spaces">
<text class="spaces-label">剩余车位</text> <text class="spaces-label">剩余车位</text>
<text class="spaces-number">{{ park.remainingSpaces }}</text> <text class="spaces-number">{{ park.space_count }}</text>
</view> </view>
</view> </view>
<view class="parking-item-right"> <view class="parking-item-right">
<text class="parking-name">{{ park.name }}</text> <text class="parking-name">{{ park.parking_name }}</text>
<text class="parking-distance">{{ park.distance }}km</text> <text class="parking-distance">{{ getParkDistance(park.lng, park.lat) }}km</text>
<text class="parking-address">{{ park.address }}</text> <text class="parking-address">{{ park.address }}</text>
</view> </view>
<view class="parking-selected" v-if="park.isSelected"></view> <view class="parking-selected" v-if="park.isSelected"></view>
@ -46,7 +46,7 @@
<view v-if="isCarDropdownOpen" class="car-dropdown"> <view v-if="isCarDropdownOpen" class="car-dropdown">
<view class="dropdown-arrow"></view> <view class="dropdown-arrow"></view>
<view class="car-item" v-for="(car, index) in cars" :key="index" @click="selectCar(car)"> <view class="car-item" v-for="(car, index) in cars" :key="index" @click="selectCar(car)">
{{ car }} {{ car.car_number }}
</view> </view>
</view> </view>
</view> </view>
@ -67,7 +67,7 @@
</view> </view>
<!-- 停车费展示部分 --> <!-- 停车费展示部分 -->
<view v-if="showCost" class="cost-container"> <view v-if="showCost1" class="cost-container">
<view> <view>
<image class="cost-image" <image class="cost-image"
src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/park/park_orderLoading.png" src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/park/park_orderLoading.png"
@ -111,8 +111,8 @@
</view> </view>
<view class="pay-button" @tap="confirmPayment">立即付款</view> <view class="pay-button" @tap="confirmPayment">立即付款</view>
</view> </view>
<view v-else class="cost-container not-found"> <view v-if="showCost2" class="cost-container not-found">
未找到停车记录 未找到停车记录
</view> </view>
<!-- 选择车牌颜色 --> <!-- 选择车牌颜色 -->
@ -145,46 +145,14 @@ import {
upload, upload,
NavgateTo NavgateTo
} from '../../../utils'; } from '../../../utils';
import { apiArr } from '@/api/park.js'
export default { export default {
data() { data() {
return { return {
isDropdownOpen: false, isDropdownOpen: false,
headerTitle: '衡水市民服务中心地下停车场', headerTitle: '请选择停车场',
parkingLots: [ parkingLots: [],
{
id: 1,
name: '衡水市民服务中心地下停车场',
distance: '0.45',
address: '衡水市中心街123号',
remainingSpaces: 124,
isSelected: true
},
{
id: 2,
name: '衡水市民服务中心地下停车场',
distance: '0.45',
address: '衡水市中心街123号',
remainingSpaces: 124,
isSelected: false
},
{
id: 3,
name: '衡水市民服务中心地下停车场',
distance: '0.45',
address: '衡水市中心街123号',
remainingSpaces: 124,
isSelected: false
},
{
id: 4,
name: '衡水市民服务中心地下停车场',
distance: '0.45',
address: '衡水市中心街123号',
remainingSpaces: 124,
isSelected: false
}
],
defaultNum: '', defaultNum: '',
color: '请选择', color: '请选择',
@ -197,16 +165,30 @@ export default {
// //
isCarDropdownOpen: false, isCarDropdownOpen: false,
selectedCar: '', selectedCar: '',
cars: ['冀A01233', '冀T01234', '其他车辆'], cars: [],
// //
showCost: false, showCost1: false,
showCost2: false,
parkingLotName: '上海公馆停车场', parkingLotName: '上海公馆停车场',
costAmount: '280.00', costAmount: '280.00',
currentCarNumber: '冀T11033', currentCarNumber: '冀T11033',
entryTime: '2025-08-05 12:00:00', entryTime: '2025-08-05 12:00:00',
billingTime: '3天12时37分44秒', billingTime: '3天12时37分44秒',
paymentMethod: 'wechat' paymentMethod: 'wechat',
// ID
timerId: null
}
},
onLoad() {
this.getParkList();
},
//
onUnload() {
if (this.timerId) {
clearInterval(this.timerId);
this.timerId = null;
} }
}, },
methods: { methods: {
@ -224,7 +206,7 @@ export default {
// //
park.isSelected = true; park.isSelected = true;
// //
this.$set(this, 'headerTitle', park.name); this.$set(this, 'headerTitle', park.parking_name);
// //
this.isDropdownOpen = false; this.isDropdownOpen = false;
}, },
@ -254,6 +236,34 @@ export default {
onClose() { onClose() {
this.show = false; this.show = false;
}, },
//
updateBillingTime() {
const entryDateTime = new Date(this.entryTime);
const currentDateTime = new Date();
const diff = currentDateTime - entryDateTime;
//
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
//
let timeStr = '';
if (days > 0) {
timeStr += days + '天';
}
if (hours > 0 || days > 0) {
timeStr += hours + '时';
}
if (minutes > 0 || hours > 0 || days > 0) {
timeStr += minutes + '分';
}
timeStr += seconds + '秒';
this.billingTime = timeStr;
},
// //
selectColor(index) { selectColor(index) {
this.selectedColorIndex = index; this.selectedColorIndex = index;
@ -265,8 +275,6 @@ export default {
} }
this.show = false; this.show = false;
}, },
onLoad() {
},
// //
toggleCarDropdown() { toggleCarDropdown() {
@ -275,17 +283,65 @@ export default {
// //
selectCar(car) { selectCar(car) {
this.selectedCar = car; this.selectedCar = car.car_number;
this.isCarDropdownOpen = false; this.isCarDropdownOpen = false;
if (car == '其他车辆') { if (car.car_number == '其他车辆') {
NavgateTo('../addCar/index') NavgateTo('../addCar/index')
} }
this.numberInputResult(car) this.numberInputResult(car.car_number)
}, },
// //
selectCost() { selectCost() {
this.showCost = true; const selectedParkingLot = this.parkingLots.find(park => park.isSelected);
if (!selectedParkingLot) {
uni.showToast({
title: '请先选择停车场',
icon: 'none'
});
return;
}
if (!this.defaultNum) {
uni.showToast({
title: '请输入车牌号',
icon: 'none'
});
return;
}
const params = {
parking_id: selectedParkingLot.id,
car_number: this.defaultNum,
}
request(apiArr.tempParkingInfo, "POST", params).then((res) => {
if (res) {
this.parkingLotName = res.parking.parking_name;
this.costAmount = res.fee_amount;
this.currentCarNumber = res.car_number;
this.entryTime = res.in_time;
//
if (this.timerId) {
clearInterval(this.timerId);
this.timerId = null;
}
if (res.car_billing_type == 1) {
this.billingTime = '免费车';
} else if (res.car_billing_type == 2) {
this.billingTime = '月租车';
} else {
//
this.updateBillingTime();
//
this.timerId = setInterval(() => {
this.updateBillingTime();
}, 1000);
}
this.showCost1 = true;
} else {
this.showCost2 = true;
}
})
}, },
// //
@ -295,10 +351,128 @@ export default {
// //
confirmPayment() { confirmPayment() {
console.log('确认付款', this.paymentMethod); const selectedParkingLot = this.parkingLots.find(park => park.isSelected);
// const params = {
// API car_number: this.defaultNum,
parking_id: selectedParkingLot.id,
user_id: uni.getStorageSync('userId'),
}
request(apiArr.tempParkingCreate, "POST", params).then((resVal) => {
// trans_type
// : 71, App: 51
const systemInfo = uni.getSystemInfoSync();
let trans_type = 51; // App
//
if (systemInfo.platform === 'devtools' || systemInfo.platform === 'unknown') {
trans_type = 71; //
}
//
// #ifdef MP
trans_type = 71; //
// #endif
// #ifdef APP-PLUS
trans_type = 51; // App
// #endif
const param = {
order_id: resVal.order_id,
user_id: uni.getStorageSync('userId'),
trans_type: trans_type
}
request(apiArr.tempParkingOrderPreorder, "POST", param).then(res => {
if (res && res.timeStamp && res.nonceStr && res.package && res.signType && res.paySign) {
//
uni.requestPayment({
timeStamp: res.timeStamp,
nonceStr: res.nonceStr,
package: res.package,
signType: res.signType,
paySign: res.paySign,
success: (payRes) => {
const params = {
order_id: resVal.order_id,
}
request(apiArr.tempParkingOrderQuery, "POST", params).then(res => {
this.boxshadow1 = true
})
},
fail: (payErr) => {
console.log("支付失败", payErr)
uni.showToast({
title: payErr.errMsg || '支付失败',
icon: 'none'
})
},
complete: () => {
//
}
})
} else {
console.error("获取支付参数失败,缺少必要参数")
uni.showToast({
title: '获取支付信息失败',
icon: 'none'
})
}
})
})
}, },
//
getCarList() {
const params = {
user_id: uni.getStorageSync('userId')
}
request(apiArr.carList, "POST", params).then((res) => {
this.cars = res.car_list;
this.cars.push({
car_number: '其他车辆'
})
})
},
//
getParkList() {
request(apiArr.parkList, "POST", {}).then((res) => {
this.parkingLots = res.parking_list;
})
},
//
getParkDistance(parkLng, parkLat) {
try {
let locationData = uni.getStorageSync('location');
if (!locationData) {
return '未知';
}
let location = locationData;
const userLat = location.lat;
const userLng = location.lng;
// 使Haversine
const R = 6371; //
const dLat = (parkLat - userLat) * Math.PI / 180;
const dLng = (parkLng - userLng) * Math.PI / 180;
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(userLat * Math.PI / 180) * Math.cos(parkLat * Math.PI / 180) *
Math.sin(dLng / 2) * Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c;
//
return distance.toFixed(1);
} catch (error) {
console.error('计算距离时出错:', error);
return '未知';
}
},
},
onShow() {
this.getCarList();
} }
} }
</script> </script>

View File

@ -431,6 +431,15 @@ page {
margin-top: 30rpx; margin-top: 30rpx;
} }
.shadowBox1Item_btn{
width: 110rpx;
height: 150rpx;
border: 1rpx solid red;
position: absolute;
left: 50rpx;
opacity:0;
}
.shadowBox1Item { .shadowBox1Item {
flex: 1; flex: 1;
display: flex; display: flex;

View File

@ -43,7 +43,7 @@
<view class="group-price"> <view class="group-price">
<view>{{ item.commodity_goods_info.sales_price }}/{{ <view>{{ item.commodity_goods_info.sales_price }}/{{
item.commodity_goods_info.goods_unit item.commodity_goods_info.goods_unit
}}</view> }}</view>
<!-- 运费 --> <!-- 运费 -->
<view class="goods-desc" style="margin-top: 10rpx;">运费 {{ <view class="goods-desc" style="margin-top: 10rpx;">运费 {{
item.commodity_goods_info.freight }}</view> item.commodity_goods_info.freight }}</view>
@ -240,6 +240,7 @@
</view> </view>
<view @click.stop="changeShadow"> <view @click.stop="changeShadow">
<view class="shadowBox1"> <view class="shadowBox1">
<button class="shadowBox1Item_btn" open-type="share" bindtap="onShareButtonClick"/>
<view class="shadowBox1Item" @click="shareFriend"> <view class="shadowBox1Item" @click="shareFriend">
<image <image
src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_WX.png" src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_WX.png"
@ -300,13 +301,16 @@ export default {
activeTab: 'pickup', // activeTab: 'pickup', //
quantity: 1, // quantity: 1, //
selectedPayment: 'wechat', selectedPayment: 'wechat',
boxshadow1: false, boxshadow1: true,
boxshadow2: false, boxshadow2: false,
defAddress: {}, defAddress: {},
defZTAddress: [], defZTAddress: [],
orderList1: [], orderList1: [],
orderList2: [], orderList2: [],
carList: [], carList: [],
// id
group_buy_activity_id: 0,
}; };
}, },
onLoad(options) { onLoad(options) {
@ -455,8 +459,11 @@ export default {
const params = { const params = {
user_id: uni.getStorageSync('userId'), user_id: uni.getStorageSync('userId'),
// TODO
is_group_buy: true, is_group_buy: true,
goods_list: this.orderList2.map(item => { goods_list: this.orderList2.map(item => {
// id
this.group_buy_activity_id = item.commodity_goods_info.group_buy_activity_id
const ztAddress = this.defZTAddress.find(adItem => adItem.id === item.goods_id) || {}; const ztAddress = this.defZTAddress.find(adItem => adItem.id === item.goods_id) || {};
return { return {
@ -477,8 +484,7 @@ export default {
} }
request(apiArr.createOrder, "POST", params).then(res => { request(apiArr.createOrder, "POST", params).then(resVal => {
console.log("🚀 ~ submitPayment ~ 创建订单接口...")
// trans_type // trans_type
// : 71, App: 51 // : 71, App: 51
const systemInfo = uni.getSystemInfoSync(); const systemInfo = uni.getSystemInfoSync();
@ -499,12 +505,11 @@ export default {
// #endif // #endif
const param = { const param = {
order_id: res.order_id, order_id: resVal.order_id,
user_id: uni.getStorageSync('userId'), user_id: uni.getStorageSync('userId'),
trans_type: trans_type trans_type: trans_type
} }
request(apiArr.mergePreorder, "POST", param).then(res => { request(apiArr.mergePreorder, "POST", param).then(res => {
console.log("🚀 ~ submitPayment ~ 调起微信支付..." ,param)
if (res && res.timeStamp && res.nonceStr && res.package && res.signType && res.paySign) { if (res && res.timeStamp && res.nonceStr && res.package && res.signType && res.paySign) {
// //
@ -515,11 +520,15 @@ export default {
signType: res.signType, signType: res.signType,
paySign: res.paySign, paySign: res.paySign,
success: (payRes) => { success: (payRes) => {
console.log("支付成功", payRes) const params = {
uni.showToast({ order_id: resVal.order_id,
title: '支付成功', from: 2,
icon: 'success' group_buy_activity_id: this.group_buy_activity_id,
}
request(apiArr.queryOrder, "POST", params).then(res => {
this.boxshadow1 = true
}) })
}, },
fail: (payErr) => { fail: (payErr) => {
console.log("支付失败", payErr) console.log("支付失败", payErr)

View File

@ -487,38 +487,59 @@ export default {
// //
minus(carItem, goodsIndex, item) { minus(carItem, goodsIndex, item) {
let that = this; let that = this;
if (carItem.count > 0) { if (carItem.count > 0) {
if (carItem.count == carItem.commodity_goods_info.min_order_quantity) { if (carItem.count == carItem.commodity_goods_info.min_order_quantity) {
uni.showToast({ uni.showToast({
title: '最少购买' + carItem.commodity_goods_info.min_order_quantity + '件', title: '最少购买' + carItem.commodity_goods_info.min_order_quantity + '件',
icon: 'none' icon: 'none'
}); });
request(apiArr.deleteCar, "POST", { request(apiArr.deleteCar, "POST", {
ids: [carItem.id], ids: [carItem.id],
}).then((res) => { }).then((res) => {
item.splice(goodsIndex, 1); //
// item.splice(goodsIndex, 1);
if (item.length === 0) {
const carIndex = this.shopCarList.indexOf(carItem); // API
if (carIndex == -1) { that.shopCarTotal = that.shopCarTotal - carItem.commodity_goods_info.min_order_quantity;
this.shopCarList.splice(carIndex, 1);
//
if (item.length === 0) {
//
const dayCarIndex = that.isDayCarList.findIndex(dayItem =>
dayItem.commodity_cart_and_goods_model === item
);
const normalCarIndex = that.shopCarList.findIndex(normalItem =>
normalItem.commodity_cart_and_goods_model === item
);
if (dayCarIndex !== -1) {
that.isDayCarList.splice(dayCarIndex, 1);
//
if (that.isDayCarList.length === 0) {
that.isDayshow = false;
}
}
if (normalCarIndex !== -1) {
that.shopCarList.splice(normalCarIndex, 1);
//
if (that.shopCarList.length === 0) {
that.parcelPostshow = false;
}
}
} }
}
that.calcTotal(); that.calcTotal();
that.shopCarTotal = that.shopCarTotal - 1; });
}); } else {
carItem.count = 0 this.shopCarTotal = this.shopCarTotal - 1;
that.shopCarTotal = that.shopCarTotal - carItem.commodity_goods_info.min_order_quantity; carItem.count = carItem.count - 1;
} else { this.handleQuantityChange(carItem.count, carItem);
this.shopCarTotal = this.shopCarTotal - 1; }
carItem.count = carItem.count - 1; this.calcTotal();
this.handleQuantityChange(carItem.count, carItem);
} }
this.calcTotal(); },
}
},
// //
add(carItem, goodsIndex) { add(carItem, goodsIndex) {