Bläddra i källkod

feat: notice and calendar

chenlei 1 år sedan
förälder
incheckning
c9f6277352

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
web/src/assets/images/notice.svg


+ 1 - 1
web/src/views/Visit/Visit8.vue

@@ -141,7 +141,7 @@
 
         switch (this.currentType) {
           case 0:
-            temp = all;
+            temp = this.sortList;
             break;
           case 1:
             temp = [];

+ 1 - 0
web/src/views/layout/data.js

@@ -5,6 +5,7 @@ export const topData = [
     name: "Visit",
     url: "Visit",
     children: [
+      { url:'/Layout/Visit/8',id: 2.8, name: "Calendar" },
       { url:'/Layout/Visit/1',id: 2.1, name: "Hours, Direction & Admission" },
       { url:'/Layout/Visit/2',id: 2.2, name: "Reservation" },
       { url:'/Layout/Visit/3',id: 2.3, name: "Floor Plans" },

+ 96 - 1
web/src/views/layout/index.vue

@@ -148,6 +148,16 @@
           </div>
         </div>
       </div>
+      <div v-if="noticeVisible" class="notice">
+        <div class="notice__content">
+          <img :src="require('@/assets/images/notice.svg')" />
+          <span>Notice: </span>
+          <div ref="noticeBarRef">
+            <p ref="contentRef" :style="contentStyle">Due to permanent exhibition refurbishment, our museum has been closed since October 7, 2023. We have also temporarily closed the reservation channel. The specific reopening time will be announced separately. We apologize for any inconvenience this may cause.</p>
+          </div>
+          <i class="el-icon-close" @click="closeNotice" />
+        </div>
+      </div>
       <!-- 嵌套路由 -->
       <Router-view />
       <!-- 底部固定栏 -->
@@ -282,6 +292,11 @@ export default {
     //这里存放数据
     return {
       topData,
+      time: 0,
+      timer: undefined,
+      contentWidth: 0,
+      animateFlag: false,
+      noticeVisible: true,
       loveFlag: false,
       searchTxt: "",
       searchTxt2: "",
@@ -293,6 +308,10 @@ export default {
       ],
       // 控制二级菜单的高亮
       menaInd: null,
+      contentStyle: {
+        transitionDuration: '0s',
+        transform: 'translateX(0px)'
+      },
     };
   },
   //监听属性 类似于data概念
@@ -356,13 +375,53 @@ export default {
         }, 100);
       } else this.$router.push(url).catch(() => {});
     },
+    initNotice() {
+      const barWidth = this.$refs.noticeBarRef.offsetWidth
+      const contentWidth = this.$refs.contentRef.offsetWidth
+      if (contentWidth >= barWidth) {
+        this.contentWidth = contentWidth
+        this.animateFlag = true
+        this.openCycle()
+      }
+    },
+    openCycle () {
+      this.time = this.contentWidth / 70
+      this.startAnimate()
+      this.timer = setInterval(() => {
+        this.startAnimate()
+      }, this.time * 1000)
+      this.$once('hook:beforeDestroy', () => {
+        clearInterval(this.timer)
+        this.timer = null
+      })
+    },
+    // 开启动画
+    startAnimate () {
+      this.contentStyle = {
+        transitionDuration: '0s',
+        transform: `translateX(${this.$refs.noticeBarRef.offsetWidth}px)`
+      }
+      setTimeout(() => {
+        this.contentStyle = {
+          transitionDuration: `${this.time}s`,
+          transform: `translateX(-${this.contentWidth}px)`
+        }
+      }, 50)
+    },
+    closeNotice() {
+      this.noticeVisible = false
+      clearInterval(this.timer)
+      this.timer = null
+    }
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {
     this.menaInd = this.$route.path;
   },
   //生命周期 - 挂载完成(可以访问DOM元素)
-  mounted() {},
+  mounted() {
+    this.initNotice();
+  },
   beforeCreate() {}, //生命周期 - 创建之前
   beforeMount() {}, //生命周期 - 挂载之前
   beforeUpdate() {}, //生命周期 - 更新之前
@@ -679,4 +738,40 @@ export default {
     }
   }
 }
+.notice {
+  position: absolute;
+  top: 60px;
+  width: 100%;
+  color: white;
+  padding: 6px 0;
+  background-color: #CC1424;
+  z-index: 3;
+
+  &__content {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    position: relative;
+    width: 1300px;
+    margin: 0 auto;
+
+    div {
+      flex : 1;
+      width: 0;
+      overflow: hidden;
+      white-space: nowrap;
+
+      p {
+        width: fit-content;
+        transition-timing-function: linear;
+      }
+    }
+    i {
+      cursor: pointer;
+    }
+    img {
+      width: 20px;
+    }
+  }
+}
 </style>

+ 25 - 1
webM/src/views/Layout/index.vue

@@ -26,8 +26,19 @@
         />
       </div>
     </div>
+    <div v-if="noticeVisible" class="notice" :style="{top: `${noticeTop}px`}">
+      <van-notice-bar mode="closeable"
+        left-icon="volume-o"
+        color="#ffffff"
+        :delay="3"
+        background="rgb(116, 18, 11)"
+        text="Due to permanent exhibition refurbishment, our museum has been closed since October 7, 2023. We have also temporarily closed the reservation channel. The specific reopening time will be announced separately. We apologize for any inconvenience this may cause."
+        @close="noticeVisible = false"
+      />
+    </div>
+    <div :style="{height: `${noticeVisible ? 90 : 50}px`}" />
     <!-- 子页面 -->
-    <Router-view />
+    <Router-view @handleNoticeTop="handleNoticeTop" />
     <!-- 点击菜单 -->
     <div class="meanPage" v-show="meanPage">
       <!-- 毛玻璃 -->
@@ -145,6 +156,8 @@ export default {
   data() {
     //这里存放数据
     return {
+      noticeVisible: true,
+      noticeTop: 50,
       // 搜索的变量
       searcShow: false,
       txt: "",
@@ -376,6 +389,9 @@ export default {
       if (dom.scrollTop > 400) this.srocllShow = true;
       else this.srocllShow = false;
     },
+    handleNoticeTop(top) {
+      this.noticeTop = top || 50;
+    }
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {},
@@ -693,4 +709,12 @@ export default {
     font-size: 12px;
   }
 }
+
+.notice {
+  position: fixed;
+  top: 50px;
+  left: 0;
+  right: 0;
+  z-index: 9;
+}
 </style>

+ 6 - 4
webM/src/views/Visit/datePanel.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="visit8">
     <div class="banner8">
-      <van-swipe :show-indicators="false" @change="(index) => currentBanner = index">
+      <van-swipe ref="carousel" :show-indicators="false" :autoplay="3000" @change="(index) => currentBanner = index">
         <van-swipe-item v-for="item in bannerList" :key="`${item.id}-${selectedDay.getTime()}`">
           <van-image
             width="100%"
@@ -90,7 +90,7 @@
       <div v-else class="empty">no more</div>
     </div>
 
-    <van-calendar v-model="showStartDatePicker" :min-date="minDate" @confirm="handleStartDateConfirm" />
+    <van-calendar ref="startPicker" v-model="showStartDatePicker" :min-date="minDate" @confirm="handleStartDateConfirm" />
     <van-calendar v-model="showEndDatePicker" :min-date="startDate" @confirm="handleEndDateConfirm" />
   </div>
 </template>
@@ -165,7 +165,7 @@
 
         switch (this.currentType) {
           case 0:
-            temp = all;
+            temp = this.sortList;
             break;
           case 1:
             temp = [];
@@ -266,9 +266,11 @@
     watch: {
       selectedDay(v) {
         if (this.$refs.carousel) {
-          this.$refs.carousel.setActiveItem(0);
+          this.$refs.carousel.swipeTo(0);
           this.currentBanner = 0;
           this.startDate = v;
+
+          this.$refs.startPicker.reset(v);
         }
       },
       startDate(v) {

+ 26 - 21
webM/src/views/Visit/index.vue

@@ -7,12 +7,13 @@
     <div class="main">
       <div class="mainBox" :class="{ curSorll: menaSon }">
         <div class="rowAll">
-          <div
-            @click="cutTab(index)"
-            class="row"
+          <div 
             v-for="(item, index) in tabData"
-            :key="index"
-            :class="{ active: idMate === index }"
+            :key="item.id"
+            class="row"
+            :id="`row${item.id}`"
+            :class="{ active: idMate === item.id }"
+            @click="cutTab(item.id)"
           >
             {{ item.name }}
           </div>
@@ -148,14 +149,14 @@ export default {
     //这里存放数据
     return {
       tabData: [
-        { name: "Calendar", path: "/Layout/Visit/8" },
-        { name: "Hours, Direction & Admission", path: "/Layout/Visit/1" },
-        { name: "Reservation", path: "/Layout/Visit/2" },
-        { name: "Floor Plans", path: "/Layout/Visit/3" },
-        { name: "Audio Guide & Tour", path: "/Layout/Visit/4" },
-        { name: "Accessibility", path: "/Layout/Visit/5" },
-        { name: "Café & Shop", path: "/Layout/Visit/6" },
-        { name: "Visitor Guidelines", path: "/Layout/Visit/7" },
+        { id: 7, name: "Calendar", path: "/Layout/Visit/8" },
+        { id: 0, name: "Hours, Direction & Admission", path: "/Layout/Visit/1" },
+        { id: 1, name: "Reservation", path: "/Layout/Visit/2" },
+        { id: 2, name: "Floor Plans", path: "/Layout/Visit/3" },
+        { id: 3, name: "Audio Guide & Tour", path: "/Layout/Visit/4" },
+        { id: 4, name: "Accessibility", path: "/Layout/Visit/5" },
+        { id: 5, name: "Café & Shop", path: "/Layout/Visit/6" },
+        { id: 6, name: "Visitor Guidelines", path: "/Layout/Visit/7" },
       ],
       xianInd: "B1",
       xian: ["B1", "F1", "F2", "F3", "F4", "F5", "F6"],
@@ -221,6 +222,9 @@ export default {
       this.pageSrool(id - 1);
       this.erjiTop(id - 1);
     },
+    menaSon(v) {
+      this.$emit('handleNoticeTop', v ? 70 : 0)
+    }
   },
   //方法集合
   methods: {
@@ -249,10 +253,10 @@ export default {
         setTimeout(() => {
           this.idMate = index;
           // 获取二级选中元素距离左侧的距离
-          let sonScroll = document.querySelectorAll(".rowAll .row");
+          let sonScroll = document.querySelector(".rowAll #row" + index);
           let sonScrollAll = document.querySelector(".mainBox");
           sonScrollAll.scrollTo({
-            left: sonScroll[index].offsetLeft - 100,
+            left: sonScroll.offsetLeft - 100,
             behavior: "smooth",
           });
         }, 100);
@@ -306,7 +310,13 @@ export default {
             LayoutTop.style.display = "flex";
             this.menaSon = false;
           }
-          if (scrollDom.scrollTop < Visit1.offsetTop + Visit1.offsetHeight - 70)
+
+          if (
+            scrollDom.scrollTop <
+            Visit8.offsetTop + Visit8.offsetHeight - 70
+          )
+            temp = 7;
+          else if (scrollDom.scrollTop < Visit1.offsetTop + Visit1.offsetHeight - 70)
             temp = 0;
           else if (
             scrollDom.scrollTop <
@@ -333,11 +343,6 @@ export default {
             Visit6.offsetTop + Visit6.offsetHeight - 70
           )
             temp = 5;
-          else if (
-            scrollDom.scrollTop <
-            Visit8.offsetTop + Visit8.offsetHeight - 70
-          )
-            temp = 8;
           else temp = 6;
           this.erjiTop(temp);
         };