Browse Source

feat: 完善

jinx 7 months ago
parent
commit
bac9befc1c

+ 5 - 1
README.md

@@ -1 +1,5 @@
-https://houseoss.4dkankan.com/project/4dwall/index.html
+
+# oss线上更新地址
+https://houseoss.4dkankan.com/project/4dwall/index.html
+
+# node 版本 >=18

+ 1 - 1
index.html

@@ -4,7 +4,7 @@
     <meta charset="UTF-8" />
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
-    <title>四维万物墙</title>
+    <title>央视网云上展览</title>
     <!-- <script src="https://4dkk.4dage.com/v4-test/www/viewer/static/lib/vconsole.js"></script> -->
     <!-- <script>
       new VConsole()

+ 4 - 3
package.json

@@ -11,13 +11,14 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
-    "lib-flexible": "^0.3.2",
     "@vitejs/plugin-vue": "^5.2.1",
+    "lib-flexible": "^0.3.2",
     "sass": "^1.83.4",
     "scss": "^0.2.4",
     "swiper": "5.4.5",
     "vite": "^6.0.7",
+    "vue": "^3.5.13",
     "vue-perfectlooper": "^1.4.0",
-    "vue": "^3.5.13"
+    "xlsx": "^0.18.5"
   }
-}
+}

+ 5 - 4
public/json/data.json

@@ -1,12 +1,13 @@
 [
   {
-    "name": "广东博物馆",
+    "name": "23年",
     "list": [
       [
         {
           "src": "1.png",
           "name": "广彩天使图盘",
-          "modelUrl": "https://zzbbh.4dage.com/webM/dist/model-page/model.html?m=BBH_nj19&v=1"
+          "modelUrl": "https://zzbbh.4dage.com/webM/dist/model-page/model.html?m=BBH_nj19&v=1",
+          "desc":"这是一段文字单位介绍这是一段文字单位介绍这是一段文字单位介绍这是一段文字单位介绍这是一段文字单位介绍这是一段文字单位介绍。"
         },
         {
           "src": "2.png",
@@ -86,7 +87,7 @@
     ]
   },
   {
-    "name": "德国博物馆",
+    "name": "24年",
     "list": [
       [
         {
@@ -172,7 +173,7 @@
     ]
   },
   {
-    "name": "南通博物馆",
+    "name": "25年",
     "list": [
       [
         {

File diff suppressed because it is too large
+ 1016 - 0
public/json/test.json


BIN
src/assets/img/home_bg.jpg


File diff suppressed because it is too large
+ 9 - 0
src/assets/img/home_title.svg


+ 16 - 0
src/assets/img/icon-close.svg

@@ -0,0 +1,16 @@
+<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="icon-close2">
+<circle id="Ellipse 16" cx="60" cy="60" r="60" fill="url(#paint0_linear_15_669)"/>
+<circle id="Ellipse 18" cx="60" cy="60" r="50" stroke="#FFFBED" stroke-width="1.5"/>
+<g id="Group 435">
+<path id="Vector 1" d="M36.8711 82.8711L82.6128 37.1294" stroke="#FFFBED" stroke-width="5.6"/>
+<path id="Vector 2" d="M82.6121 82.8713L36.8704 37.1296" stroke="#FFFBED" stroke-width="5.6"/>
+</g>
+</g>
+<defs>
+<linearGradient id="paint0_linear_15_669" x1="60" y1="0" x2="60" y2="120" gradientUnits="userSpaceOnUse">
+<stop stop-color="#6D624C"/>
+<stop offset="1" stop-color="#92866D"/>
+</linearGradient>
+</defs>
+</svg>

+ 26 - 0
src/assets/img/more.svg

@@ -0,0 +1,26 @@
+<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="more">
+<circle id="Ellipse 16" cx="60" cy="60" r="60" fill="url(#paint0_linear_15_557)"/>
+<circle id="Ellipse 18" cx="60" cy="60" r="50" stroke="#FFFBED" stroke-width="1.5"/>
+<g id="Group 1104">
+<g id="Group 1102">
+<rect id="Rectangle 148" x="32" y="36" width="48" height="5" fill="#FFFBED"/>
+<rect id="Rectangle 151" x="84" y="36" width="5" height="5" fill="#FFFBED"/>
+</g>
+<g id="Group 1103">
+<rect id="Rectangle 148_2" x="32" y="58" width="48" height="5" fill="#FFFBED"/>
+<rect id="Rectangle 151_2" x="84" y="58" width="5" height="5" fill="#FFFBED"/>
+</g>
+<g id="Group 1102_2">
+<rect id="Rectangle 148_3" x="32" y="80" width="48" height="5" fill="#FFFBED"/>
+<rect id="Rectangle 151_3" x="84" y="80" width="5" height="5" fill="#FFFBED"/>
+</g>
+</g>
+</g>
+<defs>
+<linearGradient id="paint0_linear_15_557" x1="60" y1="0" x2="60" y2="120" gradientUnits="userSpaceOnUse">
+<stop stop-color="#6D624C"/>
+<stop offset="1" stop-color="#92866D"/>
+</linearGradient>
+</defs>
+</svg>

+ 12 - 0
src/assets/img/niandai.svg

@@ -0,0 +1,12 @@
+<svg width="400" height="120" viewBox="0 0 400 120" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="niandai">
+<rect id="Rectangle 147" width="400" height="120" rx="60" fill="url(#paint0_linear_15_571)"/>
+<rect id="Rectangle 148" x="10" y="10" width="380" height="100" rx="50" stroke="#FFFBED" stroke-width="1.5"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_15_571" x1="200" y1="0" x2="200" y2="120" gradientUnits="userSpaceOnUse">
+<stop stop-color="#6D624C"/>
+<stop offset="1" stop-color="#92866D"/>
+</linearGradient>
+</defs>
+</svg>

+ 5 - 1
src/assets/style.css

@@ -10,7 +10,11 @@ body {
   width: 100%;
   height: 100%;
 }
-
+* {
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0;
+}
 body {
   margin: 0;
 }

+ 122 - 38
src/views/home/iframeView/index.vue

@@ -1,23 +1,61 @@
 <!--  -->
 <template>
   <div class="iframe-view">
-    <div class="title">{{ iframeData.name }}</div>
-    <div class="iframe-box" v-if="iframeData.modelUrl">
+    <div class="close-btn" @click="close"></div>
+
+    <div class="iframe-box" v-if="iframeData.type == '3D'">
       <iframe :src="iframeData.modelUrl" frameborder="0"></iframe>
     </div>
-    <p class="support">四维时代提供技术支持</p>
-    <div class="close-btn" @click="close">关闭</div>
+    <div v-else-if="iframeData.type == '2D'" class="image-box">
+      <div class="swiper-dom view-container">
+        <div class="swiper-wrapper">
+          <div class="swiper-slide">
+            <div class="item-box" @click="changeIframe(i)">
+              <img :src="`resource/img/1.png`" alt="" />
+            </div>
+          </div>
+          <div class="swiper-slide">
+            <div class="item-box" @click="changeIframe(i)">
+              <img :src="`resource/img/1.png`" alt="" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="content">
+      <div class="scroll-box">
+        <p class="title">{{ iframeData.name }}</p>
+        <p class="desc">
+          <span style="font-weight: bold">{{ iframeData.age }}</span
+          ><br /><span style="font-weight: bold">{{ iframeData.collection }}</span
+          ><br /><span style="text-indent: 2em; display: block">{{ iframeData.desc }}</span>
+        </p>
+      </div>
+    </div>
   </div>
 </template>
 
 <script setup>
-import { reactive, ref, toRefs, onBeforeMount, onMounted, defineEmits, defineProps } from "vue";
+import "swiper/css/swiper.css";
+import Swiper from "swiper";
+import { reactive, ref, toRefs, onBeforeMount, onMounted, defineEmits, defineProps, nextTick } from "vue";
 const props = defineProps(["iframeData"]);
 const emits = defineEmits(["close"]);
 
 const close = () => {
   emits("close");
 };
+let imageSwiper = null;
+const options = {
+  freeMode: false,
+};
+const setSwiper = () => {
+  imageSwiper = new Swiper(".view-container", options);
+};
+
+nextTick(() => {
+  setSwiper();
+});
 </script>
 <style lang="scss" scoped>
 .iframe-view {
@@ -27,8 +65,14 @@ const close = () => {
   z-index: 10;
   top: 0;
   left: 0;
-  background: rgba(0,0,0,0.5);
-  backdrop-filter: blur(4px);
+
+  background-size: cover;
+  background-repeat: no-repeat;
+  background-position: 50%;
+  background-image: url("@/assets/img/home_bg.jpg");
+  color: #fff;
+
+  z-index: 101;
   .iframe-box {
     width: 100%;
     height: 100%;
@@ -37,41 +81,81 @@ const close = () => {
       height: 100%;
     }
   }
-  .title {
-    margin-top: 55px;
-    position: absolute;
-    width: 310px;
-    height: 60px;
-    top: 0;
-    left: 50%;
-    transform: translateX(-50%);
-    z-index: 999;
-    font-size: 0.64rem;
-    color: #fff;
-    text-align: center;
-  }
-  .support {
-    position: absolute;
-    z-index: 1;
-    font-size: 16px;
-    color: #17181d;
-    font-weight: 100;
-    left: 50%;
-    transform: translateX(-50%);
-    bottom: 13vh;
-    letter-spacing: 1px;
-    text-shadow: rgb(51 51 51) 0 1px 1px;
+  .image-box {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    .item-box {
+      position: relative;
+      img {
+        object-fit: contain;
+        width: 100%;
+        height: 100%;
+      }
+    }
   }
+
   .close-btn {
     position: absolute;
-    bottom: 5%;
-    right: 50%;
-    transform: translateX(50%);
-    width: 58px;
-    height: 58px;
+    top: 0.5333rem;
+    right: 0.5333rem;
+    width: 1.0667rem;
+    height: 1.0667rem;
     color: #fff;
-    font-size: 20px;
-    z-index: 999999999;
+    z-index: 102;
+    background: url("@/assets/img/icon-close.svg") no-repeat;
+    background-size: 100%;
+  }
+  .content {
+    border-radius: 0.5333rem 0.5333rem 0 0;
+    padding: 0.72rem 0.2667rem 0.72rem 0.72rem;
+    background: linear-gradient(180deg, rgba(109, 98, 76, 1) 0%, rgba(146, 134, 109, 1) 100%);
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    .scroll-box {
+      width: 100%;
+      max-height: 5.3333rem;
+      padding-right: 0.4533rem;
+      overflow-y: auto;
+      /* 自定义整个滚动条 */
+      &::-webkit-scrollbar {
+        width: 3px; /* 滚动条宽度 */
+      }
+
+      /* 自定义滚动条轨道 */
+      &::-webkit-scrollbar-track {
+        background: transparent; /* 轨道颜色 */
+      }
+
+      /* 自定义滚动条的滑块(thumb) */
+      &::-webkit-scrollbar-thumb {
+        background: #fffbed; /* 滑块颜色 */
+      }
+
+      /* 当hover或active状态时,自定义滑块的颜色 */
+      &::-webkit-scrollbar-thumb:hover {
+        background: #555;
+      }
+      .title {
+        font-family: Source Han Sans CN, Source Han Sans CN;
+        font-weight: bold;
+        font-size: 0.48rem;
+        color: #fffbed;
+        line-height: 0.56rem;
+        margin-bottom: 0.2667rem;
+      }
+      .desc {
+        font-family: Source Han Sans CN, Source Han Sans CN;
+        font-weight: 400;
+        font-size: 0.32rem;
+        color: #fffbed;
+        line-height: 0.64rem;
+      }
+    }
   }
 }
 </style>

+ 386 - 84
src/views/home/index.vue

@@ -1,51 +1,58 @@
 <!--  -->
 <template>
-  <div class="home">
-    <div class="title">万物墙</div>
-    <div class="en-title">4DWall</div>
+  <div class="home" @click="showSwitch = false">
+    <input type="file" @change="readFile" accept=".xlsx" />
+    <div class="title"></div>
     <template v-if="currentData">
-      <div class="swiper-dom swiper-container">
+      <div class="swiper-dom swiper-container" v-if="currentData.list[0] && currentData.list[0].length">
         <div class="swiper-wrapper">
           <div class="swiper-slide" v-for="i in currentData.list[0]">
             <div class="item-box" @click="changeIframe(i)">
-              <img :src="`resource/img/${i.src}`" alt="" />
+              <img :src="`resource/img/${i.thumb ? i.thumb : '1.png'}`" alt="" />
               <span class="item-name">{{ i.name }}</span>
             </div>
           </div>
         </div>
       </div>
-      <div class="swiper-dom swiper-container1" dir="rtl">
+      <div class="swiper-dom swiper-container1" dir="rtl" v-if="currentData?.list[1] && currentData?.list[1].length">
         <div class="swiper-wrapper">
           <div class="swiper-slide" v-for="i in currentData.list[1]">
             <div class="item-box" @click="changeIframe(i)">
-              <img :src="`resource/img/${i.src}`" alt="" />
+              <img :src="`resource/img/${i.thumb ? i.thumb : '1.png'}`" alt="" />
               <span class="item-name">{{ i.name }}</span>
             </div>
           </div>
         </div>
       </div>
-      <div class="swiper-dom swiper-container2">
+      <div class="swiper-dom swiper-container2" v-if="currentData?.list[2] && currentData?.list[2].length">
         <div class="swiper-wrapper">
           <div class="swiper-slide" v-for="i in currentData.list[2]">
             <div class="item-box" @click="changeIframe(i)">
-              <img :src="`resource/img/${i.src}`" alt="" />
+              <img :src="`resource/img/${i.thumb ? i.thumb : '1.png'}`" alt="" />
               <span class="item-name">{{ i.name }}</span>
             </div>
           </div>
         </div>
       </div>
     </template>
-
-    <div class="switch" v-if="currentData">
-      <div class="current-item" @click="showSwitch = !showSwitch">
-        <span>{{ currentData.name }}</span>
-        <div class="arrow"></div>
-      </div>
-      <div class="switch-list" :class="{ open: showSwitch }">
-        <div class="switch-item" @click="changeItem(i)" v-for="(i, index) in swiperData">
-          <span>{{ i.name }}</span>
+    <div class="bottom-controls" @click.stop="" v-if="currentData">
+      <div class="switch">
+        <div class="current-item" @click="showSwitch = !showSwitch">
+          <span>{{ currentData.name }}</span>
+          <div class="arrow"></div>
+        </div>
+        <div class="switch-list" :class="{ open: showSwitch }">
+          <div class="scroll-box">
+            <div class="switch-item" :class="{ active: currentData.name == '全部' }" @click="changeItem('all')">
+              <span>全部</span>
+            </div>
+            <div class="switch-item" :class="{ active: currentData.name == i.name }" @click="changeItem(i, index)" v-for="(i, index) in swiperData">
+              <span>{{ i.name }}</span>
+            </div>
+          </div>
         </div>
       </div>
+      <div class="more-btn" @click="goMore()"></div>
     </div>
   </div>
   <iframeView v-if="showIframe" :iframeData="iframeData" @close="closeIframe" />
@@ -55,7 +62,118 @@
 import iframeView from "./iframeView/index.vue";
 import "swiper/css/swiper.css";
 import Swiper from "swiper";
-import { reactive, ref, toRefs, onBeforeMount, onMounted, nextTick } from "vue";
+import { reactive, ref, toRefs, onBeforeMount, onMounted, nextTick, watch } from "vue";
+import * as XLSX from "xlsx";
+const readFile = (e) => {
+  const files = e.target.files;
+  // 如果没有文件名
+  if (files.length <= 0) {
+    return false;
+  } else if (!/\.(xls|xlsx)$/.test(files[0].name.toLowerCase())) {
+    this.$Message.error("上传格式不正确,请上传xls或者xlsx格式");
+    return false;
+  }
+
+  const fileReader = new FileReader();
+  fileReader.onload = (ev) => {
+    try {
+      const data = ev.target.result;
+      // 切换为新的调用方式
+      const workbook = XLSX.read(data, {
+        type: "binary",
+      });
+
+      let table = workbook.Sheets;
+      let keys = workbook.SheetNames;
+      console.log(workbook);
+      let array = [];
+
+      keys.forEach((item) => {
+        let obj = {};
+        obj.name = item;
+        // obj.list = XLSX.utils.sheet_to_json(table[item]);
+        obj.list = procressData(
+          XLSX.utils.sheet_to_json(table[item], {
+            /** Default value for null/undefined values */
+            defval: "", //给defval赋值为空的字符串
+          })
+        );
+        array.push(obj);
+      });
+      console.log(array);
+      console.log(JSON.stringify(array));
+      // // 取第一张表
+      // const wsname = workbook.SheetNames[0];
+      // // 切换为新的调用方式 生成json表格内容
+      // const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]);
+      // console.log(ws);
+      // // 后续为自己对ws数据的处理
+    } catch (e) {
+      return false;
+    }
+  };
+  fileReader.readAsBinaryString(files[0]);
+};
+// 表格时间转换
+function excelToJsDate(serialNumber) {
+  var date = new Date(1900, 0, serialNumber - 1);
+
+  const year = date.getFullYear();
+  const month = date.getMonth() + 1;
+  const day = date.getDate();
+
+  return year + "年" + month + "月" + day + "日";
+}
+
+const procressData = (list) => {
+  let array = [];
+  list.forEach((item) => {
+    let obj = {};
+    for (let key in item) {
+      switch (key) {
+        case "年代":
+          obj["age"] = item[key];
+          break;
+        case "序号":
+          obj["index"] = item[key];
+          break;
+        case "文物名称":
+          obj["name"] = item[key];
+          break;
+        case "文物简介":
+          obj["desc"] = item[key];
+          break;
+        case "文物类型":
+          if (item[key] === "二维") {
+            obj["type"] = "2D";
+          } else if (item[key] === "三维") {
+            obj["type"] = "3D";
+          }
+
+          break;
+        case "更新日期":
+          obj["updateTime"] = excelToJsDate(item[key]);
+          break;
+        case "馆藏":
+          obj["collection"] = item[key];
+          break;
+        case "模型链接":
+          obj["modelUrl"] = item[key];
+          break;
+        case "缩略图名称":
+          obj["thumb"] = item[key];
+          break;
+        case "详情图名称":
+          obj["deatilsImg"] = item[key];
+          break;
+        default:
+          break;
+      }
+    }
+    array.push(obj);
+  });
+  return array;
+};
 
 const swiperData = ref(null); //所有数据
 const currentData = ref(null); //当前展示的数据
@@ -70,12 +188,15 @@ const swiperOptions = {
     stopOnLastSlide: false, //切换到最后一个时不停止自动播放
     disableOnInteraction: false, //触碰后不停止自动播放
   },
-  slidesPerView: 2.8,
+  slidesPerView: 2.5,
   spaceBetween: 10,
   freeMode: false,
   speed: 10000, //切换速度
   on: {
-    slideChangeTransitionEnd: function (e) {},
+    slideChangeTransitionEnd: function () {
+      // console.error("slideChangeTransitionEnd");
+      // this.autoplay.start();
+    },
     init: function (swiper) {},
   },
 };
@@ -83,52 +204,157 @@ let mySwiper = null;
 let mySwiper1 = null;
 let mySwiper2 = null;
 const setSwiper = () => {
+  toggleOptions(0);
   mySwiper = new Swiper(".swiper-container", swiperOptions);
 };
 const setSwiper1 = () => {
+  toggleOptions(1);
   mySwiper1 = new Swiper(".swiper-container1", swiperOptions);
 };
 const setSwiper2 = () => {
+  toggleOptions(2);
   mySwiper2 = new Swiper(".swiper-container2", swiperOptions);
 };
+
+//个数小于4个不允许轮播
+const toggleOptions = (index) => {
+  if (currentData.value.list[index].length < 3) {
+    swiperOptions.loop = false;
+    swiperOptions.autoplay = false;
+    swiperOptions.speed = 300;
+    swiperOptions.freeMode = true;
+  } else {
+    swiperOptions.loop = true;
+    swiperOptions.autoplay = {
+      delay: 0, //每循环一圈,间隔时间,无缝轮询,则为0
+      stopOnLastSlide: false, //切换到最后一个时不停止自动播放
+      disableOnInteraction: false, //触碰后不停止自动播放
+    };
+    swiperOptions.speed = 10000;
+    swiperOptions.freeMode = false;
+  }
+};
 const closeIframe = () => {
   showIframe.value = false;
 };
 const changeIframe = (item) => {
-  console.error(item)
+  console.error(item);
   iframeData.value = item;
   showIframe.value = true;
 };
 
 const loadJosnData = () => {
-  fetch("./json/data.json")
+  // fetch("./json/data.json")
+  fetch("./json/test.json")
     .then((res) => res.json())
     .then((res) => {
       swiperData.value = res;
-      currentData.value = res[0];
-      console.log(res);
-      nextTick(() => {
-        initSwiper();
-      });
+      // currentData.value = res[0];
+      console.error(swiperData.value);
+      hanlderSwiper({ name: "全部" });
     });
 };
 const initSwiper = () => {
-  setSwiper();
-  setSwiper1();
-  setSwiper2();
+  clearSwiper();
+  if (currentData.value.list[0] && currentData.value.list[0].length) {
+    setSwiper();
+  }
+  if (currentData.value.list[1] && currentData.value.list[1].length) {
+    setSwiper1();
+  }
+
+  if (currentData.value.list[2] && currentData.value.list[2].length) {
+    setSwiper2();
+  }
+};
+const hanlderSwiper = (item) => {
+  let list = [];
+  if (item.name == "全部") {
+    swiperData.value.forEach((item) => {
+      list = list.concat(item.list);
+    });
+  } else {
+    list = item.list;
+  }
+
+  let length = list.length;
+  console.error(length);
+
+  let groupList = [];
+  //少于3个的情况
+  if (length <= 3) {
+    groupList.push(list);
+    currentData.value = {
+      list: groupList,
+      name: item.name,
+    };
+    return;
+  }
+  // 只有三行
+  if (length >= 18) {
+    let group = 0;
+    if (length % 3 == 0) {
+      group = Math.ceil(length / 3);
+    } else {
+      group = (length - (length % 3)) / 3;
+    }
+
+    let one = list.slice(0, group);
+    let two = list.slice(group, 2 * group);
+    let three = list.slice(2 * group, length);
+    groupList.push(one);
+    groupList.push(two);
+    groupList.push(three);
+  } else if (length >= 6 && length < 18) {
+    // 只有两行
+    let one = list.slice(0, 6);
+    let two = list.slice(6, length);
+    groupList.push(one);
+    groupList.push(two);
+  } else if (length >= 4 && length < 6) {
+    // 只有一行
+    let one = list.slice(0, length);
+    groupList.push(one);
+  }
+
+  currentData.value = {
+    list: groupList,
+    name: item.name,
+  };
 };
 const clearSwiper = () => {
-  mySwiper.destroy();
-  mySwiper1.destroy();
-  mySwiper2.destroy();
+  mySwiper && mySwiper.destroy();
+  mySwiper1 && mySwiper1.destroy();
+  mySwiper2 && mySwiper2.destroy();
 };
-const changeItem = (item) => {
-  currentData.value = item;
+watch(
+  () => currentData.value,
+  (val) => {
+    console.error(val);
+    nextTick(() => {
+      initSwiper();
+    });
+  }
+);
+const changeItem = (item, index) => {
+  if (item === "all") {
+    hanlderSwiper({ name: "全部" });
+    showSwitch.value = false;
+
+    return;
+  }
+  // currentData.value = item;
+
+  hanlderSwiper(item);
   showSwitch.value = false;
-  clearSwiper();
-  nextTick(() => {
-    initSwiper();
-  });
+  // clearSwiper();
+  // nextTick(() => {
+  //   initSwiper();
+  // });
+};
+const goMore = () => {
+  window.location.href =
+    "https://content-static.cctvnews.cctv.com/snow-book/special.html?channelId=1160&page_type=share&specialId=17446950343365427321&toc_style_id=feeds_with_title&track_id=FA013000-00D6-4290-9087-29BF32E38470_759124785810&share_to=wechat";
 };
 onMounted(() => {
   loadJosnData();
@@ -142,19 +368,17 @@ onMounted(() => {
   background-size: cover;
   background-repeat: no-repeat;
   background-position: 50%;
-  background-image: url("https://zzbbh.4dage.com/webM/dist/img/bg.d8cfb8a5.jpg");
+  background-image: url("@/assets/img/home_bg.jpg");
   color: #fff;
   .title {
-    font-size: 0.8rem;
     text-align: center;
-    margin-top: 0.5333rem;
-    margin-bottom: 0.5333rem;
-  }
-  .en-title {
-    font-size: 0.64rem;
-    text-align: center;
-    margin-bottom: 0.5333rem;
+    margin: 60px auto 1.4667rem;
+    width: 8.2133rem;
+    height: 2.0667rem;
+    background: url("@/assets/img/home_title.svg") no-repeat;
+    background-size: 100%;
   }
+
   .item-box {
     // display: flex;
     position: relative;
@@ -170,58 +394,136 @@ onMounted(() => {
       -ms-writing-mode: tb-lr;
       writing-mode: vertical-lr;
       display: inline-block;
-      color: #9c8e4f;
-      text-shadow: 0 0 4px #000;
+      color: #6d624c;
+      // text-shadow: 0 0 4px #000;
       letter-spacing: 2px;
-      font-family: KaiTi;
-      font-size: 14px;
+      font-family: Source Han Sans CN, Source Han Sans CN;
+      font-size: 0.32rem;
+      height: 100%;
+      text-align: center;
     }
   }
-  .switch {
+  .bottom-controls {
     position: absolute;
     bottom: 0.5333rem;
     left: 50%;
     transform: translateX(-50%);
-    .current-item {
-      font-size: 0.64rem;
-      position: relative;
-      display: flex;
-      align-items: center;
-
-      .arrow {
-        width: 0.32rem;
-        height: 0.32rem;
-        background: url(../../assets/img/arrow.png) no-repeat;
-        background-size: 100%;
-        margin-left: 0.1333rem;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    z-index: 100;
+
+    .switch {
+      width: 3.56rem;
+      height: 1.0667rem;
+      background: url("@/assets/img/niandai.svg") no-repeat;
+      background-size: 100%;
+      font-family: Source Han Sans CN, Source Han Sans CN;
+      font-weight: 400;
+      font-size: 0.36rem;
+      color: #fffbed;
+      line-height: 0.36rem;
+      // padding: 0 0.3067rem 0 0;
+      .current-item {
+        position: relative;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        height: 100%;
+        padding: 0 0.4933rem;
+        > span {
+          width: 100%;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+        .arrow {
+          width: 0.32rem;
+          height: 0.32rem;
+          background: url(../../assets/img/arrow.png) no-repeat;
+          background-size: 100%;
+          margin-left: 0.1333rem;
+        }
       }
-    }
-    .switch-list {
-      width: 100%;
-      position: absolute;
-      font-size: 0.5333rem;
-      bottom: 110%;
-      background: #fff;
-      color: #000;
-      text-align: center;
-      transition: all 0.3s;
-      transform: scale(0);
-      transform-origin: center bottom;
-      opacity: 0;
-      &.open {
-        transform: scale(1);
-        opacity: 1;
+      .switch-list {
+        padding: 0.2667rem 0.4933rem;
+        width: 100%;
+        box-sizing: border-box;
+        position: absolute;
+        bottom: 110%;
+        background: linear-gradient(180deg, rgba(109, 98, 76, 1) 0%, rgba(146, 134, 109, 1) 100%);
+        color: #fffbed;
+        text-align: center;
+        transition: all 0.3s;
+        transform: scale(0);
+        transform-origin: center bottom;
+        border-radius: 0.1067rem;
+        opacity: 0;
+        &.open {
+          transform: scale(1);
+          opacity: 1;
+        }
+        .scroll-box {
+          max-height: 5.7333rem;
+          overflow-y: auto;
+
+          /* 自定义整个滚动条 */
+          &::-webkit-scrollbar {
+            width: 3px; /* 滚动条宽度 */
+          }
+
+          /* 自定义滚动条轨道 */
+          &::-webkit-scrollbar-track {
+            background: transparent; /* 轨道颜色 */
+          }
+
+          /* 自定义滚动条的滑块(thumb) */
+          &::-webkit-scrollbar-thumb {
+            background: #fffbed; /* 滑块颜色 */
+          }
+
+          /* 当hover或active状态时,自定义滑块的颜色 */
+          &::-webkit-scrollbar-thumb:hover {
+            background: #555;
+          }
+
+          .switch-item {
+            height: 0.8rem;
+            display: flex;
+            align-items: center;
+            justify-content: flex-start;
+            // padding: 0 0 0 0.4933rem;
+            &.active {
+              color: #e8e050;
+            }
+            > span {
+              width: 100%;
+              overflow: hidden;
+              text-overflow: ellipsis;
+              white-space: nowrap;
+              text-align: left;
+            }
+          }
+        }
       }
     }
+    .more-btn {
+      width: 1.0667rem;
+      height: 1.0667rem;
+      background: url("@/assets/img/more.svg") no-repeat;
+      background-size: 100%;
+      margin-left: 0.2667rem;
+    }
   }
 }
 </style>
 <style>
 .swiper-dom {
   width: 100%;
-  margin-top: 10px;
-  margin-bottom: 10px;
+  /* margin-top: 10px; */
+  margin-bottom: 0.5333rem;
   overflow: visible !important;
+  padding: 0 20px;
 }
 .swiper-wrapper {
   transition-timing-function: linear !important;

+ 58 - 0
yarn.lock

@@ -442,6 +442,11 @@
   resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz#87b309a6379c22b926e696893237826f64339b6f"
   integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==
 
+adler-32@~1.3.0:
+  version "1.3.1"
+  resolved "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz#1dbf0b36dda0012189a32b3679061932df1821e2"
+  integrity sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==
+
 braces@^3.0.3:
   version "3.0.3"
   resolved "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
@@ -449,6 +454,14 @@ braces@^3.0.3:
   dependencies:
     fill-range "^7.1.1"
 
+cfb@~1.2.1:
+  version "1.2.2"
+  resolved "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz#94e687628c700e5155436dac05f74e08df23bc44"
+  integrity sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==
+  dependencies:
+    adler-32 "~1.3.0"
+    crc-32 "~1.2.0"
+
 chokidar@^4.0.0:
   version "4.0.3"
   resolved "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30"
@@ -456,6 +469,16 @@ chokidar@^4.0.0:
   dependencies:
     readdirp "^4.0.1"
 
+codepage@~1.15.0:
+  version "1.15.0"
+  resolved "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab"
+  integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==
+
+crc-32@~1.2.0, crc-32@~1.2.1:
+  version "1.2.2"
+  resolved "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff"
+  integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
+
 csstype@^3.1.0, csstype@^3.1.3:
   version "3.1.3"
   resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
@@ -521,6 +544,11 @@ fill-range@^7.1.1:
   dependencies:
     to-regex-range "^5.0.1"
 
+frac@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b"
+  integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==
+
 fsevents@~2.3.2, fsevents@~2.3.3:
   version "2.3.3"
   resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
@@ -668,6 +696,13 @@ source-map@^0.6.1:
   resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
   integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
 
+ssf@~0.11.2:
+  version "0.11.2"
+  resolved "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c"
+  integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==
+  dependencies:
+    frac "~1.1.2"
+
 ssr-window@^2.0.0:
   version "2.0.0"
   resolved "https://registry.npmmirror.com/ssr-window/-/ssr-window-2.0.0.tgz#98c301aef99523317f8d69618f0010791096efc4"
@@ -724,3 +759,26 @@ vue@^3.5.13:
     "@vue/runtime-dom" "3.5.13"
     "@vue/server-renderer" "3.5.13"
     "@vue/shared" "3.5.13"
+
+wmf@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da"
+  integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==
+
+word@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.npmmirror.com/word/-/word-0.3.0.tgz#8542157e4f8e849f4a363a288992d47612db9961"
+  integrity sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==
+
+xlsx@^0.18.5:
+  version "0.18.5"
+  resolved "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz#16711b9113c848076b8a177022799ad356eba7d0"
+  integrity sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==
+  dependencies:
+    adler-32 "~1.3.0"
+    cfb "~1.2.1"
+    codepage "~1.15.0"
+    crc-32 "~1.2.1"
+    ssf "~0.11.2"
+    wmf "~1.0.1"
+    word "~0.3.0"