You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
10 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="order-page">
<view class="header-title">我的购票</view>
<!-- 订单卡片列表 -->
<view class="order-list">
<!-- 已购票 -->
<view class="order-card purchased">
<view class="order-card-header">
<view class="status purchased"><span class="status-text">已购票</span></view>
<view class="date">2024-01-15</view>
</view>
<view class="order-info">
<view class="flight">苏航666(ZJ12345)</view>
<view class="desc"> 南向北 | 下午批次</view>
</view>
<view class="order-actions single-btn">
<button class="detail-btn" @click="onShowDetail"></button>
</view>
</view>
<!-- -->
<view class="order-card pending">
<view class="order-card-header">
<view class="status pending"><span class="status-text">待确认</span></view>
<view class="date">2024-01-15</view>
</view>
<view class="order-info">
<view class="flight">苏航666(ZJ12345)</view>
<view class="desc"> 北向南 | 上午批次</view>
</view>
<view class="order-actions">
<button class="cancel-btn" :disabled="false" @click="onCancelOrder"></button>
<button class="detail-btn" @click="onShowDetail"></button>
</view>
</view>
<!-- -->
<view class="order-card confirmed">
<view class="order-card-header">
<view class="status confirmed"><span class="status-text">已确认</span></view>
<view class="date">2024-01-15</view>
</view>
<view class="order-info">
<view class="flight">苏航666(ZJ12345)</view>
<view class="desc"> 北向南 | 上午批次</view>
</view>
<view class="order-actions">
<button class="detail-btn" @click="onShowDetail"></button>
<button class="buy-btn" @click="goPayOrder"></button>
</view>
</view>
<!-- -->
<view class="order-card cancelled">
<view class="order-card-header">
<view class="status cancelled"><span class="status-text">已取消</span></view>
<view class="date">2024-01-15</view>
</view>
<view class="order-info">
<view class="flight">苏航666(ZJ12345)</view>
<view class="desc"> 北向南 | 上午批次</view>
</view>
<view class="order-actions">
<button class="detail-btn" @click="onShowDetail"></button>
<button class="rebook-btn" @click="goReservation"></button>
</view>
</view>
</view>
<view v-if="showDetail" class="detail-modal-mask">
<view class="detail-modal">
<view class="modal-close" @click="onCloseDetail">×</view>
<view class="modal-title">船舶信息</view>
<view class="modal-row"><text class="modal-label">过闸方向</text><text>{{ detailInfo.direction }}</text></view>
<view class="modal-row"><text class="modal-label">批次号</text><text>{{ detailInfo.batchNo }}</text></view>
<view class="modal-row"><text class="modal-label">船舶信息</text><text>{{ detailInfo.ship }}</text></view>
<view class="modal-row"><text class="modal-label">购票时间</text><text>{{ detailInfo.time }}</text></view>
<view class="modal-row"><text class="modal-label">支付方式</text><text>{{ detailInfo.payType }}</text></view>
<view class="modal-row">
<text class="modal-label">支付金额</text>
<text class="modal-amount">¥{{ detailInfo.amount }}</text>
</view>
<button class="modal-confirm-btn" @click="onCloseDetail"></button>
</view>
</view>
</view>
</template>
<script>
import { API } from '@/config/index.js'
export default {
name: 'OrderPage',
data() {
return {
showDetail: false,
detailInfo: {
direction: '北向南过闸',
batchNo: '2025040101',
ship: '苏航666(ZJ12345)',
time: '2024-01-15 10:30',
payType: '微信支付',
amount: '120.00'
},
reservationStatusEnum: [],
reservationList: []
}
},
onShow() {
this.fetchReservationStatusEnum().then(() => {
this.fetchReservationList();
});
},
methods: {
async fetchReservationStatusEnum() {
const token = uni.getStorageSync('token');
if (!token) return;
try {
const res = await new Promise((resolve, reject) => {
uni.request({
url: `${API.RESERVATION_STATUS_ENUM}?token=${token}`,
method: 'GET',
success: resolve,
fail: reject
});
});
if (res.data && res.data.errcode === 0) {
this.reservationStatusEnum = res.data.data;
}
} catch (e) {
// 可选:错误处理
}
},
async fetchReservationList() {
const token = uni.getStorageSync('token');
if (!token) return;
try {
const res = await new Promise((resolve, reject) => {
uni.request({
url: `${API.RESERVATION_LIST}?token=${token}`,
method: 'GET',
success: resolve,
fail: reject
});
});
if (res.data && res.data.errcode === 0) {
this.reservationList = res.data.data;
}
} catch (e) {
// 可选:错误处理
}
},
onCancelOrder() {
uni.showModal({
title: '提示',
content: '确定要取消该预约吗?',
confirmText: '确定',
cancelText: '再想想',
success: (res) => {
if (res.confirm) {
// 这里写取消预约的逻辑
uni.showToast({ title: '已取消预约', icon: 'success' });
}
}
});
},
onShowDetail() {
this.showDetail = true;
},
onCloseDetail() {
this.showDetail = false;
},
goPayOrder() {
uni.navigateTo({ url: '/pages/order/pay_order' });
},
goReservation() {
uni.navigateTo({ url: '/pages/reservation/index' });
}
}
}
</script>
<style scoped>
.order-page {
background: linear-gradient(180deg, #cbe6ff 0%, #f6faff 100%);
min-height: 100vh;
padding-bottom: 20px;
font-family: 'SourceHanSansCN', 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
.header-title {
text-align: center;
font-size: 36rpx;
font-weight: bold;
padding-top: 7vh;
letter-spacing: 2rpx;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 16px 10px 16px;
background: linear-gradient(180deg, #cbe6ff 0%, #f6faff 100%);
}
.back-btn, .more-btn {
font-size: 24px;
color: #333;
}
.title {
font-size: 22px;
font-weight: bold;
color: #222;
}
.order-list {
padding: 10px 0 0 0;
margin-top: 44rpx;
}
.order-card {
background: #fff;
border-radius: 10px;
margin: 0 16px 16px 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
padding: 18px 18px 12px 18px;
height: 340rpx;
}
.order-card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.status {
font-size: 12px;
border-radius: 8rpx;
padding: 2px 8px;
color: #fff;
font-weight: 500;
display: inline-block;
transform: skewX(-20deg);
border: none;
}
.status-text {
display: inline-block;
transform: skewX(20deg);
}
.status.purchased { background: #22c58b; }
.status.pending { background: #ff9800; }
.status.confirmed { background: #217aff; }
.status.cancelled { background: #bdbdbd; }
.date { color: #173766; font-size: 15px; }
.order-info {
margin-bottom: 24px;
}
.flight {
font-size: 16px;
font-weight: 500;
margin-top: 12px;
}
.desc {
color: #888;
font-size: 14px;
margin-top: 10px;
}
.order-actions {
display: flex;
gap: 12px;
}
button {
flex: 1;
border-radius: 4px;
padding: 8px 0;
font-size: 16px;
margin: 0;
}
.detail-btn {
background: #e4f3fe;
color: #217aff;
height: 69rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
margin-left: auto;
}
.order-actions.single-btn {
justify-content: flex-end;
}
.order-actions.single-btn .detail-btn {
flex: 0 0 auto;
width: 153px;
}
.buy-btn, .rebook-btn {
background: linear-gradient(90deg, #3b7cff 0%, #5bb6ff 100%);
color: #fff;
height: 69rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
}
.cancel-btn {
background: #ededed;
color: #bdbdbd;
height: 69rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
}
.cancel-btn[disabled] {
opacity: 1;
}
.tabbar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 60px;
background: #fff;
display: flex;
border-top: 1px solid #eaeaea;
z-index: 10;
}
.tab-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #888;
font-size: 14px;
}
.tab-item.active {
color: #217aff;
}
.icon {
font-size: 22px;
margin-bottom: 2px;
}
.detail-modal-mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.detail-modal {
background: #fff;
border-radius: 20px;
padding: 64rpx 56rpx 48rpx 56rpx;
width: 90vw;
max-width: 500px;
min-height: 420px;
margin: 0 auto;
position: relative;
display: flex;
flex-direction: column;
}
.detail-modal-content {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
}
.modal-close {
position: absolute;
right: 24rpx;
top: 24rpx;
font-size: 44rpx;
color: #222;
z-index: 2;
cursor: pointer;
}
.modal-title {
font-size: 38rpx;
font-weight: bold;
margin-bottom: 40rpx;
text-align: left;
}
.modal-row {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 34rpx;
color: #222;
margin-bottom: 36rpx;
}
.modal-label {
color: #3b4a6b;
min-width: 180rpx;
font-size: 34rpx;
}
.modal-amount {
color: #217aff;
font-size: 32rpx;
font-weight: bold;
}
.modal-confirm-btn {
width: 220px;
height: 44px;
line-height: 44px;
border-radius: 12px;
background: linear-gradient(90deg, #3b7cff 0%, #5bb6ff 100%);
color: #fff;
font-size: 18px;
font-weight: 500;
margin: 40px auto 0 auto;
border: none;
outline: none;
display: block;
padding: 0 !important;
box-sizing: border-box;
}
</style>