Browse Source

共享空间

master
wangyx 2 months ago
parent
commit
30c3e151e1
  1. 16
      api/index.js
  2. 15
      app.json
  3. 14
      custom-tab-bar/index.js
  4. 7
      pages/index/index.js
  5. 8
      pages/mine/mine.js
  6. 64
      pages/serve/serve.js
  7. 6
      pages/serve/serve.wxml
  8. 46
      project.private.config.json
  9. 182
      subpages/mine/mySpace/mySpace.js
  10. 11
      subpages/mine/mySpace/mySpace.json
  11. 32
      subpages/mine/mySpace/mySpace.wxml
  12. 37
      subpages/mine/mySpace/mySpace.wxss
  13. 202
      subpages/space/list/list.js
  14. 11
      subpages/space/list/list.json
  15. 37
      subpages/space/list/list.wxml
  16. 60
      subpages/space/list/list.wxss
  17. 338
      subpages/space/reserve/reserve.js
  18. 8
      subpages/space/reserve/reserve.json
  19. 35
      subpages/space/reserve/reserve.wxml
  20. 131
      subpages/space/reserve/reserve.wxss

16
api/index.js

@ -67,3 +67,19 @@ export function repairList(pamars) {
export function incidentsList(pamars) { export function incidentsList(pamars) {
return fly.get(`/bysmp/incidents/list`,pamars) return fly.get(`/bysmp/incidents/list`,pamars)
} }
// 共享空间预约
export function appointment(data) {
return fly.post(`/bys/mzShareAppointmentRec/appointment`, data);
}
// 预约记录
export function appointmentRecList(pamars) {
return fly.get(`/bys/mzShareAppointmentRec/page`, pamars);
}
// 共享空间列表
export function spacePage(pamars) {
return fly.get(`/bys/mzShareSpace/page`, pamars);
}
// 共享空间详情
export function spaceInfo(pamars) {
return fly.get(`/bys/mzShareSpace/detail`, pamars);
}

15
app.json

@ -29,7 +29,8 @@
"evaluate/evaluate", "evaluate/evaluate",
"checkInEvaluate/checkInEvaluate", "checkInEvaluate/checkInEvaluate",
"repairList/repairList", "repairList/repairList",
"eventList/eventList" "eventList/eventList",
"mySpace/mySpace"
] ]
}, },
{ {
@ -65,6 +66,13 @@
"pages": [ "pages": [
"signingCompleted/signingCompleted" "signingCompleted/signingCompleted"
] ]
},{
"root": "subpages/space",
"name":"space",
"pages":[
"list/list",
"reserve/reserve"
]
} }
], ],
"window": { "window": {
@ -89,6 +97,11 @@
"text": "我的", "text": "我的",
"pagePath": "pages/mine/mine", "pagePath": "pages/mine/mine",
"iconPath": "images/icon/home.png" "iconPath": "images/icon/home.png"
},{
"text": "服务",
"pagePath": "pages/serve/serve",
"iconPath": "images/icon/serve Copy.png"
} }
] ]
}, },

14
custom-tab-bar/index.js

@ -22,13 +22,13 @@ Component({
// selectedIconPath: "/images/icon/message-a.png", // selectedIconPath: "/images/icon/message-a.png",
// text: "消息", // text: "消息",
// }, // },
// { {
// pagePath: "/pages/serve/serve", pagePath: "/pages/serve/serve",
// iconPath: "/images/icon/serve-a.png", iconPath: "/images/icon/serve-a.png",
// selectedIconPath: "/images/icon/serve.png", selectedIconPath: "/images/icon/serve.png",
// bulge:false, bulge:false,
// text: "服务", text: "服务",
// }, },
// { // {
// pagePath: "/pages/life/life", // pagePath: "/pages/life/life",
// iconPath: "/images/icon/life.png", // iconPath: "/images/icon/life.png",

7
pages/index/index.js

@ -57,7 +57,8 @@ Page({
searchValue: "", searchValue: "",
policyList:[],//政策列表 policyList:[],//政策列表
getUserInfo:{}, getUserInfo:{},
bindPhone:false bindPhone:false,
userInfo: {}
}, },
/** /**
@ -221,7 +222,7 @@ Page({
}) })
}else if(e.currentTarget.dataset.url === '/subpages/OCRCard/pages/index/index'){ }else if(e.currentTarget.dataset.url === '/subpages/OCRCard/pages/index/index'){
if(!this.data.bindPhone){ if(!this.data.bindPhone){
if(this.data.userInfo.idCard){ if(this.data.userInfo && this.data.userInfo.idCard){
this.selectMzGraduateInfo({idCard:this.data.userInfo.idCard}) this.selectMzGraduateInfo({idCard:this.data.userInfo.idCard})
}else{ }else{
wx.navigateTo({ wx.navigateTo({
@ -235,7 +236,7 @@ Page({
} }
}else if(e.currentTarget.dataset.url === '/subpages/index/checkOutConfirm/index/index'){ }else if(e.currentTarget.dataset.url === '/subpages/index/checkOutConfirm/index/index'){
if(!this.data.bindPhone){ if(!this.data.bindPhone){
if(this.data.userInfo.idCard){ if(this.data.userInfo && this.data.userInfo.idCard){
wx.navigateTo({ wx.navigateTo({
url: `/subpages/index/checkOutConfirm/index/index`, url: `/subpages/index/checkOutConfirm/index/index`,
}) })

8
pages/mine/mine.js

@ -29,10 +29,10 @@ Page({
label:'问题反馈', label:'问题反馈',
url:'/subpages/mine/eventList/eventList' url:'/subpages/mine/eventList/eventList'
}, },
// { {
// label:'共享空间', label:'共享空间',
// url:'' url:'/subpages/mine/mySpace/mySpace'
// } }
], ],
registerFlag:false registerFlag:false
}, },

64
pages/serve/serve.js

@ -1,13 +1,16 @@
// pages/serve/serve.js // pages/serve/serve.js
const app = getApp() const app = getApp()
import { getUserInfo as fetchUserInfo } from "../../api/user";
import { selectMzGraduateInfo } from "../../api/index";
Page({ Page({
/** /**
* 页面的初始数据 * 页面的初始数据
*/ */
data: { data: {
userInfo: {},
bindPhone: false,
}, },
/** /**
@ -31,7 +34,7 @@ Page({
* 生命周期函数--监听页面显示 * 生命周期函数--监听页面显示
*/ */
onShow() { onShow() {
this.getUserInfo()
}, },
/** /**
@ -67,13 +70,55 @@ Page({
*/ */
onShareAppMessage() { onShareAppMessage() {
},
getUserInfo() {
fetchUserInfo().then((res) => {
app.globalData.userInfo = res.data;
this.setData({
userInfo: res.data,
bindPhone: !Boolean(res.data && res.data.phone)
});
})
}, },
toEventAdd(){ toEventAdd(){
wx.navigateTo({ wx.navigateTo({
url: '/subpages/eventAdd/add/add', url: '/subpages/eventAdd/add/add',
}) })
}, },
selectMzGraduateInfo(obj) {
selectMzGraduateInfo({ idCard: obj.idCard })
.then((res) => {
if (res.data.signType === 0 && res.data.contract) {
app.globalData.userInfo.chooseRoomId = res.data.chooseRecId;
res.data.contract = res.data.contract.replace(
"https://h5.esign.cn",
"https://hxm5112004501.h5.esign.cn"
);
wx.navigateTo({
url:
"/pages/webView/webView?url=" +
encodeURIComponent(res.data.contract),
});
} else if (res.data.signType === 1) {
wx.navigateTo({
url: "/pages/noData/noData?msg=暂无合同签订&idCard=" + obj.idCard,
});
} else {
wx.navigateTo({
url: "/pages/noData/noData?msg=暂无合同签订&idCard=" + obj.idCard,
});
}
})
.catch(() => {
wx.navigateTo({
url: "/pages/noData/noData?msg=暂无合同签订&idCard=" + obj.idCard,
});
});
},
toPage(e){ toPage(e){
if (!wx.getStorageSync('token')) {
return
}
console.log(e); console.log(e);
if(e.currentTarget.dataset.url && e.currentTarget.dataset.url != '/subpages/OCRCard/pages/index/index' && e.currentTarget.dataset.url != '/subpages/index/checkOutConfirm/index/index'){ if(e.currentTarget.dataset.url && e.currentTarget.dataset.url != '/subpages/OCRCard/pages/index/index' && e.currentTarget.dataset.url != '/subpages/index/checkOutConfirm/index/index'){
if(e.currentTarget.dataset.url === '/pages/serve/serve'){ if(e.currentTarget.dataset.url === '/pages/serve/serve'){
@ -86,10 +131,8 @@ Page({
}) })
}else if(e.currentTarget.dataset.url === '/subpages/OCRCard/pages/index/index'){ }else if(e.currentTarget.dataset.url === '/subpages/OCRCard/pages/index/index'){
if(!this.data.bindPhone){ if(!this.data.bindPhone){
if(this.data.userInfo.idCard){ if(this.data.userInfo && this.data.userInfo.idCard){
wx.navigateTo({ this.selectMzGraduateInfo({ idCard: this.data.userInfo.idCard })
url: `/subpages/index/checkInUser/checkInUser?idCard=${this.data.userInfo.idCard}&name=${this.data.userInfo.name}&phone=${this.data.userInfo.phone}`,
})
}else{ }else{
wx.navigateTo({ wx.navigateTo({
url: `/subpages/OCRCard/pages/index/index`, url: `/subpages/OCRCard/pages/index/index`,
@ -102,7 +145,7 @@ Page({
} }
}else if(e.currentTarget.dataset.url === '/subpages/index/checkOutConfirm/index/index'){ }else if(e.currentTarget.dataset.url === '/subpages/index/checkOutConfirm/index/index'){
if(!this.data.bindPhone){ if(!this.data.bindPhone){
if(this.data.userInfo.idCard){ if(this.data.userInfo && this.data.userInfo.idCard){
wx.navigateTo({ wx.navigateTo({
url: `/subpages/index/checkOutConfirm/index/index`, url: `/subpages/index/checkOutConfirm/index/index`,
}) })
@ -122,5 +165,10 @@ Page({
wx.navigateTo({ wx.navigateTo({
url: '/subpages/bsPage/bsPage/bsPage', url: '/subpages/bsPage/bsPage/bsPage',
}) })
} },
toYuyue(){
wx.navigateTo({
url: '/subpages/space/list/list',
})
}
}) })

6
pages/serve/serve.wxml

@ -40,12 +40,12 @@
<van-button color="#ecf6ff" round custom-style="color:#999999" size="small" bind:click="toBsPage">去报事</van-button> <van-button color="#ecf6ff" round custom-style="color:#999999" size="small" bind:click="toBsPage">去报事</van-button>
</view> </view>
</view> --> </view> -->
<!-- <view class="card flex flex-col list"> <view class="card flex flex-col list">
<view class="title">共享空间</view> <view class="title">共享空间</view>
<view class="card flex items-center"> <view class="card flex items-center">
<image src="../../images/icon/555.png" class="icon-80 mr-30" mode=""/> <image src="../../images/icon/555.png" class="icon-80 mr-30" mode=""/>
<view class="flex-1 text-30">共享空间</view> <view class="flex-1 text-30">共享空间</view>
<van-button color="#ecf6ff" round custom-style="color:#999999" size="small ">去处理</van-button> <van-button color="#ecf6ff" round custom-style="color:#999999" size="small" bind:click="toYuyue">去预约</van-button>
</view> </view>
</view> --> </view>
</view> </view>

46
project.private.config.json

@ -15,12 +15,54 @@
"miniprogram": { "miniprogram": {
"list": [ "list": [
{ {
"name": "subpages/mine/editUser/editUser", "name": "subpages/mine/mySpace/mySpace",
"pathName": "subpages/mine/editUser/editUser", "pathName": "subpages/mine/mySpace/mySpace",
"query": "", "query": "",
"scene": null, "scene": null,
"launchMode": "default" "launchMode": "default"
}, },
{
"name": "subpages/space/list/list",
"pathName": "subpages/space/list/list",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "subpages/mine/mySpace/mySpace",
"pathName": "subpages/mine/mySpace/mySpace",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "subpages/space/reserve/reserve",
"pathName": "subpages/space/reserve/reserve",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "subpages/space/list/list",
"pathName": "subpages/space/list/list",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "pages/serve/serve",
"pathName": "pages/serve/serve",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "subpages/mine/editUser/editUser",
"pathName": "subpages/mine/editUser/editUser",
"query": "",
"launchMode": "default",
"scene": null
},
{ {
"name": "pages/noData/noData", "name": "pages/noData/noData",
"pathName": "pages/noData/noData", "pathName": "pages/noData/noData",

182
subpages/mine/mySpace/mySpace.js

@ -0,0 +1,182 @@
// subpages/mine/mySpace/mySpace.js
import { appointmentRecList } from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
list: [],
pageNum: 1,
pageSize: 10,
total: 0,
loading: false,
refreshing: false,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
this.setData({
list: [],
pageNum: 1,
});
this.getList();
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
this.setData({
refreshing: true,
pageNum: 1,
list: []
});
this.getList().finally(() => {
wx.stopPullDownRefresh();
this.setData({
refreshing: false
});
});
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {},
toReserve(e) {
wx.navigateTo({
url: `/subpages/space/reserve/reserve?id=${e.currentTarget.dataset.item.id}`,
});
},
getList() {
if (this.data.loading) return;
this.setData({
loading: true
});
let parm = {
pageSize: this.data.pageSize,
pageNum: this.data.pageNum,
};
return appointmentRecList(parm)
.then((res) => {
if (res.code === 200) {
const newData = res.data.records.map((item) => {
return {
...item,
// 格式化预约日期和时间
appointmentDate: item.appointmentDate || "",
appointTime: item.appointTime || "",
// 添加状态显示
statusText: this.getStatusText(item),
statusColor: this.getStatusColor(item)
};
});
this.setData({
list: this.data.pageNum === 1 ? newData : this.data.list.concat(newData),
total: res.data.total,
loading: false
});
}
})
.catch((err) => {
this.setData({
loading: false
});
wx.showToast({
title: err.msg || "获取数据失败",
duration: 2000,
icon: "none",
});
});
},
scrolltolower() {
if (this.data.loading) return;
if (this.data.list.length < this.data.total) {
this.setData({
pageNum: this.data.pageNum + 1,
});
this.getList();
} else if (this.data.list.length > 0) {
wx.showToast({
icon: "none",
title: "没有更多了",
});
}
},
toEvaluate(e) {
wx.navigateTo({
url: `/subpages/mine/evaluate/evaluate?id=${
e.currentTarget.dataset.item.checkInRecId
}&obj=${JSON.stringify({
apartmentName: e.currentTarget.dataset.item.apartmentName,
buildingName: e.currentTarget.dataset.item.buildingName,
buildingName: e.currentTarget.dataset.item.buildingName,
roomType: e.currentTarget.dataset.item.roomType,
unitName: e.currentTarget.dataset.item.unitName,
checkInRecId: e.currentTarget.dataset.item.checkInRecId,
houseName: e.currentTarget.dataset.item.houseName,
})}`,
});
},
// 获取状态文本
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'; // 已完成 - 灰色
}
},
});

11
subpages/mine/mySpace/mySpace.json

@ -0,0 +1,11 @@
{
"usingComponents": {
"no-data": "../../../components/noData/nodata",
"van-divider": "@vant/weapp/divider/index",
"van-button": "@vant/weapp/button/index",
"van-rate": "@vant/weapp/rate/index"
},
"navigationBarTitleText": "我的共享空间",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
}

32
subpages/mine/mySpace/mySpace.wxml

@ -0,0 +1,32 @@
<!-- subpages/mine/mySpace/mySpace.wxml -->
<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>
<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="address" style="color: #666; font-size: 28rpx; margin-bottom: 10rpx;">
{{item.address}}
</view>
<view class="date" style="color: #333; font-size: 28rpx; margin-bottom: 10rpx;">
{{item.appointmentDate}} {{item.appointTime}}
</view>
<view class="status" style="color:{{item.statusColor}}; font-size: 28rpx;">
{{item.statusText}}
</view>
</view>
</view>
</view>
<!-- 加载更多提示 -->
<view class="loading-more" wx:if="{{loading}}" style="text-align: center; padding: 20rpx; color: #999;">
加载中...
</view>
</scroll-view>
<no-data isShow="{{list.length === 0 && !loading}}"></no-data>

37
subpages/mine/mySpace/mySpace.wxss

@ -0,0 +1,37 @@
/* subpages/mine/mySpace/mySpace.wxss */
.name {
font-size: 32rpx;
}
.position {
font-size: 30rpx;
line-height: 32rpx;
}
.date {
font-size: 26rpx;
color: #BFBFBF;
line-height: 40rpx;
}
.status{
font-size: 26rpx;
margin-top: 10rpx;
}
.btn {
position: relative;
}
.doc {
color: #08b3b3;
font-size: 20rpx;
}
.scroll-view {
padding: 20rpx;
box-sizing: border-box;
background: #eff0f3;
min-height: 100vh;
}

202
subpages/space/list/list.js

@ -0,0 +1,202 @@
// subpages/space/list/list.js
import { spacePage } from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
list: [],
pageNum: 1,
pageSize: 10,
total: 0,
loading: false,
hasMore: true,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
this.getList(true); // 页面显示时刷新数据
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
this.getList(true); // 下拉刷新
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
this.loadMore(); // 上拉加载更多
},
/**
* 用户点击右上角分享
*/
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}`,
});
},
getList(isRefresh = false) {
// 如果正在加载中,直接返回
if (this.data.loading) return;
// 如果是刷新,重置分页参数
if (isRefresh) {
this.setData({
pageNum: 1,
list: [],
hasMore: true,
});
}
// 如果没有更多数据,直接返回
if (!this.data.hasMore && !isRefresh) {
wx.showToast({
icon: "none",
title: "没有更多了",
});
return;
}
this.setData({ loading: true });
let parm = {
pageSize: this.data.pageSize,
pageNum: this.data.pageNum,
};
spacePage(parm)
.then((res) => {
if (res.code === 200) {
const newData = res.data.records.map((item) => {
return {
...item,
// 处理可预约周几的显示
appointmentWeekText: this.formatAppointmentWeek(
item.appointmentWeek
),
// 处理预约时间段的显示
appointmentTimeText: this.formatAppointmentTime(
item.appointmentTimeAm,
item.appointmentTimePm
),
};
});
const currentList = isRefresh ? [] : this.data.list;
const updatedList = currentList.concat(newData);
// 判断是否还有更多数据
const hasMore = newData.length === this.data.pageSize && updatedList.length < res.data.total;
this.setData({
list: updatedList,
total: res.data.total,
hasMore: hasMore,
loading: false,
});
// 如果是下拉刷新,停止刷新动画
if (isRefresh) {
wx.stopPullDownRefresh();
}
}
})
.catch((err) => {
this.setData({ loading: false });
wx.showToast({
title: err.msg || "加载失败",
duration: 2000,
icon: "none",
});
// 如果是下拉刷新,停止刷新动画
if (isRefresh) {
wx.stopPullDownRefresh();
}
});
},
scrolltolower() {
this.loadMore();
},
loadMore() {
if (!this.data.hasMore) {
wx.showToast({
icon: "none",
title: "没有更多了",
});
return;
}
// 增加页码
this.setData({
pageNum: this.data.pageNum + 1,
});
this.getList();
},
// 格式化可预约周几
formatAppointmentWeek(appointmentWeek) {
if (!appointmentWeek || !Array.isArray(appointmentWeek)) {
return "";
}
// 将中文周几转换为显示格式
const weekMap = {
: "周一",
: "周二",
: "周三",
: "周四",
: "周五",
: "周六",
: "周日",
};
return appointmentWeek.map((week) => weekMap[week] || week).join(",");
},
// 格式化预约时间段
formatAppointmentTime(appointmentTimeAm, appointmentTimePm) {
const timeSlots = [];
if (appointmentTimeAm) {
timeSlots.push(`上午 ${appointmentTimeAm}`);
}
if (appointmentTimePm) {
timeSlots.push(`下午 ${appointmentTimePm}`);
}
return timeSlots.join(" ");
},
});

11
subpages/space/list/list.json

@ -0,0 +1,11 @@
{
"usingComponents": {
"no-data": "../../../components/noData/nodata",
"van-divider": "@vant/weapp/divider/index",
"van-button": "@vant/weapp/button/index",
"van-rate": "@vant/weapp/rate/index"
},
"navigationBarTitleText": "共享空间",
"enablePullDownRefresh": true,
"onReachBottomDistance": 50
}

37
subpages/space/list/list.wxml

@ -0,0 +1,37 @@
<!-- 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="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="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>
<view class="date" wx:if="{{item.status==='5'}}">
{{item.inDate}} 至 {{item.actualOutDate}}
</view>
</view>
</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>
</view>
</view>
<!-- 加载更多提示 -->
<view wx:if="{{list.length > 0}}" class="load-more">
<view wx:if="{{loading}}" class="loading-text">
<text>加载中...</text>
</view>
</view>
</scroll-view>
<no-data isShow="{{list.length === 0 && !loading}}"></no-data>

60
subpages/space/list/list.wxss

@ -0,0 +1,60 @@
/* subpages/space/list/list.wxss */
.card{
height:280rpx ;
}
.name {
font-size: 32rpx;
}
.position{
font-size: 30rpx;
line-height: 32rpx;
}
.date {
font-size: 26rpx;
color: #BFBFBF;
line-height: 40rpx;
}
.btn{
position: relative;
}
.doc {
color: #08b3b3;
font-size: 20rpx;
}
.scroll-view {
padding: 20rpx;
box-sizing: border-box;
background: #eff0f3;
min-height: 100vh;
}
/* 加载更多样式 */
.load-more {
padding: 20rpx 0;
text-align: center;
}
.loading-text, .no-more-text {
font-size: 28rpx;
color: #999;
}
.loading-text text::before {
content: '';
display: inline-block;
width: 20rpx;
height: 20rpx;
border: 2rpx solid #ccc;
border-top-color: #0DC6C6;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 10rpx;
vertical-align: middle;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

338
subpages/space/reserve/reserve.js

@ -0,0 +1,338 @@
// subpages/space/reserve/reserve.js
import { appointment, spaceInfo } from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
bannerUrl: 'https://img.yzcdn.cn/vant/cat.jpeg',
roomName: '第一会议室',
openDate: '周一至周五',
openTimeText: '上午09:00-下午18:00',
dateList: [],
selectedDateIndex: 0,
timeSlots: [],
rangeStartIndex: -1,
rangeEndIndex: -1,
chosenText: '',
spaceDetail: null,
appointDates: [],
appointmentTimes: []
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
console.log("11",options);
this.setData({
id: options.id,
roomName: options.roomName,
openDate: options.openDate,
openTimeText: options.openTimeText,
bannerUrl: options.imgUrls,
});
this.getDetail(); // 获取详情后会自动初始化日期和时间段
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
/**
* 生命周期函数--监听页面显示
*/
onShow() {},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {},
/**
* 用户点击右上角分享
*/
onShareAppMessage() { },
// 获取详情
getDetail() {
spaceInfo({ id: this.data.id }).then(res => {
console.log(res);
if (res.code === 200 && res.data) {
this.setData({
spaceDetail: res.data,
appointDates: res.data.appointDates || [],
appointmentTimes: res.data.appointmentTimes || []
});
// 根据接口数据初始化日期和时间段
this.initDatesFromAPI();
this.initTimeSlotsFromAPI();
}
}).catch(err => {
wx.showToast({
title: err.msg || '获取详情失败',
icon: 'none'
});
})
},
initDates() {
const weekMap = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const today = new Date();
const dates = [];
for (let i = 0; i < 7; i++) {
const d = new Date(today.getFullYear(), today.getMonth(), today.getDate() + i);
const isToday = i === 0;
dates.push({
label: isToday ? '今天' : weekMap[d.getDay()],
day: d.getDate(),
date: `${d.getFullYear()}-${('0' + (d.getMonth() + 1)).slice(-2)}-${('0' + d.getDate()).slice(-2)}`,
});
}
this.setData({
dateList: dates,
selectedDateIndex: 0,
});
},
// 根据接口数据初始化日期
initDatesFromAPI() {
const { appointDates } = this.data;
if (!appointDates || appointDates.length === 0) {
this.initDates(); // 如果没有接口数据,使用默认逻辑
return;
}
const today = new Date().toISOString().split('T')[0]; // 今天的日期 YYYY-MM-DD
const dates = appointDates.map((item, index) => {
const date = new Date(item.appointDate);
const isToday = item.appointDate === today;
return {
label: isToday ? '今天' : item.week,
day: date.getDate(),
date: item.appointDate,
canAppoint: item.canAppoint,
disabled: !item.canAppoint
};
});
// 找到第一个可预约的日期作为默认选中
let defaultIndex = 0;
for (let i = 0; i < dates.length; i++) {
if (dates[i].canAppoint) {
defaultIndex = i;
break;
}
}
this.setData({
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: '' });
},
// 根据接口数据初始化时间段
initTimeSlotsFromAPI() {
const { appointmentTimes } = this.data;
if (!appointmentTimes || appointmentTimes.length === 0) {
this.initTimeSlots(); // 如果没有接口数据,使用默认逻辑
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})/);
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,
timeText: item.appointmentTime,
status: item.canAppoint ? 'available' : 'disabled'
};
});
this.setData({
timeSlots: slots,
rangeStartIndex: -1,
rangeEndIndex: -1,
chosenText: ''
});
},
selectDate(e) {
const { index } = e.currentTarget.dataset;
const selectedDate = this.data.dateList[index];
// 检查是否可预约
if (selectedDate.disabled) {
wx.showToast({
title: '该日期不可预约',
icon: 'none'
});
return;
}
this.setData({ selectedDateIndex: index });
this.initTimeSlotsFromAPI(); // 使用接口数据初始化时间段
},
toggleSlot(e) {
const { index } = e.currentTarget.dataset;
const list = this.data.timeSlots.slice();
const slot = list[index];
if (slot.status === 'disabled') return;
const { rangeStartIndex, rangeEndIndex } = this.data;
// 无选择 -> 单选
if (rangeStartIndex === -1) {
for (let i = 0; i < list.length; i++) if (list[i].status === 'selected') list[i].status = 'available';
list[index].status = 'selected';
this.setData({
timeSlots: list,
rangeStartIndex: index,
rangeEndIndex: index,
chosenText: `${slot.start} - ${slot.end}`
});
return;
}
// 已有单选
if (rangeStartIndex !== -1 && rangeEndIndex === rangeStartIndex) {
// 点击同一格 -> 清空
if (index === rangeStartIndex) {
list[index].status = 'available';
this.setData({ timeSlots: list, rangeStartIndex: -1, rangeEndIndex: -1, chosenText: '' });
return;
}
// 点击另一格 -> 扩展成区间(需避开禁用)
const start = Math.min(rangeStartIndex, index);
const end = Math.max(rangeStartIndex, index);
for (let i = start; i <= end; i++) if (list[i].status === 'disabled') {
wx.showToast({ icon: 'none', title: '所选区间包含不可预约时段' });
return;
}
for (let i = start; i <= end; i++) list[i].status = 'selected';
this.setData({
timeSlots: list,
rangeStartIndex: start,
rangeEndIndex: end,
chosenText: `${list[start].start} - ${list[end].end}`
});
return;
}
// 已有区间 -> 下一次点击无论何处都折叠为所点单格
if (rangeStartIndex !== -1 && rangeEndIndex !== -1) {
// 清空之前区间
for (let i = 0; i < list.length; i++) {
if (list[i].status === 'selected') list[i].status = 'available';
}
// 选中新点为单选
list[index].status = 'selected';
this.setData({
timeSlots: list,
rangeStartIndex: index,
rangeEndIndex: index,
chosenText: `${list[index].start} - ${list[index].end}`
});
return;
}
},
confirmReserve() {
const { rangeStartIndex, rangeEndIndex, timeSlots, selectedDateIndex, dateList, id } = this.data;
if (rangeStartIndex === -1) {
wx.showToast({ icon: 'none', title: '请先选择预约时段' });
return;
}
const start = rangeStartIndex;
const end = rangeEndIndex === -1 ? rangeStartIndex : rangeEndIndex;
const selectedDate = dateList[selectedDateIndex];
const startSlot = timeSlots[start];
const endSlot = timeSlots[end];
// 收集选中的时间段ID
const selectedTimeIds = [];
for (let i = start; i <= end; i++) {
if (timeSlots[i].apiId) {
selectedTimeIds.push(timeSlots[i].apiId);
}
}
const appointmentData = {
shareSpaceId: id,
appointmentDate: selectedDate.date,
timeIds: selectedTimeIds,
};
console.log('预约数据:', appointmentData);
// 调用预约接口
appointment(appointmentData).then(res => {
if (res.code === 200) {
wx.showToast({
title: '预约成功',
icon: 'success'
});
// 可以跳转到预约成功页面或返回上一页
setTimeout(() => {
wx.navigateBack();
}, 1500);
} else {
wx.showToast({
title: res.msg || '预约失败',
icon: 'none'
});
}
}).catch(err => {
wx.showToast({
title: err.msg || '预约失败',
icon: 'none'
});
});
}
})

8
subpages/space/reserve/reserve.json

@ -0,0 +1,8 @@
{
"usingComponents": {
"van-image": "@vant/weapp/image/index",
"van-divider": "@vant/weapp/divider/index",
"van-button": "@vant/weapp/button/index",
"van-tag": "@vant/weapp/tag/index"
}
}

35
subpages/space/reserve/reserve.wxml

@ -0,0 +1,35 @@
<!-- subpages/space/reserve/reserve.wxml -->
<view class="page">
<view class="banner">
<van-image width="100%" height="360rpx" src="{{bannerUrl}}" fit="cover" radius="0" />
</view>
<view class=" banner-overlay">
<view class="room-name">{{roomName}}</view>
<view class="open-time">{{openDate}}</view>
<view class="open-time">{{openTimeText}}</view>
</view>
<view class="section">
<scroll-view scroll-x class="date-strip">
<view class="date-item {{selectedDateIndex === index ? 'active' : ''}} {{item.disabled ? 'disabled' : ''}}" wx:for="{{dateList}}" wx:key="index" data-index="{{index}}" bindtap="selectDate">
<view class="date-label">{{item.label}}</view>
<view class="date-day">{{item.day}}</view>
</view>
</scroll-view>
<view class="section-title">预约时段</view>
<view class="slot-grid">
<view wx:for="{{timeSlots}}" wx:key="index" class="slot {{item.status}}" data-index="{{index}}" bindtap="toggleSlot">
<view class="slot-line">{{item.start}}</view>
<view class="slot-sep">至</view>
<view class="slot-line">{{item.end}}</view>
</view>
</view>
<view class="chosen" wx:if="{{chosenText}}">已选择:{{chosenText}}</view>
</view>
<view class="footer">
<van-button type="primary" block round color="linear-gradient(90deg, #0DC6C6, #13C2C2, #46DBD5)" custom-style="width:400rpx;height:76rpx;" bind:click="confirmReserve">
确定
</van-button>
</view>
</view>

131
subpages/space/reserve/reserve.wxss

@ -0,0 +1,131 @@
/* subpages/space/reserve/reserve.wxss */
.page {
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;
padding: 18rpx;
background: #fff;
border-radius: 20rpx;
}
.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{
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;
align-items: center;
justify-content: center;
width: 100rpx;
height: 120rpx;
border-radius: 16rpx;
color: #666;
margin-right: 16rpx;
}
.date-item .date-label {
font-size: 26rpx;
}
.date-item .date-day {
margin-top: 8rpx;
width: 56rpx;
height: 56rpx;
line-height: 56rpx;
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;
margin-top: 12rpx;
}
.slot {
width: calc(25% - 16rpx);
margin-right: 16rpx;
margin-top: 16rpx;
border-radius: 16rpx;
padding: 12rpx 0;
text-align: center;
background: #f7f8fa;
color: #000;
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{
margin-top: 20rpx;
color: #13c2c2;
font-size: 26rpx;
}
.footer {
padding: 24rpx;
}
Loading…
Cancel
Save