Browse Source

共享空间优化

master
wangyx 2 days ago
parent
commit
bfd8dc3f40
  1. 4
      api/index.js
  2. BIN
      images/mine/s3.png
  3. 2
      pages/mine/mine.wxml
  4. BIN
      subpages/images/icon01.png
  5. BIN
      subpages/images/icon02.png
  6. 39
      subpages/mine/mySpace/mySpace.js
  7. 12
      subpages/mine/mySpace/mySpace.wxml
  8. 2
      subpages/space/list/list.js
  9. 20
      subpages/space/list/list.wxml
  10. 2
      subpages/space/list/list.wxss
  11. 110
      subpages/space/reserve/reserve.js
  12. 1
      subpages/space/reserve/reserve.wxml
  13. 46
      subpages/space/reserve/reserve.wxss

4
api/index.js

@ -83,3 +83,7 @@ export function spacePage(pamars) {
export function spaceInfo(pamars) {
return fly.get(`/bys/mzShareSpace/detail`, pamars);
}
// 根据共享空间和日期查询可预约时间段;
export function queryAppointTime(pamars) {
return fly.get(`/bys/mzShareSpace/queryAppointTime`, pamars);
}

BIN
images/mine/s3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

2
pages/mine/mine.wxml

@ -79,7 +79,7 @@
<view class="service-c">
<view class="flex p10" style="width: 180rpx;background-color: #f3f9fc;border-radius: 10rpx;" wx:for="{{serviceNavList}}" bind:tap="toInfo" data-url="{{item.url}}">
<image src="{{'../../images/mine/s'+(index + 1)+'.png'}}" class="icon-40 mr-10" />
<view>{{item.label}}</view>
<view style="white-space:nowrap;">{{item.label}}</view>
</view>
</view>
</view>

BIN
subpages/images/icon01.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
subpages/images/icon02.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

39
subpages/mine/mySpace/mySpace.js

@ -93,12 +93,10 @@ Page({
const newData = res.data.records.map((item) => {
return {
...item,
// 格式化预约日期和时间
// 格式化预约日期和时间(保留展示所需字段)
appointmentDate: item.appointmentDate || "",
appointTime: item.appointTime || "",
// 添加状态显示
statusText: this.getStatusText(item),
statusColor: this.getStatusColor(item)
statusColor: this.getColorByStatus(item.currentStatus)
};
});
@ -151,32 +149,9 @@ Page({
});
},
// 获取状态文本
getStatusText(item) {
// 根据实际业务逻辑判断状态
const now = new Date();
const appointmentDate = new Date(item.appointmentDate);
if (appointmentDate > now) {
return '已预约';
} else if (appointmentDate.toDateString() === now.toDateString()) {
return '使用中';
} else {
return '已完成';
}
},
// 获取状态颜色
getStatusColor(item) {
const now = new Date();
const appointmentDate = new Date(item.appointmentDate);
if (appointmentDate > now) {
return '#17C4C4'; // 已预约 - 青色
} else if (appointmentDate.toDateString() === now.toDateString()) {
return '#FA9E0A'; // 使用中 - 橙色
} else {
return '#999'; // 已完成 - 灰色
}
},
getColorByStatus(status) {
if (status === 1) return '#17C4C4';
if (status === 2) return '#FA9E0A';
return '#999';
}
});

12
subpages/mine/mySpace/mySpace.wxml

@ -2,15 +2,16 @@
<scroll-view scroll-y class="scroll-view" bindscrolltolower="scrolltolower" wx:if="{{list.length>0}}" enable-back-to-top refresher-enabled="{{true}}" bindrefresherrefresh="onPullDownRefresh" refresher-triggered="{{refreshing}}">
<view class="card" wx:key="id" wx:for="{{list}}">
<view class="flex flex-sb">
<view class="name font-bold">{{item.apartmentName}}</view>
<view class="flex name font-bold">
<image src="{{'../../images/icon01.png'}}" class="icon-40 mr-10" />
{{item.apartmentName}}
</view>
</view>
<van-divider dashed />
<view class="item flex">
<image src="{{item.imgUrls[0]}}" style="width: 200rpx;height:152rpx;margin-right: 16rpx;border-radius: 10rpx;" mode="aspectFill" />
<view class="flex flex-col flex-1">
<view class="space-name font-bold" style="margin:10rpx 0 10rpx 0;">
{{item.name}}
</view>
<view class="space-name font-bold" style="margin:10rpx 0 10rpx 0;">{{item.name}}</view>
<view class="address" style="color: #666; font-size: 28rpx; margin-bottom: 10rpx;">
{{item.address}}
</view>
@ -18,12 +19,11 @@
{{item.appointmentDate}} {{item.appointTime}}
</view>
<view class="status" style="color:{{item.statusColor}}; font-size: 28rpx;">
{{item.statusText}}
{{item.currentStatus==1?'已预约':item.currentStatus==2?'使用中':item.currentStatus==3?'已完成':''}}
</view>
</view>
</view>
</view>
<!-- 加载更多提示 -->
<view class="loading-more" wx:if="{{loading}}" style="text-align: center; padding: 20rpx; color: #999;">
加载中...

2
subpages/space/list/list.js

@ -60,7 +60,7 @@ Page({
onShareAppMessage() {},
toReserve(e) {
wx.navigateTo({
url: `/subpages/space/reserve/reserve?id=${e.currentTarget.dataset.item.id}&roomName=${e.currentTarget.dataset.item.name}&openDate=${e.currentTarget.dataset.item.appointmentWeekText}&openTimeText=${e.currentTarget.dataset.item.appointmentTimeText}&imgUrls=${e.currentTarget.dataset.item.imgUrls}`,
url: `/subpages/space/reserve/reserve?id=${e.currentTarget.dataset.item.id}&roomName=${e.currentTarget.dataset.item.name}&openDate=${e.currentTarget.dataset.item.appointmentWeekText}&openTimeText=${e.currentTarget.dataset.item.appointmentTimeText}&imgUrls=${e.currentTarget.dataset.item.imgUrls[0]}&address=${e.currentTarget.dataset.item.address}`,
});
},
getList(isRefresh = false) {

20
subpages/space/list/list.wxml

@ -1,15 +1,19 @@
<!-- subpages/space/list/list.wxml -->
<scroll-view scroll-y class="scroll-view" bindscrolltolower="scrolltolower" wx:if="{{list.length>0}}">
<view class="card " wx:key="index" wx:for="{{list}}">
<view class="flex flex-sb">
<view class="flex name font-bold">
<image src="{{'../../images/icon01.png'}}" class="icon-40 mr-10" />
{{item.address}}
</view>
</view>
<van-divider dashed />
<view class="item flex">
<image src="{{item.imgUrls[0]}}" style="width: 200rpx;height:152rpx;margin-right: 16rpx;border-radius: 10rpx;" mode="" />
<view class="flex flex-col flex-1">
<!-- <view class="flex flex-sb">
<view class="name font-bold">{{item.name}}</view>
</view> -->
<view class="position" style="margin:10rpx 0 10rpx 0;">
{{item.name}}
</view>
<!-- <view class="flex flex-sb"> -->
<!-- </view> -->
<view class="position" style="margin:10rpx 0 10rpx 0;">{{item.name}}</view>
<view class="date">{{item.appointmentWeekText}}</view>
<view class="date" wx:if="{{item.appointmentTimeText}}">{{item.appointmentTimeText}}</view>
<view class="date" wx:if="{{item.status==='1'}}">{{item.inDate}} 至 {{item.outDate}}</view>
@ -20,12 +24,11 @@
</view>
<!-- <van-divider dashed /> -->
<view class="flex flex-sb px-20 btn">
<van-button round size="small" bind:click="toReserve" data-item="{{item}}" color="linear-gradient(to right, #0DC6C6, #13C2C2,#46DBD5)" custom-style="position:absolute;right:0rpx;bottom:-60rpx;">
<van-button round size="small" bind:click="toReserve" data-item="{{item}}" color="linear-gradient(to right, #0DC6C6, #13C2C2,#46DBD5)" custom-style="position:absolute;right:0rpx;bottom:-60rpx;">
预约
</van-button>
</view>
</view>
<!-- 加载更多提示 -->
<view wx:if="{{list.length > 0}}" class="load-more">
<view wx:if="{{loading}}" class="loading-text">
@ -33,5 +36,4 @@
</view>
</view>
</scroll-view>
<no-data isShow="{{list.length === 0 && !loading}}"></no-data>

2
subpages/space/list/list.wxss

@ -1,6 +1,6 @@
/* subpages/space/list/list.wxss */
.card{
height:280rpx ;
height:370rpx ;
}
.name {
font-size: 32rpx;

110
subpages/space/reserve/reserve.js

@ -1,12 +1,12 @@
// subpages/space/reserve/reserve.js
import { appointment, spaceInfo } from "../../../api/index";
import { appointment, spaceInfo, queryAppointTime } from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
bannerUrl: 'https://img.yzcdn.cn/vant/cat.jpeg',
bannerUrl: '',
roomName: '第一会议室',
openDate: '周一至周五',
openTimeText: '上午09:00-下午18:00',
@ -18,7 +18,8 @@ Page({
chosenText: '',
spaceDetail: null,
appointDates: [],
appointmentTimes: []
appointmentTimes: [],
address: '',
},
/**
@ -32,6 +33,7 @@ Page({
openDate: options.openDate,
openTimeText: options.openTimeText,
bannerUrl: options.imgUrls,
address: options.address,
});
this.getDetail(); // 获取详情后会自动初始化日期和时间段
},
@ -78,7 +80,7 @@ Page({
this.setData({
spaceDetail: res.data,
appointDates: res.data.appointDates || [],
appointmentTimes: res.data.appointmentTimes || []
appointmentTimes: []
});
// 根据接口数据初始化日期和时间段
this.initDatesFromAPI();
@ -86,7 +88,7 @@ Page({
}
}).catch(err => {
wx.showToast({
title: err.msg || '获取详情失败',
title: err.msg ,
icon: 'none'
});
})
@ -115,12 +117,20 @@ Page({
initDatesFromAPI() {
const { appointDates } = this.data;
if (!appointDates || appointDates.length === 0) {
this.initDates(); // 如果没有接口数据,使用默认逻辑
// 删除默认逻辑:当无可预约日期时,直接清空并返回
this.setData({
dateList: [],
selectedDateIndex: 0,
timeSlots: [],
rangeStartIndex: -1,
rangeEndIndex: -1,
chosenText: ''
});
return;
}
const today = new Date().toISOString().split('T')[0]; // 今天的日期 YYYY-MM-DD
const dates = appointDates.map((item, index) => {
const dates = appointDates.map((item) => {
const date = new Date(item.appointDate);
const isToday = item.appointDate === today;
return {
@ -145,60 +155,46 @@ Page({
dateList: dates,
selectedDateIndex: defaultIndex,
});
},
initTimeSlots() {
const ranges = [
['09:00', '09:30'], ['09:30', '10:00'], ['10:00', '10:30'], ['10:30', '11:00'],
['11:00', '11:30'], ['11:30', '12:00'], ['12:00', '12:30'], ['12:30', '13:00'],
['13:00', '13:30'], ['13:30', '14:00'], ['14:00', '14:30'], ['14:30', '15:00'],
['15:00', '15:30'], ['15:30', '16:00'], ['16:00', '16:30'], ['16:30', '17:00'],
['17:00', '17:30'], ['17:30', '18:00'], ['18:00', '18:30'], ['18:30', '19:00'],
];
const slots = ranges.map((r, idx) => ({
id: `${r[0]}-${r[1]}`,
start: r[0],
end: r[1],
status: idx < 3 ? 'disabled' : 'available'
}));
this.setData({ timeSlots: slots, rangeStartIndex: -1, rangeEndIndex: -1, chosenText: '' });
// 初始化默认日期的时间段(调用后端 queryAppointTime)
const defaultDate = dates[defaultIndex] && dates[defaultIndex].date;
if (defaultDate) {
this.fetchTimeSlotsForDate(defaultDate);
}
},
// 根据接口数据初始化时间段
// 根据接口数据初始化时间段(新的数据结构:时间段挂在 appointDates 每个日期项内)
initTimeSlotsFromAPI() {
const { appointmentTimes } = this.data;
const { appointDates, selectedDateIndex } = this.data;
if (!appointDates || appointDates.length === 0) return;
const dateItem = appointDates[selectedDateIndex] || {};
const appointmentTimes = dateItem.appointmentTimes || dateItem.times || [];
if (!appointmentTimes || appointmentTimes.length === 0) {
this.initTimeSlots(); // 如果没有接口数据,使用默认逻辑
this.setData({ timeSlots: [], rangeStartIndex: -1, rangeEndIndex: -1, chosenText: '' });
return;
}
const slots = appointmentTimes.map((item, index) => {
// 解析时间段,例如 "09:00至09:29" -> start: "09:00", end: "09:29"
const timeMatch = item.appointmentTime.match(/(\d{2}:\d{2})至(\d{2}:\d{2})/);
const slots = appointmentTimes.map((item) => {
const timeMatch = (item.appointmentTime || '').match(/(\d{2}:\d{2})至(\d{2}:\d{2})/);
let start = '00:00';
let end = '00:30';
if (timeMatch) {
start = timeMatch[1];
end = timeMatch[2];
}
return {
id: item.id,
apiId: item.id, // 保存接口返回的ID
start: start,
end: end,
apiId: item.id,
start,
end,
timeText: item.appointmentTime,
status: item.canAppoint ? 'available' : 'disabled'
};
});
this.setData({
timeSlots: slots,
rangeStartIndex: -1,
rangeEndIndex: -1,
chosenText: ''
});
this.setData({ timeSlots: slots, rangeStartIndex: -1, rangeEndIndex: -1, chosenText: '' });
},
selectDate(e) {
@ -215,7 +211,8 @@ Page({
}
this.setData({ selectedDateIndex: index });
this.initTimeSlotsFromAPI(); // 使用接口数据初始化时间段
// 每次选择都请求后端查询当日可预约时间段
this.fetchTimeSlotsForDate(selectedDate.date);
},
toggleSlot(e) {
@ -334,5 +331,36 @@ Page({
icon: 'none'
});
});
},
// 根据日期查询可预约时间段
fetchTimeSlotsForDate(date) {
const { id } = this.data;
if (!id || !date) return;
queryAppointTime({ id, currentDate: date })
.then((res) => {
if (res.code === 200 && Array.isArray(res.data)) {
const { appointDates, selectedDateIndex } = this.data;
const dateItem = appointDates[selectedDateIndex] || {};
dateItem.appointmentTimes = res.data; // 将查询到的时间段更新到 appointDates 的对应日期项中
appointDates[selectedDateIndex] = dateItem;
this.setData({
appointDates, // 更新 appointDates 数组
appointmentTimes: [], // 清空独立的 appointmentTimes
});
this.initTimeSlotsFromAPI(); // 重新初始化时间段
} else {
wx.showToast({
title: res.msg || "获取时间段失败",
icon: "none",
});
}
})
.catch((err) => {
wx.showToast({
title: err.msg || "获取时间段失败",
icon: "none",
});
});
}
})

1
subpages/space/reserve/reserve.wxml

@ -5,6 +5,7 @@
</view>
<view class=" banner-overlay">
<view class="room-name">{{roomName}}</view>
<view class="open-time">{{address}}</view>
<view class="open-time">{{openDate}}</view>
<view class="open-time">{{openTimeText}}</view>
</view>

46
subpages/space/reserve/reserve.wxss

@ -3,22 +3,27 @@
background: #f8f8f8;
min-height: 100vh;
}
.banner {
position: relative;
}
.banner-overlay {
padding: 20rpx;
background: #fff;
}
.room-name {
font-size: 32rpx;
font-weight: 600;
}
.open-time {
margin-top: 8rpx;
font-size: 26rpx;
color: #BFBFBF;
}
.section {
margin: 0 18rpx;
margin-top: 12rpx;
@ -27,27 +32,32 @@
border-radius: 20rpx;
}
.section-row{
.section-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.section-title {
font-size: 32rpx;
font-weight: 600;
margin-bottom: 16rpx;
margin-left: 10rpx;
}
.range-switch{
.range-switch {
display: flex;
align-items: center;
color: #666;
font-size: 26rpx;
}
.date-strip {
white-space: nowrap;
padding-bottom: 12rpx;
}
.date-item {
display: inline-flex;
flex-direction: column;
@ -59,9 +69,11 @@
color: #666;
margin-right: 16rpx;
}
.date-item .date-label {
font-size: 26rpx;
}
.date-item .date-day {
margin-top: 8rpx;
width: 56rpx;
@ -70,62 +82,78 @@
text-align: center;
border-radius: 50%;
}
.date-item.active {
/* background: #e6fffb; */
color: #13c2c2;
}
.date-item.active .date-day {
background: #13c2c2;
color: #fff;
}
.date-item.disabled {
color: #bfbfbf;
opacity: 0.5;
}
.date-item.disabled .date-day {
background: #f0f0f0;
color: #bfbfbf;
}
.slot-grid {
display: flex;
flex-wrap: wrap;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 16rpx;
grid-row-gap: 16rpx;
margin-top: 12rpx;
}
.slot {
width: calc(25% - 16rpx);
margin-right: 16rpx;
margin-top: 16rpx;
width: 100%;
margin: 0;
box-sizing: border-box;
border-radius: 16rpx;
padding: 12rpx 0;
text-align: center;
background: #f7f8fa;
color: #000;
border:1px solid rgba(111, 195, 160, 1);
border: 1px solid rgba(111, 195, 160, 1);
}
.slot:nth-child(4n) {
margin-right: 0;
}
.slot .slot-line {
font-size: 28rpx;
}
.slot .slot-sep {
font-size: 24rpx;
color: inherit;
}
.slot.disabled {
background: #ededed;
color: #bfbfbf;
border: none;
}
.slot.selected {
background: #13c2c2;
color: #fff;
}
.chosen{
.chosen {
margin-top: 20rpx;
color: #13c2c2;
font-size: 26rpx;
}
.footer {
padding: 24rpx;
}
Loading…
Cancel
Save