From 30c3e151e18c6464814385a9442e393f72737e7c Mon Sep 17 00:00:00 2001
From: wangyx <2838268875@qq.com>
Date: Wed, 20 Aug 2025 18:03:01 +0800
Subject: [PATCH] =?UTF-8?q?=E5=85=B1=E4=BA=AB=E7=A9=BA=E9=97=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
api/index.js | 16 ++
app.json | 15 +-
custom-tab-bar/index.js | 14 +-
pages/index/index.js | 7 +-
pages/mine/mine.js | 8 +-
pages/serve/serve.js | 64 +++++-
pages/serve/serve.wxml | 6 +-
project.private.config.json | 46 +++-
subpages/mine/mySpace/mySpace.js | 182 +++++++++++++++
subpages/mine/mySpace/mySpace.json | 11 +
subpages/mine/mySpace/mySpace.wxml | 32 +++
subpages/mine/mySpace/mySpace.wxss | 37 +++
subpages/space/list/list.js | 202 +++++++++++++++++
subpages/space/list/list.json | 11 +
subpages/space/list/list.wxml | 37 +++
subpages/space/list/list.wxss | 60 +++++
subpages/space/reserve/reserve.js | 338 ++++++++++++++++++++++++++++
subpages/space/reserve/reserve.json | 8 +
subpages/space/reserve/reserve.wxml | 35 +++
subpages/space/reserve/reserve.wxss | 131 +++++++++++
20 files changed, 1232 insertions(+), 28 deletions(-)
create mode 100644 subpages/mine/mySpace/mySpace.js
create mode 100644 subpages/mine/mySpace/mySpace.json
create mode 100644 subpages/mine/mySpace/mySpace.wxml
create mode 100644 subpages/mine/mySpace/mySpace.wxss
create mode 100644 subpages/space/list/list.js
create mode 100644 subpages/space/list/list.json
create mode 100644 subpages/space/list/list.wxml
create mode 100644 subpages/space/list/list.wxss
create mode 100644 subpages/space/reserve/reserve.js
create mode 100644 subpages/space/reserve/reserve.json
create mode 100644 subpages/space/reserve/reserve.wxml
create mode 100644 subpages/space/reserve/reserve.wxss
diff --git a/api/index.js b/api/index.js
index 6097067..e327d30 100644
--- a/api/index.js
+++ b/api/index.js
@@ -67,3 +67,19 @@ export function repairList(pamars) {
export function incidentsList(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);
+}
diff --git a/app.json b/app.json
index 0bcdea1..3f54aeb 100644
--- a/app.json
+++ b/app.json
@@ -29,7 +29,8 @@
"evaluate/evaluate",
"checkInEvaluate/checkInEvaluate",
"repairList/repairList",
- "eventList/eventList"
+ "eventList/eventList",
+ "mySpace/mySpace"
]
},
{
@@ -65,6 +66,13 @@
"pages": [
"signingCompleted/signingCompleted"
]
+ },{
+ "root": "subpages/space",
+ "name":"space",
+ "pages":[
+ "list/list",
+ "reserve/reserve"
+ ]
}
],
"window": {
@@ -89,6 +97,11 @@
"text": "我的",
"pagePath": "pages/mine/mine",
"iconPath": "images/icon/home.png"
+ },{
+ "text": "服务",
+ "pagePath": "pages/serve/serve",
+ "iconPath": "images/icon/serve Copy.png"
+
}
]
},
diff --git a/custom-tab-bar/index.js b/custom-tab-bar/index.js
index c5cc6d3..8e0a8da 100644
--- a/custom-tab-bar/index.js
+++ b/custom-tab-bar/index.js
@@ -22,13 +22,13 @@ Component({
// selectedIconPath: "/images/icon/message-a.png",
// text: "消息",
// },
- // {
- // pagePath: "/pages/serve/serve",
- // iconPath: "/images/icon/serve-a.png",
- // selectedIconPath: "/images/icon/serve.png",
- // bulge:false,
- // text: "服务",
- // },
+ {
+ pagePath: "/pages/serve/serve",
+ iconPath: "/images/icon/serve-a.png",
+ selectedIconPath: "/images/icon/serve.png",
+ bulge:false,
+ text: "服务",
+ },
// {
// pagePath: "/pages/life/life",
// iconPath: "/images/icon/life.png",
diff --git a/pages/index/index.js b/pages/index/index.js
index 993dc7c..802b600 100644
--- a/pages/index/index.js
+++ b/pages/index/index.js
@@ -57,7 +57,8 @@ Page({
searchValue: "",
policyList:[],//政策列表
getUserInfo:{},
- bindPhone:false
+ bindPhone:false,
+ userInfo: {}
},
/**
@@ -221,7 +222,7 @@ Page({
})
}else if(e.currentTarget.dataset.url === '/subpages/OCRCard/pages/index/index'){
if(!this.data.bindPhone){
- if(this.data.userInfo.idCard){
+ if(this.data.userInfo && this.data.userInfo.idCard){
this.selectMzGraduateInfo({idCard:this.data.userInfo.idCard})
}else{
wx.navigateTo({
@@ -235,7 +236,7 @@ Page({
}
}else if(e.currentTarget.dataset.url === '/subpages/index/checkOutConfirm/index/index'){
if(!this.data.bindPhone){
- if(this.data.userInfo.idCard){
+ if(this.data.userInfo && this.data.userInfo.idCard){
wx.navigateTo({
url: `/subpages/index/checkOutConfirm/index/index`,
})
diff --git a/pages/mine/mine.js b/pages/mine/mine.js
index 4deaab0..b3dfa68 100644
--- a/pages/mine/mine.js
+++ b/pages/mine/mine.js
@@ -29,10 +29,10 @@ Page({
label:'问题反馈',
url:'/subpages/mine/eventList/eventList'
},
- // {
- // label:'共享空间',
- // url:''
- // }
+ {
+ label:'共享空间',
+ url:'/subpages/mine/mySpace/mySpace'
+ }
],
registerFlag:false
},
diff --git a/pages/serve/serve.js b/pages/serve/serve.js
index e2ca39f..a318dad 100644
--- a/pages/serve/serve.js
+++ b/pages/serve/serve.js
@@ -1,13 +1,16 @@
// pages/serve/serve.js
const app = getApp()
+import { getUserInfo as fetchUserInfo } from "../../api/user";
+import { selectMzGraduateInfo } from "../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
-
+ userInfo: {},
+ bindPhone: false,
},
/**
@@ -31,7 +34,7 @@ Page({
* 生命周期函数--监听页面显示
*/
onShow() {
-
+ this.getUserInfo()
},
/**
@@ -67,13 +70,55 @@ Page({
*/
onShareAppMessage() {
+ },
+ getUserInfo() {
+ fetchUserInfo().then((res) => {
+ app.globalData.userInfo = res.data;
+ this.setData({
+ userInfo: res.data,
+ bindPhone: !Boolean(res.data && res.data.phone)
+ });
+ })
},
toEventAdd(){
wx.navigateTo({
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){
+ if (!wx.getStorageSync('token')) {
+ return
+ }
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 === '/pages/serve/serve'){
@@ -86,10 +131,8 @@ Page({
})
}else if(e.currentTarget.dataset.url === '/subpages/OCRCard/pages/index/index'){
if(!this.data.bindPhone){
- if(this.data.userInfo.idCard){
- wx.navigateTo({
- url: `/subpages/index/checkInUser/checkInUser?idCard=${this.data.userInfo.idCard}&name=${this.data.userInfo.name}&phone=${this.data.userInfo.phone}`,
- })
+ if(this.data.userInfo && this.data.userInfo.idCard){
+ this.selectMzGraduateInfo({ idCard: this.data.userInfo.idCard })
}else{
wx.navigateTo({
url: `/subpages/OCRCard/pages/index/index`,
@@ -102,7 +145,7 @@ Page({
}
}else if(e.currentTarget.dataset.url === '/subpages/index/checkOutConfirm/index/index'){
if(!this.data.bindPhone){
- if(this.data.userInfo.idCard){
+ if(this.data.userInfo && this.data.userInfo.idCard){
wx.navigateTo({
url: `/subpages/index/checkOutConfirm/index/index`,
})
@@ -122,5 +165,10 @@ Page({
wx.navigateTo({
url: '/subpages/bsPage/bsPage/bsPage',
})
- }
+ },
+ toYuyue(){
+ wx.navigateTo({
+ url: '/subpages/space/list/list',
+ })
+ }
})
\ No newline at end of file
diff --git a/pages/serve/serve.wxml b/pages/serve/serve.wxml
index 03dfd70..2632c69 100644
--- a/pages/serve/serve.wxml
+++ b/pages/serve/serve.wxml
@@ -40,12 +40,12 @@
去报事
-->
-
+
\ No newline at end of file
diff --git a/project.private.config.json b/project.private.config.json
index 2ba5663..fa28701 100644
--- a/project.private.config.json
+++ b/project.private.config.json
@@ -15,12 +15,54 @@
"miniprogram": {
"list": [
{
- "name": "subpages/mine/editUser/editUser",
- "pathName": "subpages/mine/editUser/editUser",
+ "name": "subpages/mine/mySpace/mySpace",
+ "pathName": "subpages/mine/mySpace/mySpace",
"query": "",
"scene": null,
"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",
"pathName": "pages/noData/noData",
diff --git a/subpages/mine/mySpace/mySpace.js b/subpages/mine/mySpace/mySpace.js
new file mode 100644
index 0000000..e27afc7
--- /dev/null
+++ b/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'; // 已完成 - 灰色
+ }
+ },
+});
\ No newline at end of file
diff --git a/subpages/mine/mySpace/mySpace.json b/subpages/mine/mySpace/mySpace.json
new file mode 100644
index 0000000..8310f18
--- /dev/null
+++ b/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"
+}
diff --git a/subpages/mine/mySpace/mySpace.wxml b/subpages/mine/mySpace/mySpace.wxml
new file mode 100644
index 0000000..56f4863
--- /dev/null
+++ b/subpages/mine/mySpace/mySpace.wxml
@@ -0,0 +1,32 @@
+
+
+
+
+ {{item.apartmentName}}
+
+
+
+
+
+
+ {{item.name}}
+
+
+ {{item.address}}
+
+
+ {{item.appointmentDate}} {{item.appointTime}}
+
+
+ {{item.statusText}}
+
+
+
+
+
+
+
+ 加载中...
+
+
+
\ No newline at end of file
diff --git a/subpages/mine/mySpace/mySpace.wxss b/subpages/mine/mySpace/mySpace.wxss
new file mode 100644
index 0000000..87611fe
--- /dev/null
+++ b/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;
+}
\ No newline at end of file
diff --git a/subpages/space/list/list.js b/subpages/space/list/list.js
new file mode 100644
index 0000000..13ac693
--- /dev/null
+++ b/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(" ");
+ },
+});
diff --git a/subpages/space/list/list.json b/subpages/space/list/list.json
new file mode 100644
index 0000000..9247526
--- /dev/null
+++ b/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
+}
diff --git a/subpages/space/list/list.wxml b/subpages/space/list/list.wxml
new file mode 100644
index 0000000..b8c4d98
--- /dev/null
+++ b/subpages/space/list/list.wxml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+ {{item.appointmentWeekText}}
+ {{item.appointmentTimeText}}
+ {{item.inDate}} 至 {{item.outDate}}
+
+ {{item.inDate}} 至 {{item.actualOutDate}}
+
+
+
+
+
+
+ 预约
+
+
+
+
+
+
+
+ 加载中...
+
+
+
+
+
\ No newline at end of file
diff --git a/subpages/space/list/list.wxss b/subpages/space/list/list.wxss
new file mode 100644
index 0000000..9afccee
--- /dev/null
+++ b/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); }
+}
\ No newline at end of file
diff --git a/subpages/space/reserve/reserve.js b/subpages/space/reserve/reserve.js
new file mode 100644
index 0000000..6b1604b
--- /dev/null
+++ b/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'
+ });
+ });
+ }
+})
\ No newline at end of file
diff --git a/subpages/space/reserve/reserve.json b/subpages/space/reserve/reserve.json
new file mode 100644
index 0000000..cbae814
--- /dev/null
+++ b/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"
+ }
+}
\ No newline at end of file
diff --git a/subpages/space/reserve/reserve.wxml b/subpages/space/reserve/reserve.wxml
new file mode 100644
index 0000000..00ec3ee
--- /dev/null
+++ b/subpages/space/reserve/reserve.wxml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ {{roomName}}
+ {{openDate}}
+ {{openTimeText}}
+
+
+
+
+
+ {{item.label}}
+ {{item.day}}
+
+
+ 预约时段
+
+
+ {{item.start}}
+ 至
+ {{item.end}}
+
+
+
+ 已选择:{{chosenText}}
+
+
+
\ No newline at end of file
diff --git a/subpages/space/reserve/reserve.wxss b/subpages/space/reserve/reserve.wxss
new file mode 100644
index 0000000..932ac8b
--- /dev/null
+++ b/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;
+}
\ No newline at end of file