223 lines
4.7 KiB
Vue
223 lines
4.7 KiB
Vue
<template>
|
||
<view class="reservation-item reservation-box">
|
||
<view class="column reservation-inner" @click="openReservationPopup()">
|
||
<view class="row title title-row mt-10">
|
||
<view class="title">{{ reservation.title || '麻将预约' }}</view>
|
||
<view class="status-text" :style="getStatusStyle(reservation.status)">
|
||
{{ getStatusText(reservation.status) }}
|
||
</view>
|
||
</view>
|
||
|
||
<view class="row row-text row-center mt-10">
|
||
<text class="ml-20">{{ formatTimeRange(reservation.start_time, reservation.end_time) }}</text>
|
||
</view>
|
||
|
||
<view class="row row-center mt-10">
|
||
<text class="row-text ml-20">{{ reservation.room_name || '' }}</text>
|
||
</view>
|
||
|
||
<view class="row row-center mt-10">
|
||
<text class="row-text ml-20">已约牌友:</text>
|
||
<image v-for="(participant, pIndex) in reservation.participants" :key="pIndex"
|
||
:src="participant.avatarImage || '/static/default-avatar.png'" class="avatar" mode="aspectFill" />
|
||
<view class="center evaluate-btn" v-if="reservation.status == 2" @click.stop="onEvaluate()">
|
||
<text class="evaluate-btn-text">牌友评价</text>
|
||
</view>
|
||
</view>
|
||
<view class="mt-20" style="height: 10rpx;"></view>
|
||
</view>
|
||
|
||
<!-- 评价弹窗由父页面控制 -->
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
// 仅负责展示与触发评价事件
|
||
import { inject } from 'vue'
|
||
const props = defineProps({
|
||
reservation: {
|
||
type: Object,
|
||
required: true
|
||
}
|
||
})
|
||
const emit = defineEmits(['evaluate', 'click'])
|
||
|
||
const onEvaluate = () => {
|
||
emit('evaluate', props.reservation)
|
||
// openEvaluatePop?.(props.reservation)
|
||
}
|
||
|
||
const formatTimeRange = (startTime, endTime) => {
|
||
if (!startTime || !endTime) return '时间未设置'
|
||
const start = new Date(startTime)
|
||
const end = new Date(endTime)
|
||
const startStr = `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, '0')}-${String(start.getDate()).padStart(2, '0')} ${String(start.getHours()).padStart(2, '0')}:${String(start.getMinutes()).padStart(2, '0')}`
|
||
const endStr = `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, '0')}-${String(end.getDate()).padStart(2, '0')} ${String(end.getHours()).padStart(2, '0')}:${String(end.getMinutes()).padStart(2, '0')}`
|
||
return `${startStr} ~ ${endStr}`
|
||
}
|
||
|
||
const getStatusText = (status) => {
|
||
const map = { 0: '待开始', 1: '进行中', 2: '已结束', 3: "已取消" }
|
||
return map[status] || '未知状态'
|
||
}
|
||
const getStatusStyle = (status) => {
|
||
const map = { 0: 'color: #1989FA', 1: 'color: #999', 2: 'color: #999', 3: 'color: #999' }
|
||
return map[status] || 'color: #999'
|
||
}
|
||
const openReservationPopup = () => {
|
||
emit('click', props.reservation)
|
||
// openReservationPopupf?.(props.reservation)
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.reservation-item {
|
||
background: linear-gradient(180deg, #D7F0DD 0%, #FFFFFF 100%);
|
||
box-shadow: 0rpx 0rpx 10rpx 0rpx rgba(0, 0, 0, 0.25);
|
||
border-radius: 46rpx 46rpx 46rpx 46rpx;
|
||
transition: transform 0.2s;
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
}
|
||
}
|
||
|
||
.reservation-box {
|
||
width: 100%;
|
||
border-radius: 25rpx;
|
||
background-color: #F2F3F5;
|
||
}
|
||
|
||
.reservation-inner {
|
||
width: 95%;
|
||
margin: 20rpx auto 20rpx;
|
||
}
|
||
|
||
.title {
|
||
font-family: PingFang SC, PingFang SC;
|
||
font-weight: 500;
|
||
font-size: 35rpx;
|
||
color: #322A2A;
|
||
text-align: left;
|
||
font-style: normal;
|
||
text-transform: none;
|
||
}
|
||
|
||
.title-row {
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.row-text {
|
||
font-family: PingFang SC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 30rpx;
|
||
color: #575757;
|
||
text-align: left;
|
||
font-style: normal;
|
||
text-transform: none;
|
||
}
|
||
|
||
.row-center {
|
||
align-items: center;
|
||
}
|
||
|
||
.mt-20 {
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.mt-10 {
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
|
||
.ml-20 {
|
||
margin-left: 20rpx;
|
||
}
|
||
|
||
.avatar {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
border-radius: 50%;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.status-text {
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.evaluate-btn {
|
||
width: 120rpx;
|
||
height: 30px;
|
||
background-color: #1989FA;
|
||
border-radius: 10rpx;
|
||
margin-left: auto;
|
||
}
|
||
|
||
.evaluate-btn-text {
|
||
font-size: 24rpx;
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.popup-container {
|
||
width: 650rpx;
|
||
background-color: #FFFFFF;
|
||
border-radius: 10rpx;
|
||
}
|
||
|
||
.popup-inner {
|
||
width: 90%;
|
||
margin: 0 auto 0;
|
||
}
|
||
|
||
.popup-title {
|
||
font-size: 26rpx;
|
||
margin-top: 30rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.popup-desc {
|
||
font-size: 24rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.panel-box {
|
||
width: 100%;
|
||
background-color: #F2F3F5;
|
||
border-radius: 10rpx;
|
||
padding-top: 20rpx;
|
||
padding-bottom: 20rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.down-icon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
margin-left: auto;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.font-24 {
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.action-row {
|
||
margin-top: 50rpx;
|
||
height: 80rpx;
|
||
color: #FFFFFF;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.action-btn {
|
||
flex: 1;
|
||
background-color: #1989FA;
|
||
border-radius: 10rpx;
|
||
}
|
||
|
||
.info-tip {
|
||
font-size: 24rpx;
|
||
text-align: center;
|
||
margin-top: 20rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
</style>
|