tremble 2 rokov pred
commit
18a869a9dc
94 zmenil súbory, kde vykonal 4814 pridanie a 0 odobranie
  1. 5 0
      .gitignore
  2. 13 0
      index.html
  3. 20 0
      package.json
  4. 62 0
      src/App.vue
  5. BIN
      src/assets/images/banner-js.jpg
  6. BIN
      src/assets/images/bg-top.jpg
  7. BIN
      src/assets/images/bg.jpg
  8. BIN
      src/assets/images/c-bg.jpg
  9. BIN
      src/assets/images/close.png
  10. BIN
      src/assets/images/close_thin.png
  11. BIN
      src/assets/images/h-left.jpg
  12. BIN
      src/assets/images/home-img/1.png
  13. BIN
      src/assets/images/home-img/10.png
  14. BIN
      src/assets/images/home-img/11.png
  15. BIN
      src/assets/images/home-img/12.png
  16. BIN
      src/assets/images/home-img/13.png
  17. BIN
      src/assets/images/home-img/14.png
  18. BIN
      src/assets/images/home-img/15.png
  19. BIN
      src/assets/images/home-img/16.png
  20. BIN
      src/assets/images/home-img/17.png
  21. BIN
      src/assets/images/home-img/18.png
  22. BIN
      src/assets/images/home-img/19.png
  23. BIN
      src/assets/images/home-img/2.png
  24. BIN
      src/assets/images/home-img/20.png
  25. BIN
      src/assets/images/home-img/21.png
  26. BIN
      src/assets/images/home-img/3.png
  27. BIN
      src/assets/images/home-img/4.png
  28. BIN
      src/assets/images/home-img/5.png
  29. BIN
      src/assets/images/home-img/6.png
  30. BIN
      src/assets/images/home-img/7.png
  31. BIN
      src/assets/images/home-img/8.png
  32. BIN
      src/assets/images/home-img/9.png
  33. BIN
      src/assets/images/hp_bg.jpg
  34. BIN
      src/assets/images/jiantou.png
  35. BIN
      src/assets/images/logo.png
  36. BIN
      src/assets/images/qiang.jpg
  37. BIN
      src/assets/images/question_icon.png
  38. BIN
      src/assets/images/title.png
  39. BIN
      src/assets/images/title_bg.png
  40. BIN
      src/assets/images/title_vbg.png
  41. BIN
      src/assets/images/two/1.1.jpg
  42. BIN
      src/assets/images/two/1.2.jpg
  43. BIN
      src/assets/images/two/1.3.jpg
  44. BIN
      src/assets/images/two/1.4.jpg
  45. BIN
      src/assets/images/two/1.5.jpg
  46. BIN
      src/assets/images/two/1.6.jpg
  47. BIN
      src/assets/images/two/2.1.jpg
  48. BIN
      src/assets/images/two/2.2.jpg
  49. BIN
      src/assets/images/two/2.3.jpg
  50. BIN
      src/assets/images/two/2.4.jpg
  51. BIN
      src/assets/images/two/2.5.jpg
  52. BIN
      src/assets/images/two/2.6.jpg
  53. BIN
      src/assets/images/two/3.jpg
  54. BIN
      src/assets/images/two/4.1.jpg
  55. BIN
      src/assets/images/two/4.2.jpg
  56. BIN
      src/assets/images/two/4.3.jpg
  57. BIN
      src/assets/images/two/4.4.jpg
  58. BIN
      src/assets/images/two/4.5.jpg
  59. BIN
      src/assets/images/two/4.6.jpg
  60. BIN
      src/assets/images/two/5.1.jpg
  61. BIN
      src/assets/images/two/5.10.jpg
  62. BIN
      src/assets/images/two/5.11.jpg
  63. BIN
      src/assets/images/two/5.12.jpg
  64. BIN
      src/assets/images/two/5.2.jpg
  65. BIN
      src/assets/images/two/5.3.jpg
  66. BIN
      src/assets/images/two/5.4.jpg
  67. BIN
      src/assets/images/two/5.5.jpg
  68. BIN
      src/assets/images/two/5.6.jpg
  69. BIN
      src/assets/images/two/5.7.jpg
  70. BIN
      src/assets/images/two/5.8.jpg
  71. BIN
      src/assets/images/two/5.9.jpg
  72. BIN
      src/assets/images/txt_active.png
  73. BIN
      src/assets/images/txt_default.png
  74. BIN
      src/assets/style/SourceHanSerifCN-Bold.otf
  75. BIN
      src/assets/style/SourceHanSerifCN-Regular.otf
  76. 50 0
      src/assets/style/my-reset.css
  77. 47 0
      src/assets/style/reset.css
  78. 103 0
      src/components/CollectionSwiper.vue
  79. 53 0
      src/components/CustomTitle.vue
  80. 209 0
      src/components/Directory.vue
  81. 152 0
      src/components/Dropdown.vue
  82. 72 0
      src/components/Search.vue
  83. 192 0
      src/components/detail/ThreeDetail.vue
  84. 209 0
      src/components/detail/TwoDetail.vue
  85. 451 0
      src/data/category.js
  86. 1536 0
      src/data/index.js
  87. 13 0
      src/main.js
  88. 27 0
      src/router/index.js
  89. 379 0
      src/utils/browser.js
  90. 19 0
      src/utils/index.js
  91. 112 0
      src/views/cultural-relic.vue
  92. 275 0
      src/views/home.vue
  93. 21 0
      vite.config.js
  94. 794 0
      yarn.lock

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+node_modules
+.DS_Store
+dist
+dist-ssr
+*.local

+ 13 - 0
index.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
+  <title>乐山大佛文物展示系统</title>
+</head>
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.js"></script>
+</body>
+</html>

+ 20 - 0
package.json

@@ -0,0 +1,20 @@
+{
+  "name": "vite",
+  "version": "0.0.0",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build"
+  },
+  "dependencies": {
+    "@rollup/plugin-inject": "^5.0.3",
+    "swiper": "^9.2.4",
+    "vue": "^3.2.45",
+    "vue-router": "^4.1.6"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^3.2.0",
+    "less": "^4.1.3",
+    "unplugin-vue-components": "^0.22.11",
+    "vite": "^3.2.4"
+  }
+}

+ 62 - 0
src/App.vue

@@ -0,0 +1,62 @@
+
+<template>
+  <router-view class="pc" />
+</template>
+
+<script setup>
+</script>
+
+
+<style>
+@import "@/assets/style/reset.css";
+@import "@/assets/style/my-reset.css";
+
+* {
+  margin: 0;
+  padding: 0;
+}
+
+body {
+  font-size: 16px;
+  background-color: #F5F5F5;
+}
+
+
+::-webkit-scrollbar {
+  display: none;
+}
+
+html,
+body,
+#app {
+  height: 100%;
+  width: 100%;
+  overflow: hidden;
+}
+
+#app {
+  /* background-image: url('@/assets/images/bg.jpg'); */
+  background-size: cover;
+}
+
+li {
+  list-style: none;
+}
+
+
+.v-enter-active,
+.v-leave-active {
+  transition: opacity 0.3s ease;
+}
+
+.v-enter-from,
+.v-leave-to {
+  opacity: 0;
+}
+
+.van-ellipsis {
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+</style>

BIN
src/assets/images/banner-js.jpg


BIN
src/assets/images/bg-top.jpg


BIN
src/assets/images/bg.jpg


BIN
src/assets/images/c-bg.jpg


BIN
src/assets/images/close.png


BIN
src/assets/images/close_thin.png


BIN
src/assets/images/h-left.jpg


BIN
src/assets/images/home-img/1.png


BIN
src/assets/images/home-img/10.png


BIN
src/assets/images/home-img/11.png


BIN
src/assets/images/home-img/12.png


BIN
src/assets/images/home-img/13.png


BIN
src/assets/images/home-img/14.png


BIN
src/assets/images/home-img/15.png


BIN
src/assets/images/home-img/16.png


BIN
src/assets/images/home-img/17.png


BIN
src/assets/images/home-img/18.png


BIN
src/assets/images/home-img/19.png


BIN
src/assets/images/home-img/2.png


BIN
src/assets/images/home-img/20.png


BIN
src/assets/images/home-img/21.png


BIN
src/assets/images/home-img/3.png


BIN
src/assets/images/home-img/4.png


BIN
src/assets/images/home-img/5.png


BIN
src/assets/images/home-img/6.png


BIN
src/assets/images/home-img/7.png


BIN
src/assets/images/home-img/8.png


BIN
src/assets/images/home-img/9.png


BIN
src/assets/images/hp_bg.jpg


BIN
src/assets/images/jiantou.png


BIN
src/assets/images/logo.png


BIN
src/assets/images/qiang.jpg


BIN
src/assets/images/question_icon.png


BIN
src/assets/images/title.png


BIN
src/assets/images/title_bg.png


BIN
src/assets/images/title_vbg.png


BIN
src/assets/images/two/1.1.jpg


BIN
src/assets/images/two/1.2.jpg


BIN
src/assets/images/two/1.3.jpg


BIN
src/assets/images/two/1.4.jpg


BIN
src/assets/images/two/1.5.jpg


BIN
src/assets/images/two/1.6.jpg


BIN
src/assets/images/two/2.1.jpg


BIN
src/assets/images/two/2.2.jpg


BIN
src/assets/images/two/2.3.jpg


BIN
src/assets/images/two/2.4.jpg


BIN
src/assets/images/two/2.5.jpg


BIN
src/assets/images/two/2.6.jpg


BIN
src/assets/images/two/3.jpg


BIN
src/assets/images/two/4.1.jpg


BIN
src/assets/images/two/4.2.jpg


BIN
src/assets/images/two/4.3.jpg


BIN
src/assets/images/two/4.4.jpg


BIN
src/assets/images/two/4.5.jpg


BIN
src/assets/images/two/4.6.jpg


BIN
src/assets/images/two/5.1.jpg


BIN
src/assets/images/two/5.10.jpg


BIN
src/assets/images/two/5.11.jpg


BIN
src/assets/images/two/5.12.jpg


BIN
src/assets/images/two/5.2.jpg


BIN
src/assets/images/two/5.3.jpg


BIN
src/assets/images/two/5.4.jpg


BIN
src/assets/images/two/5.5.jpg


BIN
src/assets/images/two/5.6.jpg


BIN
src/assets/images/two/5.7.jpg


BIN
src/assets/images/two/5.8.jpg


BIN
src/assets/images/two/5.9.jpg


BIN
src/assets/images/txt_active.png


BIN
src/assets/images/txt_default.png


BIN
src/assets/style/SourceHanSerifCN-Bold.otf


BIN
src/assets/style/SourceHanSerifCN-Regular.otf


+ 50 - 0
src/assets/style/my-reset.css

@@ -0,0 +1,50 @@
+@font-face {
+  font-family: 'Source Han Serif CN';
+  src: url(./SourceHanSerifCN-Regular.otf);
+}
+
+@font-face {
+  font-family: 'Source Han Serif CN-Bold';
+  src: url(./SourceHanSerifCN-Bold.otf);
+}
+
+* {
+  /* 阻止safari在用户交互设置一些元素的背景色 */
+  -webkit-tap-highlight-color: transparent;
+  font-family: 'Source Han Serif CN';
+  font-display: optional;
+}
+
+html {
+  overflow: hidden;
+}
+
+body {
+  text-align: justify;
+}
+
+a {
+  color: initial;
+  text-decoration: initial;
+  outline: none;
+}
+
+button {
+  padding: 0;
+  cursor: pointer;
+  background-color: initial;
+  border: initial;
+  outline: none;
+}
+
+img {
+  user-select: none;
+}
+
+menu {
+  list-style-type: initial;
+}
+
+li {
+  display: initial;
+}

+ 47 - 0
src/assets/style/reset.css

@@ -0,0 +1,47 @@
+/* http://meyerweb.com/eric/tools/css/reset/ 
+   v2.0 | 20110126
+   License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+	margin: 0;
+	padding: 0;
+	border: 0;
+	font-size: 100%;
+	vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure, 
+footer, header, hgroup, menu, nav, section {
+	display: block;
+}
+body {
+	line-height: 1;
+}
+ol, ul {
+	list-style: none;
+}
+blockquote, q {
+	quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+	content: '';
+	content: none;
+}
+table {
+	border-collapse: collapse;
+	border-spacing: 0;
+}

+ 103 - 0
src/components/CollectionSwiper.vue

@@ -0,0 +1,103 @@
+<template>
+  <swiper :modules="modules" :space-between="38" :scrollbar="{ draggable: true }" :freeMode="true" :observer="true"
+    :mousewheel="true" :grid="{
+      rows: 2,
+    }" :slidesPerView="'auto'" @swiper="onSwiper" @slideChange="onSlideChange">
+    <swiper-slide class='slide-item' v-for="item in list" :key="item">
+      <img v-lazy="`${$config.MODELLINKPERFIX}/images/${item.id}.jpg`"
+        :src="`${$config.MODELLINKPERFIX}/images/${item.id}.jpg`" alt="">
+      <span :title="item.name" class='i-name'>{{ item.name }}</span>
+    </swiper-slide>
+  </swiper>
+
+    
+  <teleport to='body'>
+    <Transition>
+      <ThreeDetail @close="isShowHP = false" v-if="isShowHP" />
+    </Transition>
+  </teleport>
+</template>
+
+<script setup>
+import { Grid, FreeMode, Mousewheel } from 'swiper';
+// Import Swiper Vue.js components
+import { Swiper, SwiperSlide } from 'swiper/vue';
+import { ref } from 'vue';
+import ThreeDetail from "@/components/detail/ThreeDetail.vue";
+
+// Import Swiper styles
+import 'swiper/css';
+import 'swiper/css/grid';
+import 'swiper/css/free-mode';
+import 'swiper/css/mousewheel';
+
+import { menu, rawData } from "@/data/index.js";
+
+const onSwiper = (swiper) => {
+  console.log(swiper);
+};
+const onSlideChange = () => {
+  console.log('slide change');
+};
+
+const list = ref(rawData)
+const isShowHP =ref(true)
+
+
+const modules = [Grid, FreeMode, Mousewheel]
+
+</script>
+
+
+
+
+<style lang="less" scoped>
+.swiper {
+  height: 100%;
+  width: 100%;
+
+  .swiper-slide {
+    text-align: center;
+    font-size: 18px;
+    width: 406px;
+    height: 268px;
+    background-size: cover;
+    border-radius: 10px;
+    display: inline-block;
+    position: relative;
+    overflow: hidden;
+    box-sizing: border-box;
+    cursor: pointer;
+    >img{
+      width: 100%;
+      height: 100%;
+      object-fit: cover;
+    }
+
+    .i-name {
+      position: absolute;
+      transform: translateY(-100%);
+      left: 0;
+      bottom: 0;
+      width: 100%;
+      height: 100%;
+      line-height: 1.5;
+      padding: 0 10px;
+      color: #EAE7DA;
+      box-sizing: border-box;
+      background: #911927;
+      font-size: 24px;
+      display: flex;
+      flex-wrap: wrap;
+      justify-content: center;
+      align-items: center;
+      transition: transform .3s ease;
+    }
+    &:hover{
+      .i-name{
+        transform: translateY(0);
+      }
+    }
+  }
+}
+</style>

+ 53 - 0
src/components/CustomTitle.vue

@@ -0,0 +1,53 @@
+<template>
+  <div :class="['custom-title', size, direction]" :style="{ backgroundImage: `url(${bgimg})` }">
+    {{ word }}
+  </div>
+</template>
+
+<script setup>
+const props = defineProps({
+  word: String,
+  size: {
+    default: 'normal',
+    type: String
+  },
+  direction: {
+    default: '',
+    type: String
+  }
+})
+
+let bgimg = utils.getImageUrl('title_vbg.png');
+
+
+</script>
+
+<style lang="less" scoped>
+.custom-title {
+  background-size: 100% 100%;
+  background-repeat: no-repeat;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  letter-spacing: 2px;
+  font-size: 20px;
+  writing-mode: vertical-lr;
+  color: #EAE7DA;
+  min-height: 215px;
+  min-width: 50px;
+  flex-shrink: 0;
+  &.mini {
+
+  }
+
+  &.column {
+    display: flex;
+    flex-direction: column;
+    flex-wrap: wrap;
+
+    >li {
+      margin-right: 0.5rem;
+    }
+  }
+}
+</style>

+ 209 - 0
src/components/Directory.vue

@@ -0,0 +1,209 @@
+<template>
+  <div class="dir-con">
+    <swiper class="dir-body" :modules="modules" :space-between="80" :scrollbar="{ draggable: true }" :freeMode="true"
+      :slides-per-view="'auto'" :observer="true" :mousewheel="true">
+      <swiper-slide class="mobileslide" v-for="(item, index) in dirlist" :key="item.id">
+        <div class="db-slide">
+          <CustomTitle :word="item.name" />
+          <ul class="imgcon" :class="`imgcon${index + 1}`">
+            <li @click="onClickItem(sub)" :class="`imgli${idx + 1}`" v-for="(sub, idx) in item.imgs" :key="sub.id">
+              <img :src="$getImageUrl(`two/${sub.id}.jpg`)" alt="">
+              <span :title="sub.name" class='i-name'>{{ sub.name }}</span>
+            </li>
+          </ul>
+        </div>
+      </swiper-slide>
+    </swiper>
+  </div>
+
+  
+  <teleport to='body'>
+    <Transition>
+      <TwoDetail @close="isShowHP = false" v-if="isShowHP" />
+    </Transition>
+  </teleport>
+</template>
+
+<script setup>
+import { nextTick, watch, onMounted, getCurrentInstance, ref } from "vue"
+import { two } from "@/data/category";
+import CustomTitle from "@/components/CustomTitle.vue";
+import TwoDetail from "@/components/detail/TwoDetail.vue";
+
+import { FreeMode, Mousewheel } from 'swiper';
+// Import Swiper Vue.js components
+import { Swiper, SwiperSlide } from 'swiper/vue';
+
+import 'swiper/css';
+import 'swiper/css/free-mode';
+import 'swiper/css/mousewheel';
+
+const dirlist = two.data
+
+const onSwiper = (swiper) => {
+  console.log(swiper);
+};
+const onSlideChange = () => {
+  console.log('slide change');
+};
+
+const modules = [FreeMode, Mousewheel]
+
+
+const isShowHP = ref(true)
+
+
+const instance = getCurrentInstance()
+const globalProperties = instance.appContext.app.config.globalProperties
+
+
+
+const onClickItem = item => {
+}
+
+
+
+onMounted(() => {
+})
+
+
+</script>
+
+<style lang="less" scoped>
+// 定义变量
+@grid-columns: 4;
+@grid-rows: 2;
+
+// 循环生成样式规则
+.generate-styles() {
+  .loop (@i) when (@i <=@grid-rows * @grid-columns) {
+    .imgli@{i} {
+      grid-area: e('imgli@{i}');
+    }
+
+    .loop(@i + 1);
+  }
+
+  .loop(1);
+}
+
+
+.dir-con {
+  height: 100%;
+  box-sizing: border-box;
+
+
+  .dir-body {
+    height: 100%;
+    position: relative;
+    overflow: hidden;
+
+    .swiper-wrapper {
+      height: 100%;
+
+      .swiper-slide {
+        display: flex;
+        height: 100%;
+        width: auto;
+        font-size: 0;
+
+        .db-slide {
+          display: flex;
+          align-items: flex-start;
+          height: 100%;
+          @ligap: 10px;
+
+
+          .imgcon {
+            height: 100%;
+            font-size: 0;
+            display: grid;
+            gap: @ligap;
+            margin-left: @ligap * 3;
+
+            >li {
+              display: inline-block;
+              height: 100%;
+              overflow: hidden;
+              font-size: 0;
+              cursor: pointer;
+              position: relative;
+              border-radius: 4px;
+              >img {
+                width: 100%;
+                height: 100%;
+                object-fit: cover;
+                border: 2px solid #fff;
+                border-radius: 4px;
+                box-sizing: border-box;
+              }
+
+              .i-name {
+                content: '';
+                position: absolute;
+                transform: translateY(-100%);
+                left: 0;
+                bottom: 0;
+                width: 100%;
+                height: 100%;
+                line-height: 1.5;
+                padding: 0 10px;
+                color: #EAE7DA;
+                box-sizing: border-box;
+                background: #911927;
+                font-size: 24px;
+                display: flex;
+                flex-wrap: wrap;
+                justify-content: center;
+                align-items: center;
+                transition: transform .3s ease;
+              }
+
+              &:hover {
+                .i-name {
+                  transform: translateY(0);
+                }
+              }
+            }
+
+            .generate-styles()
+          }
+
+          .imgcon1 {
+            grid-template-areas:
+              'imgli1 imgli2 imgli3 imgli4 imgli4 imgli4 imgli4 imgli4 imgli4 imgli4 imgli4 imgli4 imgli6'
+              'imgli1 imgli2 imgli5 imgli5 imgli5 imgli5 imgli5 imgli5 imgli5 imgli5 imgli5 imgli5 imgli6';
+          }
+
+          .imgcon2 {
+            grid-template-areas:
+              'imgli1 imgli2 imgli3 imgli4'
+              'imgli1 imgli2 imgli5 imgli6';
+          }
+
+          .imgcon3 {
+            display: flex;
+          }
+
+          .imgcon4 {
+            grid-template-areas:
+              'imgli1 imgli2 imgli3 imgli3 imgli5 imgli6'
+              'imgli1 imgli2 imgli4 imgli4 imgli5 imgli6';
+          }
+
+          .imgcon5 {
+            grid-template-rows: repeat(3, 1fr);
+            /* 定义四行,每行高度相等 */
+            grid-template-columns: repeat(4, 1fr);
+
+            /* 定义三列,每列宽度相等 */
+            >li {
+              grid-area: auto !important;
+            }
+          }
+        }
+      }
+    }
+
+  }
+}</style>

+ 152 - 0
src/components/Dropdown.vue

@@ -0,0 +1,152 @@
+<template>
+  <div class="dropdown">
+    <div class="dropdown-toggle" @click="toggleDropdown">
+      {{ selected }}
+      <i class="arrow" :class="{ 'up': isOpen, 'down': !isOpen }"></i>
+    </div>
+    <transition name="fade">
+      <div class="dropdown-menu" v-if="isOpen">
+        <div class="dropdown-item" @click="selectOption('全部')">全部</div>
+        <div class="dropdown-item" v-for="option in options" :key="option" @click="selectOption(option)">{{ option }}
+        </div>
+      </div>
+    </transition>
+  </div>
+</template>
+
+<script>
+import { ref, watchEffect } from 'vue';
+
+export default {
+  name: 'Dropdown',
+  props: {
+    options: {
+      type: Array,
+      required: true,
+    },
+    defaultOption: {
+      type: String,
+      default: '全部',
+    },
+  },
+  setup(props) {
+    const isOpen = ref(false);
+    const selected = ref(props.defaultOption);
+
+    const toggleDropdown = () => {
+      isOpen.value = !isOpen.value;
+    };
+
+    const selectOption = (option) => {
+      selected.value = option;
+      isOpen.value = false;
+    };
+
+
+    const onClickOutside = (event) => {
+      if (event.target.closest('.dropdown') === null) {
+        isOpen.value = false;
+      }
+    };
+
+    const addClickOutsideListener = () => {
+      document.addEventListener('click', onClickOutside);
+    };
+
+    const removeClickOutsideListener = () => {
+      document.removeEventListener('click', onClickOutside);
+    };
+
+    return {
+      isOpen,
+      selected,
+      toggleDropdown,
+      selectOption,
+      addClickOutsideListener,
+      removeClickOutsideListener,
+    };
+  },
+  mounted() {
+    this.addClickOutsideListener();
+  },
+  unmounted() {
+    this.removeClickOutsideListener();
+  },
+};
+</script>
+
+<style lang="less">
+.dropdown {
+  position: relative;
+  display: inline-block;
+  margin-right: 1rem;
+}
+
+.dropdown-toggle {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0 1rem;
+  cursor: pointer;
+  width: 190px;
+  height: 40px;
+  background: #FFFFFF;
+  border-radius: 50px;
+  border: 1px solid #999999;
+}
+
+.arrow {
+  margin-left: 0.5rem;
+  width: 0;
+  height: 0;
+  border-style: solid;
+  border-width: 5px 5px 0 5px;
+  border-color: #666 transparent transparent transparent;
+  transition: transform 0.3s ease;
+
+  &.up {
+    transform: rotate(180deg);
+  }
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: calc(100% + 8px);
+  left: 0;
+  min-width: 10rem;
+  padding: 0.5rem 0;
+  width: 100%;
+  background-color: #fff;
+  border-radius: 4px;
+  z-index: 1;
+  width: 100%;
+  background: rgba(159, 25, 39, 0.9);
+  border-radius: 10px;
+}
+
+.dropdown-item {
+  display: block;
+  padding: 0.5rem 1rem;
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+
+  &:hover {
+    color: rgba(211, 180, 83, 1);
+  }
+}
+
+.dropdown-menu.show {
+  display: block;
+}
+
+.fade-enter-active,
+.fade-leave-active {
+  transition: opacity 0.3s ease;
+}
+
+.fade-enter-from,
+.fade-leave-to {
+  opacity: 0;
+}
+</style>

+ 72 - 0
src/components/Search.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="search">
+    <div class="inputcon">
+      <input type="text" v-model="keyword" :placeholder="placeholder" />
+      <van-icon name="search" />
+    </div>
+    <van-button round type="primary" @click="search">查询</van-button>
+    <van-button round type="primary" plain @click="search">重置</van-button>
+  </div>
+</template>
+
+<script>
+import { ref } from 'vue';
+
+export default {
+  name: 'Search',
+  props: {
+    placeholder: {
+      type: String,
+      default: '请输入关键字',
+    },
+  },
+  setup(props, { emit }) {
+    const keyword = ref('');
+
+    const search = () => {
+      emit('search', keyword.value);
+    };
+
+    return {
+      keyword,
+      search,
+    };
+  },
+};
+</script>
+
+<style lang="less">
+.search {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  width: 100%;
+
+  .inputcon {
+    width: 310px;
+    height: 40px;
+    position: relative;
+
+    input[type='text'] {
+      border-radius: 4px;
+      padding: 0 40px 0 20px;
+      width: 100%;
+      height: 100%;
+      background: #FFFFFF;
+      border-radius: 50px;
+      border: 1px solid #999999;
+      box-sizing: border-box;
+    }
+
+    >i {
+      position: absolute;
+      right: 16px;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+  }
+
+
+}
+</style>
+

+ 192 - 0
src/components/detail/ThreeDetail.vue

@@ -0,0 +1,192 @@
+<template>
+  <div class="two-hp">
+    <div class="content">
+      <img class="bg" :src="popImg" alt="">
+      <div class="inner">
+        <div class="left">
+          <video ref="video$" muted autoplay :poster="videoPostImg" class="initial-video" playsinline="true"
+            x5-playsinline="true" webkit-playsinline="true"
+            src="https://culture.4dage.com/demo/gaoxinqu/source/videos/video.mp4" @mousedown.passive.stop
+            @touchstart.passive.stop @wheel.passive.stop />
+        </div>
+        <div class="right">
+          <h2>明蓝釉女陶侍俑</h2>
+          <p>年代:汉朝 </p>
+          <p>尺寸:长19,宽17.5,高33厘米</p>
+          <swiper class="dir-body" :modules="modules" :space-between="10" :scrollbar="{ draggable: true }"
+            :freeMode="true" :slides-per-view="'auto'" :observer="true" :mousewheel="true">
+            <swiper-slide v-for="item in 5" :key="item.id">
+              <div class="db-slide" @click="showIfr = true">
+                <img src="https://4dscene.4dage.com/culturalrelics/FJBWG/images/fj01.jpg" alt="">
+              </div>
+            </swiper-slide>
+          </swiper>
+        </div>
+      </div>
+      <img class="close" @click="$emit('close')" :src="closeImg" alt="">
+    </div>
+
+    <Transition>
+      <div class="ifrcontent" v-if="showIfr">
+        <div class="title">明蓝釉女陶侍俑</div>
+        <iframe src="https://4dscene.4dage.com/culturalrelics/FJBWG/Model2.html?m=fj01" frameborder="0"></iframe>
+        <img class="close" @click="showIfr = false" :src="close_thin" alt="">
+      </div>
+    </Transition>
+    
+  </div>
+</template>
+
+<script setup>
+import { ref } from "vue"
+import { Grid, FreeMode, Mousewheel } from 'swiper';
+import { Swiper, SwiperSlide } from 'swiper/vue';
+
+import 'swiper/css';
+import 'swiper/css/grid';
+import 'swiper/css/free-mode';
+import 'swiper/css/mousewheel';
+
+
+const popImg = utils.getImageUrl(`hp_bg.jpg`)
+const closeImg = utils.getImageUrl(`close.png`)
+const close_thin = utils.getImageUrl(`close_thin.png`)
+const showIfr = ref(false)
+
+const modules = [Grid, FreeMode, Mousewheel]
+
+</script>
+
+<style lang="less" scoped>
+.two-hp {
+  position: fixed;
+  top: 0;
+  z-index: 999;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(190, 180, 166, 0.8);
+  backdrop-filter: blur(20px);
+
+  .content,
+  .ifrcontent {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    width: 70%;
+    border-radius: 10px;
+    overflow: hidden;
+
+    .inner {
+      display: flex;
+      position: absolute;
+      left: 0;
+      top: 0;
+      bottom: 0;
+      right: 0;
+      width: 100%;
+      height: 100%;
+      display: flex;
+      align-items: center;
+      padding: 0 30px;
+
+      .left {
+        width: 60%;
+        flex-shrink: 0;
+        padding: 10px;
+        border: 3px solid #83796F;
+
+        >video {
+          width: 100%;
+        }
+      }
+
+      .right {
+        padding-left: 30px;
+        width: 33%;
+        box-sizing: border-box;
+
+        >h2 {
+          color: #911927;
+          font-size: 30px;
+          line-height: 1.5;
+          margin-bottom: 10px;
+        }
+
+        >p {
+          font-size: 26px;
+          color: #7A6553;
+          line-height: 1.5;
+        }
+
+        .dir-body {
+          position: relative;
+          margin-top: 40%;
+
+          .swiper-wrapper {
+            width: 100%;
+
+            .swiper-slide {
+              width: 50%;
+              border-radius: 5px;
+              overflow: hidden;
+
+              .db-slide {
+                width: 100%;
+                cursor: pointer;
+                >img {
+                  width: 100%;
+                }
+              }
+            }
+          }
+
+        }
+      }
+    }
+
+    .bg {
+      width: 100%;
+    }
+
+    .close {
+      position: absolute;
+      right: 20px;
+      top: 20px;
+      z-index: 99;
+      cursor: pointer;
+      width: 50px;
+    }
+  }
+
+  .ifrcontent {
+    z-index: 1;
+    width: 80%;
+    height: 80%;
+    background: rgba(0, 0, 0, 0.5);
+
+    .title {
+      position: absolute;
+      left: 20px;
+      color: #fff;
+      line-height: 45px;
+      height: 45px;
+      padding: 0 40px 0 20px;
+      top: 20px;
+      z-index: 99;
+      background-image: linear-gradient(90deg, #911927, rgba(145, 25, 39, 0));
+    }
+
+    >iframe {
+      width: 100%;
+      height: 100%;
+    }
+
+    .close {
+      width: 40px;
+    }
+  }
+}</style>

+ 209 - 0
src/components/detail/TwoDetail.vue

@@ -0,0 +1,209 @@
+<template>
+  <div class="two-hp">
+    <div class="content">
+      <img class="bg" :src="popImg" alt="">
+      <div class="inner">
+        <div class="left">
+          <video ref="video$" muted autoplay :poster="videoPostImg" class="initial-video" playsinline="true"
+            x5-playsinline="true" webkit-playsinline="true"
+            src="https://culture.4dage.com/demo/gaoxinqu/source/videos/video.mp4" @mousedown.passive.stop
+            @touchstart.passive.stop @wheel.passive.stop />
+        </div>
+        <div class="right">
+          <h2>明蓝釉女陶侍俑</h2>
+          <ul>
+            <li v-for="item in 10" :key="item">
+              <img src="https://4dscene.4dage.com/culturalrelics/FJBWG/images/fj01.jpg" alt="">
+              <span :title="'明蓝釉女陶侍俑'" class='i-name'>明蓝釉女陶侍俑</span>
+            </li>
+          </ul>
+        </div>
+      </div>
+      <img class="close" @click="$emit('close')" :src="closeImg" alt="">
+    </div>
+
+    <Transition>
+      <div class="ifrcontent" v-if="showIfr">
+        <div class="title">明蓝釉女陶侍俑</div>
+        <img src="https://4dscene.4dage.com/culturalrelics/FJBWG/images/fj01.jpg" class="imgcon" alt="">
+        <img class="close" @click="showIfr = false" :src="close_thin" alt="">
+      </div>
+    </Transition>
+
+  </div>
+</template>
+
+<script setup>
+import { ref } from "vue"
+
+const popImg = utils.getImageUrl(`hp_bg.jpg`)
+const closeImg = utils.getImageUrl(`close.png`)
+const close_thin = utils.getImageUrl(`close_thin.png`)
+const showIfr = ref(true)
+
+
+</script>
+
+<style lang="less" scoped>
+.two-hp {
+  position: fixed;
+  top: 0;
+  z-index: 999;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(190, 180, 166, 0.8);
+  backdrop-filter: blur(20px);
+
+  .content,
+  .ifrcontent {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    width: 70%;
+    border-radius: 10px;
+    overflow: hidden;
+
+    .inner {
+      display: flex;
+      position: absolute;
+      left: 0;
+      top: 0;
+      bottom: 0;
+      right: 0;
+      width: 100%;
+      height: 100%;
+      display: flex;
+      align-items: center;
+      padding: 0 30px;
+
+      .left {
+        width: 60%;
+        flex-shrink: 0;
+        padding: 10px;
+        border: 3px solid #83796F;
+        height: 73%;
+
+        >video {
+          width: 100%;
+          height: 100%;
+        }
+      }
+
+      .right {
+        padding-left: 30px;
+        width: 33%;
+        box-sizing: border-box;
+        height: 73%;
+        display: flex;
+        flex-direction: column;
+
+        >h2 {
+          color: #911927;
+          font-size: 26px;
+          line-height: 1.5;
+          margin-bottom: 10px;
+        }
+
+        >ul {
+          width: 100%;
+          display: flex;
+          flex-wrap: wrap;
+          max-height: 86%;
+          overflow-y: auto;
+
+          >li {
+            width: 49%;
+            border-radius: 4px;
+            overflow: hidden;
+            margin-bottom: 2px;
+            position: relative;
+            cursor: pointer;
+
+            &:nth-of-type(2n) {
+              margin-left: 1%;
+            }
+
+            >img {
+              width: 100%;
+            }
+
+            .i-name {
+              content: '';
+              position: absolute;
+              transform: translateY(-100%);
+              left: 0;
+              bottom: 0;
+              width: 100%;
+              height: 100%;
+              line-height: 1.5;
+              padding: 0 10px;
+              color: #EAE7DA;
+              box-sizing: border-box;
+              background: #911927;
+              font-size: 18px;
+              display: flex;
+              flex-wrap: wrap;
+              justify-content: center;
+              align-items: center;
+              transition: transform .3s ease;
+            }
+
+            &:hover {
+              .i-name {
+                transform: translateY(0);
+              }
+            }
+          }
+        }
+
+      }
+    }
+
+    .bg {
+      width: 100%;
+    }
+
+    .close {
+      position: absolute;
+      right: 20px;
+      top: 20px;
+      z-index: 99;
+      cursor: pointer;
+      width: 50px;
+    }
+  }
+
+  .ifrcontent {
+    z-index: 1;
+    width: 80%;
+    height: 80%;
+    background: linear-gradient(180deg, #75736E 0%, #BCBBB8 100%);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    .title {
+      position: absolute;
+      left: 20px;
+      color: #fff;
+      line-height: 45px;
+      height: 45px;
+      padding: 0 40px 0 20px;
+      top: 20px;
+      z-index: 99;
+      background-image: linear-gradient(90deg, #911927, rgba(145, 25, 39, 0));
+    }
+
+    .imgcon {
+      max-width: 90%;
+      max-height: 90%;
+    }
+
+    .close {
+      width: 40px;
+    }
+  }
+}</style>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 451 - 0
src/data/category.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1536 - 0
src/data/index.js


+ 13 - 0
src/main.js

@@ -0,0 +1,13 @@
+import { createApp } from 'vue';
+import App from './App.vue';
+import router from './router'
+import utils from './utils/index'
+
+const app = createApp(App)
+app.config.globalProperties.$getImageUrl = utils.getImageUrl
+app.config.globalProperties.$config = {
+  CDNPERFIX:"https://4dscene.4dage.com/wuhu/FuJian",
+  MODELLINKPERFIX:"https://4dscene.4dage.com/culturalrelics/FJBWG",
+}
+app.use(router).mount('#app');
+

+ 27 - 0
src/router/index.js

@@ -0,0 +1,27 @@
+import { createRouter, createWebHashHistory } from 'vue-router'
+import Home from '@/views/home.vue'
+
+const routes = [
+  {
+    path: '/',
+    name: 'Home',
+    component: Home
+  }
+]
+
+
+const router = createRouter({
+  history: createWebHashHistory(),
+  routes
+})
+
+
+
+router.beforeEach((to, from, next) => {
+  setTimeout(() => {
+    window.scrollTo(0, 0)
+  }, 200);
+  next();
+});
+
+export default router

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 379 - 0
src/utils/browser.js


+ 19 - 0
src/utils/index.js

@@ -0,0 +1,19 @@
+export default {
+  throttle: function (fn, interval) {
+    let lastRunTime = 0
+
+    return function (...args) {
+      let elapsedTime = Date.now() - lastRunTime
+      if (elapsedTime < interval) {
+        return
+      }
+
+      let context = this
+      lastRunTime = Date.now()
+      fn.apply(context, args)
+    }
+  },
+  getImageUrl(name) {
+    return new URL(`../assets/images/${name}`, import.meta.url).href
+  }
+}

+ 112 - 0
src/views/cultural-relic.vue

@@ -0,0 +1,112 @@
+<template>
+  <div class="collection">
+    <div class="c-header">
+      <img draggable="false" class="logo" :src="$getImageUrl('logo.png')" alt="">
+      <img @click="$emit('close')" draggable="false" class="close" :src="$getImageUrl('close.png')" alt="">
+    </div>
+    <div class="c-con">
+      <ul class="ccheader">
+        <li @click="activeIdx='three'" :class="{active:activeIdx==='three'}">
+          <img draggable="false" :src="$getImageUrl(`${activeIdx==='three'?'txt_active.png':'txt_default.png'}`)" alt="">
+          <span>三维文物</span>
+        </li>
+        
+        <li @click="activeIdx='two'" :class="{active:activeIdx==='two'}">
+          <img draggable="false" :src="$getImageUrl(`${activeIdx==='two'?'txt_active.png':'txt_default.png'}`)" alt="">
+          <span>二维文物</span>
+        </li>
+      </ul>
+
+      <div class="cclist">
+        <Directory v-if="activeIdx==='two'" />
+        <CollectionSwiper v-else/>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+import CollectionSwiper from '@/components/CollectionSwiper.vue';
+import Directory from '@/components/Directory.vue';
+
+const activeIdx = ref('three')
+
+</script>
+
+<style lang="less">
+.collection {
+  width: 100%;
+  height: 100%;
+  background-image: url('@/assets/images/c-bg.jpg');
+  background-size: cover;
+  background-repeat: no-repeat;
+  display: flex;
+  align-items: center;
+  position: fixed;
+  left: 0;
+  top: 0;
+  z-index: 999;
+
+  .c-header {
+    .logo {
+      position: absolute;
+      left: 2rem;
+      top: 2rem;
+      width: 6%;
+    }
+
+    .close {
+      position: absolute;
+      right: 2rem;
+      top: 2rem;
+      width: 3%;
+      cursor: pointer;
+    }
+
+  }
+
+  .c-con {
+    height: 80%;
+    width: 100%;
+    box-sizing: border-box;
+    padding: 32px 10px 32px 50px;
+
+    .ccheader {
+      position: relative;
+      z-index: 99;
+      display: flex;
+      width: 100%;
+      justify-content: center;
+      >li{
+        position: relative;
+        font-size: 0;
+        margin: 0 1rem;
+        cursor: pointer;
+        >span{
+          font-size: 1rem;
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          transform: translate(-50%,-50%);
+          color: #7A6553;
+        }
+        >img{
+          max-width: 100%;
+        }
+        &.active{
+          >span{
+            color: #EAE7DA;
+          }
+        }
+      }
+    }
+
+    .cclist {
+      width: 100%;
+      height: calc(100% - 50px);
+      margin-top: 40px;
+    }
+  }
+}
+</style>

+ 275 - 0
src/views/home.vue

@@ -0,0 +1,275 @@
+<template>
+  <div class="home" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp" @mouseleave="onMouseLeave"
+    @touchstart.passive="onTouchStart" @touchmove.prevent="onTouchMove" @touchend="onTouchEnd"
+    @touchcancel="onTouchCancel" @wheel.passive="onWheel">
+
+    <div ref="hcon$" class="h-con" :style="{
+      left: `-${translateLength}px`,
+    }">
+      <div class="h-left">
+        <img draggable="false" :src="$getImageUrl('h-left.jpg')" alt="">
+        <div class="l-con">
+          <img draggable="false" class="title" :src="$getImageUrl('title.png')" alt="">
+        </div>
+      </div>
+
+      <div class="h-right">
+        <ul>
+          <li v-for="item in 21" :key="item">
+            <img @click="isShowCR = true" draggable="false" class="title" :src="$getImageUrl(`home-img/${item}.png`)" alt="">
+          </li>
+        </ul>
+      </div>
+    </div>
+
+    <teleport to='body'>
+      <Transition>
+        <CulturalRelic @close="isShowCR = false" v-if="isShowCR" />
+      </Transition>
+    </teleport>
+  </div>
+</template>
+
+<script setup>
+import { onBeforeUnmount, onMounted, ref } from "vue"
+
+import CulturalRelic from "@/views/cultural-relic.vue"
+
+
+
+const isMouseDown = ref(false);
+const lastMoveEventTimeStamp = ref(0);
+const moveSpeed = ref(0);
+const lastTouchPos = ref(0);
+const maxTranslateLength = ref(0);
+
+// 动画帧相关
+const lastAnimationTimeStamp = ref(0);
+const animationFrameId = ref(0);
+
+const isShowCR = ref(true);
+
+
+
+// 镜头平移相关
+const translateLength = ref(0);
+
+
+const hcon$ = ref(null)
+
+const animationFrameTask = () => {
+  const timeStamp = Date.now()
+  const timeElapsed = timeStamp - lastAnimationTimeStamp.value
+
+  // 速度减慢
+  if (moveSpeed.value > 0) {
+    moveSpeed.value -= 0.003 * timeElapsed
+    if (moveSpeed.value < 0) {
+      moveSpeed.value = 0
+    }
+  } else if (moveSpeed.value < 0) {
+    moveSpeed.value += 0.003 * timeElapsed
+    if (moveSpeed.value > 0) {
+      moveSpeed.value = 0
+    }
+  }
+
+  // 根据速度更新距离
+  translateLength.value += moveSpeed.value * timeElapsed
+  if (translateLength.value < 0) {
+    translateLength.value = 0
+  } else if (translateLength.value > maxTranslateLength.value) {
+    translateLength.value = maxTranslateLength.value
+    moveSpeed.value = 0
+  }
+
+  lastAnimationTimeStamp.value = timeStamp
+  animationFrameId.value = requestAnimationFrame(animationFrameTask)
+}
+
+const calcTranslateLimit = () => {
+  maxTranslateLength.value = hcon$.value.clientWidth - window.innerWidth
+}
+
+const onMouseDown = () => {
+  isMouseDown.value = true
+  moveSpeed.value = 0
+  lastMoveEventTimeStamp.value = 0
+  lastAnimationTimeStamp.value = Date.now()
+}
+
+
+const onMouseMove = (e) => {
+  if (isMouseDown.value) {
+    // 有些pc端浏览器比如firefox会有两次事件时间戳相同的情况发生。
+    if (lastMoveEventTimeStamp.value && (e.timeStamp - lastMoveEventTimeStamp.value > 1)) {
+      // 更新speed
+      const currentMoveSpeed = - e.movementX / (e.timeStamp - lastMoveEventTimeStamp.value)
+      moveSpeed.value = moveSpeed.value * 0.9 + currentMoveSpeed * 0.1
+    }
+    lastMoveEventTimeStamp.value = e.timeStamp
+  }
+}
+
+const onMouseUp = () => {
+  isMouseDown.value = false
+}
+
+const onMouseLeave = () => {
+  isMouseDown.value = false
+}
+
+const onTouchStart = (e) => {
+  isMouseDown.value = true
+  moveSpeed.value = 0
+  lastMoveEventTimeStamp.value = 0
+  lastAnimationTimeStamp.value = Date.now()
+  lastTouchPos.value = e.changedTouches[0].clientX
+}
+
+
+const onTouchMove = (e) => {
+  if (isMouseDown.value && e.changedTouches.length === 1) {
+    // 疯狂操作的极端情况下两个时间戳之间的时差会不合理,甚至为0
+    if (lastMoveEventTimeStamp.value && (e.timeStamp - lastMoveEventTimeStamp.value > 1)) {
+      // 更新speed
+      const currentMoveSpeed = - (e.changedTouches[0].clientX - lastTouchPos.value) / (e.timeStamp - lastMoveEventTimeStamp.value) * 1.5
+      moveSpeed.value = moveSpeed.value * 0.9 + currentMoveSpeed * 0.1
+      lastTouchPos.value = e.changedTouches[0].clientX
+    }
+    lastMoveEventTimeStamp.value = e.timeStamp
+  }
+}
+
+
+const onTouchEnd = () => {
+  isMouseDown.value = false
+}
+
+
+const onTouchCancel = () => {
+  isMouseDown.value = false
+}
+
+
+const onWheel = (e) => {
+  translateLength.value += e.deltaY
+  if (translateLength.value < 0) {
+    translateLength.value = 0
+  } else if (translateLength.value > maxTranslateLength.value) {
+    translateLength.value = maxTranslateLength.value
+    moveSpeed.value = 0
+  }
+}
+
+
+
+onMounted(() => {
+  animationFrameId.value = requestAnimationFrame(animationFrameTask)
+  window.addEventListener('resize', calcTranslateLimit)
+  calcTranslateLimit()
+  document.onreadystatechange = () => {
+    if (document.readyState === 'complete') {
+      // 页面上所有资源加载完成后执行的逻辑
+      console.log('所有资源加载完成');
+      calcTranslateLimit()
+    }
+  };
+})
+
+onBeforeUnmount(() => {
+  document.onreadystatechange = null
+  window.removeEventListener('resize', calcTranslateLimit)
+})
+
+
+
+
+</script>
+
+<style lang="less" scoped>
+.home {
+  // background-image: url('@/assets/images/bg-top.png');
+  height: 100%;
+  width: 100%;
+
+  .h-con {
+    height: 100%;
+    display: flex;
+    width: max-content;
+    position: relative;
+
+    .h-left {
+      height: 100%;
+      position: relative;
+      width: max-content;
+
+      >img {
+        height: 100%;
+      }
+
+      .l-con {
+
+        .logo {
+          position: absolute;
+          left: 1rem;
+          top: 1rem;
+          width: 16%;
+        }
+
+        .title {
+          position: absolute;
+          left: 50%;
+          top: 50%;
+          width: 70%;
+          transform: translate(-50%, -50%);
+        }
+      }
+    }
+
+    .h-right {
+      background-image: url('@/assets/images/bg-top.jpg');
+      background-repeat: no-repeat;
+      background-size: auto 80%;
+      background-color: #dddad1;
+      background-position: 0 0;
+      height: 100%;
+      position: relative;
+      font-size: 0;
+      user-select: none;
+
+      &::after {
+        width: 100%;
+        position: absolute;
+        bottom: 0;
+        content: '';
+        display: inline-block;
+        height: 20%;
+        box-sizing: border-box;
+        border-top: 2rem solid #8B8980;
+        background-image: linear-gradient(180deg, #93918A 0%, #AAA89F 63%);
+      }
+
+      >ul {
+        height: 100%;
+        position: relative;
+        z-index: 999;
+        display: flex;
+        align-items: flex-end;
+        padding-left: 10rem;
+        margin-bottom: 10rem;
+
+        >li {
+          list-style: none;
+          margin: 0 6rem;
+
+          >img {
+            max-width: 80%;
+            cursor: pointer;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 21 - 0
vite.config.js

@@ -0,0 +1,21 @@
+import vue from "@vitejs/plugin-vue";
+import path from 'path';
+import inject from '@rollup/plugin-inject'
+
+export default {
+  plugins: [
+    vue(),
+    inject({
+      utils: '/src/utils/index.js',
+    })
+  ],
+  base: './',
+  resolve: {
+    alias: {
+      '@': path.resolve(__dirname, './src/'),
+    }
+  },
+  server: {
+    host: '0.0.0.0'
+  }
+};

+ 794 - 0
yarn.lock

@@ -0,0 +1,794 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@antfu/utils@^0.7.2":
+  version "0.7.2"
+  resolved "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.2.tgz#3bb6f37a6b188056fe9e2f363b6aa735ed65d7ca"
+  integrity sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==
+
+"@babel/parser@^7.16.4":
+  version "7.21.4"
+  resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17"
+  integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==
+
+"@esbuild/android-arm@0.15.18":
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.15.18.tgz#266d40b8fdcf87962df8af05b76219bc786b4f80"
+  integrity sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==
+
+"@esbuild/linux-loong64@0.15.18":
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz#128b76ecb9be48b60cf5cfc1c63a4f00691a3239"
+  integrity sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==
+
+"@jridgewell/sourcemap-codec@^1.4.13":
+  version "1.4.15"
+  resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+  integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@nodelib/fs.scandir@2.1.5":
+  version "2.1.5"
+  resolved "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+  integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+  dependencies:
+    "@nodelib/fs.stat" "2.0.5"
+    run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+  version "2.0.5"
+  resolved "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+  integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+  version "1.2.8"
+  resolved "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+  integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+  dependencies:
+    "@nodelib/fs.scandir" "2.1.5"
+    fastq "^1.6.0"
+
+"@rollup/plugin-inject@^5.0.3":
+  version "5.0.3"
+  resolved "https://registry.npmmirror.com/@rollup/plugin-inject/-/plugin-inject-5.0.3.tgz#0783711efd93a9547d52971db73b2fb6140a67b1"
+  integrity sha512-411QlbL+z2yXpRWFXSmw/teQRMkXcAAC8aYTemc15gwJRpvEVDQwoe+N/HTFD8RFG8+88Bme9DK2V9CVm7hJdA==
+  dependencies:
+    "@rollup/pluginutils" "^5.0.1"
+    estree-walker "^2.0.2"
+    magic-string "^0.27.0"
+
+"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.2":
+  version "5.0.2"
+  resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33"
+  integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==
+  dependencies:
+    "@types/estree" "^1.0.0"
+    estree-walker "^2.0.2"
+    picomatch "^2.3.1"
+
+"@types/estree@^1.0.0":
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194"
+  integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
+
+"@vitejs/plugin-vue@^3.2.0":
+  version "3.2.0"
+  resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-3.2.0.tgz#a1484089dd85d6528f435743f84cdd0d215bbb54"
+  integrity sha512-E0tnaL4fr+qkdCNxJ+Xd0yM31UwMkQje76fsDVBBUCoGOUPexu2VDUYHL8P4CwV+zMvWw6nlRw19OnRKmYAJpw==
+
+"@vue/compiler-core@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.47.tgz#3e07c684d74897ac9aa5922c520741f3029267f8"
+  integrity sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==
+  dependencies:
+    "@babel/parser" "^7.16.4"
+    "@vue/shared" "3.2.47"
+    estree-walker "^2.0.2"
+    source-map "^0.6.1"
+
+"@vue/compiler-dom@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz#a0b06caf7ef7056939e563dcaa9cbde30794f305"
+  integrity sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==
+  dependencies:
+    "@vue/compiler-core" "3.2.47"
+    "@vue/shared" "3.2.47"
+
+"@vue/compiler-sfc@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz#1bdc36f6cdc1643f72e2c397eb1a398f5004ad3d"
+  integrity sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==
+  dependencies:
+    "@babel/parser" "^7.16.4"
+    "@vue/compiler-core" "3.2.47"
+    "@vue/compiler-dom" "3.2.47"
+    "@vue/compiler-ssr" "3.2.47"
+    "@vue/reactivity-transform" "3.2.47"
+    "@vue/shared" "3.2.47"
+    estree-walker "^2.0.2"
+    magic-string "^0.25.7"
+    postcss "^8.1.10"
+    source-map "^0.6.1"
+
+"@vue/compiler-ssr@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz#35872c01a273aac4d6070ab9d8da918ab13057ee"
+  integrity sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==
+  dependencies:
+    "@vue/compiler-dom" "3.2.47"
+    "@vue/shared" "3.2.47"
+
+"@vue/devtools-api@^6.4.5":
+  version "6.5.0"
+  resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07"
+  integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==
+
+"@vue/reactivity-transform@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz#e45df4d06370f8abf29081a16afd25cffba6d84e"
+  integrity sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==
+  dependencies:
+    "@babel/parser" "^7.16.4"
+    "@vue/compiler-core" "3.2.47"
+    "@vue/shared" "3.2.47"
+    estree-walker "^2.0.2"
+    magic-string "^0.25.7"
+
+"@vue/reactivity@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.47.tgz#1d6399074eadfc3ed35c727e2fd707d6881140b6"
+  integrity sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==
+  dependencies:
+    "@vue/shared" "3.2.47"
+
+"@vue/runtime-core@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.47.tgz#406ebade3d5551c00fc6409bbc1eeb10f32e121d"
+  integrity sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==
+  dependencies:
+    "@vue/reactivity" "3.2.47"
+    "@vue/shared" "3.2.47"
+
+"@vue/runtime-dom@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz#93e760eeaeab84dedfb7c3eaf3ed58d776299382"
+  integrity sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==
+  dependencies:
+    "@vue/runtime-core" "3.2.47"
+    "@vue/shared" "3.2.47"
+    csstype "^2.6.8"
+
+"@vue/server-renderer@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.47.tgz#8aa1d1871fc4eb5a7851aa7f741f8f700e6de3c0"
+  integrity sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==
+  dependencies:
+    "@vue/compiler-ssr" "3.2.47"
+    "@vue/shared" "3.2.47"
+
+"@vue/shared@3.2.47":
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c"
+  integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==
+
+acorn@^8.8.2:
+  version "8.8.2"
+  resolved "https://registry.npmmirror.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
+  integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
+
+anymatch@~3.1.2:
+  version "3.1.3"
+  resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+  integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+  dependencies:
+    normalize-path "^3.0.0"
+    picomatch "^2.0.4"
+
+balanced-match@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+  integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+binary-extensions@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+  integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+brace-expansion@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+  integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+  dependencies:
+    balanced-match "^1.0.0"
+
+braces@^3.0.2, braces@~3.0.2:
+  version "3.0.2"
+  resolved "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+  integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+  dependencies:
+    fill-range "^7.0.1"
+
+chokidar@^3.5.3:
+  version "3.5.3"
+  resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+  integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+  dependencies:
+    anymatch "~3.1.2"
+    braces "~3.0.2"
+    glob-parent "~5.1.2"
+    is-binary-path "~2.1.0"
+    is-glob "~4.0.1"
+    normalize-path "~3.0.0"
+    readdirp "~3.6.0"
+  optionalDependencies:
+    fsevents "~2.3.2"
+
+copy-anything@^2.0.1:
+  version "2.0.6"
+  resolved "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz#092454ea9584a7b7ad5573062b2a87f5900fc480"
+  integrity sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==
+  dependencies:
+    is-what "^3.14.1"
+
+csstype@^2.6.8:
+  version "2.6.21"
+  resolved "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
+  integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
+
+debug@^3.2.6:
+  version "3.2.7"
+  resolved "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+  integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+  dependencies:
+    ms "^2.1.1"
+
+debug@^4.3.4:
+  version "4.3.4"
+  resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+  integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+  dependencies:
+    ms "2.1.2"
+
+errno@^0.1.1:
+  version "0.1.8"
+  resolved "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
+  integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
+  dependencies:
+    prr "~1.0.1"
+
+esbuild-android-64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz#20a7ae1416c8eaade917fb2453c1259302c637a5"
+  integrity sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==
+
+esbuild-android-arm64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz#9cc0ec60581d6ad267568f29cf4895ffdd9f2f04"
+  integrity sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==
+
+esbuild-darwin-64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz#428e1730ea819d500808f220fbc5207aea6d4410"
+  integrity sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==
+
+esbuild-darwin-arm64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz#b6dfc7799115a2917f35970bfbc93ae50256b337"
+  integrity sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==
+
+esbuild-freebsd-64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz#4e190d9c2d1e67164619ae30a438be87d5eedaf2"
+  integrity sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==
+
+esbuild-freebsd-arm64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz#18a4c0344ee23bd5a6d06d18c76e2fd6d3f91635"
+  integrity sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==
+
+esbuild-linux-32@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz#9a329731ee079b12262b793fb84eea762e82e0ce"
+  integrity sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==
+
+esbuild-linux-64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz#532738075397b994467b514e524aeb520c191b6c"
+  integrity sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==
+
+esbuild-linux-arm64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz#5372e7993ac2da8f06b2ba313710d722b7a86e5d"
+  integrity sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==
+
+esbuild-linux-arm@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz#e734aaf259a2e3d109d4886c9e81ec0f2fd9a9cc"
+  integrity sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==
+
+esbuild-linux-mips64le@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz#c0487c14a9371a84eb08fab0e1d7b045a77105eb"
+  integrity sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==
+
+esbuild-linux-ppc64le@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz#af048ad94eed0ce32f6d5a873f7abe9115012507"
+  integrity sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==
+
+esbuild-linux-riscv64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz#423ed4e5927bd77f842bd566972178f424d455e6"
+  integrity sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==
+
+esbuild-linux-s390x@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz#21d21eaa962a183bfb76312e5a01cc5ae48ce8eb"
+  integrity sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==
+
+esbuild-netbsd-64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz#ae75682f60d08560b1fe9482bfe0173e5110b998"
+  integrity sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==
+
+esbuild-openbsd-64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz#79591a90aa3b03e4863f93beec0d2bab2853d0a8"
+  integrity sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==
+
+esbuild-sunos-64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz#fd528aa5da5374b7e1e93d36ef9b07c3dfed2971"
+  integrity sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==
+
+esbuild-windows-32@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz#0e92b66ecdf5435a76813c4bc5ccda0696f4efc3"
+  integrity sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==
+
+esbuild-windows-64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz#0fc761d785414284fc408e7914226d33f82420d0"
+  integrity sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==
+
+esbuild-windows-arm64@0.15.18:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz#5b5bdc56d341d0922ee94965c89ee120a6a86eb7"
+  integrity sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==
+
+esbuild@^0.15.9:
+  version "0.15.18"
+  resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.15.18.tgz#ea894adaf3fbc036d32320a00d4d6e4978a2f36d"
+  integrity sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==
+  optionalDependencies:
+    "@esbuild/android-arm" "0.15.18"
+    "@esbuild/linux-loong64" "0.15.18"
+    esbuild-android-64 "0.15.18"
+    esbuild-android-arm64 "0.15.18"
+    esbuild-darwin-64 "0.15.18"
+    esbuild-darwin-arm64 "0.15.18"
+    esbuild-freebsd-64 "0.15.18"
+    esbuild-freebsd-arm64 "0.15.18"
+    esbuild-linux-32 "0.15.18"
+    esbuild-linux-64 "0.15.18"
+    esbuild-linux-arm "0.15.18"
+    esbuild-linux-arm64 "0.15.18"
+    esbuild-linux-mips64le "0.15.18"
+    esbuild-linux-ppc64le "0.15.18"
+    esbuild-linux-riscv64 "0.15.18"
+    esbuild-linux-s390x "0.15.18"
+    esbuild-netbsd-64 "0.15.18"
+    esbuild-openbsd-64 "0.15.18"
+    esbuild-sunos-64 "0.15.18"
+    esbuild-windows-32 "0.15.18"
+    esbuild-windows-64 "0.15.18"
+    esbuild-windows-arm64 "0.15.18"
+
+estree-walker@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
+  integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
+
+fast-glob@^3.2.12:
+  version "3.2.12"
+  resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+  integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
+  dependencies:
+    "@nodelib/fs.stat" "^2.0.2"
+    "@nodelib/fs.walk" "^1.2.3"
+    glob-parent "^5.1.2"
+    merge2 "^1.3.0"
+    micromatch "^4.0.4"
+
+fastq@^1.6.0:
+  version "1.15.0"
+  resolved "https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+  integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+  dependencies:
+    reusify "^1.0.4"
+
+fill-range@^7.0.1:
+  version "7.0.1"
+  resolved "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+  integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+  dependencies:
+    to-regex-range "^5.0.1"
+
+fsevents@~2.3.2:
+  version "2.3.2"
+  resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+  integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+  integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+  version "5.1.2"
+  resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+  integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+  dependencies:
+    is-glob "^4.0.1"
+
+graceful-fs@^4.1.2:
+  version "4.2.11"
+  resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+  integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+has@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+  integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+  dependencies:
+    function-bind "^1.1.1"
+
+iconv-lite@^0.6.3:
+  version "0.6.3"
+  resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
+  integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3.0.0"
+
+image-size@~0.5.0:
+  version "0.5.5"
+  resolved "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
+  integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==
+
+is-binary-path@~2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+  integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+  dependencies:
+    binary-extensions "^2.0.0"
+
+is-core-module@^2.11.0:
+  version "2.12.0"
+  resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4"
+  integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==
+  dependencies:
+    has "^1.0.3"
+
+is-extglob@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+  integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1, is-glob@~4.0.1:
+  version "4.0.3"
+  resolved "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+  integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+  dependencies:
+    is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+  integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-what@^3.14.1:
+  version "3.14.1"
+  resolved "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1"
+  integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==
+
+less@^4.1.3:
+  version "4.1.3"
+  resolved "https://registry.npmmirror.com/less/-/less-4.1.3.tgz#175be9ddcbf9b250173e0a00b4d6920a5b770246"
+  integrity sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==
+  dependencies:
+    copy-anything "^2.0.1"
+    parse-node-version "^1.0.1"
+    tslib "^2.3.0"
+  optionalDependencies:
+    errno "^0.1.1"
+    graceful-fs "^4.1.2"
+    image-size "~0.5.0"
+    make-dir "^2.1.0"
+    mime "^1.4.1"
+    needle "^3.1.0"
+    source-map "~0.6.0"
+
+local-pkg@^0.4.2:
+  version "0.4.3"
+  resolved "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.4.3.tgz#0ff361ab3ae7f1c19113d9bb97b98b905dbc4963"
+  integrity sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==
+
+magic-string@^0.25.7:
+  version "0.25.9"
+  resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
+  integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
+  dependencies:
+    sourcemap-codec "^1.4.8"
+
+magic-string@^0.27.0:
+  version "0.27.0"
+  resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3"
+  integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==
+  dependencies:
+    "@jridgewell/sourcemap-codec" "^1.4.13"
+
+make-dir@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+  integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+  dependencies:
+    pify "^4.0.1"
+    semver "^5.6.0"
+
+merge2@^1.3.0:
+  version "1.4.1"
+  resolved "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+  integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.4:
+  version "4.0.5"
+  resolved "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+  integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+  dependencies:
+    braces "^3.0.2"
+    picomatch "^2.3.1"
+
+mime@^1.4.1:
+  version "1.6.0"
+  resolved "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+  integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+minimatch@^5.1.1:
+  version "5.1.6"
+  resolved "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
+  integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
+  dependencies:
+    brace-expansion "^2.0.1"
+
+ms@2.1.2:
+  version "2.1.2"
+  resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+  integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@^2.1.1:
+  version "2.1.3"
+  resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+nanoid@^3.3.6:
+  version "3.3.6"
+  resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
+  integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
+
+needle@^3.1.0:
+  version "3.2.0"
+  resolved "https://registry.npmmirror.com/needle/-/needle-3.2.0.tgz#07d240ebcabfd65c76c03afae7f6defe6469df44"
+  integrity sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==
+  dependencies:
+    debug "^3.2.6"
+    iconv-lite "^0.6.3"
+    sax "^1.2.4"
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+  version "3.0.0"
+  resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+  integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+parse-node-version@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b"
+  integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==
+
+path-parse@^1.0.7:
+  version "1.0.7"
+  resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+  integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+picocolors@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+  integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+  version "2.3.1"
+  resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+  integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pify@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+  integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+postcss@^8.1.10, postcss@^8.4.18:
+  version "8.4.23"
+  resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab"
+  integrity sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==
+  dependencies:
+    nanoid "^3.3.6"
+    picocolors "^1.0.0"
+    source-map-js "^1.0.2"
+
+prr@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+  integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==
+
+queue-microtask@^1.2.2:
+  version "1.2.3"
+  resolved "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+  integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+readdirp@~3.6.0:
+  version "3.6.0"
+  resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+  integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+  dependencies:
+    picomatch "^2.2.1"
+
+resolve@^1.22.1:
+  version "1.22.2"
+  resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
+  integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
+  dependencies:
+    is-core-module "^2.11.0"
+    path-parse "^1.0.7"
+    supports-preserve-symlinks-flag "^1.0.0"
+
+reusify@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+  integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rollup@^2.79.1:
+  version "2.79.1"
+  resolved "https://registry.npmmirror.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7"
+  integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==
+  optionalDependencies:
+    fsevents "~2.3.2"
+
+run-parallel@^1.1.9:
+  version "1.2.0"
+  resolved "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+  integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+  dependencies:
+    queue-microtask "^1.2.2"
+
+"safer-buffer@>= 2.1.2 < 3.0.0":
+  version "2.1.2"
+  resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+sax@^1.2.4:
+  version "1.2.4"
+  resolved "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+  integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+semver@^5.6.0:
+  version "5.7.1"
+  resolved "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+  integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+source-map-js@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
+  integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
+source-map@^0.6.1, source-map@~0.6.0:
+  version "0.6.1"
+  resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+sourcemap-codec@^1.4.8:
+  version "1.4.8"
+  resolved "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
+  integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
+
+ssr-window@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz#dc6b3ee37be86ac0e3ddc60030f7b3bc9b8553be"
+  integrity sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==
+
+supports-preserve-symlinks-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+  integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+swiper@^9.2.4:
+  version "9.2.4"
+  resolved "https://registry.npmmirror.com/swiper/-/swiper-9.2.4.tgz#2fa3cf58cef586366f674a10fa56fe6eec2026fe"
+  integrity sha512-L7y3K/iiMXNYQ94FbfcJn7jex4QPnS4+voXGupTdC+UHW4XrR40QDdm4c9hXJ+Br0Il7PP0vP1W3goM9/Ly6Sg==
+  dependencies:
+    ssr-window "^4.0.2"
+
+to-regex-range@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+  integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+  dependencies:
+    is-number "^7.0.0"
+
+tslib@^2.3.0:
+  version "2.5.0"
+  resolved "https://registry.npmmirror.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
+  integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
+
+unplugin-vue-components@^0.22.11:
+  version "0.22.12"
+  resolved "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-0.22.12.tgz#39013f77be72d32df9d6ca1599e592a484015612"
+  integrity sha512-FxyzsuBvMCYPIk+8cgscGBQ345tvwVu+qY5IhE++eorkyvA4Z1TiD/HCiim+Kbqozl10i4K+z+NCa2WO2jexRA==
+  dependencies:
+    "@antfu/utils" "^0.7.2"
+    "@rollup/pluginutils" "^5.0.2"
+    chokidar "^3.5.3"
+    debug "^4.3.4"
+    fast-glob "^3.2.12"
+    local-pkg "^0.4.2"
+    magic-string "^0.27.0"
+    minimatch "^5.1.1"
+    resolve "^1.22.1"
+    unplugin "^1.0.1"
+
+unplugin@^1.0.1:
+  version "1.3.1"
+  resolved "https://registry.npmmirror.com/unplugin/-/unplugin-1.3.1.tgz#7af993ba8695d17d61b0845718380caf6af5109f"
+  integrity sha512-h4uUTIvFBQRxUKS2Wjys6ivoeofGhxzTe2sRWlooyjHXVttcVfV/JiavNd3d4+jty0SVV0dxGw9AkY9MwiaCEw==
+  dependencies:
+    acorn "^8.8.2"
+    chokidar "^3.5.3"
+    webpack-sources "^3.2.3"
+    webpack-virtual-modules "^0.5.0"
+
+vite@^3.2.4:
+  version "3.2.6"
+  resolved "https://registry.npmmirror.com/vite/-/vite-3.2.6.tgz#a0538710e69532225d9c0ba6a23f4158b51267fd"
+  integrity sha512-nTXTxYVvaQNLoW5BQ8PNNQ3lPia57gzsQU/Khv+JvzKPku8kNZL6NMUR/qwXhMG6E+g1idqEPanomJ+VZgixEg==
+  dependencies:
+    esbuild "^0.15.9"
+    postcss "^8.4.18"
+    resolve "^1.22.1"
+    rollup "^2.79.1"
+  optionalDependencies:
+    fsevents "~2.3.2"
+
+vue-router@^4.1.6:
+  version "4.1.6"
+  resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz#b70303737e12b4814578d21d68d21618469375a1"
+  integrity sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==
+  dependencies:
+    "@vue/devtools-api" "^6.4.5"
+
+vue@^3.2.45:
+  version "3.2.47"
+  resolved "https://registry.npmmirror.com/vue/-/vue-3.2.47.tgz#3eb736cbc606fc87038dbba6a154707c8a34cff0"
+  integrity sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==
+  dependencies:
+    "@vue/compiler-dom" "3.2.47"
+    "@vue/compiler-sfc" "3.2.47"
+    "@vue/runtime-dom" "3.2.47"
+    "@vue/server-renderer" "3.2.47"
+    "@vue/shared" "3.2.47"
+
+webpack-sources@^3.2.3:
+  version "3.2.3"
+  resolved "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
+  integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
+webpack-virtual-modules@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz#362f14738a56dae107937ab98ea7062e8bdd3b6c"
+  integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==