9 changed files with 976 additions and 75 deletions
-
162pages.json
-
8pages/home/home.vue
-
10pages/user/user.vue
-
5static/iconfont.css
-
BINstatic/iconfont.ttf
-
BINstatic/images/lib.png
-
336subpkg/pages/booking-detail/booking-detail.vue
-
289subpkg/pages/booking-record/booking-record.vue
-
241subpkg/pages/seat-booking/seat-booking.vue
|
After Width: 150 | Height: 150 | Size: 46 KiB |
@ -0,0 +1,336 @@ |
|||||
|
<template> |
||||
|
<view class="booking-detail"> |
||||
|
<view class="section"> |
||||
|
<view class="section-title">日期选择</view> |
||||
|
<view class="calendar"> |
||||
|
<view class="calendar-header"> |
||||
|
<text class="month">{{ currentYear }}年{{ currentMonth }}月</text> |
||||
|
</view> |
||||
|
<view class="calendar-weekdays"> |
||||
|
<text v-for="day in weekdays" :key="day" class="weekday">{{ day }}</text> |
||||
|
</view> |
||||
|
<view class="calendar-days"> |
||||
|
<view |
||||
|
v-for="(day, index) in calendarDays" |
||||
|
:key="index" |
||||
|
class="day-item" |
||||
|
:class="{ |
||||
|
'other-month': !day.currentMonth, |
||||
|
'selected': day.date === selectedDate, |
||||
|
'disabled': !day.available, |
||||
|
'today': day.isToday |
||||
|
}" |
||||
|
@click="selectDate(day)" |
||||
|
> |
||||
|
<text class="day-num">{{ day.day }}</text> |
||||
|
<text v-if="day.available && !day.isToday" class="available-tag">开放日</text> |
||||
|
<text v-if="day.isToday" class="today-tag">今天</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="section"> |
||||
|
<view class="section-title">时间选择</view> |
||||
|
<view class="time-slots"> |
||||
|
<view |
||||
|
v-for="slot in timeSlots" |
||||
|
:key="slot.id" |
||||
|
class="time-slot" |
||||
|
:class="{ 'selected': selectedTime === slot.time }" |
||||
|
@click="selectTime(slot)" |
||||
|
> |
||||
|
<text class="time-text">{{ slot.time }}</text> |
||||
|
<text v-if="slot.available" class="available-badge">可选</text> |
||||
|
<text v-else class="unavailable-badge">已满</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="bottom-bar"> |
||||
|
<button class="btn-primary" @click="confirmBooking">确认预约</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
currentYear: new Date().getFullYear(), |
||||
|
currentMonth: new Date().getMonth() + 1, |
||||
|
selectedDate: '', |
||||
|
selectedTime: '', |
||||
|
weekdays: ['日', '一', '二', '三', '四', '五', '六'], |
||||
|
calendarDays: [], |
||||
|
timeSlots: [ |
||||
|
{ id: 1, time: '09:15-12:45', available: true }, |
||||
|
{ id: 2, time: '13:00-16:30', available: false }, |
||||
|
{ id: 3, time: '16:45-20:15', available: true } |
||||
|
] |
||||
|
}; |
||||
|
}, |
||||
|
onLoad(options) { |
||||
|
this.generateCalendar(); |
||||
|
}, |
||||
|
methods: { |
||||
|
generateCalendar() { |
||||
|
const year = this.currentYear; |
||||
|
const month = this.currentMonth; |
||||
|
const firstDay = new Date(year, month - 1, 1); |
||||
|
const lastDay = new Date(year, month, 0); |
||||
|
const daysInMonth = lastDay.getDate(); |
||||
|
const startWeekday = firstDay.getDay(); |
||||
|
const today = new Date(); |
||||
|
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`; |
||||
|
|
||||
|
const days = []; |
||||
|
const prevMonthLastDay = new Date(year, month - 1, 0).getDate(); |
||||
|
for (let i = startWeekday - 1; i >= 0; i--) { |
||||
|
days.push({ |
||||
|
day: prevMonthLastDay - i, |
||||
|
date: '', |
||||
|
currentMonth: false, |
||||
|
available: false, |
||||
|
isToday: false |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const todayDate = new Date(); |
||||
|
const availableDates = []; |
||||
|
for (let i = 0; i < 7; i++) { |
||||
|
const date = new Date(todayDate); |
||||
|
date.setDate(todayDate.getDate() + i); |
||||
|
const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; |
||||
|
availableDates.push(dateStr); |
||||
|
} |
||||
|
|
||||
|
for (let i = 1; i <= daysInMonth; i++) { |
||||
|
const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(i).padStart(2, '0')}`; |
||||
|
const isAvailable = availableDates.includes(dateStr); |
||||
|
const isToday = dateStr === todayStr; |
||||
|
|
||||
|
days.push({ |
||||
|
day: i, |
||||
|
date: dateStr, |
||||
|
currentMonth: true, |
||||
|
available: isAvailable, |
||||
|
isToday: isToday |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const remainingDays = 42 - days.length; |
||||
|
for (let i = 1; i <= remainingDays; i++) { |
||||
|
days.push({ |
||||
|
day: i, |
||||
|
date: '', |
||||
|
currentMonth: false, |
||||
|
available: false, |
||||
|
isToday: false |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
this.calendarDays = days; |
||||
|
if (availableDates.length > 0) { |
||||
|
this.selectedDate = availableDates[0]; |
||||
|
} |
||||
|
}, |
||||
|
selectDate(day) { |
||||
|
if (!day.available || !day.currentMonth) return; |
||||
|
this.selectedDate = day.date; |
||||
|
}, |
||||
|
selectTime(slot) { |
||||
|
if (!slot.available) return; |
||||
|
this.selectedTime = slot.time; |
||||
|
}, |
||||
|
confirmBooking() { |
||||
|
if (!this.selectedDate) { |
||||
|
uni.showToast({ title: '请选择日期', icon: 'none' }); |
||||
|
return; |
||||
|
} |
||||
|
if (!this.selectedTime) { |
||||
|
uni.showToast({ title: '请选择时间段', icon: 'none' }); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
uni.showLoading({ title: '预约中...' }); |
||||
|
setTimeout(() => { |
||||
|
uni.hideLoading(); |
||||
|
uni.showModal({ |
||||
|
title: '预约成功', |
||||
|
content: `您已成功预约\n日期:${this.selectedDate}\n时间:${this.selectedTime}`, |
||||
|
showCancel: false, |
||||
|
confirmText: '确定', |
||||
|
success: () => { |
||||
|
uni.navigateBack({ delta: 2 }); |
||||
|
} |
||||
|
}); |
||||
|
}, 1500); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.booking-detail { |
||||
|
min-height: 100vh; |
||||
|
background-color: #f5f5f5; |
||||
|
padding-bottom: 70px; |
||||
|
} |
||||
|
|
||||
|
.section { |
||||
|
background-color: #fff; |
||||
|
margin: 10px; |
||||
|
border-radius: 12px; |
||||
|
padding: 16px; |
||||
|
} |
||||
|
|
||||
|
.section-title { |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
color: #333; |
||||
|
margin-bottom: 16px; |
||||
|
} |
||||
|
|
||||
|
/* 日历 */ |
||||
|
.calendar-header { |
||||
|
text-align: center; |
||||
|
margin-bottom: 12px; |
||||
|
} |
||||
|
.month { |
||||
|
font-size: 16px; |
||||
|
color: #333; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.calendar-weekdays { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
.weekday { |
||||
|
width: 14.28%; |
||||
|
text-align: center; |
||||
|
font-size: 13px; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.calendar-days { |
||||
|
display: flex; |
||||
|
flex-wrap: wrap; |
||||
|
} |
||||
|
.day-item { |
||||
|
width: 14.28%; |
||||
|
aspect-ratio: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin-bottom: 6px; |
||||
|
border-radius: 6px; |
||||
|
position: relative; |
||||
|
} |
||||
|
.day-item.other-month .day-num { |
||||
|
color: #ccc; |
||||
|
} |
||||
|
.day-item.disabled .day-num { |
||||
|
color: #ccc; |
||||
|
} |
||||
|
.day-item.selected { |
||||
|
background-color: #01a4fe; |
||||
|
} |
||||
|
.day-item.selected .day-num { |
||||
|
color: #fff; |
||||
|
font-size: 15px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.day-item.selected .available-tag, |
||||
|
.day-item.selected .today-tag { |
||||
|
color: rgba(255, 255, 255, 0.9); |
||||
|
font-size: 10px; |
||||
|
} |
||||
|
.day-item.today:not(.selected) { |
||||
|
background-color: #fff3cd; |
||||
|
} |
||||
|
.day-item.today:not(.selected) .day-num { |
||||
|
color: #856404; |
||||
|
} |
||||
|
|
||||
|
.day-num { |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
} |
||||
|
.available-tag { |
||||
|
font-size: 10px; |
||||
|
color: #01a4fe; |
||||
|
margin-top: 2px; |
||||
|
} |
||||
|
.today-tag { |
||||
|
font-size: 10px; |
||||
|
color: #856404; |
||||
|
margin-top: 2px; |
||||
|
} |
||||
|
|
||||
|
/* 时间选择 */ |
||||
|
.time-slots { |
||||
|
display: flex; |
||||
|
flex-wrap: wrap; |
||||
|
gap: 10px; |
||||
|
} |
||||
|
.time-slot { |
||||
|
width: calc(50% - 5px); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
padding: 12px; |
||||
|
background-color: #f8f8f8; |
||||
|
border-radius: 8px; |
||||
|
border: 1px solid transparent; |
||||
|
} |
||||
|
.time-slot.selected { |
||||
|
background-color: #e8f4fd; |
||||
|
border-color: #01a4fe; |
||||
|
} |
||||
|
.time-text { |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
} |
||||
|
.available-badge { |
||||
|
font-size: 12px; |
||||
|
color: #01a4fe; |
||||
|
background-color: #e8f4fd; |
||||
|
padding: 2px 8px; |
||||
|
border-radius: 10px; |
||||
|
} |
||||
|
.unavailable-badge { |
||||
|
font-size: 12px; |
||||
|
color: #999; |
||||
|
background-color: #f0f0f0; |
||||
|
padding: 2px 8px; |
||||
|
border-radius: 10px; |
||||
|
} |
||||
|
|
||||
|
/* 底部按钮 */ |
||||
|
.bottom-bar { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
padding: 10px; |
||||
|
background-color: #fff; |
||||
|
box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
.btn-primary { |
||||
|
width: 100%; |
||||
|
height: 44px; |
||||
|
line-height: 44px; |
||||
|
background-color: #01a4fe; |
||||
|
color: #fff; |
||||
|
border-radius: 22px; |
||||
|
font-size: 15px; |
||||
|
border: none; |
||||
|
} |
||||
|
.btn-primary::after { |
||||
|
border: none; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,289 @@ |
|||||
|
<template> |
||||
|
<view class="activity-list"> |
||||
|
<view class="tab-box"> |
||||
|
<view |
||||
|
class="tab-item" |
||||
|
:class="{ active: currentTab === 0 }" |
||||
|
@click="switchTab(0)" |
||||
|
> |
||||
|
未开始 |
||||
|
</view> |
||||
|
<view |
||||
|
class="tab-item" |
||||
|
:class="{ active: currentTab === 1 }" |
||||
|
@click="switchTab(1)" |
||||
|
> |
||||
|
进行中 |
||||
|
</view> |
||||
|
<view |
||||
|
class="tab-item" |
||||
|
:class="{ active: currentTab === 2 }" |
||||
|
@click="switchTab(2)" |
||||
|
> |
||||
|
已结束 |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<scroll-view |
||||
|
scroll-y |
||||
|
refresher-enabled |
||||
|
:refresher-triggered="refreshing" |
||||
|
@refresherrefresh="onRefresh" |
||||
|
lower-threshold="100" |
||||
|
class="scroll-view" |
||||
|
> |
||||
|
<view |
||||
|
class="activity-item" |
||||
|
v-for="item in displayList" |
||||
|
:key="item.id" |
||||
|
@click="toActivityDetail(item)" |
||||
|
> |
||||
|
<view class="activity-info"> |
||||
|
<text class="title">{{ item.area }}</text> |
||||
|
<view class="item-info"> |
||||
|
<text class="label">开始时间:</text> |
||||
|
<text class="value">{{ item.startTime }}</text> |
||||
|
</view> |
||||
|
<view class="item-info"> |
||||
|
<text class="label">结束时间:</text> |
||||
|
<text class="value">{{ item.endTime }}</text> |
||||
|
</view> |
||||
|
<view class="item-info"> |
||||
|
<text class="label">座位号:</text> |
||||
|
<text class="value">{{ item.seatNumber }}</text> |
||||
|
</view> |
||||
|
<view class="item-info"> |
||||
|
<text class="label">状态:</text> |
||||
|
<text class="value status-tag" :class="item.statusClass">{{ item.statusText }}</text> |
||||
|
</view> |
||||
|
<view class="btn-box" v-if="item.status === 0"> |
||||
|
<button class="activity-btn" type="primary" @click.stop="cancelAppoint(item)"> |
||||
|
取消预约 |
||||
|
</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="empty-box" v-if="displayList.length === 0"> |
||||
|
<uni-icons type="empty" size="80" color="#ccc"></uni-icons> |
||||
|
<text class="empty-text">{{ getEmptyText() }}</text> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
currentTab: 0, |
||||
|
activityList: [], |
||||
|
refreshing: false |
||||
|
}; |
||||
|
}, |
||||
|
computed: { |
||||
|
displayList() { |
||||
|
const statusMap = { |
||||
|
0: [0, '0', '未开始', 'pending'], |
||||
|
1: [1, '1', '进行中', 'ongoing'], |
||||
|
2: [2, '2', '已结束', 'ended'] |
||||
|
}; |
||||
|
const targetStatuses = statusMap[this.currentTab] || []; |
||||
|
return this.activityList.filter(item => { |
||||
|
const itemStatus = String(item.status); |
||||
|
return targetStatuses.some(status => String(status) === itemStatus); |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
onLoad() { |
||||
|
this.getActivityList(); |
||||
|
}, |
||||
|
methods: { |
||||
|
switchTab(index) { |
||||
|
this.currentTab = index; |
||||
|
}, |
||||
|
|
||||
|
getActivityList() { |
||||
|
this.refreshing = true; |
||||
|
setTimeout(() => { |
||||
|
const rawData = [ |
||||
|
{id:1,area:'一楼自习区',startTime:'2026-05-21 08:00:00',endTime:'2026-05-21 11:30:00',seatNumber:'8号',status:0,statusText:'已预约'}, |
||||
|
{id:2,area:'综合阅览一',startTime:'2026-05-21 08:00:00',endTime:'2026-05-21 11:30:00',seatNumber:'8号',status:1,statusText:'进行中'}, |
||||
|
{id:4,area:'专题阅览室',startTime:'2026-05-21 08:00:00',endTime:'2026-05-21 11:30:00',seatNumber:'8号',status:0,statusText:'已预约'}, |
||||
|
]; |
||||
|
this.activityList = rawData.map(item => ({ |
||||
|
...item, |
||||
|
statusClass: `status-${item.status}` |
||||
|
})); |
||||
|
this.refreshing = false; |
||||
|
}, 500); |
||||
|
}, |
||||
|
|
||||
|
onRefresh() { |
||||
|
this.getActivityList(); |
||||
|
}, |
||||
|
|
||||
|
cancelAppoint(item) { |
||||
|
uni.showModal({ |
||||
|
title: '提示', |
||||
|
content: `确定要取消${item.area}的预约吗?`, |
||||
|
success: (res) => { |
||||
|
if (res.confirm) { |
||||
|
uni.showToast({ title: '取消成功', icon: 'success' }); |
||||
|
this.getActivityList(); |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
toActivityDetail(item) { |
||||
|
uni.navigateTo({ |
||||
|
url: "/subpkg/pages/activity-detail/activity-detail?item=" + encodeURIComponent(JSON.stringify(item)) |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
getEmptyText() { |
||||
|
const textMap = { |
||||
|
0: '未开始', |
||||
|
1: '进行中', |
||||
|
2: '已结束' |
||||
|
} |
||||
|
return `暂无${textMap[this.currentTab]}的预约~` |
||||
|
} |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.activity-list { |
||||
|
padding: 0; |
||||
|
height: 100vh; |
||||
|
box-sizing: border-box; |
||||
|
background-color: #f5f5f5; |
||||
|
} |
||||
|
|
||||
|
.tab-box { |
||||
|
display: flex; |
||||
|
background-color: #fff; |
||||
|
margin-bottom: 10px; |
||||
|
position: sticky; |
||||
|
top: 0; |
||||
|
z-index: 99; |
||||
|
} |
||||
|
.tab-item { |
||||
|
flex: 1; |
||||
|
text-align: center; |
||||
|
padding: 12px 0; |
||||
|
font-size: 15px; |
||||
|
color: #666; |
||||
|
position: relative; |
||||
|
} |
||||
|
.tab-item.active { |
||||
|
color: #01a4fe; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.tab-item.active::after { |
||||
|
content: ''; |
||||
|
position: absolute; |
||||
|
width: 30px; |
||||
|
height: 3px; |
||||
|
background-color: #01a4fe; |
||||
|
bottom: 0; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
border-radius: 2px; |
||||
|
} |
||||
|
|
||||
|
.scroll-view { |
||||
|
height: calc(100vh - 60px); |
||||
|
padding: 0 12px; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.empty-box { |
||||
|
height: calc(100vh - 200px); |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
.empty-text { |
||||
|
margin-top: 16px; |
||||
|
font-size: 14px; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.activity-item { |
||||
|
background: #fff; |
||||
|
border-radius: 12px; |
||||
|
margin-bottom: 12px; |
||||
|
overflow: hidden; |
||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06); |
||||
|
cursor: pointer; |
||||
|
transition: transform 0.2s; |
||||
|
|
||||
|
&:active { |
||||
|
transform: scale(0.98); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.activity-info { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: flex-start; |
||||
|
padding: 16px; |
||||
|
.title { |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
color: #222; |
||||
|
margin-bottom: 12px; |
||||
|
display: block; |
||||
|
} |
||||
|
.item-info { |
||||
|
display: flex; |
||||
|
padding: 4px 0; |
||||
|
font-size: 14px; |
||||
|
.label { |
||||
|
color: #666; |
||||
|
width: 72px; |
||||
|
} |
||||
|
.value { |
||||
|
color: #333; |
||||
|
flex: 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 正确的状态样式 */ |
||||
|
.status-tag { |
||||
|
padding: 2px 8px; |
||||
|
border-radius: 4px; |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
.status-tag.status-0 { |
||||
|
color: #01a4fe; |
||||
|
background: #e6f7ff; |
||||
|
} |
||||
|
.status-tag.status-1 { |
||||
|
color: #00b42a; |
||||
|
background: #e6ffed; |
||||
|
} |
||||
|
.status-tag.status-2 { |
||||
|
color: #999; |
||||
|
background: #f5f5f5; |
||||
|
} |
||||
|
|
||||
|
.btn-box { |
||||
|
width: 100%; |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
margin-top: 10px; |
||||
|
} |
||||
|
.activity-btn { |
||||
|
background-color: #01a4fe; |
||||
|
font-size: 13px; |
||||
|
border-radius: 6px; |
||||
|
padding: 0 14px; |
||||
|
height: 28px; |
||||
|
line-height: 28px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,241 @@ |
|||||
|
<template> |
||||
|
<view class="seat-booking"> |
||||
|
<!-- 顶部横幅 --> |
||||
|
<view class="banner"> |
||||
|
<image class="banner-bg" src="@/static/images/mingqi-beij@2x.png" mode="aspectFill"></image> |
||||
|
<view class="banner-overlay"> |
||||
|
<text class="banner-text">葛店经济开发区图书馆预约</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="content"> |
||||
|
<!-- 场馆选择下拉框 --> |
||||
|
<!-- <view class="venue-select"> |
||||
|
<picker :value="venueIndex" :range="venues" @change="onVenueChange"> |
||||
|
<view class="picker-content"> |
||||
|
<text>{{ venues[venueIndex] }}</text> |
||||
|
<uni-icons type="down" size="16" color="#666" /> |
||||
|
</view> |
||||
|
</picker> |
||||
|
</view> --> |
||||
|
|
||||
|
<!-- 楼层/区域卡片列表 --> |
||||
|
<view class="floor-list"> |
||||
|
<view class="floor-item" v-for="floor in floorList" :key="floor.id"> |
||||
|
<text class="floor-name">{{ floor.floor }}</text> |
||||
|
<div class="floor-info"> |
||||
|
<view class="floor-left"> |
||||
|
<text class="floor-title">{{ floor.title }}</text> |
||||
|
<image class="banner-bg" src="@/static/images/lib.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
<view class="floor-right"> |
||||
|
<text class="floor-desc">{{ floor.desc }}</text> |
||||
|
<view style="display: flex; justify-content: flex-end; width: 100%; text-align: end;"> |
||||
|
<button class="booking-btn" @click="bookingFloor(floor)">预约</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</div> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
venueIndex: 0, |
||||
|
venues: ['所有场馆', '东馆', '西馆', '南馆'], |
||||
|
floorList: [ |
||||
|
{ |
||||
|
id: 1, |
||||
|
floor: '3楼', |
||||
|
title: '综合阅览一', |
||||
|
desc: '葛店图书馆三楼阅读广场共有464个座位,为读者提供备电源,读者可预约选择心仪的座位。区域采光良好,环境优美,读者可在休息时一览楼下的风景。', |
||||
|
image: '@/static/images/lib.png' |
||||
|
}, |
||||
|
{ |
||||
|
id: 2, |
||||
|
floor: '3楼', |
||||
|
title: '少儿阅览室', |
||||
|
desc: '少儿阅览室共有464个座位,为读者提供备电源、读者可自助选择位置,各个区采光良好,环境优美,读者可在休息时一览楼下的风景。', |
||||
|
image: '@/static/images/lib.png' |
||||
|
}, |
||||
|
{ |
||||
|
id: 3, |
||||
|
floor: '3楼', |
||||
|
title: '专题阅览室', |
||||
|
desc: '专题阅览室共有464个座位,为读者提供备电源、读者可自助选择位置,各个区采光良好,环境优美,读者可在休息时一览楼下的风景。', |
||||
|
image: '@/static/images/lib.png' |
||||
|
} |
||||
|
] |
||||
|
}; |
||||
|
}, |
||||
|
onLoad() { |
||||
|
this.loadSeatInfo(); |
||||
|
}, |
||||
|
methods: { |
||||
|
loadSeatInfo() { |
||||
|
console.log('加载座位信息'); |
||||
|
}, |
||||
|
onVenueChange(e) { |
||||
|
this.venueIndex = e.detail.value; |
||||
|
console.log('切换场馆:', this.venues[this.venueIndex]); |
||||
|
}, |
||||
|
bookingFloor(floor) { |
||||
|
uni.navigateTo({ |
||||
|
url: `/subpkg/pages/booking-detail/booking-detail?floor=${floor.floor}&title=${floor.title}` |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.seat-booking { |
||||
|
min-height: 100vh; |
||||
|
background-color: #f5f7fa; |
||||
|
} |
||||
|
|
||||
|
/* 顶部横幅 */ |
||||
|
.banner { |
||||
|
position: relative; |
||||
|
height: 140px; |
||||
|
} |
||||
|
.banner-bg { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
.banner-overlay { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, 0.2); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
.banner-text { |
||||
|
color: #fff; |
||||
|
font-size: 20px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
padding: 16px; |
||||
|
// margin-top: -20px; |
||||
|
position: relative; |
||||
|
z-index: 10; |
||||
|
} |
||||
|
|
||||
|
/* 场馆选择下拉框 */ |
||||
|
.venue-select { |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
margin-bottom: 16px; |
||||
|
} |
||||
|
.picker-content { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 4px; |
||||
|
padding: 8px 16px; |
||||
|
background-color: #fff; |
||||
|
border: 1px solid #ddd; |
||||
|
border-radius: 4px; |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
/* 楼层卡片 */ |
||||
|
.floor-list { |
||||
|
background-color: #fff; |
||||
|
border-radius: 12px; |
||||
|
padding: 16px; |
||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.05); |
||||
|
} |
||||
|
.floor-item { |
||||
|
margin-bottom: 16px; |
||||
|
padding-bottom: 16px; |
||||
|
border-bottom: 1px solid #eee; |
||||
|
&:last-child { |
||||
|
margin-bottom: 0; |
||||
|
padding-bottom: 0; |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.floor-name { |
||||
|
display: block; |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
padding-bottom: 8px; |
||||
|
} |
||||
|
.floor-info{ |
||||
|
display: inline-flex; |
||||
|
align-items: flex-start; |
||||
|
justify-content: space-between; |
||||
|
} |
||||
|
|
||||
|
.floor-left { |
||||
|
position: relative; |
||||
|
width: 90px; |
||||
|
height: 100px; |
||||
|
border-radius: 8px; |
||||
|
margin-right: 12px; |
||||
|
} |
||||
|
|
||||
|
.floor-image { |
||||
|
width: 90px; |
||||
|
height: 100px; |
||||
|
|
||||
|
object-fit: cover; |
||||
|
} |
||||
|
.floor-title { |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
text-align: center; |
||||
|
padding: 4px 0; |
||||
|
background-color: rgba(0, 0, 0, 0.5); |
||||
|
color: #fff; |
||||
|
// font-weight: bold; |
||||
|
font-size: 12px; |
||||
|
// font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.floor-right { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: space-between; |
||||
|
} |
||||
|
|
||||
|
.floor-desc { |
||||
|
font-size: 13px; |
||||
|
color: #666; |
||||
|
line-height: 1.5; |
||||
|
margin-bottom: 8px; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
display: -webkit-box; |
||||
|
-webkit-box-orient: vertical; |
||||
|
-webkit-line-clamp: 3; |
||||
|
} |
||||
|
.booking-btn { |
||||
|
background-color: #01a4fe; |
||||
|
color: #fff; |
||||
|
font-size: 14px; |
||||
|
padding: 0 20px; |
||||
|
border: none; |
||||
|
margin: 6px 0 0 0; |
||||
|
height: 30px; |
||||
|
line-height: 30px; |
||||
|
} |
||||
|
.booking-btn::after { |
||||
|
border: none; |
||||
|
} |
||||
|
</style> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue