2025-05-28 09:16:29 +08:00
|
|
|
|
<!--
|
|
|
|
|
* @Descripttion: 门票活动页面
|
|
|
|
|
* @version: 1.0.0
|
|
|
|
|
* @Author: Assistant
|
|
|
|
|
* @Date: 2025-01-22
|
|
|
|
|
-->
|
|
|
|
|
<template>
|
|
|
|
|
<view class="ticket-container">
|
|
|
|
|
<!-- Tab切换 -->
|
|
|
|
|
<view class="tab-container">
|
|
|
|
|
<view class="tab-wrapper">
|
|
|
|
|
<view
|
|
|
|
|
class="tab-item"
|
|
|
|
|
:class="{ active: currentTab === 0 }"
|
|
|
|
|
@click="switchTab(0)"
|
|
|
|
|
>
|
|
|
|
|
<text class="tab-text">门票活动</text>
|
|
|
|
|
<view class="tab-line" v-if="currentTab === 0"></view>
|
|
|
|
|
</view>
|
|
|
|
|
<view
|
|
|
|
|
class="tab-item"
|
|
|
|
|
:class="{ active: currentTab === 1 }"
|
|
|
|
|
@click="switchTab(1)"
|
|
|
|
|
>
|
|
|
|
|
<text class="tab-text">我的门票</text>
|
|
|
|
|
<view class="tab-line" v-if="currentTab === 1"></view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 内容区域 -->
|
|
|
|
|
<view class="content-area">
|
|
|
|
|
<!-- 门票活动列表 -->
|
|
|
|
|
<view v-if="currentTab === 0" class="activity-list">
|
|
|
|
|
<view
|
|
|
|
|
class="activity-card"
|
|
|
|
|
v-for="item in activityList"
|
|
|
|
|
:key="item.pkId"
|
|
|
|
|
>
|
|
|
|
|
<view class="card-content">
|
|
|
|
|
<view class="activity-image">
|
|
|
|
|
<image :src="item.actCover" mode="aspectFill"></image>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="activity-info">
|
|
|
|
|
<view class="activity-title">{{ item.actName }}</view>
|
|
|
|
|
<view class="activity-detail">
|
|
|
|
|
<text class="detail-label">活动日期:</text>
|
|
|
|
|
<text class="detail-value"
|
|
|
|
|
>{{ item.actStartDate }}~{{ item.actEndDate }}</text
|
|
|
|
|
>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="activity-detail">
|
|
|
|
|
<text class="detail-label">购买日期:</text>
|
|
|
|
|
<text class="detail-value"
|
|
|
|
|
>{{ item.disStartDate }}~{{ item.disEndDate }}</text
|
|
|
|
|
>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="activity-detail">
|
|
|
|
|
<text class="detail-label">总票数:</text>
|
|
|
|
|
<text class="detail-value">{{ item.quantity }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="bottom-section">
|
|
|
|
|
<view class="price-info">
|
|
|
|
|
<text class="price-symbol">¥</text>
|
|
|
|
|
<text class="price-value">{{ item.payMoney }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<button class="buy-btn" @click="goBuyTicket(item)">购买</button>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 空状态 -->
|
|
|
|
|
<view v-if="!activityList.length && !loading" class="empty-state">
|
|
|
|
|
<text class="empty-text">没有更多数据了</text>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 加载状态 -->
|
|
|
|
|
<view v-if="loading" class="loading-state">
|
|
|
|
|
<u-loading-icon mode="spinner"></u-loading-icon>
|
|
|
|
|
<text class="loading-text">加载中...</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 我的门票列表 -->
|
|
|
|
|
<view v-if="currentTab === 1" class="ticket-list">
|
|
|
|
|
<view class="ticket-card" v-for="item in ticketList" :key="item.pkId">
|
|
|
|
|
<view class="ticket-header">
|
|
|
|
|
<text class="order-code">订单编号:{{ item.orderCode }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-content">
|
|
|
|
|
<view class="ticket-info">
|
|
|
|
|
<view class="ticket-title">{{ item.actName }}</view>
|
|
|
|
|
<!-- 基础信息:始终显示 -->
|
|
|
|
|
<view class="ticket-detail">
|
|
|
|
|
<text class="detail-label">门票价格:</text>
|
|
|
|
|
<text class="detail-value price">¥{{ item.price }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail">
|
|
|
|
|
<text class="detail-label">支付时间:</text>
|
|
|
|
|
<text class="detail-value">{{ item.creationTime }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail">
|
|
|
|
|
<text class="detail-label">支付编号:</text>
|
|
|
|
|
<text class="detail-value">{{ item.memberCode }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail">
|
|
|
|
|
<text class="detail-label">支付昵称:</text>
|
|
|
|
|
<text class="detail-value">{{ item.memberName }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail">
|
|
|
|
|
<text class="detail-label">姓名:</text>
|
|
|
|
|
<text class="detail-value">{{ item.buyName }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail">
|
|
|
|
|
<text class="detail-label">联系方式:</text>
|
|
|
|
|
<text class="detail-value">{{ item.phone }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 展开显示的更多信息 -->
|
|
|
|
|
<view v-if="item.expanded" class="expanded-details">
|
|
|
|
|
<view class="ticket-detail" v-if="item.idCard">
|
|
|
|
|
<text class="detail-label">证件证号:</text>
|
|
|
|
|
<text class="detail-value">{{ item.idCard }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail" v-if="item.sexVal">
|
|
|
|
|
<text class="detail-label">性别:</text>
|
|
|
|
|
<text class="detail-value">{{ item.sexVal }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail" v-if="item.clothSize">
|
|
|
|
|
<text class="detail-label">服装尺寸:</text>
|
|
|
|
|
<text class="detail-value">{{ item.clothSize }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail" v-if="item.cohabitant">
|
|
|
|
|
<text class="detail-label">同住人:</text>
|
|
|
|
|
<text class="detail-value">{{ item.cohabitant }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="ticket-detail" v-if="item.emergencyPhone">
|
|
|
|
|
<text class="detail-label">紧急联系方式:</text>
|
|
|
|
|
<text class="detail-value">{{ item.emergencyPhone }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 操作按钮:仅在24小时内显示 -->
|
|
|
|
|
<view
|
|
|
|
|
v-if="isWithin24Hours(item.creationTime)"
|
|
|
|
|
class="action-buttons"
|
|
|
|
|
>
|
|
|
|
|
<button class="cancel-btn" @click="showCancelConfirm(item)">
|
|
|
|
|
撤销门票
|
|
|
|
|
</button>
|
|
|
|
|
<button class="edit-btn" @click="showEditModal(item)">
|
|
|
|
|
修改信息
|
|
|
|
|
</button>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="expand-action" @click="toggleExpand(item)">
|
|
|
|
|
<text class="expand-text">{{
|
|
|
|
|
item.expanded ? '收起' : '查看更多'
|
|
|
|
|
}}</text>
|
|
|
|
|
<u-icon
|
|
|
|
|
:name="item.expanded ? 'arrow-up' : 'arrow-down'"
|
|
|
|
|
size="12"
|
|
|
|
|
color="#999"
|
|
|
|
|
></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 空状态 -->
|
|
|
|
|
<view v-if="!ticketList.length && !ticketLoading" class="empty-state">
|
|
|
|
|
<text class="empty-text">没有更多数据了</text>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 加载状态 -->
|
|
|
|
|
<view v-if="ticketLoading" class="loading-state">
|
|
|
|
|
<u-loading-icon mode="spinner"></u-loading-icon>
|
|
|
|
|
<text class="loading-text">加载中...</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 撤销确认弹窗 -->
|
|
|
|
|
<u-modal
|
2025-05-28 10:45:36 +08:00
|
|
|
|
:show="showCancelModal"
|
2025-05-28 09:16:29 +08:00
|
|
|
|
title="确认撤销"
|
|
|
|
|
:content="cancelModalContent"
|
2025-05-28 10:45:36 +08:00
|
|
|
|
:show-cancel-button="true"
|
2025-05-28 09:16:29 +08:00
|
|
|
|
confirm-text="确认撤销"
|
|
|
|
|
cancel-text="取消"
|
|
|
|
|
@confirm="confirmCancel"
|
|
|
|
|
@cancel="showCancelModal = false"
|
|
|
|
|
></u-modal>
|
|
|
|
|
|
|
|
|
|
<!-- 修改信息弹窗 -->
|
2025-05-28 10:45:36 +08:00
|
|
|
|
<u-popup :show="editModalVisible" mode="center" border-radius="12">
|
2025-05-28 09:16:29 +08:00
|
|
|
|
<view class="edit-modal">
|
|
|
|
|
<view class="modal-header">
|
|
|
|
|
<text class="modal-title">修改门票信息</text>
|
|
|
|
|
<u-icon name="close" size="20" @click="closeEditModal"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<scroll-view scroll-y class="modal-content">
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label optional">活动名称</text>
|
|
|
|
|
<input
|
|
|
|
|
class="form-input disabled"
|
|
|
|
|
:value="editForm.actName"
|
|
|
|
|
disabled
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label optional">订单编号</text>
|
|
|
|
|
<input
|
|
|
|
|
class="form-input disabled"
|
|
|
|
|
:value="editForm.orderCode"
|
|
|
|
|
disabled
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form-item">
|
2025-05-28 10:45:36 +08:00
|
|
|
|
<text class="form-label">姓名</text>
|
2025-05-28 09:16:29 +08:00
|
|
|
|
<input
|
|
|
|
|
class="form-input"
|
|
|
|
|
v-model="editForm.buyName"
|
|
|
|
|
placeholder="请输入姓名"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form-item">
|
2025-05-28 10:45:36 +08:00
|
|
|
|
<text class="form-label">手机号</text>
|
2025-05-28 09:16:29 +08:00
|
|
|
|
<input
|
|
|
|
|
class="form-input"
|
|
|
|
|
v-model="editForm.phone"
|
|
|
|
|
placeholder="请输入手机号"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form-item">
|
2025-05-28 10:45:36 +08:00
|
|
|
|
<text class="form-label">身份证号</text>
|
2025-05-28 09:16:29 +08:00
|
|
|
|
<input
|
|
|
|
|
class="form-input"
|
|
|
|
|
v-model="editForm.idCard"
|
|
|
|
|
placeholder="请输入身份证号"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form-item">
|
2025-05-28 10:45:36 +08:00
|
|
|
|
<text class="form-label">性别</text>
|
2025-05-28 09:16:29 +08:00
|
|
|
|
<u-radio-group v-model="editForm.sex" direction="row">
|
2025-05-28 10:45:36 +08:00
|
|
|
|
<u-radio :name="1" label="男"></u-radio>
|
2025-05-28 16:22:21 +08:00
|
|
|
|
<u-radio :name="2" label="女"></u-radio>
|
2025-05-28 09:16:29 +08:00
|
|
|
|
</u-radio-group>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form-item">
|
2025-05-28 10:45:36 +08:00
|
|
|
|
<text class="form-label">尺码</text>
|
2025-05-28 09:16:29 +08:00
|
|
|
|
<input
|
|
|
|
|
class="form-input"
|
|
|
|
|
v-model="editForm.clothSize"
|
|
|
|
|
placeholder="请输入尺码"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label optional">同住人</text>
|
|
|
|
|
<input
|
|
|
|
|
class="form-input"
|
|
|
|
|
v-model="editForm.cohabitant"
|
|
|
|
|
placeholder="请输入同住人"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label optional">紧急联系人</text>
|
|
|
|
|
<input
|
|
|
|
|
class="form-input"
|
|
|
|
|
v-model="editForm.emergencyPhone"
|
|
|
|
|
placeholder="请输入紧急联系人电话"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
</scroll-view>
|
|
|
|
|
<view class="modal-footer">
|
|
|
|
|
<button class="confirm-btn" @click="updateTicketInfo">确定</button>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</u-popup>
|
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-05-28 10:45:36 +08:00
|
|
|
|
import {
|
|
|
|
|
getTicketActivityList,
|
|
|
|
|
getMyTicketList,
|
|
|
|
|
cancelTicket,
|
|
|
|
|
updateTicket,
|
|
|
|
|
} from '@/config/ticket.js'
|
2025-05-28 09:16:29 +08:00
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
currentTab: 0,
|
|
|
|
|
activityList: [],
|
|
|
|
|
ticketList: [],
|
|
|
|
|
loading: false,
|
|
|
|
|
ticketLoading: false,
|
|
|
|
|
activityPage: {
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
},
|
|
|
|
|
ticketPage: {
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
},
|
|
|
|
|
// 弹窗相关
|
|
|
|
|
showCancelModal: false,
|
|
|
|
|
editModalVisible: false,
|
|
|
|
|
selectedTicket: null,
|
|
|
|
|
editForm: {
|
|
|
|
|
pkId: '',
|
|
|
|
|
actName: '',
|
|
|
|
|
memberCode: '',
|
|
|
|
|
memberName: '',
|
|
|
|
|
orderCode: '',
|
|
|
|
|
orderAmount: '',
|
|
|
|
|
price: '',
|
|
|
|
|
quantity: '',
|
|
|
|
|
buyName: '',
|
|
|
|
|
phone: '',
|
|
|
|
|
idCard: '',
|
|
|
|
|
sex: '',
|
|
|
|
|
sexVal: '',
|
|
|
|
|
clothSize: '',
|
|
|
|
|
cohabitant: '',
|
|
|
|
|
emergencyPhone: '',
|
|
|
|
|
creationTime: '',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
// 撤销弹窗内容
|
|
|
|
|
cancelModalContent() {
|
|
|
|
|
return this.selectedTicket
|
|
|
|
|
? `确定要撤销订单 ${this.selectedTicket.orderCode} 吗?撤销后不可恢复。`
|
|
|
|
|
: '确定要撤销此订单吗?撤销后不可恢复。'
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
onLoad() {
|
|
|
|
|
this.loadActivityList()
|
|
|
|
|
},
|
|
|
|
|
onPullDownRefresh() {
|
|
|
|
|
this.refreshCurrentTab()
|
|
|
|
|
},
|
|
|
|
|
// onReachBottom() {
|
|
|
|
|
// this.loadMoreData()
|
|
|
|
|
// },
|
|
|
|
|
methods: {
|
|
|
|
|
// 返回上一页
|
|
|
|
|
goBack() {
|
|
|
|
|
uni.navigateBack()
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 切换Tab
|
|
|
|
|
switchTab(index) {
|
|
|
|
|
this.currentTab = index
|
|
|
|
|
if (index === 0) {
|
|
|
|
|
this.loadActivityList()
|
|
|
|
|
} else {
|
|
|
|
|
this.loadTicketList()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 刷新当前Tab数据
|
|
|
|
|
refreshCurrentTab() {
|
|
|
|
|
if (this.currentTab === 0) {
|
|
|
|
|
this.activityPage.pageNum = 1
|
|
|
|
|
this.activityList = []
|
|
|
|
|
this.loadActivityList()
|
|
|
|
|
} else {
|
|
|
|
|
this.ticketPage.pageNum = 1
|
|
|
|
|
this.ticketList = []
|
|
|
|
|
this.loadTicketList()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 加载更多数据
|
|
|
|
|
loadMoreData() {
|
|
|
|
|
if (this.currentTab === 0) {
|
|
|
|
|
this.activityPage.pageNum++
|
|
|
|
|
this.loadActivityList()
|
|
|
|
|
} else {
|
|
|
|
|
this.ticketPage.pageNum++
|
|
|
|
|
this.loadTicketList()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 加载活动列表
|
|
|
|
|
async loadActivityList() {
|
|
|
|
|
this.loading = true
|
|
|
|
|
try {
|
|
|
|
|
const res = await getTicketActivityList(this.activityPage)
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
if (this.activityPage.pageNum === 1) {
|
|
|
|
|
this.activityList = res.rows || []
|
|
|
|
|
} else {
|
|
|
|
|
this.activityList.push(...(res.rows || []))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载活动列表失败:', error)
|
|
|
|
|
uni.$u.toast('加载失败,请重试')
|
|
|
|
|
} finally {
|
|
|
|
|
this.loading = false
|
|
|
|
|
uni.stopPullDownRefresh()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 加载门票列表
|
|
|
|
|
async loadTicketList() {
|
|
|
|
|
this.ticketLoading = true
|
|
|
|
|
try {
|
|
|
|
|
const res = await getMyTicketList(this.ticketPage)
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
if (this.ticketPage.pageNum === 1) {
|
|
|
|
|
this.ticketList = res.rows || []
|
|
|
|
|
} else {
|
|
|
|
|
this.ticketList.push(...(res.rows || []))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载门票列表失败:', error)
|
|
|
|
|
uni.$u.toast('加载失败,请重试')
|
|
|
|
|
} finally {
|
|
|
|
|
this.ticketLoading = false
|
|
|
|
|
uni.stopPullDownRefresh()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 去购买门票
|
|
|
|
|
goBuyTicket(activity) {
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
url: `/pages/ticket/buy?activityId=${activity.pkId}&activityName=${encodeURIComponent(activity.actName)}&price=${activity.payMoney}`,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 查看门票详情
|
|
|
|
|
goTicketDetail(ticket) {
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
url: `/pages/ticket/detail?ticketId=${ticket.pkId}`,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 切换展开/收起状态
|
|
|
|
|
toggleExpand(item) {
|
|
|
|
|
// 使用 $set 确保响应式更新
|
|
|
|
|
this.$set(item, 'expanded', !item.expanded)
|
|
|
|
|
},
|
|
|
|
|
|
2025-05-28 10:45:36 +08:00
|
|
|
|
// 判断是否为当天购买
|
2025-05-28 09:16:29 +08:00
|
|
|
|
isWithin24Hours(creationTime) {
|
|
|
|
|
if (!creationTime) return false
|
|
|
|
|
const createDate = new Date(creationTime)
|
|
|
|
|
const now = new Date()
|
2025-05-28 10:45:36 +08:00
|
|
|
|
|
|
|
|
|
// 获取创建日期的年月日
|
|
|
|
|
const createYear = createDate.getFullYear()
|
|
|
|
|
const createMonth = createDate.getMonth()
|
|
|
|
|
const createDay = createDate.getDate()
|
|
|
|
|
|
|
|
|
|
// 获取当前日期的年月日
|
|
|
|
|
const nowYear = now.getFullYear()
|
|
|
|
|
const nowMonth = now.getMonth()
|
|
|
|
|
const nowDay = now.getDate()
|
|
|
|
|
|
|
|
|
|
// 判断是否为同一天
|
|
|
|
|
return (
|
|
|
|
|
createYear === nowYear &&
|
|
|
|
|
createMonth === nowMonth &&
|
|
|
|
|
createDay === nowDay
|
|
|
|
|
)
|
2025-05-28 09:16:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 显示撤销确认弹窗
|
|
|
|
|
showCancelConfirm(ticket) {
|
|
|
|
|
this.selectedTicket = ticket
|
|
|
|
|
this.showCancelModal = true
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 确认撤销门票
|
|
|
|
|
async confirmCancel() {
|
|
|
|
|
if (!this.selectedTicket) return
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
uni.showLoading({ title: '撤销中...' })
|
2025-05-28 10:45:36 +08:00
|
|
|
|
const res = await cancelTicket({
|
|
|
|
|
orderCode: this.selectedTicket.orderCode,
|
|
|
|
|
})
|
2025-05-28 09:16:29 +08:00
|
|
|
|
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
uni.$u.toast('撤销成功')
|
|
|
|
|
this.showCancelModal = false
|
|
|
|
|
this.selectedTicket = null
|
|
|
|
|
// 刷新列表
|
|
|
|
|
this.refreshCurrentTab()
|
|
|
|
|
} else {
|
|
|
|
|
uni.$u.toast(res.msg || '撤销失败')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('撤销门票失败:', error)
|
|
|
|
|
uni.$u.toast('撤销失败,请重试')
|
|
|
|
|
} finally {
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 显示修改信息弹窗
|
|
|
|
|
showEditModal(ticket) {
|
|
|
|
|
this.selectedTicket = ticket
|
|
|
|
|
// 填充表单数据
|
|
|
|
|
this.editForm = {
|
|
|
|
|
pkId: ticket.pkId,
|
|
|
|
|
actName: ticket.actName,
|
|
|
|
|
memberCode: ticket.memberCode,
|
|
|
|
|
memberName: ticket.memberName,
|
|
|
|
|
orderCode: ticket.orderCode,
|
|
|
|
|
orderAmount: ticket.orderAmount,
|
|
|
|
|
price: ticket.price,
|
|
|
|
|
quantity: ticket.quantity,
|
|
|
|
|
buyName: ticket.buyName || '',
|
|
|
|
|
phone: ticket.phone || '',
|
|
|
|
|
idCard: ticket.idCard || '',
|
|
|
|
|
sex: ticket.sex || '',
|
|
|
|
|
sexVal: ticket.sexVal || '',
|
|
|
|
|
clothSize: ticket.clothSize || '',
|
|
|
|
|
cohabitant: ticket.cohabitant || '',
|
|
|
|
|
emergencyPhone: ticket.emergencyPhone || '',
|
|
|
|
|
creationTime: ticket.creationTime,
|
|
|
|
|
}
|
|
|
|
|
this.editModalVisible = true
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 关闭修改弹窗
|
|
|
|
|
closeEditModal() {
|
|
|
|
|
this.editModalVisible = false
|
|
|
|
|
this.selectedTicket = null
|
|
|
|
|
this.editForm = {
|
|
|
|
|
pkId: '',
|
|
|
|
|
actName: '',
|
|
|
|
|
memberCode: '',
|
|
|
|
|
memberName: '',
|
|
|
|
|
orderCode: '',
|
|
|
|
|
orderAmount: '',
|
|
|
|
|
price: '',
|
|
|
|
|
quantity: '',
|
|
|
|
|
buyName: '',
|
|
|
|
|
phone: '',
|
|
|
|
|
idCard: '',
|
|
|
|
|
sex: '',
|
|
|
|
|
sexVal: '',
|
|
|
|
|
clothSize: '',
|
|
|
|
|
cohabitant: '',
|
|
|
|
|
emergencyPhone: '',
|
|
|
|
|
creationTime: '',
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 更新门票信息
|
|
|
|
|
async updateTicketInfo() {
|
|
|
|
|
// 表单验证
|
|
|
|
|
if (!this.editForm.buyName) {
|
|
|
|
|
uni.$u.toast('请输入姓名')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!this.editForm.phone) {
|
|
|
|
|
uni.$u.toast('请输入手机号')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!this.editForm.idCard) {
|
|
|
|
|
uni.$u.toast('请输入身份证号')
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-05-28 15:29:20 +08:00
|
|
|
|
if (!this.editForm.sex && this.editForm.sex !== 0) {
|
2025-05-28 09:16:29 +08:00
|
|
|
|
uni.$u.toast('请选择性别')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!this.editForm.clothSize) {
|
|
|
|
|
uni.$u.toast('请输入尺码')
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-05-28 15:29:20 +08:00
|
|
|
|
if (this.editForm.emergencyPhone === this.editForm.phone) {
|
|
|
|
|
uni.$u.toast('紧急联系方式不能与联系方式相同')
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-05-28 09:16:29 +08:00
|
|
|
|
|
|
|
|
|
// 设置性别值
|
2025-05-28 16:22:21 +08:00
|
|
|
|
this.editForm.sexVal = this.editForm.sex === 1 ? '男' : '女'
|
2025-05-28 09:16:29 +08:00
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
uni.showLoading({ title: '更新中...' })
|
2025-05-28 10:45:36 +08:00
|
|
|
|
const res = await updateTicket(this.editForm)
|
2025-05-28 09:16:29 +08:00
|
|
|
|
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
uni.$u.toast('修改成功')
|
|
|
|
|
this.closeEditModal()
|
|
|
|
|
// 刷新列表
|
|
|
|
|
this.refreshCurrentTab()
|
|
|
|
|
} else {
|
|
|
|
|
uni.$u.toast(res.msg || '修改失败')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('更新门票信息失败:', error)
|
|
|
|
|
uni.$u.toast('修改失败,请重试')
|
|
|
|
|
} finally {
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
2025-05-28 10:45:36 +08:00
|
|
|
|
::v-deep(.uni-scroll-view) {
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
}
|
2025-05-28 09:16:29 +08:00
|
|
|
|
.ticket-container {
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
background: #f8f8f8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.custom-navbar {
|
|
|
|
|
position: fixed;
|
|
|
|
|
top: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
z-index: 999;
|
|
|
|
|
background: #fff;
|
|
|
|
|
padding-top: var(--status-bar-height);
|
|
|
|
|
border-bottom: 2rpx solid #eee;
|
|
|
|
|
|
|
|
|
|
.navbar-content {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
height: 88rpx;
|
|
|
|
|
padding: 0 32rpx;
|
|
|
|
|
|
|
|
|
|
.back-btn {
|
|
|
|
|
width: 80rpx;
|
|
|
|
|
height: 80rpx;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.navbar-title {
|
|
|
|
|
flex: 1;
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 36rpx;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.placeholder {
|
|
|
|
|
width: 80rpx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab-container {
|
|
|
|
|
position: fixed;
|
|
|
|
|
top: calc(var(--status-bar-height) + 88rpx);
|
|
|
|
|
left: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
z-index: 998;
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-bottom: 2rpx solid #eee;
|
|
|
|
|
|
|
|
|
|
.tab-wrapper {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
.tab-item {
|
|
|
|
|
flex: 1;
|
|
|
|
|
position: relative;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding: 32rpx 0;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
|
|
.tab-text {
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
color: #666;
|
|
|
|
|
transition: color 0.3s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab-line {
|
|
|
|
|
position: absolute;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
width: 60rpx;
|
|
|
|
|
height: 6rpx;
|
|
|
|
|
background: #005bac;
|
|
|
|
|
border-radius: 3rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&.active .tab-text {
|
|
|
|
|
color: #005bac;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.content-area {
|
2025-05-28 15:29:20 +08:00
|
|
|
|
margin-top: calc(100rpx);
|
2025-05-28 09:16:29 +08:00
|
|
|
|
padding: 24rpx;
|
2025-05-28 15:29:20 +08:00
|
|
|
|
min-height: calc(100vh - 100rpx);
|
2025-05-28 09:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.activity-card {
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
|
|
|
|
border: 1rpx solid #f0f0f0;
|
|
|
|
|
|
|
|
|
|
.card-content {
|
|
|
|
|
display: flex;
|
|
|
|
|
padding: 24rpx;
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
|
|
|
|
.activity-image {
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
width: 208rpx;
|
|
|
|
|
height: 208rpx;
|
|
|
|
|
border-radius: 40rpx;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
image {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.activity-info {
|
|
|
|
|
flex: 1;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
|
|
.activity-title {
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.activity-detail {
|
|
|
|
|
display: flex;
|
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
|
|
|
|
|
|
.detail-label {
|
|
|
|
|
font-size: 20rpx;
|
|
|
|
|
color: #999;
|
|
|
|
|
min-width: 140rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.detail-value {
|
|
|
|
|
font-size: 20rpx;
|
|
|
|
|
color: #666;
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bottom-section {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
.price-info {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: baseline;
|
|
|
|
|
color: #ff4444;
|
|
|
|
|
|
|
|
|
|
.price-symbol {
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
margin-right: 2rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.price-value {
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.buy-btn {
|
|
|
|
|
background: #005bac;
|
|
|
|
|
color: #fff;
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 40rpx;
|
|
|
|
|
padding: 0rpx 32rpx;
|
|
|
|
|
font-size: 20rpx;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ticket-card {
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
padding: 24rpx;
|
|
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
|
|
|
|
|
|
|
|
|
.ticket-header {
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
|
|
|
|
.order-code {
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #999;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ticket-content {
|
|
|
|
|
.ticket-info {
|
|
|
|
|
.ticket-title {
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ticket-detail {
|
|
|
|
|
display: flex;
|
|
|
|
|
margin-bottom: 12rpx;
|
|
|
|
|
|
|
|
|
|
.detail-label {
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #999;
|
|
|
|
|
min-width: 140rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.detail-value {
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #666;
|
|
|
|
|
|
|
|
|
|
&.price {
|
2025-05-28 10:45:36 +08:00
|
|
|
|
color: #ff4444;
|
2025-05-28 09:16:29 +08:00
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.expanded-details {
|
|
|
|
|
animation: fadeIn 0.3s ease-in-out;
|
|
|
|
|
|
|
|
|
|
.ticket-detail {
|
|
|
|
|
margin-bottom: 12rpx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
margin-top: 16rpx;
|
|
|
|
|
padding: 16rpx 0;
|
|
|
|
|
|
|
|
|
|
.cancel-btn,
|
|
|
|
|
.edit-btn {
|
|
|
|
|
flex: 1;
|
|
|
|
|
height: 60rpx;
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 30rpx;
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.cancel-btn {
|
|
|
|
|
background: #fff;
|
|
|
|
|
color: #ff4444;
|
|
|
|
|
border: 2rpx solid #ff4444;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.edit-btn {
|
|
|
|
|
background: #005bac;
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.expand-action {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
margin-top: 16rpx;
|
|
|
|
|
padding: 16rpx 0;
|
|
|
|
|
border-top: 1rpx solid #eee;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: background-color 0.2s;
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
background-color: #f8f8f8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.expand-text {
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #999;
|
|
|
|
|
margin-right: 8rpx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.empty-state,
|
|
|
|
|
.loading-state {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
padding: 120rpx 0;
|
|
|
|
|
|
|
|
|
|
.empty-text,
|
|
|
|
|
.loading-text {
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
color: #999;
|
|
|
|
|
margin-top: 16rpx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes fadeIn {
|
|
|
|
|
from {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-10rpx);
|
|
|
|
|
}
|
|
|
|
|
to {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 修改信息弹窗样式
|
|
|
|
|
.edit-modal {
|
|
|
|
|
width: 640rpx;
|
2025-05-28 10:45:36 +08:00
|
|
|
|
max-height: 90vh;
|
2025-05-28 09:16:29 +08:00
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 24rpx;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
|
|
.modal-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
padding: 32rpx;
|
|
|
|
|
border-bottom: 2rpx solid #eee;
|
|
|
|
|
|
|
|
|
|
.modal-title {
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.modal-content {
|
2025-05-28 10:45:36 +08:00
|
|
|
|
max-height: 70vh;
|
2025-05-28 09:16:29 +08:00
|
|
|
|
padding: 32rpx;
|
2025-05-28 10:45:36 +08:00
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
padding-bottom: 20px;
|
|
|
|
|
overflow-y: hidden;
|
2025-05-28 09:16:29 +08:00
|
|
|
|
.form-item {
|
|
|
|
|
margin-bottom: 32rpx;
|
|
|
|
|
|
|
|
|
|
.form-label {
|
|
|
|
|
display: block;
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
color: #333;
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
|
|
|
|
&::after {
|
|
|
|
|
content: '*';
|
|
|
|
|
color: #ff4444;
|
|
|
|
|
margin-left: 4rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&.optional::after {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-input {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 80rpx;
|
|
|
|
|
padding: 0 24rpx;
|
|
|
|
|
border: 2rpx solid #ddd;
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
color: #333;
|
|
|
|
|
background: #fff;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
|
|
&.disabled {
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
color: #999;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:focus {
|
|
|
|
|
border-color: #005bac;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.modal-footer {
|
|
|
|
|
padding: 32rpx;
|
|
|
|
|
border-top: 2rpx solid #eee;
|
|
|
|
|
|
|
|
|
|
.confirm-btn {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 80rpx;
|
|
|
|
|
background: #005bac;
|
|
|
|
|
color: #fff;
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 40rpx;
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|