Bladeren bron

新增讲解服务和在线展览

wangfumin 3 maanden geleden
bovenliggende
commit
98e0bb25db

+ 2 - 1
app.json

@@ -18,7 +18,8 @@
     "pages/index/news/news",
     "pages/user/feedback/index",
     "pages/user/map/index",
-    "pages/exhibition/activeDetails/index"
+    "pages/exhibition/activeDetails/index",
+    "pages/index/online/index"
   ],
   "subPackages": [
     {

BIN
imgs/icon_online.png


+ 22 - 1
pages/exhibition/activeDetails/index.js

@@ -15,7 +15,8 @@ Page({
     shouldShowBackButton: true,
     isPreviewMode: false,
     formattedPublishTime: '',
-    isLoggedIn: false
+    isLoggedIn: false,
+    isExpired: false
   },
 
   /**
@@ -236,12 +237,14 @@ Page({
           // const content = this.getContentForParsing(response);
           // const parsedContent = this.parseContent(content);
           let article = response.context;
+          const isExpired = that.isActivityExpired(response.endTime);
           WxParse.wxParse('article', 'html', article, that, 5);
           // 格式化发布时间
           const formattedTime = this.formatTimeWithDash(response.publish);
           
           this.setData({
             detailData: response,
+            isExpired: isExpired,
             // contentItems: parsedContent,
             formattedPublishTime: formattedTime
           });
@@ -264,6 +267,24 @@ Page({
       });
   },
 
+  // 检查活动是否已过期(按日期比较)
+  isActivityExpired(endTime) {
+    if (!endTime) return false;
+    
+    const today = new Date();
+    const activityEndDate = new Date(endTime);
+    
+    // 只比较日期,忽略具体时间
+    const todayDateString = today.getFullYear() + '-' + 
+      String(today.getMonth() + 1).padStart(2, '0') + '-' + 
+      String(today.getDate()).padStart(2, '0');
+    
+    const endDateString = activityEndDate.getFullYear() + '-' + 
+      String(activityEndDate.getMonth() + 1).padStart(2, '0') + '-' + 
+      String(activityEndDate.getDate()).padStart(2, '0');
+    // 如果活动结束日期小于今天,则认为已过期
+    return endDateString < todayDateString;
+  },
   /**
    * 获取用于解析的内容
    */

+ 1 - 1
pages/exhibition/activeDetails/index.wxml

@@ -55,7 +55,7 @@
     </view>
     
     <!-- 活动预约按钮 -->
-    <view wx:if="{{detailData.subscribe === 1 && fromtype == 'activity' && isLoggedIn}}" class="active-preview-btn">
+    <view wx:if="{{detailData.subscribe === 1 && !isExpired && fromtype == 'activity' && isLoggedIn}}" class="active-preview-btn">
       <view class="preview-btn" bindtap="goToActivePreview">
         活动预约
       </view>

+ 46 - 1
pages/index/active-people/active-people.js

@@ -11,7 +11,9 @@ Page({
     showSuccessModal: false,
     isFormValid: false,
     idTypes: [{value: 1, name: '身份证'}],
-    existingVisitors: [] // 我的联系人列表
+    existingVisitors: [], // 我的联系人列表
+    appointmentServices: [], // 讲解服务列表
+    selectedServiceId: 0 // 选中的讲解服务ID,默认为0(不需要讲解服务)
   },
 
   onLoad(options) {
@@ -44,6 +46,9 @@ Page({
     
     // 加载已有参观人数据
     this.loadExistingVisitors();
+    
+    // 加载讲解服务列表
+    this.loadAppointmentServices();
   },
 
   // 新增参观人
@@ -264,6 +269,45 @@ Page({
       existingVisitors[index].selected = !existingVisitors[index].selected;
       this.setData({
         existingVisitors: existingVisitors
+        });
+    },
+
+    // 加载讲解服务列表
+    loadAppointmentServices() {
+      museumApi.getAppointmentServiceList()
+        .then(response => {
+          console.log('获取讲解服务列表成功:', response);
+          if (response && response.length > 0) {
+            // 确保第一个是"不需要讲解服务"
+            const services = response;
+            // 默认选中第一个服务(通常是"不需要讲解服务")
+            this.setData({ 
+              appointmentServices: services,
+              selectedServiceId: services[0].id
+            });
+          }
+        })
+        .catch(error => {
+          console.error('获取讲解服务列表失败:', error);
+          // 如果接口失败,使用默认数据
+          const defaultServices = [
+            { id: 0, name: '不需要讲解服务', price: 0 },
+            { id: 1, name: '展厅基本列', price: 120 },
+            { id: 2, name: '展厅基本列、黑油山地貌、外景文物', price: 150 },
+            { id: 3, name: '展厅基本列、黑油山地貌、外景文物、临展厅', price: 180 }
+          ];
+          this.setData({ 
+            appointmentServices: defaultServices,
+            selectedServiceId: defaultServices[0].id
+          });
+        });
+    },
+
+    // 选择讲解服务
+    selectAppointmentService(e) {
+      const serviceId = e.currentTarget.dataset.serviceId;
+      this.setData({
+        selectedServiceId: parseInt(serviceId)
       });
     },
 
@@ -326,6 +370,7 @@ Page({
         activityId: this.data.activityId || 0,
         appointmentSlotsId: this.data.appointmentSlotsId || 0,
         appointmentTime: this.data.selectedDate,
+        appointmentServiceId: this.data.selectedServiceId, // 添加讲解服务ID
         type: this.data.type,
         visitors: this.data.visitors.map(visitor => ({
           cardType: this.data.idTypes[visitor.idTypeIndex].value,

+ 23 - 1
pages/index/active-people/active-people.wxml

@@ -4,7 +4,7 @@
     <image class="bg-img" src="https://klmybwg.4dage.com/mini/wxImg/indexPage/img.png" mode="aspectFill"></image>
     <view class="date-content">
       <view class="date-label"><text class="title">预约日期:</text>{{selectedDate}}</view>
-      <view class="time-label"><text class="title">活动标题:</text>{{title}}</view>
+      <view class="time-label"><text class="title">活动标题:</text><view class="title-content">{{title}}</view></view>
     </view>
   </view>
 
@@ -93,6 +93,28 @@
       </view>
     </scroll-view>
 
+    <!-- 讲解服务 -->
+    <view class="service-section" wx:if="{{appointmentServices && appointmentServices.length}}">
+      <view class="service-title"><text class="border-fix"></text>讲解服务</view>
+      <view class="service-list">
+        <view 
+          wx:for="{{appointmentServices}}" 
+          wx:key="id" 
+          class="service-item {{selectedServiceId === item.id ? 'selected' : ''}}"
+          bindtap="selectAppointmentService"
+          data-service-id="{{item.id}}"
+        >
+          <view class="service-content">
+            <view class="service-name">{{item.context}}</view>
+            <view class="service-price" wx:if="{{item.remark > 0}}">收费{{item.remark}}元</view>
+          </view>
+          <view class="service-checkbox {{selectedServiceId === item.id ? 'checked' : ''}}">
+            <text class="check-icon" wx:if="{{selectedServiceId === item.id}}">✓</text>
+          </view>
+        </view>
+      </view>
+    </view>
+
     <!-- 下一步按钮 -->
     <view class="next-button-container">
       <view class="next-btn {{!isFormValid ? 'disabled' : ''}}" bindtap="submitReservation" disabled="{{!isFormValid}}">下一步</view>

+ 100 - 8
pages/index/active-people/active-people.wxss

@@ -1,16 +1,21 @@
 .visit-people-container {
-  height: 97vh;
+  height: 100vh;
   background: url('https://klmybwg.4dage.com/mini/wxImg/bg.png');
-  padding: 32rpx;
   padding-bottom: 0;
   overflow: hidden;
 }
 
+.main-content{
+  height: calc(100vh - 320rpx - 64rpx);
+  overflow-y: auto;
+  padding: 0 36rpx;
+}
 .date-info {
   height: 212rpx;
   position: relative;
   margin: 4rpx;
   margin-top: 0;
+  padding: 30rpx 30rpx 0 30rpx;
 }
 
 .bg-img {
@@ -20,8 +25,8 @@
 
 .date-content {
   position: absolute;
-  width: 70%;
-  top: 40rpx;
+  width: 80%;
+  top: 65rpx;
   left: 70rpx;
   background: rgba(255, 255, 255, 0.9);
   border-radius: 16rpx;
@@ -29,19 +34,27 @@
 }
 
 .date-label, .time-label {
+  display: flex;
   font-size: 32rpx;
   color: #333;
   margin: 10rpx 0;
 }
 
+.title-content{
+  width: 400rpx;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
 .title {
+  width: 30%;
   color: #B1967B;
 }
 
 .action-buttons {
   display: flex;
   gap: 20rpx;
-  padding: 0 32rpx;
   margin-bottom: 40rpx;
 }
 
@@ -65,9 +78,7 @@
 }
 
 .visitor-list {
-  height: calc(100vh - 460rpx - 64rpx);
-  overflow-y: auto;
-  padding-bottom: 20rpx;
+
 }
 
 .visitor-card {
@@ -187,6 +198,87 @@
   background: #ccc;
 }
 
+/* 讲解服务样式 */
+.service-section {
+  padding: 10rpx;
+  margin-bottom: 30rpx;
+}
+.border-fix{
+  display: inline-block;
+  height: 40rpx;
+  width: 12rpx;
+  background: #A5886B;
+  margin-right: 26rpx;
+}
+.service-title {
+  display: flex;
+  align-items: center;
+  height: 80rpx;
+  font-size: 38rpx;
+  font-weight: bold;
+  color: #A5886B;
+  margin-bottom: 20rpx;
+}
+
+.service-list {
+  display: flex;
+  flex-direction: column;
+  gap: 20rpx;
+}
+
+.service-item {
+  position: relative;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 30rpx;
+  border: 2rpx solid rgba(91,71,46,0.5);
+  border-radius: 10rpx;
+  background: rgba(177,150,123,0.3);
+  transition: all 0.3s ease;
+}
+
+.service-item.selected {
+  background: none;
+  border: 1px solid rgba(91,71,46,0.5);
+}
+
+.service-content {
+  flex: 1;
+}
+
+.service-name {
+  font-size: 28rpx;
+  color: #5B472E;
+}
+
+.service-price {
+  font-size: 22rpx;
+  color: #5B472E;
+}
+
+.service-checkbox {
+  position: absolute;
+  right: 0;
+  top: 0;
+  width: 42rpx;
+  height: 42rpx;
+  border-radius: 0 10rpx 0 10rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 28rpx;
+  color: white;
+  background: transparent;
+}
+
+.service-checkbox.checked {
+  background: #AA9D8B;
+}
+.check-icon{
+  font-size: 28rpx;
+}
+
 /* 选择已有参观人页面样式 */
 .existing-page {
   padding: 32rpx;

+ 59 - 12
pages/index/activity/activity.js

@@ -6,35 +6,67 @@ Page({
   data: {
     activeList: [],
     loading: false,
-    urlImg: urlImg
+    urlImg: urlImg,
+    currentPage: 1,
+    pageSize: 10,
+    hasMore: true,
+    loadingMore: false
   },
 
   onLoad() {
-    this.getActivityList();
+    this.getActivityList(true);
   },
 
   onPullDownRefresh() {
-    this.getActivityList();
+    this.getActivityList(true);
+  },
+
+  // 页面滚动到底部时触发
+  onReachBottom() {
+    if (this.data.hasMore && !this.data.loadingMore) {
+      this.loadMore();
+    }
   },
 
   // 获取活动列表
-  async getActivityList() {
-    this.setData({ loading: true });
+  async getActivityList(isRefresh = false) {
+    const page = isRefresh ? 1 : this.data.currentPage;
+    
+    if (isRefresh) {
+      this.setData({ loading: true });
+    } else {
+      this.setData({ loadingMore: true });
+    }
     
     try {
       const response = await museumApi.getSocialActivityList({
-        pageNum: 1,
-        pageSize: 10,
+        pageNum: page,
+        pageSize: this.data.pageSize,
         status: 1
       });
       
-      if (response && response.records) {
+      console.log('活动数据:', response);
+      
+      // 获取活动数据并进行筛选
+      let activeList = response.records || response.list || response.data || response || [];
+      
+      // 筛选有效的活动数据 - 确保有activityId和title
+      activeList = activeList.filter(item => {
+        return item && item.activityId && item.title;
+      });
+
+      if (isRefresh) {
+        // 刷新时替换数据
         this.setData({
-          activeList: response.records
+          activeList,
+          currentPage: 1,
+          hasMore: activeList.length >= this.data.pageSize
         });
       } else {
+        // 加载更多时追加数据
         this.setData({
-          activeList: []
+          activeList: [...this.data.activeList, ...activeList],
+          hasMore: activeList.length >= this.data.pageSize
         });
       }
     } catch (error) {
@@ -43,12 +75,27 @@ Page({
         title: '加载失败',
         icon: 'none'
       });
+      if (isRefresh) {
+        this.setData({ activeList: [] });
+      }
     } finally {
-      this.setData({ loading: false });
-      wx.stopPullDownRefresh();
+      this.setData({ 
+        loading: false,
+        loadingMore: false
+      });
+      if (isRefresh) {
+        wx.stopPullDownRefresh();
+      }
     }
   },
 
+  // 加载更多数据
+  loadMore() {
+    const nextPage = this.data.currentPage + 1;
+    this.setData({ currentPage: nextPage });
+    this.getActivityList(false);
+  },
+
   // 返回首页
   goBack() {
     wx.navigateBack();

+ 20 - 11
pages/index/activity/activity.wxml

@@ -12,20 +12,29 @@
     <view class="loading-text">加载中...</view>
   </view>
   <view wx:else class="content-section">
-    <view class="collection-list">
-      <view class="collection-item" wx:for="{{activeList}}" wx:key="activityId" bindtap="viewActivity" data-item="{{item}}">
-        <view class="item-image-container">
-          <image src="{{urlImg + item.infoImg}}" class="item-image" mode="aspectFill" />
-          <view class="view-button">
-            <text>查看</text>
-            <text class="arrow">></text>
-          </view>
-          <view class="item-info">
-            <view class="item-title">{{ item.title || '暂无标题' }}</view>
-            <view class="item-description">{{ item.remark || '暂无描述' }}</view>
+    <view wx:if="{{activeList && activeList.length > 0}}">
+      <view class="collection-list">
+        <view class="collection-item" wx:for="{{activeList}}" wx:key="activityId" bindtap="viewActivity" data-item="{{item}}">
+          <view class="item-image-container">
+            <image src="{{urlImg + item.infoImg}}" class="item-image" mode="aspectFill" />
+            <view class="view-button">
+              <text>查看</text>
+              <text class="arrow">></text>
+            </view>
+            <view class="item-info">
+              <view class="item-title">{{ item.title || '暂无标题' }}</view>
+              <view class="item-description">{{ item.remark || '暂无描述' }}</view>
+            </view>
           </view>
         </view>
       </view>
+      <!-- 加载更多提示 -->
+      <view wx:if="{{loadingMore}}" class="loading-more">
+        <view class="loading-text">加载中...</view>
+      </view>
+      <view wx:elif="{{!hasMore && activeList.length > 0}}" class="no-more">
+        <view class="no-more-text">没有更多数据了</view>
+      </view>
     </view>
     <!-- 空状态 -->
     <view wx:if="{{activeList.length === 0}}" class="empty-state">

+ 21 - 0
pages/index/activity/activity.wxss

@@ -144,4 +144,25 @@
   font-size: 36rpx;
   color: #584735;
   opacity: 0.6;
+}
+
+/* 加载更多样式 */
+.loading-more {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 40rpx 0;
+}
+
+.no-more {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 40rpx 0;
+}
+
+.no-more-text {
+  font-size: 28rpx;
+  color: #584735;
+  opacity: 0.6;
 }

+ 5 - 0
pages/index/index.js

@@ -241,6 +241,11 @@ Page({
       case 'introduce':
         this.navigateToWebview('/allDetailsShow?id=1&type=museum');
         break;
+      case 'online':
+        wx.navigateTo({
+          url: '/pages/index/online/index',
+        })
+        break;
     }
   },
 

+ 8 - 4
pages/index/index.wxml

@@ -39,6 +39,10 @@
         <image src="https://klmybwg.4dage.com/mini/wxImg/indexPage/introduce.png" alt="展馆介绍" class="function-icon"></image>
         <text class="function-text">展馆介绍</text>
       </view>
+      <view class="function-item" bindtap="handleFunctionClick" data-type="online">
+        <image src="/imgs/icon_online.png" alt="线上展览" class="function-icon"></image>
+        <text class="function-text">线上展览</text>
+      </view>
     </view>
 
     <!-- 展览资讯 -->
@@ -68,7 +72,7 @@
         <text class="view-more" bindtap="viewMore" data-section="exhibition">查看更多 +</text>
       </view>
       <view wx:if="{{exhibitionList && exhibitionList.length > 0}}">
-        <scroll-view class="scroll-container" scroll-x="{{true}}">
+        <view class="scroll-container" >
           <view class="scroll-wrapper">
             <view class="exhibition-item" wx:for="{{exhibitionList}}" wx:key="exhibitId" bindtap="viewExhibition" data-item="{{item}}">
               <image src="{{urlImg + item.img}}" alt="展览" class="exhibition-img" mode="aspectFill"></image>
@@ -77,7 +81,7 @@
               </view>
             </view>
           </view>
-        </scroll-view>
+        </view>
       </view>
       <view wx:else class="empty-data">
         <text class="empty-text">暂无数据</text>
@@ -91,8 +95,8 @@
         <text class="view-more" bindtap="viewMore" data-section="activity">查看更多 +</text>
       </view>
       <view wx:if="{{activeList && activeList.length > 0}}">
-        <scroll-view class="scroll-container" scroll-x="{{true}}">
-          <view class="scroll-wrapper">
+        <scroll-view class="scroll-container2" scroll-x="{{true}}">
+          <view class="scroll-wrapper2">
             <view class="activity-item" wx:for="{{activeList}}" wx:key="activityId" bindtap="viewActivity" data-item="{{item}}">
               <view class="active-top">
                 <image src="{{urlImg + item.indexImg}}" alt="活动" class="activity-img" mode="aspectFill"></image>

+ 11 - 8
pages/index/index.wxss

@@ -54,7 +54,7 @@
   display: flex;
   flex-direction: column;
   align-items: center;
-  width: 22%;
+  width: 18%;
 }
 
 .function-item-disabled {
@@ -62,8 +62,8 @@
 }
 
 .function-icon {
-  width: 112rpx;
-  height: 112rpx;
+  width: 100rpx;
+  height: 100rpx;
   margin-bottom: 10rpx;
 }
 
@@ -72,7 +72,7 @@
 }
 
 .function-text {
-  font-size: 32rpx;
+  font-size: 28rpx;
   color: #B1967B;
 }
 
@@ -167,24 +167,27 @@
 }
 
 /* 滚动容器 */
-.scroll-container {
+.scroll-container2 {
   white-space: nowrap;
 }
 
-.scroll-wrapper {
+.scroll-wrapper2 {
   display: inline-flex;
   padding-bottom: 10rpx;
 }
+.scroll-wrapper {
+  padding-bottom: 10rpx;
+}
 
 /* 展览项 */
 .exhibition-item {
   position: relative;
   flex: 0 0 auto;
   width: 650rpx;
-  height: 412rpx;
-  margin-right: 20rpx;
+  height: 176rpx;
   border-radius: 16rpx;
   overflow: hidden;
+  margin-bottom: 20rpx;
 }
 
 .exhibition-item:last-child {

+ 129 - 0
pages/index/online/index.js

@@ -0,0 +1,129 @@
+// pages/index/activity/activity.js
+const { museumApi } = require('../../../utils/api.js');
+const { navigateToWebview, urlImg } = require('../../../utils/util.js');
+
+Page({
+  data: {
+    exhibitionList: [], // 展览列表
+    loading: false,
+    urlImg: urlImg,
+    currentPage: 1,
+    pageSize: 10,
+    hasMore: true,
+    loadingMore: false
+  },
+
+  onLoad() {
+    this.getExhibitionList(true);
+  },
+
+  onPullDownRefresh() {
+    this.getExhibitionList(true);
+  },
+
+  // 页面滚动到底部时触发
+  onReachBottom() {
+    if (this.data.hasMore && !this.data.loadingMore) {
+      this.loadMore();
+    }
+  },
+
+    /**
+   * 获取展览列表
+   */
+    async getExhibitionList(isRefresh = false, params = {}) {
+        const page = isRefresh ? 1 : this.data.currentPage;
+        
+        if (isRefresh) {
+          this.setData({ loading: true });
+        } else {
+          this.setData({ loadingMore: true });
+        }
+
+        try {
+          const response = await museumApi.getExhibitionList({
+            pageNum: page,
+            pageSize: this.data.pageSize,
+            status: 1,
+            ...params
+          });
+          
+          console.log('展览数据:', response);
+          
+          // 获取展览数据并进行筛选
+          let exhibitionList = response.records || response.list || response.data || response || [];
+          
+          // 筛选有效的展览数据 - 确保有exhibitId和title
+          exhibitionList = exhibitionList.filter(item => {
+            return item && item.exhibitId && item.webSite;
+          });
+
+          if (isRefresh) {
+            // 刷新时替换数据
+            this.setData({ 
+              exhibitionList,
+              currentPage: 1,
+              hasMore: exhibitionList.length >= this.data.pageSize
+            });
+          } else {
+            // 加载更多时追加数据
+            this.setData({ 
+              exhibitionList: [...this.data.exhibitionList, ...exhibitionList],
+              hasMore: exhibitionList.length >= this.data.pageSize
+            });
+          }
+
+          return response;
+        } catch (error) {
+          console.error('获取展览数据失败:', error);
+          wx.showToast({
+            title: '加载失败',
+            icon: 'none'
+          });
+          if (isRefresh) {
+            this.setData({ exhibitionList: [] });
+          }
+        } finally {
+          this.setData({ 
+            loading: false,
+            loadingMore: false
+          });
+          if (isRefresh) {
+            wx.stopPullDownRefresh();
+          }
+        }
+      },
+
+  // 加载更多数据
+  loadMore() {
+    const nextPage = this.data.currentPage + 1;
+    this.setData({ currentPage: nextPage });
+    this.getExhibitionList(false);
+  },
+
+
+  // 返回首页
+  goBack() {
+    wx.navigateBack();
+  },
+
+   // 展览项点击事件
+   viewExhibition(e) {
+      const item = e.currentTarget.dataset.item;
+      console.log('查看展览详情:', item);
+      wx.navigateTo({
+        url: `/pages/exhibition/activeDetails/index?isFrom=weixin&id=${item.exhibitId}&type=exhibition`
+      });
+   },
+
+   // 组件:线上观展点击
+   viewExhibition(e) {
+    const item = e.currentTarget.dataset.item;
+    if (item) {
+      console.log('跳转到线上观展:', item.webSite);
+      navigateToWebview(item.webSite, 'open');
+    } else {
+      console.log('webSite为空');
+    }
+  },
+});

+ 8 - 0
pages/index/online/index.json

@@ -0,0 +1,8 @@
+{
+    "navigationBarTitleText": "克拉玛依市博物馆",
+    "navigationBarBackgroundColor": "#ffffff",
+    "navigationBarTextStyle": "black",
+    "backgroundColor": "#f5f5f5",
+    "enablePullDownRefresh": true,
+    "usingComponents": {}
+  }

+ 39 - 0
pages/index/online/index.wxml

@@ -0,0 +1,39 @@
+<view class="activity-container">
+  <!-- 返回按钮 -->
+  <!-- <view class="back-button" bindtap="goBack">
+    <image src="https://klmybwg.4dage.com/mini/wxImg/indexPage/icon_back.png" mode="aspectFit"></image>
+  </view> -->
+
+  <!-- 标题 -->
+  <view class="section-title">线上展览</view>
+
+  <!-- 活动列表 -->
+  <view wx:if="{{loading}}" class="loading-container">
+    <view class="loading-text">加载中...</view>
+  </view>
+  <view wx:else class="content-section">
+    <view wx:if="{{exhibitionList && exhibitionList.length > 0}}">
+      <view class="scroll-container">
+        <view class="scroll-wrapper">
+            <view class="exhibition-item" wx:for="{{exhibitionList}}" wx:key="exhibitId" bindtap="viewExhibition" data-item="{{item}}">
+                <image src="{{urlImg + item.img}}" alt="展览" class="exhibition-img" mode="aspectFill"></image>
+                <view class="exhibition-info">
+                <text class="exhibition-title">{{item.title}}</text>
+                </view>
+            </view>
+        </view>
+        <!-- 加载更多提示 -->
+        <view wx:if="{{loadingMore}}" class="loading-more">
+          <view class="loading-text">加载中...</view>
+        </view>
+        <view wx:elif="{{!hasMore && exhibitionList.length > 0}}" class="no-more">
+          <view class="no-more-text">没有更多数据了</view>
+        </view>
+      </view>
+    </view>
+    <!-- 空状态 -->
+    <view wx:if="{{exhibitionList.length === 0}}" class="empty-state">
+      <view class="empty-text">暂无展览数据</view>
+    </view>
+  </view>
+</view>

+ 222 - 0
pages/index/online/index.wxss

@@ -0,0 +1,222 @@
+/* pages/index/activity/activity.wxss */
+.activity-container {
+  position: relative;
+  height: 100vh;
+  padding: 40rpx;
+  background: url('https://klmybwg.4dage.com/mini/wxImg/bg.png') no-repeat;
+  background-size: cover;
+}
+
+.back-button {
+  position: absolute;
+  top: 20rpx;
+  left: 20rpx;
+  width: 80rpx;
+  height: 80rpx;
+  border-radius: 50%;
+  z-index: 10;
+}
+
+.back-button image {
+  width: 80rpx;
+  height: 80rpx;
+}
+
+.section-title {
+  font-size: 40rpx;
+  font-weight: bold;
+  color: #584735;
+  margin: 36rpx 0 32rpx 0;
+  position: relative;
+  padding-bottom: 20rpx;
+}
+
+.section-title::after {
+  content: '';
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 4rpx;
+  background: linear-gradient(90deg, rgba(91, 71, 46, 0.5) 0%, rgba(91, 71, 46, 0) 100%);
+}
+
+.content-section {
+  padding: 0 20rpx 40rpx 20rpx;
+}
+
+.collection-list {
+  display: flex;
+  flex-direction: column;
+  gap: 30rpx;
+}
+
+.collection-item {
+  background-color: #fff;
+  border-radius: 16rpx;
+  overflow: hidden;
+  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
+}
+
+.item-image-container {
+  position: relative;
+  height: 436rpx;
+  overflow: hidden;
+}
+
+.item-image {
+  width: 100%;
+  height: 100%;
+}
+
+.view-button {
+  position: absolute;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 160rpx;
+  height: 72rpx;
+  top: 24rpx;
+  right: 24rpx;
+  background-color: rgba(0, 0, 0, 0.2);
+  color: #fff;
+  border-radius: 100rpx;
+  font-size: 24rpx;
+  border: 2rpx solid #fff;
+}
+
+.view-button text {
+  font-size: 28rpx;
+}
+
+.arrow {
+  margin-left: 12rpx;
+  font-size: 24rpx;
+}
+
+.item-info {
+  position: absolute;
+  width: 90%;
+  bottom: 32rpx;
+  left: 48rpx;
+}
+
+.item-title {
+  font-family: 'heavy';
+  font-size: 40rpx;
+  font-weight: bold;
+  color: #fff;
+  margin-bottom: 8rpx;
+}
+
+.item-description {
+  font-size: 24rpx;
+  color: #fff;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+/* 加载状态样式 */
+.loading-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 400rpx;
+}
+
+.loading-text {
+  font-size: 36rpx;
+  color: #584735;
+  opacity: 0.8;
+}
+
+/* 空状态样式 */
+.empty-state {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 400rpx;
+  margin-top: 100rpx;
+}
+
+.empty-text {
+  font-size: 36rpx;
+  color: #584735;
+  opacity: 0.6;
+}
+
+/* 展览列表样式 */
+.scroll-container {
+  display: flex;
+  flex-direction: column;
+}
+
+.scroll-wrapper {
+  display: flex;
+  flex-direction: column;
+}
+
+/* 展览项 */
+.exhibition-item {
+  position: relative;
+  flex: 0 0 auto;
+  width: 100%;
+  height: 320rpx;
+  border-radius: 10rpx;
+  overflow: hidden;
+  margin-bottom: 20rpx;
+}
+
+.exhibition-item:last-child {
+  margin-right: 0;
+}
+
+.exhibition-img {
+  width: 100%;
+  height: 320rpx;
+}
+
+.exhibition-info {
+  width: 100%;
+  height: 60rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  opacity: 0.8;
+  position: absolute;
+  bottom: 0;
+  background: #B1967B;
+}
+
+.exhibition-title {
+  font-family: "heavy";
+  font-size: 32rpx;
+  color: #fff;
+  font-weight: bold;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  padding: 0 16rpx;
+}
+
+/* 加载更多样式 */
+.loading-more {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 40rpx 0;
+}
+
+.no-more {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 40rpx 0;
+}
+
+.no-more-text {
+  font-size: 28rpx;
+  color: #584735;
+  opacity: 0.6;
+}

+ 45 - 1
pages/index/visit-people/visit-people.js

@@ -12,7 +12,8 @@ Page({
     showSuccessModal: false,
     isFormValid: false,
     idTypes: [{value: 1, name: '身份证'}],
-    existingVisitors: [] // 我的联系人列表
+    existingVisitors: [], // 我的联系人列表
+    selectedServiceId: 0 // 选中的讲解服务ID,默认为0(不需要讲解服务)
   },
 
   onLoad(options) {
@@ -34,6 +35,9 @@ Page({
     
     // 加载已有参观人数据
     this.loadExistingVisitors();
+
+    // 加载讲解服务列表
+    this.loadAppointmentServices();
   },
 
   // 新增参观人
@@ -257,6 +261,45 @@ Page({
       });
     },
 
+    // 加载讲解服务列表
+    loadAppointmentServices() {
+      museumApi.getAppointmentServiceList()
+        .then(response => {
+          console.log('获取讲解服务列表成功:', response);
+          if (response && response.length > 0) {
+            // 确保第一个是"不需要讲解服务"
+            const services = response;
+            // 默认选中第一个服务(通常是"不需要讲解服务")
+            this.setData({ 
+              appointmentServices: services,
+              selectedServiceId: services[0].id
+            });
+          }
+        })
+        .catch(error => {
+          console.error('获取讲解服务列表失败:', error);
+          // 如果接口失败,使用默认数据
+          const defaultServices = [
+            { id: 0, name: '不需要讲解服务', price: 0 },
+            { id: 1, name: '展厅基本列', price: 120 },
+            { id: 2, name: '展厅基本列、黑油山地貌、外景文物', price: 150 },
+            { id: 3, name: '展厅基本列、黑油山地貌、外景文物、临展厅', price: 180 }
+          ];
+          this.setData({ 
+            appointmentServices: defaultServices,
+            selectedServiceId: defaultServices[0].id
+          });
+        });
+    },
+
+    // 选择讲解服务
+    selectAppointmentService(e) {
+      const serviceId = e.currentTarget.dataset.serviceId;
+      this.setData({
+        selectedServiceId: parseInt(serviceId)
+      });
+    },
+
     // 确认选择已有参观人
     confirmExistingVisitors() {
       const selectedVisitors = this.data.existingVisitors.filter(visitor => visitor.selected);
@@ -315,6 +358,7 @@ Page({
       const requestData = {
         activityId: this.data.type === 2 ? this.data.activityId : 0,
         appointmentSlotsId: this.data.appointmentSlotsId || 0,
+        appointmentServiceId: this.data.selectedServiceId, // 添加讲解服务ID
         appointmentTime: this.data.selectedDate,
         type: this.data.type,
         visitors: this.data.visitors.map(visitor => ({

+ 22 - 0
pages/index/visit-people/visit-people.wxml

@@ -93,6 +93,28 @@
       </view>
     </scroll-view>
 
+    <!-- 讲解服务 -->
+    <view class="service-section" wx:if="{{appointmentServices && appointmentServices.length}}">
+      <view class="service-title"><text class="border-fix"></text>讲解服务</view>
+      <view class="service-list">
+        <view 
+          wx:for="{{appointmentServices}}" 
+          wx:key="id" 
+          class="service-item {{selectedServiceId === item.id ? 'selected' : ''}}"
+          bindtap="selectAppointmentService"
+          data-service-id="{{item.id}}"
+        >
+          <view class="service-content">
+            <view class="service-name">{{item.context}}</view>
+            <view class="service-price" wx:if="{{item.remark > 0}}">收费{{item.remark}}元</view>
+          </view>
+          <view class="service-checkbox {{selectedServiceId === item.id ? 'checked' : ''}}">
+            <text class="check-icon" wx:if="{{selectedServiceId === item.id}}">✓</text>
+          </view>
+        </view>
+      </view>
+    </view>
+
     <!-- 下一步按钮 -->
     <view class="next-button-container">
       <view class="next-btn {{!isFormValid ? 'disabled' : ''}}" bindtap="submitReservation" disabled="{{!isFormValid}}">下一步</view>

+ 89 - 5
pages/index/visit-people/visit-people.wxss

@@ -1,11 +1,17 @@
 .visit-people-container {
-  height: 97vh;
+  height: 100vh;
   background: url('https://klmybwg.4dage.com/mini/wxImg/bg.png');
   padding: 32rpx;
   padding-bottom: 0;
   overflow: hidden;
 }
 
+.main-content{
+  height: calc(100vh - 320rpx - 64rpx);
+  overflow-y: auto;
+  padding: 0 36rpx;
+}
+
 .date-info {
   height: 212rpx;
   position: relative;
@@ -41,7 +47,6 @@
 .action-buttons {
   display: flex;
   gap: 20rpx;
-  padding: 0 32rpx;
   margin-bottom: 40rpx;
 }
 
@@ -65,9 +70,6 @@
 }
 
 .visitor-list {
-  height: calc(100vh - 460rpx - 64rpx);
-  overflow-y: auto;
-  padding-bottom: 20rpx;
 }
 
 .visitor-card {
@@ -187,6 +189,88 @@
   background: #ccc;
 }
 
+/* 讲解服务样式 */
+.service-section {
+  padding: 10rpx;
+  margin-bottom: 30rpx;
+}
+.border-fix{
+  display: inline-block;
+  height: 40rpx;
+  width: 12rpx;
+  background: #A5886B;
+  margin-right: 26rpx;
+}
+.service-title {
+  display: flex;
+  align-items: center;
+  height: 80rpx;
+  font-size: 38rpx;
+  font-weight: bold;
+  color: #A5886B;
+  margin-bottom: 20rpx;
+}
+
+.service-list {
+  display: flex;
+  flex-direction: column;
+  gap: 20rpx;
+}
+
+.service-item {
+  position: relative;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 30rpx;
+  border: 2rpx solid rgba(91,71,46,0.5);
+  border-radius: 10rpx;
+  background: rgba(177,150,123,0.3);
+  transition: all 0.3s ease;
+}
+
+.service-item.selected {
+  background: none;
+  border: 1px solid rgba(91,71,46,0.5);
+}
+
+.service-content {
+  flex: 1;
+}
+
+.service-name {
+  font-size: 28rpx;
+  color: #5B472E;
+}
+
+.service-price {
+  font-size: 22rpx;
+  color: #5B472E;
+}
+
+.service-checkbox {
+  position: absolute;
+  right: 0;
+  top: 0;
+  width: 42rpx;
+  height: 42rpx;
+  border-radius: 0 10rpx 0 10rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 28rpx;
+  color: white;
+  background: transparent;
+}
+
+.service-checkbox.checked {
+  background: #AA9D8B;
+}
+.check-icon{
+  font-size: 28rpx;
+}
+
+
 /* 选择已有参观人页面样式 */
 .existing-page {
   padding: 32rpx;

+ 2 - 1
pages/user/my-preview/index.js

@@ -158,7 +158,8 @@ Page({
         activityName: item.activityTitle || '',
         status: item.status,
         visitors: item.visitors || [],
-        isExpired: isExpired
+        isExpired: isExpired,
+        serviceName: item.serviceName
       };
     });
   },

+ 4 - 0
pages/user/my-preview/index.wxml

@@ -54,6 +54,10 @@
             </view>
           </view>
         </view>
+        <view wx:if="{{item.serviceName}}">
+          <view class="section-title">讲解服务</view>
+          <text class="visitor-value">{{item.serviceName}}</text>
+        </view>
       </view>
     </view>
     

+ 9 - 5
pages/user/my-preview/index.wxss

@@ -73,6 +73,10 @@
 
 /* 值样式 */
 .value {
+  width: 250rpx;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
   font-size: 32rpx;
   color: #B1967B;
 }
@@ -113,11 +117,11 @@
 
 /* 区域标题 */
 .section-title {
-  font-size: 28rpx;
-  color: #333;
+  font-size: 32rpx;
+  color: #584735;
   font-weight: 600;
-  margin-bottom: 20rpx;
-  margin-top: 30rpx;
+  margin-bottom: 26rpx;
+  margin-top: 26rpx;
 }
 
 .section-title:first-child {
@@ -143,7 +147,7 @@
 /* 参观人标签 */
 .visitor-label {
   font-size: 32rpx;
-  color: #584735;
+  color: #B1967B;
   margin-right: 10rpx;
   min-width: 140rpx;
 }

+ 9 - 0
utils/api.js

@@ -399,6 +399,15 @@ const museumApi = {
       method: 'POST',
       useToken: true
     });
+  },
+
+  // 获取讲解服务列表
+  getAppointmentServiceList() {
+    return request({
+      url: '/museum/appointmentService/list',
+      method: 'post',
+      useToken: true
+    });
   }
 };