782 lines
18 KiB
Vue
Raw Permalink 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="container">
<!-- 自定义导航栏 -->
<!-- <view class="nav-bar">
<view class="nav-left" @click="handleBack">
<u-icon name="arrow-left" size="44"></u-icon>
<text>返回</text>
</view>
<text class="nav-title">近山社区</text>
</view> -->
<view v-if="tabsReady">
<u-tabs :list="tabList" :current="currentTab" @change="handleTabChange" border="false"
active-color="#1989fa" bg-color="#f8f8f8"></u-tabs>
<!-- 会议室列表 -->
<view class="room-list" v-if="currentTab === 0">
<view v-if="meetingRoomList.length === 0" class="empty-container">
<text>暂无会议室数据 ({{ meetingRoomList }})</text>
</view>
<view class="room-item" v-for="(item, index) in meetingRoomList" :key="index"
@click="goDetail(item.roomInfo || item)">
<image class="room-img" :src="`${IMAGE_BASE_URL}`+item.imgs[0]">
</image>
<view class="room-info">
<view class="room-header">
<view class="room-name">{{ item.title}}</view>
<view class="room-status" :class="item.status == 2 ? 'available':''">可预约</view>
</view>
<view class="room-meta">
<view class="meta-item">
<u-icon name="account" size="30" color="#666"></u-icon>
<text>可容纳人数:{{ item.maxNum }}人</text>
</view>
</view>
</view>
</view>
</view>
<!-- 预约记录列表 -->
<view class="order-list" v-else>
<u-loading-page :loading="dataloading"></u-loading-page>
<view v-if="orderList.length === 0" class="empty-container">
<noData />
</view>
<view class="order-item" v-for="(item, index) in orderList" :key="index">
<view class="order-header">
<view class="order-name">{{ item.roomInfo ? item.roomInfo.title : '会议室' }}</view>
<view class="order-status" :class="item.status == 0 ? 'available':''">
{{ getStatusText(item.status) }}
</view>
</view>
<view class="order-content">
<!-- <image class="room-img" :src="`${IMAGE_BASE_URL}`+item.imgs[0]"></image> -->
<view class="order-details">
<view class="detail-item">
<u-icon name="account" size="36" color="#666" class="detail-icon"></u-icon>
<text v-if="item.companyName==''">联系人: {{ item.userName }} ({{ item.userPhone }})</text>
<text v-else>负责人: {{ item.concatName }} ({{ item.concatPhone }})</text>
</view>
<view class="detail-item">
<u-icon name="calendar" size="36" color="#666" class="detail-icon"></u-icon>
<text>预约日期: {{ formatDate(item.createdAt) }}</text>
</view>
<view class="detail-item">
<u-icon name="clock" size="30" color="#666" class="detail-icon"></u-icon>
<text>时间段: {{`${item.startTime}~${item.endTime}`}}</text>
</view>
<view class="detail-item">
<u-icon name="tags" size="30" color="#666" class="detail-icon"></u-icon>
<text>事由主题: {{formatName(item.applyTheme)}}</text>
</view>
<view class="detail-item">
<u-icon name="pushpin" size="30" color="#666" class="detail-icon"></u-icon>
<text>申请场次及人数: {{`${item.counter}/${item.num}`}}</text>
</view>
<view class="detail-item" v-if="item.remark">
<u-icon name="edit-pen" size="36" color="#666" class="detail-icon"></u-icon>
<text>备注: {{ item.remark }}</text>
</view>
</view>
</view>
<view class="order-actions">
<!-- <u-button type="primary" plain @click="goDetail(item.roomInfo || item)">查看详情</u-button> -->
<u-button type="error" plain @click="cancelOrder(item.id)">
取消预约
</u-button>
</view>
</view>
</view>
</view>
<view v-else class="loading-container">
<u-loading-icon mode="circle" size="36"></u-loading-icon>
<text class="loading-text">加载会议室信息中...</text>
</view>
<!-- <u-popup :show="show" mode="center" :round="10">
<instructionVue @change='readChange'/>
<u-button type="primary" text="我已知晓" :disabled="hasReaded" @click="show=false"></u-button>
</u-popup> -->
<!-- 保持原有结构不变 -->
<view class="copyright-fixed">
<Copyright :footerHeight="'0'" />
</view>
</view>
</template>
<script>
import {
get,
post,
del
} from '@/utils/request';
import {
IMAGE_BASE_URL,
BASE_URL
} from '@/utils/config';
import {
formatTime,
formatRelativeTime
} from '@/utils/timeFormat';
import instructionVue from '../../components/instruction.vue';
import noData from '../../components/noData.vue'
import Copyright from '@/components/gx-copyright.vue';
import {
applyType,
usages,
thingThemes
} from '@/utils/dict.js'
export default {
components: {
instructionVue,
noData,
Copyright
},
data() {
return {
hasReaded: true,
checkboxValue1: [],
// 基本案列数据
checkboxList1: [{
name: '苹果',
disabled: false
},
{
name: '香蕉',
disabled: false
},
{
name: '橙子',
disabled: true
}
],
IMAGE_BASE_URL,
tabsReady: false,
show: true,
title: '使用说明',
content: '',
tabList: [{
name: '共享空间'
},
{
name: '预约记录'
}
],
currentTab: 0,
meetingRoomList: [],
orderList: [], // 新增单独订单列表
dialogList:[1,5,4,2,6]
};
},
onLoad() {
this.getList();
// this.fetchMeetingRooms().then(() => {
// this.$nextTick(() => {
// this.tabsReady = true;
// });
// });
},
// mounted() {
// this.getList();
// },
computed: {
formattedOrderList() {
return this.orderList.map(item => ({
...item,
roomTitle: item.roomInfo ? item.roomInfo.title : '会议室',
hasImages: item.roomInfo && item.roomInfo.imgs && item.roomInfo.imgs.length > 0,
firstImage: item.roomInfo && item.roomInfo.imgs && item.roomInfo.imgs[0] ?
`${IMAGE_BASE_URL}${item.roomInfo.imgs[0]}` : ''
}))
}
},
methods: {
handleBack() {
// 固定跳转首页
uni.redirectTo({
url: '/pages/mine/index'
});
},
formatName(value) {
return thingThemes.getName(value)
},
handleTabChange(index) {
this.currentTab = index.index;
if (index.index == 1) {
this.getOrderList();
} else {
this.getList();
}
},
// 格式化日期
formatDate(dateString) {
if (!dateString) return '';
const date = new Date(dateString);
return `${date.getFullYear()}${date.getMonth() + 1}${date.getDate()}`;
},
// 格式化时间段
formatTimeRange(startAt, endAt) {
if (!startAt || !endAt) return '';
const start = new Date(startAt);
const end = new Date(endAt);
return `${start.getHours()}:${start.getMinutes().toString().padStart(2, '0')} - ${end.getHours()}:${end.getMinutes().toString().padStart(2, '0')}`;
},
// 获取状态文本
getStatusText(status) {
const statusMap = {
1: '待提交',
2: '待审核',
3: '审核通过',
99: '审核不通过'
};
return statusMap[status] || '未知状态';
},
// 获取状态样式类
getStatusClass(status) {
const classMap = {
0: 'pending',
1: 'confirmed',
2: 'cancelled',
3: 'rejected',
4: 'completed'
};
return classMap[status] || '';
},
// 取消预约
async cancelOrder(orderId) {
try {
uni.showLoading({
title: '处理中...',
mask: true
});
const res = await del(`/api/v1/app_auth/metting-room/order/${orderId}`);
if (res?.success) {
uni.showToast({
title: '取消成功',
icon: 'success'
});
this.getOrderList();
} else {
uni.showToast({
title: res?.message || '取消失败',
icon: 'none'
});
}
} catch (err) {
uni.showToast({
title: '取消失败',
icon: 'none'
});
} finally {
uni.hideLoading();
}
},
goDetail(item) {
console.log("====item",item)
// 安全获取ID兼容各种可能的字段名
const id = item.id;
const isSelfStudy = item.title === '自习室';
if (!id) {
uni.showToast({
title: '会议室信息异常',
icon: 'none'
});
return;
}
// 如果是自习室,先弹出提示确认框
if (item.roomType == 2&&item.num!==4 ) {
uni.showModal({
title: '温馨提示',
content: '自习室预约时间按月为单位,单次预约最长一个月,请确认是否继续?',
confirmColor: '#007AFF', // 可根据uView主题色调整
success: (res) => {
if (res.confirm) {
// 用户点击确定,执行跳转
this.navigateToDetail(id, true);
} else if (res.cancel) {
// 用户点击取消,可选操作(如提示取消)
uni.showToast({
title: '已取消',
icon: 'none'
});
}
},
fail: (err) => {
console.error('弹窗失败:', err);
uni.showToast({
title: '操作失败',
icon: 'none'
});
}
});
} else if(this.dialogList.includes(item.num)){
uni.showModal({
title: '温馨提示',
content: ' 可预约时段工作日上午8:30 - 11:30,下午13:30 - 17:00',
confirmColor: '#007AFF', // 可根据uView主题色调整
success: (res) => {
if (res.confirm) {
// 用户点击确定,执行跳转
this.navigateToDetail(id, false);
} else if (res.cancel) {
// 用户点击取消,可选操作(如提示取消)
uni.showToast({
title: '已取消',
icon: 'none'
});
}
},
fail: (err) => {
console.error('弹窗失败:', err);
uni.showToast({
title: '操作失败',
icon: 'none'
});
}
});
}else {
// 非自习室,直接跳转
this.navigateToDetail(id, false);
}
},
// 封装跳转逻辑,避免重复代码
navigateToDetail(id, isSelfStudy) {
uni.navigateTo({
url: `/pages/meetingDetail/index?Id=${encodeURIComponent(id)}&isSelfStudy=${isSelfStudy}`,
success: () => {
console.log('导航成功ID:', id);
},
fail: (err) => {
console.error('导航失败:', err);
uni.showToast({
title: '打开详情页失败',
icon: 'none'
});
}
});
},
// 获取会议室列表
async getList() {
try {
wx.showLoading({title:'加载中...',mask:true})
const res = await get('/api/v1/apps/home/metting-room', {
current: 1,
pageSize: 10,
});
if (res?.success) {
this.meetingRoomList = [...res.data];
this.tabsReady = true;
}
} catch (err) {
uni.showToast({
title: '加载列表失败',
icon: 'none'
});
} finally {
wx.hideLoading()
}
},
// 获取我的预约记录
async getOrderList() {
try {
wx.showLoading({title:'加载中...',mask:true})
const res = await get('/api/v1/app_auth/metting-room/order', {
current: 1,
pageSize: 10,
});
if (res?.success) {
this.orderList = [...res.data];
this.tabsReady = true;
}
} catch (err) {
console.error('获取我的求助失败:', err);
uni.showToast({
title: '加载列表失败',
icon: 'none'
});
} finally {
wx.hideLoading()
}
},
}
};
</script>
<style lang="scss" scoped>
// 定义变量
$primary-color: #1989fa;
$success-color: #07c160;
$warning-color: #ff976a;
$error-color: #ee0a24;
$text-color: #333;
$sub-text-color: #666;
$light-text-color: #999;
$border-color: #f0f0f0;
$bg-color: #f8f8f8;
$card-radius: 24rpx;
$tag-radius: 8rpx;
.container {
background-color: $bg-color;
padding: 20rpx;
min-height: 100vh;
box-sizing: border-box;
display: flex; /* 新增 */
flex-direction: column; /* 新增 */
padding-bottom: calc(100rpx + 80rpx); /* 调整为footer高度 + copyright高度 */
// .copyright-fixed {
// position: fixed;
// bottom: 0;
// left: 0;
// right: 0;
// z-index: 10; /* 防止被其他元素遮挡 */
// }
.nav-bar {
display: flex;
align-items: center;
padding: 15px;
// background-color: #fff;
border-bottom: 1px solid #f5f5f5;
padding-top: 60rpx;
}
.nav-left {
display: flex;
align-items: center;
// margin-right: 10px;
}
.nav-title {
flex: 1;
text-align: center;
// font-weight: bold;
width: 100%;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 70vh;
.loading-text {
margin-top: 32rpx;
font-size: 30rpx;
color: $sub-text-color;
}
}
.room-list {
padding: 30rpx;
.room-item {
display: flex;
margin-bottom: 30rpx;
border-radius: $card-radius;
overflow: hidden;
background-color: #fff;
box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.04);
.room-img {
width: 240rpx;
height: 240rpx;
flex-shrink: 0;
}
.room-info {
flex: 1;
padding: 24rpx 30rpx;
display: flex;
flex-direction: column;
.room-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
.room-name {
font-size: 32rpx;
font-weight: bold;
color: $text-color;
}
.room-status {
font-size: 24rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
&.available {
background-color: rgba($success-color, 0.1);
color: $success-color;
}
&.pending {
background-color: rgba($warning-color, 0.1);
color: $warning-color;
}
&.confirmed {
background-color: rgba($primary-color, 0.1);
color: $primary-color;
}
}
}
.room-meta {
display: flex;
margin: 16rpx 0 24rpx;
.meta-item {
display: flex;
align-items: center;
margin-right: 30rpx;
font-size: 26rpx;
color: $sub-text-color;
u-icon {
margin-right: 8rpx;
}
}
}
.room-facilities {
display: flex;
flex-wrap: wrap;
margin-top: auto;
.facility-tag {
font-size: 22rpx;
padding: 4rpx 16rpx;
margin-right: 16rpx;
margin-bottom: 10rpx;
border-radius: $tag-radius;
background-color: #f0f7ff;
color: $primary-color;
}
}
}
}
}
.order-list {
padding: 30rpx;
.order-item {
margin-bottom: 40rpx;
border-radius: $card-radius;
overflow: hidden;
background-color: #fff;
padding: 32rpx;
box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.04);
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 24rpx;
border-bottom: 2rpx solid #f5f5f5;
.order-name {
font-size: 32rpx;
font-weight: bold;
color: $text-color;
}
.order-status {
font-size: 26rpx;
&.available {
background-color: rgba($success-color, 0.1);
color: $success-color;
}
&.pending {
color: $warning-color;
}
&.confirmed {
color: $success-color;
}
}
}
.order-details {
padding: 30rpx 0;
.detail-item {
display: flex;
align-items: center;
margin-bottom: 20rpx;
font-size: 28rpx;
color: $sub-text-color;
text {
padding-left: 30rpx;
}
.item-icon {
width: 50rpx;
height: 50rpx;
text-align: center !important;
padding-top: 20rpx;
}
.detail-icon {
display: flex;
align-items: center;
justify-content: center;
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
.detail-text {
line-height: 1.5;
}
&:last-child {
margin-bottom: 0;
}
}
}
.order-actions {
display: flex;
justify-content: flex-end;
gap: 20rpx;
padding-top: 20rpx;
border-top: 2rpx solid #f5f5f5;
}
}
}
// 空状态提示
.empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 80rpx 0;
.empty-icon {
font-size: 96rpx;
color: #ccc;
margin-bottom: 30rpx;
}
.empty-text {
font-size: 30rpx;
color: $sub-text-color;
}
}
.order-content {
display: flex;
padding: 30rpx 0;
border-bottom: 2rpx solid #f5f5f5;
}
.order-img {
width: 240rpx;
height: 180rpx;
border-radius: 12rpx;
margin-right: 30rpx;
flex-shrink: 0;
}
.order-details {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.detail-item {
display: flex;
align-items: center;
margin-bottom: 16rpx;
font-size: 28rpx;
color: #666;
&:last-child {
margin-bottom: 0;
}
}
.detail-icon {
margin-right: 16rpx;
}
/* 状态样式补充 */
.order-status {
font-size: 26rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
&.pending {
background-color: rgba(#ff976a, 0.1);
color: #ff976a;
}
&.confirmed {
background-color: rgba(#07c160, 0.1);
color: #07c160;
}
&.cancelled,
&.rejected {
background-color: rgba(#ee0a24, 0.1);
color: #ee0a24;
}
&.completed {
background-color: rgba(#1989fa, 0.1);
color: #1989fa;
}
}
.empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
.empty-icon {
color: #ccc;
margin-bottom: 30rpx;
}
.empty-text {
font-size: 30rpx;
color: #999;
}
}
}
</style>