综合服务-会议模块页面
This commit is contained in:
1 parent
db303eb0a9
commit
7a12dba8b4
7 files changed
+239
-116
No files matched your search
@@ -478,6 +478,12 @@
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的预约"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "meeting/booking-detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "预约详情"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<view class="booking-detail">
|
||||
<view class="room-info">
|
||||
<view class="room-name">{{ detail.roomName }}</view>
|
||||
<view class="room-meta">
|
||||
<text>容量:{{ detail.capacity }}</text>
|
||||
<text>位置:{{ detail.location }}</text>
|
||||
</view>
|
||||
<view v-if="detail.equipmentNames" class="room-equip">
|
||||
设备:{{ detail.equipmentNames }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="section">
|
||||
<view class="section-title">预约信息</view>
|
||||
<view class="info-row"><text class="label">预约人:</text>{{ detail.username }}</view>
|
||||
<view class="info-row"><text class="label">预约时间:</text>{{ detail.startTime }} ~ {{ detail.endTime }}</view>
|
||||
<view class="info-row"><text class="label">预约状态:</text>{{ getStatusText(detail.checkStatus) }}</view>
|
||||
<view class="info-row" v-if="detail.checkReason"><text class="label">审核意见:</text>{{ detail.checkReason }}</view>
|
||||
<view class="info-row" v-if="detail.description"><text class="label">备注:</text>{{ detail.description }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import meetingRoomApi from '@/sheep/api/meetingRoom'
|
||||
|
||||
const detail = ref<any>({})
|
||||
|
||||
function getStatusText(status: string) {
|
||||
const map: Record<string, string> = {
|
||||
'1': '审核中',
|
||||
'2': '审核通过',
|
||||
'3': '审核拒绝',
|
||||
'4': '已取消',
|
||||
'5': '已结束',
|
||||
}
|
||||
return map[status] || status
|
||||
}
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
const id = options.id
|
||||
if (!id) return
|
||||
const { code, data } = await meetingRoomApi.getBookingDetail(id)
|
||||
if (code === 0 && data) {
|
||||
detail.value = data
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.booking-detail {
|
||||
padding: 32rpx;
|
||||
.room-info {
|
||||
background: #f7f8fa;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 32rpx;
|
||||
.room-name {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.room-meta {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 8rpx;
|
||||
text {
|
||||
margin-right: 32rpx;
|
||||
}
|
||||
}
|
||||
.room-equip {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.section {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
.info-row {
|
||||
font-size: 26rpx;
|
||||
margin-bottom: 14rpx;
|
||||
.label {
|
||||
color: #888;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -221,7 +221,7 @@ async function reserveMeeting() {
|
||||
date,
|
||||
startTime: startSlot.startTime,
|
||||
endTime: endSlot.endTime,
|
||||
title: '会议',
|
||||
title: room.value.name || '会议',
|
||||
description: '',
|
||||
attendees: []
|
||||
})
|
||||
|
||||
@@ -230,4 +230,4 @@ function goDetail(room) {
|
||||
color: #bbb;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -11,69 +11,108 @@
|
||||
v-for="(tab, idx) in tabs"
|
||||
:key="tab"
|
||||
:class="['tab', idx === activeTab ? 'active' : '']"
|
||||
@tap="activeTab = idx"
|
||||
@tap="onTabChange(idx)"
|
||||
>{{ tab }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 优惠礼包(可选) -->
|
||||
<view class="coupon-box">
|
||||
<text class="coupon-title">优惠礼包</text>
|
||||
<text class="coupon-desc">还未购买过优惠礼包</text>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
|
||||
<!-- 预约卡片列表 -->
|
||||
<view v-for="item in reservationList" :key="item.id" class="card">
|
||||
<view class="card-header">
|
||||
<image src="/static/icons/meeting.png" class="card-icon" />
|
||||
<text class="card-title">{{ item.roomName }} → {{ item.location }}</text>
|
||||
<text class="card-status" :class="item.statusClass">{{ item.statusText }}</text>
|
||||
</view>
|
||||
<view class="card-info">
|
||||
<view>预约时间:{{ item.time }}</view>
|
||||
<view>会议主题:{{ item.subject }}</view>
|
||||
<view>参会人:{{ item.attendees }}</view>
|
||||
</view>
|
||||
<view class="card-footer">
|
||||
<view class="card-btn" v-for="btn in item.actions" :key="btn">{{ btn }}</view>
|
||||
<view v-if="reservationList.length">
|
||||
<view v-for="item in reservationList" :key="item.id" class="card">
|
||||
<view class="card-header">
|
||||
<image src="/static/icons/meeting.png" class="card-icon" />
|
||||
<text class="card-title">{{ item.title }}</text>
|
||||
<text class="card-status" :class="statusMap[item.checkStatus]?.class">{{ statusMap[item.checkStatus]?.text }}</text>
|
||||
</view>
|
||||
<view class="card-info">
|
||||
<view>预约日期:{{ item.bookingDate }}</view>
|
||||
<view>时间:{{ item.startTime }} ~ {{ item.endTime }}</view>
|
||||
<view>申请人:{{ item.createBy }}</view>
|
||||
</view>
|
||||
<view class="card-footer">
|
||||
<view class="card-btn" @tap="viewDetail(item)">查看详情</view>
|
||||
<view
|
||||
v-if="item.checkStatus === 1 || item.checkStatus === 2"
|
||||
class="card-btn cancel"
|
||||
@tap="cancelBooking(item)"
|
||||
>取消预约</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="empty">
|
||||
<image src="/static/icons/empty.png" class="empty-img" />
|
||||
<view class="empty-text">暂无预约</view>
|
||||
<view class="empty-tip">您还没有预约会议,快去预约吧!</view>
|
||||
</view>
|
||||
<MeetingTabbar activeTab="mine" />
|
||||
</view>
|
||||
<MeetingTabbar activeTab="mine" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import meetingRoomApi from '@/sheep/api/meetingRoom'
|
||||
import MeetingTabbar from '@/components/MeetingTabbar.vue'
|
||||
|
||||
const tabs = ['全部', '未开始', '已结束', '已取消']
|
||||
const tabs = ['全部', '审核中', '审核成功', '已拒绝', '已取消']
|
||||
const activeTab = ref(0)
|
||||
const reservationList = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const total = ref(0)
|
||||
const current = ref(1)
|
||||
const size = ref(10)
|
||||
|
||||
// 静态假数据,等你有接口后再对接
|
||||
const reservationList = ref([
|
||||
{
|
||||
id: 1,
|
||||
roomName: '一号会议室',
|
||||
location: '总部大厦A座',
|
||||
time: '2025-06-20 14:00~15:00',
|
||||
subject: '周例会',
|
||||
attendees: '张三、李四、王五',
|
||||
statusText: '已结束',
|
||||
statusClass: 'done',
|
||||
actions: ['更多', '再次预约']
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
roomName: '二号会议室',
|
||||
location: '总部大厦B座',
|
||||
time: '2025-06-22 09:00~10:00',
|
||||
subject: '项目讨论',
|
||||
attendees: '张三、赵六',
|
||||
statusText: '未开始',
|
||||
statusClass: 'pending',
|
||||
actions: ['取消预约', '查看详情']
|
||||
}
|
||||
])
|
||||
const statusMap = {
|
||||
1: { text: '审核中', class: 'pending' },
|
||||
2: { text: '审核成功', class: 'done' },
|
||||
3: { text: '已拒绝', class: 'cancel' },
|
||||
4: { text: '已取消', class: 'cancel' }
|
||||
}
|
||||
|
||||
function fetchReservations() {
|
||||
loading.value = true
|
||||
let checkStatus = activeTab.value === 0 ? undefined : activeTab.value // 0为全部
|
||||
meetingRoomApi.getMyBookings({
|
||||
current: current.value,
|
||||
size: size.value,
|
||||
...(checkStatus ? { checkStatus } : {})
|
||||
}).then((res: any) => {
|
||||
loading.value = false
|
||||
if (res.code === 0 && res.data && res.data.records) {
|
||||
reservationList.value = res.data.records
|
||||
total.value = res.data.total
|
||||
}
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchReservations()
|
||||
})
|
||||
|
||||
function onTabChange(idx: number) {
|
||||
activeTab.value = idx
|
||||
current.value = 1
|
||||
fetchReservations()
|
||||
}
|
||||
|
||||
function cancelBooking(item: any) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消该预约吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// TODO: 调用取消预约接口
|
||||
uni.showToast({ title: '已取消(待接入接口)', icon: 'none' })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function viewDetail(item: any) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/integrated/meeting/booking-detail?id=' + item.id
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -120,29 +159,6 @@ const reservationList = ref([
|
||||
position: absolute;
|
||||
left: 0; right: 0; bottom: 0;
|
||||
}
|
||||
.coupon-box {
|
||||
margin: 24rpx;
|
||||
background: #fffbe6;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 26rpx;
|
||||
color: #bfa243;
|
||||
position: relative;
|
||||
}
|
||||
.coupon-title {
|
||||
font-weight: 600;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
.coupon-desc {
|
||||
flex: 1;
|
||||
}
|
||||
.arrow {
|
||||
color: #bfa243;
|
||||
font-size: 32rpx;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
.card {
|
||||
margin: 24rpx;
|
||||
background: #fff;
|
||||
@@ -196,4 +212,30 @@ const reservationList = ref([
|
||||
padding: 8rpx 24rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.card-btn.cancel {
|
||||
background: #ffeaea;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
.empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 120rpx;
|
||||
color: #bbb;
|
||||
}
|
||||
.empty-img {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.empty-text {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
.empty-tip {
|
||||
font-size: 24rpx;
|
||||
color: #aaa;
|
||||
}
|
||||
</style>
|
||||
@@ -59,16 +59,7 @@
|
||||
<view v-if="!loading && visitorList.length === 0" class="empty">暂无访客记录</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="tabbar">
|
||||
<view class="tabbar-item" @tap="goHome">
|
||||
<image src="/static/icons/home.png" class="tabbar-icon" />
|
||||
<text>首页</text>
|
||||
</view>
|
||||
<view class="tabbar-item" @tap="goMine">
|
||||
<image src="/static/icons/mine.png" class="tabbar-icon" />
|
||||
<text>我的</text>
|
||||
</view>
|
||||
</view>
|
||||
<tabbar :tabBarList="tabBarList" :current="tabbarStore.current" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -489,37 +480,5 @@ onMounted(() => {
|
||||
color: #999;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.tabbar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 100rpx;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
border-top: 1px solid #eee;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.tabbar-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #888;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.tabbar-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.tabbar-item.active {
|
||||
color: #1777FF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -37,4 +37,23 @@ export default {
|
||||
method: "POST",
|
||||
data,
|
||||
}),
|
||||
|
||||
/**
|
||||
* 获取我的预约列表
|
||||
*/
|
||||
getMyBookings: (params: { current: number; size: number; checkStatus?: number }) =>
|
||||
request({
|
||||
url: '/integrated/meetingRoom/app/my-bookings',
|
||||
method: 'GET',
|
||||
params,
|
||||
}),
|
||||
|
||||
/**
|
||||
* 获取预约详情
|
||||
*/
|
||||
getBookingDetail: (id: string) =>
|
||||
request({
|
||||
url: `/integrated/meetingRoom/app/booking-detail/${id}`,
|
||||
method: 'GET',
|
||||
}),
|
||||
}
|
||||
Reference in new issue
Block a user