2025-07-28 09:54:10 +08:00

555 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="meeting-room-detail">
<!-- 顶部轮播图 -->
<u-swiper class="room-swiper" :list="list1" height="420" indicator indicatorMode="dot"
indicatorActiveColor="#2979ff" bgColor="#f8faff">
</u-swiper>
<!-- 会议室基本信息卡片 -->
<view class="info-card">
<view class="room-info">
<text class="room-name">{{detail.title}}</text>
<view class="meta-info">
<text class="room-capacity"> 可容纳 {{detail.maxNum}} </text>
</view>
<text class="room-desc" v-if="detail.description">{{detail.description}}</text>
</view>
</view>
<!-- 预订信息卡片 -->
<view class="booking-card">
<view class="card-header">
<text class="card-title">预订信息</text>
</view>
<!-- 日期选择 -->
<view class="date-section">
<view class="section-header">
<u-icon name="calendar" size="38" color="#2979ff"></u-icon>
<text class="section-title">选择日期</text>
</view>
<view class="date-display" @click="showCalendar = true">
<text>{{ formattedSelectedDate }}</text>
<u-icon name="arrow-right" color="#999"></u-icon>
</view>
</view>
<!-- 时间选择 -->
<view class="time-section">
<view class="section-header">
<u-icon name="clock" size="34" color="#2979ff"></u-icon>
<text class="section-title">选择时间段</text>
</view>
<view class="time-picker">
<view class="time-selector" @click="showStartTimePicker = true">
<text class="time-label">开始</text>
<view class="time-display">
{{ selectedStartTime }}
</view>
</view>
<view class="time-separator">—</view>
<view class="time-selector" @click="showEndTimePicker = true">
<text class="time-label">结束</text>
<view class="time-display">
{{ selectedEndTime }}
</view>
</view>
</view>
</view>
<!-- 新增备注输入区域 -->
<view class="remark-section">
<view class="section-header">
<u-icon name="edit-pen" size="34" color="#2979ff"></u-icon>
<text class="section-title">备注信息</text>
</view>
<u--textarea v-model="remark" placeholder="请输入备注信息(选填)" count maxlength="200" height="120" border="none"
:customStyle="{background: '#f8f9fa', borderRadius: '12rpx', padding: '20rpx'}"></u--textarea>
</view>
</view>
<!-- 预定须知卡片 -->
<view class="notice-card">
<view class="card-header">
<u-icon name="info-circle" size="34" color="#2979ff"></u-icon>
<text class="card-title">预订须知</text>
</view>
<view class="notice-list">
<view class="notice-item" v-for="(item, index) in noticeList" :key="index">
<text class="notice-index">{{ index + 1 }}.</text>
<text class="notice-content">{{ item }}</text>
</view>
</view>
</view>
<!-- 底部固定操作栏 -->
<view class="action-bar">
<u-button type="primary" shape="circle" @click="handleBook">立即预订</u-button>
</view>
<!-- 日历组件 -->
<u-calendar :key="calendarKey" :show="showCalendar" mode="single" :min-date="minDate" :max-date="maxDate"
@confirm="handleDateConfirm" @close="showCalendar = false" :mask-close-able="true"></u-calendar>
<!-- 时间选择器 -->
<u-datetime-picker :show="showStartTimePicker" v-model="startTimePickerValue" mode="time" format="HH:mm"
@confirm="handleStartTimeConfirm" @cancel="showStartTimePicker = false"></u-datetime-picker>
<u-datetime-picker :show="showEndTimePicker" v-model="endTimePickerValue" mode="time" format="HH:mm"
@confirm="handleEndTimeConfirm" @cancel="showEndTimePicker = false"></u-datetime-picker>
</view>
</template>
<script>
import {
get,
post
} from '@/utils/request';
import {
IMAGE_BASE_URL,
BASE_URL
} from '@/utils/config';
import {
formatTime,
formatRelativeTime
} from '@/utils/timeFormat';
import {
applyType,
usage,
thingTheme
} from '@/utils/dict.js'
export default {
data() {
const now = new Date();
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, '0');
const day = now.getDate().toString().padStart(2, '0');
// 计算默认开始/结束时间
let startHours = now.getHours();
let startMinutes = now.getMinutes() < 30 ? 30 : 0;
if (now.getMinutes() >= 30) startHours += 1;
if (startHours >= 24) startHours = 0;
let endHours = startHours + 1;
let endMinutes = startMinutes;
if (endHours >= 24) endHours = 0;
return {
// 会议室图片数组
list1: [],
detail: {},
// 日历控制(默认隐藏)
showCalendar: false,
calendarKey: 0,
// 时间选择器控制
showStartTimePicker: false,
showEndTimePicker: false,
// 使用字符串格式的时间
startTimePickerValue: `${startHours.toString().padStart(2, '0')}:${startMinutes.toString().padStart(2, '0')}`,
endTimePickerValue: `${endHours.toString().padStart(2, '0')}:${endMinutes.toString().padStart(2, '0')}`,
// 日期相关
selectedDate: `${year}-${month}-${day}`,
minDate: `${year}-${month}-${day}`,
maxDate: `${year + 1}-12-31`,
// 时间相关
selectedStartTime: `${startHours.toString().padStart(2, '0')}:${startMinutes.toString().padStart(2, '0')}`,
selectedEndTime: `${endHours.toString().padStart(2, '0')}:${endMinutes.toString().padStart(2, '0')}`,
startTimeValue: `${startHours.toString().padStart(2, '0')}:${startMinutes.toString().padStart(2, '0')}`,
endTimeValue: `${endHours.toString().padStart(2, '0')}:${endMinutes.toString().padStart(2, '0')}`,
// 新增备注字段
remark: '',
noticeList: [
'每次预订时间单位为小时最少0.5小时起预订。',
'使用优惠券支付,取消预订后优惠券会自动退还。',
'使用微信、支付宝支付,取消订单后需要转社区运营人员进行退款。',
'系统不支持自动退款。',
'场地搭建则需在活动开始48小时前支付相应保证金具体费用可与运营人员进行确认。'
],
Id: '',
};
},
onLoad(options) {
if (options && options.Id) {
this.Id = options.Id;
console.log(applyType.getAll())
console.log("====", this.Id)
}
},
computed: {
formattedSelectedDate() {
if (!this.selectedDate) return '请选择日期';
const date = new Date(this.selectedDate);
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const month = date.getMonth() + 1;
const day = date.getDate();
const weekday = weekdays[date.getDay()];
return `${month}${day}${weekday}`;
}
},
mounted() {
this.getDetail();
},
methods: {
// 获取详情页面
async getDetail() {
try {
const res = await get(`/api/v1/apps/home/metting-room/${this.Id}`);
if (!res || !res.success) {
throw new Error('获取详情失败');
}
console.log("======res", res)
// 如果有返回的图片数据,可以这样处理
if (res.data.imgs && res.data.imgs.length > 0) {
this.list1 = res.data.imgs.map(img => {
return img.startsWith('http') ? img : IMAGE_BASE_URL + img;
});
}
this.detail = {
...res.data
};
} catch (err) {
console.error('获取详情失败:', err);
}
},
handleDateConfirm(e) {
let selectedDate;
// 处理不同格式的返回值
if (Array.isArray(e)) {
selectedDate = e[0];
} else if (e.result && Array.isArray(e.result)) {
selectedDate = e.result[0];
} else if (typeof e === 'string') {
selectedDate = e;
} else {
selectedDate = e.date;
}
this.selectedDate = selectedDate;
this.showCalendar = false;
// 强制更新视图
this.$nextTick(() => {
this.calendarKey += 1;
});
},
handleStartTimeConfirm(e) {
this.selectedStartTime = e.value;
this.startTimePickerValue = e.value;
this.showStartTimePicker = false;
this.adjustEndTime();
},
handleEndTimeConfirm(e) {
this.selectedEndTime = e.value;
this.endTimePickerValue = e.value;
this.showEndTimePicker = false;
this.validateTime();
},
adjustEndTime() {
const [startH, startM] = this.selectedStartTime.split(':').map(Number);
let [endH, endM] = this.selectedEndTime.split(':').map(Number);
const startTotal = startH * 60 + startM;
let endTotal = endH * 60 + endM;
if (endTotal <= startTotal) {
endTotal = startTotal + 60;
endH = Math.floor(endTotal / 60);
endM = endTotal % 60;
this.selectedEndTime = `${endH.toString().padStart(2, '0')}:${endM.toString().padStart(2, '0')}`;
this.endTimeValue = `${endH}:${endM}`;
this.endTimePickerValue = this.selectedEndTime;
}
},
validateTime() {
const [startH, startM] = this.selectedStartTime.split(':').map(Number);
const [endH, endM] = this.selectedEndTime.split(':').map(Number);
const duration = (endH * 60 + endM) - (startH * 60 + startM);
if (duration < 30) {
uni.showToast({
title: '最少预订30分钟',
icon: 'none'
});
this.adjustEndTime();
}
},
handleBook() {
this.validateTime();
// 构建预订信息对象
const bookingInfo = {
startAt: new Date(`${this.selectedDate} ${this.selectedStartTime}`),
endAt: new Date(`${this.selectedDate} ${this.selectedEndTime}`),
remark: this.remark,
roomId: this.Id
};
console.log('提交的预订信息:', bookingInfo);
uni.showToast({
title: `已预订 ${this.formattedSelectedDate} ${this.selectedStartTime}-${this.selectedEndTime}`,
icon: 'none'
});
// 这里可以添加实际的API调用
post('/api/v1/app_auth/metting-room/order/register', bookingInfo).then((res) => {
console.log("===res", res)
if (!res || !res.success) {
throw new Error('会议室预定失败');
}
uni.showToast({
title: '会议室预定成功!',
icon: 'success'
});
this.remark = null;
setTimeout(() => {
uni.navigateTo({
url: `/pages/meetingList/index`,
success: () => {
console.log('导航成功ID:', id);
},
fail: (err) => {
console.error('导航失败:', err);
uni.showToast({
title: '打开详情页失败',
icon: 'none'
});
}
});
}, 4000)
})
// this.submitBooking(bookingInfo);
},
}
};
</script>
<style lang="scss" scoped>
.meeting-room-detail {
padding: 20rpx;
padding-bottom: 140rpx;
/* 增大底部空间 */
background-color: #f5f7fa;
}
/* 轮播图优化 */
.room-swiper {
width: 100%;
height: 420rpx;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
/* 卡片通用样式 */
.info-card,
.booking-card,
.notice-card {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
}
/* 会议室信息卡片 */
.room-info {
.room-name {
font-size: 36rpx;
font-weight: 600;
color: #333;
margin-bottom: 16rpx;
display: block;
}
.meta-info {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 16rpx;
text {
font-size: 26rpx;
color: #666;
display: flex;
align-items: center;
}
}
.room-desc {
font-size: 28rpx;
color: #666;
line-height: 1.6;
}
}
/* 卡片标题 */
.card-header {
display: flex;
align-items: center;
margin-bottom: 24rpx;
padding-bottom: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
.card-title {
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-left: 10rpx;
}
}
/* 日期选择区域 */
.date-section {
margin-bottom: 32rpx;
.section-header {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.section-title {
font-size: 28rpx;
color: #333;
margin-left: 8rpx;
}
.date-display {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 24rpx;
background: #f8f9fa;
border-radius: 12rpx;
font-size: 28rpx;
color: #333;
}
}
/* 时间选择区域 */
.time-section {
margin-bottom: 32rpx;
.time-picker {
display: flex;
align-items: center;
gap: 16rpx;
}
.time-selector {
flex: 1;
.time-label {
font-size: 26rpx;
color: #666;
margin-bottom: 8rpx;
display: block;
}
.time-display {
padding: 20rpx;
background: #f8f9fa;
border-radius: 12rpx;
text-align: center;
font-size: 28rpx;
color: #333;
}
}
.time-separator {
color: #999;
font-size: 28rpx;
padding-top: 28rpx;
}
}
/* 新增备注区域 */
.remark-section {
margin-top: 24rpx;
.section-header {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.section-title {
font-size: 28rpx;
color: #333;
margin-left: 8rpx;
}
}
/* 预订须知 */
.notice-card {
.notice-list {
.notice-item {
display: flex;
margin-bottom: 16rpx;
line-height: 1.6;
.notice-index {
color: #2979ff;
font-weight: bold;
margin-right: 8rpx;
}
.notice-content {
font-size: 26rpx;
color: #666;
flex: 1;
}
}
}
}
/* 底部操作栏 */
.action-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx;
background: #fff;
box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.08);
.u-button {
height: 88rpx;
/* 增大高度 */
font-size: 32rpx;
font-weight: 500;
}
}
/* 动画效果 */
.time-display,
.date-display {
transition: all 0.2s;
&:active {
background: #eef2f7;
transform: scale(0.98);
}
}
</style>