Преглед на файлове

Merge branch 'master' of http://192.168.0.115:3000/renyicun/NanjingMuseumWuJinZang

aamin преди 1 година
родител
ревизия
6c051d3bff

+ 11 - 2
README.md

@@ -1,4 +1,13 @@
 ## 部署测试环境
-文件存放位置:
+文件存放位置:oss://4dkk-culture/NanjingMuseumWuJinZang/
 
-访问url:
+访问url:https://culture.4dage.com/NanjingMuseumWuJinZang/index.html#/
+
+## 任一存的todos
+绘画目录页 各种切图 排版
+
+绘画详情页开发
+
+内容扩展页开发
+
+启动页

Файловите разлики са ограничени, защото са твърде много
+ 138 - 114
public/configExcel.js


public/configMultiMedia/paintings-thumb/墨竹图 (二).jpg → public/configMultiMedia/paintings-thumb/墨竹图(二).jpg


public/configMultiMedia/paintings/墨竹图 (二).jpg → public/configMultiMedia/paintings/墨竹图(二).jpg


+ 1 - 1
src/App.vue

@@ -41,7 +41,7 @@ const store = useStore()
 
 <style lang="less">
 html, body {
-  // overscroll-behavior: none;
+  overscroll-behavior: none;
   overflow: hidden;
   height: 100%;
 }

BIN
src/assets/images/home-painting-big.jpg


BIN
src/assets/images/home-painting-line-small.jpg


BIN
src/assets/images/home-painting-line.jpg


BIN
src/assets/images/poem-list-bg-1.jpg


BIN
src/assets/images/poem-list-bg-2.jpg


BIN
src/assets/images/poem-list-bg-3.jpg


BIN
src/assets/images/poem-list-bg-4.jpg


+ 1 - 1
src/useFunctions/useSizeAdapt.js

@@ -15,7 +15,7 @@ export default function useSizeAdapt(windowWidthWhenDesign = 390, windowHeightWh
       scaleRate.value = windowHeightWhenDesign / window.innerHeight
     } else {
       windowSizeWhenDesignForRef.value = windowWidthWhenDesign
-      windowSizeInCssForRef.value = '100vw'
+      windowSizeInCssForRef.value = window.innerWidth + 'px'
       scaleRate.value = windowWidthWhenDesign / window.innerWidth
     }
   }

+ 157 - 91
src/views/HomeView.vue

@@ -9,6 +9,8 @@
         class="startup"
       />
     </Transition>
+
+    <!-- 标题 -->
     <div
       class="title-wrap"
       :style="{
@@ -27,7 +29,14 @@
         元 李衎<br>
       </div>
     </div>
-    <div class="painting-wrap">
+
+    <!-- 画作 -->
+    <div
+      class="painting-wrap"
+      :style="{
+        top: `${paintingTop / windowSizeWhenDesignForRef * windowSizeInCssForRef.substring(0, windowSizeInCssForRef.length - 2)}px`
+      }"
+    >
       <div
         class="size-sign-h"
         :style="{
@@ -99,7 +108,14 @@
         draggable="false"
       >
     </div>
-    <div class="hotspot-wrap">
+
+    <!-- 热点层 -->
+    <div
+      class="hotspot-wrap"
+      :style="{
+        top: `${paintingTop / windowSizeWhenDesignForRef * windowSizeInCssForRef.substring(0, windowSizeInCssForRef.length - 2)}px`
+      }"
+    >
       <HotspotComp
         v-show="isShowHotspot"
         class="hotspot-1"
@@ -116,6 +132,31 @@
         @click="isShowHotspotDetail3 = true"
       />
     </div>
+
+    <!-- 文字介绍 -->
+    <div
+      ref="longDesc"
+      class="long-desc"
+      :style="{
+        top: `${(paintingTop + 540) / windowSizeWhenDesignForRef * windowSizeInCssForRef.substring(0, windowSizeInCssForRef.length - 2)}px`,
+        opacity: longDescOpacity,
+      }"
+    >
+      <h3>作品简介:</h3>
+      <p
+        v-for="(item, index) in homepagePaintingDesc"
+        :key="index"
+      >
+        {{ item }}
+      </p>
+      <h3>作者简介:</h3>
+      <p
+        v-for="(item, index) in homepageAuthorDesc"
+        :key="index"
+      >
+        {{ item }}
+      </p>
+    </div>
     <div
       class="fixed-desc detail-desc-stem"
       :style="{
@@ -148,32 +189,22 @@
     >
       {{ summaryDesc }}
     </div>
+
     <OperationTip
       v-if="store.state.isStartupInvisible"
       class="operation-tip"
       text="了解作品"
       :is-show="isShowOperationTip"
     />
+
     <div
-      ref="descEl"
-      class="desc"
+      ref="scrollerEl"
+      class="scroller"
     >
-      <h3>作品简介:</h3>
-      <p
-        v-for="(item, index) in homepagePaintingDesc"
-        :key="index"
-      >
-        {{ item }}
-      </p>
-      <h3>作者简介:</h3>
-      <p
-        v-for="(item, index) in homepageAuthorDesc"
-        :key="index"
-      >
-        {{ item }}
-      </p>
-      <div class="bottom-mask" />
+      <div class="inner" />
     </div>
+
+    <!-- 热点详情页 -->
     <Transition name="fade-in-out">
       <HotspotDetail1
         v-if="isShowHotspotDetail1"
@@ -226,20 +257,20 @@ const detailDescLeaf = configText.homepagePaintingDetailDescLeaf
 const detailDescStone = configText.homepagePaintingDetailDescStone
 const summaryDesc = configText.homepagePaintingSummary
 
-const descEl = ref(null)
-const descElScrollTop = ref(0)
+const scrollerEl = ref(null)
+const scrollerElScrollTop = ref(0)
 onMounted(() => {
-  descEl.value.addEventListener('scroll', (e) => {
-    descElScrollTop.value = descEl.value.scrollTop
+  scrollerEl.value.addEventListener('scroll', (e) => {
+    scrollerElScrollTop.value = scrollerEl.value.scrollTop
   })
 })
 
 const isShowOperationTip = ref(true)
-watch(descElScrollTop, (v) => {
+watch(scrollerElScrollTop, (v) => {
   if (v > 0) {
     isShowOperationTip.value = false
   }
-  if (Math.abs(v - (descEl.value.scrollHeight - descEl.value.clientHeight)) <= 1) {
+  if (Math.abs(v - (scrollerEl.value.scrollHeight - scrollerEl.value.clientHeight)) <= 1) {
     router.push({
       name: 'MoreContent',
     })
@@ -252,26 +283,58 @@ const isStartupInvisible = computed(() => {
 
 const titleOpacity = computed(() => {
   let ret = null
-  if (descElScrollTop.value <= window.innerHeight * 0.3) {
-    ret = 1 - (window.innerHeight * 0.3 - descElScrollTop.value) / (window.innerHeight * 0.3)
-  } else if (descElScrollTop.value > window.innerHeight * 0.3 && descElScrollTop.value < window.innerHeight * 0.5) {
+  if (scrollerElScrollTop.value <= window.innerHeight * 0.3) {
+    ret = 1 - (window.innerHeight * 0.3 - scrollerElScrollTop.value) / (window.innerHeight * 0.3)
+  } else if (scrollerElScrollTop.value > window.innerHeight * 0.3 && scrollerElScrollTop.value < window.innerHeight * 0.5) {
+    ret = 1
+  } else {
+    ret = 1 - (scrollerElScrollTop.value - window.innerHeight * 0.5) / (window.innerHeight * (0.75 - 0.5))
+  }
+  return ret
+})
+
+const paintingTop = computed(() => {
+  let ret = null
+  if (scrollerElScrollTop.value <= window.innerHeight * 0.5) {
+    ret = 180
+  } else if (scrollerElScrollTop.value > window.innerHeight * 0.5 && scrollerElScrollTop.value < window.innerHeight * 1) {
+    ret = (scrollerElScrollTop.value - window.innerHeight * 0.5) / (window.innerHeight * (1 - 0.5)) * (67 - 180) + 180
+  } else {
+    ret = 67
+  }
+  return ret
+})
+
+const longDesc = ref(null)
+const longDescOpacity = computed(() => {
+  let ret = null
+  if (scrollerElScrollTop.value <= window.innerHeight * 0.3) {
+    ret = 1 - (window.innerHeight * 0.3 - scrollerElScrollTop.value) / (window.innerHeight * 0.3)
+  } else if (scrollerElScrollTop.value > window.innerHeight * 0.3 && scrollerElScrollTop.value < window.innerHeight * 2) {
     ret = 1
   } else {
-    ret = 1 - (descElScrollTop.value - window.innerHeight * 0.5) / (window.innerHeight * (0.75 - 0.5))
+    ret = 1 - (scrollerElScrollTop.value - window.innerHeight * 2) / (window.innerHeight * (3 - 2))
   }
   return ret
 })
+watch(scrollerElScrollTop, (vNew, vOld) => {
+  if (vNew > window.innerHeight * 1) {
+    longDesc.value.scrollTop = vNew - window.innerHeight * 1
+  } else if (vNew < vOld && vNew <= window.innerHeight * 1) {
+    longDesc.value.scrollTop = 0
+  }
+})
 
 const stemOpacity = computed(() => {
   let ret = null
-  if (descElScrollTop.value <= window.innerHeight * 2) {
+  if (scrollerElScrollTop.value <= window.innerHeight * 3) {
     ret = 0
-  } else if (descElScrollTop.value > window.innerHeight * 2 && descElScrollTop.value < window.innerHeight * 2.5) {
-    ret = (descElScrollTop.value - window.innerHeight * 2) / (window.innerHeight * (2.5 - 2))
-  } else if (descElScrollTop.value >= window.innerHeight * 2.5 && descElScrollTop.value <= window.innerHeight * 3) {
+  } else if (scrollerElScrollTop.value > window.innerHeight * 3 && scrollerElScrollTop.value < window.innerHeight * 3.5) {
+    ret = (scrollerElScrollTop.value - window.innerHeight * 3) / (window.innerHeight * (3.5 - 3))
+  } else if (scrollerElScrollTop.value >= window.innerHeight * 3.5 && scrollerElScrollTop.value <= window.innerHeight * 4) {
     ret = 1
-  } else if (descElScrollTop.value > window.innerHeight * 3 && descElScrollTop.value < window.innerHeight * 3.5) {
-    ret = 1 - (descElScrollTop.value - window.innerHeight * 3) / (window.innerHeight * (3.5 - 3))
+  } else if (scrollerElScrollTop.value > window.innerHeight * 4 && scrollerElScrollTop.value < window.innerHeight * 4.5) {
+    ret = 1 - (scrollerElScrollTop.value - window.innerHeight * 4) / (window.innerHeight * (4.5 - 4))
   } else {
     ret = 0
   }
@@ -280,14 +343,14 @@ const stemOpacity = computed(() => {
 
 const leafOpacity = computed(() => {
   let ret = null
-  if (descElScrollTop.value <= window.innerHeight * 4) {
+  if (scrollerElScrollTop.value <= window.innerHeight * 5) {
     ret = 0
-  } else if (descElScrollTop.value > window.innerHeight * 4 && descElScrollTop.value < window.innerHeight * 4.5) {
-    ret = (descElScrollTop.value - window.innerHeight * 4) / (window.innerHeight * (4.5 - 4))
-  } else if (descElScrollTop.value >= window.innerHeight * 4.5 && descElScrollTop.value <= window.innerHeight * 5) {
+  } else if (scrollerElScrollTop.value > window.innerHeight * 5 && scrollerElScrollTop.value < window.innerHeight * 5.5) {
+    ret = (scrollerElScrollTop.value - window.innerHeight * 5) / (window.innerHeight * (5.5 - 5))
+  } else if (scrollerElScrollTop.value >= window.innerHeight * 5.5 && scrollerElScrollTop.value <= window.innerHeight * 6) {
     ret = 1
-  } else if (descElScrollTop.value > window.innerHeight * 5 && descElScrollTop.value < window.innerHeight * 5.5) {
-    ret = 1 - (descElScrollTop.value - window.innerHeight * 5) / (window.innerHeight * (5.5 - 5))
+  } else if (scrollerElScrollTop.value > window.innerHeight * 6 && scrollerElScrollTop.value < window.innerHeight * 6.5) {
+    ret = 1 - (scrollerElScrollTop.value - window.innerHeight * 6) / (window.innerHeight * (6.5 - 6))
   } else {
     ret = 0
   }
@@ -296,14 +359,14 @@ const leafOpacity = computed(() => {
 
 const stoneOpacity = computed(() => {
   let ret = null
-  if (descElScrollTop.value <= window.innerHeight * 6) {
+  if (scrollerElScrollTop.value <= window.innerHeight * 7) {
     ret = 0
-  } else if (descElScrollTop.value > window.innerHeight * 6 && descElScrollTop.value < window.innerHeight * 6.5) {
-    ret = (descElScrollTop.value - window.innerHeight * 6) / (window.innerHeight * (6.5 - 6))
-  } else if (descElScrollTop.value >= window.innerHeight * 6.5 && descElScrollTop.value <= window.innerHeight * 7) {
+  } else if (scrollerElScrollTop.value > window.innerHeight * 7 && scrollerElScrollTop.value < window.innerHeight * 7.5) {
+    ret = (scrollerElScrollTop.value - window.innerHeight * 7) / (window.innerHeight * (7.5 - 7))
+  } else if (scrollerElScrollTop.value >= window.innerHeight * 7.5 && scrollerElScrollTop.value <= window.innerHeight * 8) {
     ret = 1
-  } else if (descElScrollTop.value > window.innerHeight * 7 && descElScrollTop.value < window.innerHeight * 7.5) {
-    ret = 1 - (descElScrollTop.value - window.innerHeight * 7) / (window.innerHeight * (7.5 - 7))
+  } else if (scrollerElScrollTop.value > window.innerHeight * 8 && scrollerElScrollTop.value < window.innerHeight * 8.5) {
+    ret = 1 - (scrollerElScrollTop.value - window.innerHeight * 8) / (window.innerHeight * (8.5 - 8))
   } else {
     ret = 0
   }
@@ -312,14 +375,14 @@ const stoneOpacity = computed(() => {
 
 const summaryOpacity = computed(() => {
   let ret = null
-  if (descElScrollTop.value <= window.innerHeight * 8) {
+  if (scrollerElScrollTop.value <= window.innerHeight * 9) {
     ret = 0
-  } else if (descElScrollTop.value > window.innerHeight * 8 && descElScrollTop.value < window.innerHeight * 8.5) {
-    ret = (descElScrollTop.value - window.innerHeight * 8) / (window.innerHeight * (8.5 - 8))
-  } else if (descElScrollTop.value >= window.innerHeight * 6.5 && descElScrollTop.value <= window.innerHeight * 9) {
+  } else if (scrollerElScrollTop.value > window.innerHeight * 9 && scrollerElScrollTop.value < window.innerHeight * 9.5) {
+    ret = (scrollerElScrollTop.value - window.innerHeight * 9) / (window.innerHeight * (9.5 - 9))
+  } else if (scrollerElScrollTop.value >= window.innerHeight * 9.5 && scrollerElScrollTop.value <= window.innerHeight * 10) {
     ret = 1
-  } else if (descElScrollTop.value > window.innerHeight * 9 && descElScrollTop.value < window.innerHeight * 9.5) {
-    ret = 1 - (descElScrollTop.value - window.innerHeight * 9) / (window.innerHeight * (9.5 - 9))
+  } else if (scrollerElScrollTop.value > window.innerHeight * 10 && scrollerElScrollTop.value < window.innerHeight * 10.5) {
+    ret = 1 - (scrollerElScrollTop.value - window.innerHeight * 10) / (window.innerHeight * (10.5 - 10))
   } else {
     ret = 0
   }
@@ -328,14 +391,14 @@ const summaryOpacity = computed(() => {
 
 const sizeOpacity = computed(() => {
   let ret = null
-  if (descElScrollTop.value <= window.innerHeight * 2) {
+  if (scrollerElScrollTop.value <= window.innerHeight * 3) {
     ret = 0
-  } else if (descElScrollTop.value > window.innerHeight * 2 && descElScrollTop.value < window.innerHeight * 2.5) {
-    ret = (descElScrollTop.value - window.innerHeight * 2) / (window.innerHeight * (2.5 - 2))
-  } else if (descElScrollTop.value >= window.innerHeight * 2.5 && descElScrollTop.value <= window.innerHeight * 7) {
+  } else if (scrollerElScrollTop.value > window.innerHeight * 3 && scrollerElScrollTop.value < window.innerHeight * 3.5) {
+    ret = (scrollerElScrollTop.value - window.innerHeight * 3) / (window.innerHeight * (3.5 - 3))
+  } else if (scrollerElScrollTop.value >= window.innerHeight * 3.5 && scrollerElScrollTop.value <= window.innerHeight * 8) {
     ret = 1
-  } else if (descElScrollTop.value > window.innerHeight * 7 && descElScrollTop.value < window.innerHeight * 7.5) {
-    ret = 1 - (descElScrollTop.value - window.innerHeight * 7) / (window.innerHeight * (7.5 - 7))
+  } else if (scrollerElScrollTop.value > window.innerHeight * 8 && scrollerElScrollTop.value < window.innerHeight * 8.5) {
+    ret = 1 - (scrollerElScrollTop.value - window.innerHeight * 8) / (window.innerHeight * (8.5 - 8))
   } else {
     ret = 0
   }
@@ -344,7 +407,7 @@ const sizeOpacity = computed(() => {
 
 const isShowHotspot = computed(() => {
   let ret = null
-  if (descElScrollTop.value <= window.innerHeight * 2) {
+  if (scrollerElScrollTop.value <= window.innerHeight * 3) {
     ret = false
   } else {
     return true
@@ -361,6 +424,10 @@ const isShowHotspotDetail3 = ref(false)
 .home {
   width: 100%;
   height: 100%;
+  background-image: url(@/assets/images/home-painting-line-small.jpg);
+  background-size: cover;
+  background-repeat: no-repeat;
+  background-position: center center;
   // 滚动条,只设置某一项可能导致不生效。
   ::-webkit-scrollbar { width: 0; height: 0; }
   >.bg-mask{
@@ -369,11 +436,8 @@ const isShowHotspotDetail3 = ref(false)
     top: 0;
     width: 100%;
     height: 100%;
-    background-image: url(@/assets/images/home-painting.jpg);
-    background-size: cover;
-    background-repeat: no-repeat;
-    background-position: center center;
-    filter: grayscale(1) brightness(0.35);
+    background: rgba(59,64,60,0.67);
+    backdrop-filter: blur(calc(5 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef')));
   }
   >.startup{
     z-index: 10;
@@ -412,8 +476,7 @@ const isShowHotspotDetail3 = ref(false)
   >.painting-wrap{
     position: absolute;
     left: 50%;
-    top: 48%;
-    transform: translate(-50%, -50%);
+    transform: translate(-50%, 0);
     width: calc(309 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     height: calc(522 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     >.size-sign-h{
@@ -479,8 +542,7 @@ const isShowHotspotDetail3 = ref(false)
   >.hotspot-wrap{
     position: absolute;
     left: 50%;
-    top: 48%;
-    transform: translate(-50%, -50%);
+    transform: translate(-50%, 0);
     width: calc(309 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     height: calc(522 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     z-index: 7;
@@ -504,6 +566,29 @@ const isShowHotspotDetail3 = ref(false)
       pointer-events: initial;
     }
   }
+  >.long-desc{
+    position: absolute;
+    left: 50%;
+    bottom: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    width: calc(309 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    transform: translate(-50%, 0);
+    color: white;
+    overflow: auto;
+    font-family: KaiTi, KaiTi;
+    color: #FFFFFF;
+    >h3{
+      font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      margin-bottom: 0.5em;
+      font-weight: 600;
+    }
+    >p{
+      font-weight: 400;
+      font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      line-height: calc(25 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      text-align: justified;
+      margin-bottom: 0.5em;
+    }
+  }
   >.fixed-desc{
     position: absolute;
     left: 50%;
@@ -529,35 +614,16 @@ const isShowHotspotDetail3 = ref(false)
     bottom: calc(77 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     transform: translateX(-50%);
   }
-  >.desc{
+  >.scroller{
     position: absolute;
     left: 0;
     top: 0;
     width: 100%;
     height: 100%;
-    padding-top: 100vh;
-    color: white;
     overflow: auto;
-    padding-left: calc(37 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    padding-right: calc(37 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    font-family: KaiTi, KaiTi;
-    color: #FFFFFF;
-    >h3{
-      font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      margin-top: 1em;
-      margin-bottom: 0.5em;
-      font-weight: 600;
-    }
-    >p{
-      font-weight: 400;
-      font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      line-height: calc(25 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      text-align: justified;
-      margin-bottom: 0.5em;
-    }
-    >.bottom-mask{
+    >.inner{
       width: 100%;
-      height: 750vh;
+      height: 1000%;
     }
   }
   >.hotspot-detail{

+ 6 - 6
src/views/HotspotDetail1.vue

@@ -91,7 +91,10 @@ const craftInfo = configText.craft
   top: 0;
   width: 100%;
   height: 100%;
-  background-color: #000;
+  background-image: url(@/assets/images/home-painting-line-small.jpg);
+  background-size: cover;
+  background-repeat: no-repeat;
+  background-position: center center;
   display: flex;
   flex-direction: column;
   justify-content: space-evenly;
@@ -101,11 +104,8 @@ const craftInfo = configText.craft
     top: 0;
     width: 100%;
     height: 100%;
-    background-image: url(@/assets/images/home-painting.jpg);
-    background-size: cover;
-    background-repeat: no-repeat;
-    background-position: center center;
-    filter: grayscale(1) brightness(0.35);
+    background: rgba(59,64,60,0.67);
+    backdrop-filter: blur(calc(5 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef')));
     z-index: -1;
   }
   >.row{

+ 60 - 125
src/views/HotspotDetail2.vue

@@ -37,48 +37,41 @@
         opacity: isAnimating ? AnimationProgress.value / 100 : fixedDescOpacity,
       }"
     >
-      <div class="inner-wrap">
-        <h3>修篁树石图</h3>
-        <p>李衎(元)</p>
-        <p>轴 绢本 墨笔</p>
-        <p>南京博物院藏</p>
-      </div>
-    </div>
+      <h1>修篁树石图</h1>
+      <p class="subtitle">
+        李衎(元)
+      </p>
+      <p class="subtitle">
+        轴 绢本 墨笔
+      </p>
+      <p class="subtitle">
+        南京博物院藏
+      </p>
 
-    <OperationTip
-      v-if="store.state.isStartupInvisible"
-      class="operation-tip"
-      :is-show="isShowOperationTip"
-    />
-    <div
-      ref="descEl"
-      class="desc"
-      :style="{
-        backdropFilter: `blur(${descBlurScale}px)`,
-        backgroundColor: `rgba(0, 0, 0, ${descBgAlpha})`,
-        pointerEvents: isAnimating ? 'none' : null,
-      }"
-    >
-      <button
-        class="show-big-painting"
-        @click="showBigPainting"
-      />
-      <h3>作品简介:</h3>
+      <h2>作品简介:</h2>
       <p
         v-for="(item, index) in homepagePaintingDesc"
         :key="index"
+        class="normal-text"
       >
         {{ item }}
       </p>
-      <h3>作者简介:</h3>
+      <h2>作者简介:</h2>
       <p
         v-for="(item, index) in homepageAuthorDesc"
         :key="index"
+        class="normal-text"
       >
         {{ item }}
       </p>
-      <div class="bottom-mask" />
     </div>
+
+    <!-- <OperationTip
+      v-if="store.state.isStartupInvisible"
+      class="operation-tip"
+      :is-show="isShowOperationTip"
+    /> -->
+
     <BtnBack
       @click="emit('close')"
     />
@@ -142,56 +135,18 @@ onUnmounted(() => {
   cancelAnimationFrame(animationRequestId)
 })
 
-const descEl = ref(null)
-const descElScrollTop = ref(0)
-onMounted(() => {
-  descEl.value.addEventListener('scroll', (e) => {
-    descElScrollTop.value = descEl.value.scrollTop
-  })
-})
-
 function showBigPainting() {
-  if (descElScrollTop.value < 20) {
-    viewerApi({
-      images: [bigPainting],
-    })
-  }
+  viewerApi({
+    images: [bigPainting],
+  })
 }
 
-const isShowOperationTip = ref(true)
-watch(descElScrollTop, (v) => {
-  if (v > 0) {
-    isShowOperationTip.value = false
-  }
-})
-
-const descBlurScale = computed(() => {
-  let ret = 0
-  if (descElScrollTop.value < window.innerHeight * 0.3) {
-    ret = descElScrollTop.value / (window.innerHeight * 0.3) * 20
-  } else {
-    ret = 20
-  }
-  return ret
-})
-const descBgAlpha = computed(() => {
-  let ret = 0
-  if (descElScrollTop.value < window.innerHeight * 0.3) {
-    ret = descElScrollTop.value / (window.innerHeight * 0.3) * 0.3
-  } else {
-    ret = 0.3
-  }
-  return ret
-})
-const fixedDescOpacity = computed(() => {
-  let ret = 1
-  if (descElScrollTop.value < window.innerHeight * 0.3) {
-    ret = 1 - descElScrollTop.value / (window.innerHeight * 0.3)
-  } else {
-    ret = 0
-  }
-  return ret
-})
+// const isShowOperationTip = ref(true)
+// watch(descElScrollTop, (v) => {
+//   if (v > 0) {
+//     isShowOperationTip.value = false
+//   }
+// })
 </script>
 
 <style lang="less" scoped>
@@ -235,70 +190,50 @@ const fixedDescOpacity = computed(() => {
     left: 50%;
     bottom: 2%;
     transform: translateX(-50%);
-    width: 100%;
-    height: 20%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    >.inner-wrap{
+    width: calc(306 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(130 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    overflow: auto;
+    >h1{
       text-align: center;
-      >h3{
-        font-family: KaiTi, KaiTi;
-        font-weight: 400;
-        font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        color: #FFFFFF;
-        margin-bottom: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      }
-      >p{
-        font-family: KaiTi, KaiTi;
-        font-weight: 400;
-        font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        color: rgba(255, 255, 255, 0.8);
-        line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        margin-bottom: calc(6 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      }
+      font-family: KaiTi, KaiTi;
+      font-weight: 400;
+      font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      color: #FFFFFF;
+      margin-bottom: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     }
-  }
-  >.operation-tip{
-    position: absolute;
-    right: calc(49 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    bottom: calc(39 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-  }
-  >.desc{
-    position: absolute;
-    left: 0;
-    top: 0;
-    width: 100%;
-    height: 100%;
-    color: white;
-    overflow: auto;
-    padding-left: calc(37 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    padding-right: calc(37 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    padding-top: calc(70 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    font-family: KaiTi, KaiTi;
-    color: #FFFFFF;
-    >button.show-big-painting{
-      height: calc(602 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      width: 100%;
-      margin-bottom: calc((844 - 602 - 70) / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    >p.subtitle{
+      text-align: center;
+      font-family: KaiTi, KaiTi;
+      font-weight: 400;
+      font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      color: rgba(255, 255, 255, 0.8);
+      line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      margin-bottom: calc(6 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     }
-    >h3{
+    >h2{
+      display: inline-block;
+      margin-top: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      font-family: KaiTi, KaiTi;
+      color: #FFFFFF;
       margin-top: 1em;
       margin-bottom: 0.5em;
       font-weight: 600;
       font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     }
-    >p{
+    >p.normal-text{
+      font-family: KaiTi, KaiTi;
+      color: #FFFFFF;
       font-weight: 400;
       font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       line-height: calc(25 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       text-align: justified;
       margin-bottom: 0.5em;
     }
-    >.bottom-mask{
-      width: 100%;
-      height: 10vh;
-    }
+  }
+  >.operation-tip{
+    position: absolute;
+    right: calc(49 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    bottom: calc(39 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
   }
 }
 </style>

+ 6 - 6
src/views/HotspotDetail3.vue

@@ -91,7 +91,10 @@ const craftInfo = configText.craft
   top: 0;
   width: 100%;
   height: 100%;
-  background-color: #000;
+  background-image: url(@/assets/images/home-painting-line-small.jpg);
+  background-size: cover;
+  background-repeat: no-repeat;
+  background-position: center center;
   display: flex;
   flex-direction: column;
   justify-content: space-evenly;
@@ -101,11 +104,8 @@ const craftInfo = configText.craft
     top: 0;
     width: 100%;
     height: 100%;
-    background-image: url(@/assets/images/home-painting.jpg);
-    background-size: cover;
-    background-repeat: no-repeat;
-    background-position: center center;
-    filter: grayscale(1) brightness(0.35);
+    background: rgba(59,64,60,0.67);
+    backdrop-filter: blur(calc(5 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef')));
     z-index: -1;
   }
   >.row{

+ 212 - 18
src/views/PaintingListMenu.vue

@@ -10,12 +10,30 @@
         :key="ageName"
         class="menu-item"
       >
-        <div class="cover">
-          <span class="age">{{ ageName }}</span>
-          <span class="age-en">{{ `${ageCnToEn[ageName]} dynasty` }}</span>
-          <span class="author-list">{{ getAuthorList(paintingGroup).join('/') }}</span>
+        <div
+          class="cover"
+          @click="onClickAge(ageName)"
+        >
+          <div class="age">
+            {{ ageName }}
+          </div>
+          <div class="age-en">
+            {{ `${ageCnToEn[ageName]} dynasty` }}
+          </div>
+          <div class="author-list">
+            {{ getAuthorList(paintingGroup).join('\\') }}
+          </div>
         </div>
-        <div class="hidden-content">
+        <div
+          v-if="ageName !== '清' && !expandedAgeNameList.has(ageName)"
+          class="splitter"
+        />
+        <div
+          class="hidden-content"
+          :style="{
+            width: expandedAgeNameList.has(ageName) ? getHiddenContentWidth(paintingGroup, ageName) : '0',
+          }"
+        >
           <div
             v-if="ageName === '宋'"
             class="special-desc"
@@ -29,9 +47,17 @@
             :key="item['标题']"
             class="painting-item"
           >
-            <span class="author">{{ item['作者'] }}</span>
-            <span class="title">{{ item['标题'] }}</span>
-            <span class="type">{{ item['装裱\/材质\/笔类型'] }}</span>
+            <div class="top-wrap">
+              <div class="author">
+                {{ item['作者'] }}
+              </div>
+              <div class="title">
+                {{ item['标题'].split('\n').join('') }}
+              </div>
+              <div class="type">
+                {{ item['装裱\/材质\/笔类型'] }}
+              </div>
+            </div>
             <div class="img-wrap">
               <img
                 class=""
@@ -40,8 +66,12 @@
                 draggable="false"
               >
             </div>
-            <span class="size">{{ getPaintingSizeString(item['尺寸']) }}</span>
-            <span class="position">{{ item['馆藏'] }}</span>
+            <div class="size">
+              {{ getPaintingSizeString(item['尺寸']) }}
+            </div>
+            <div class="position">
+              {{ item['馆藏'] }}
+            </div>
           </div>
         </div>
       </div>
@@ -119,15 +149,25 @@ function getPaintingSizeString(raw) {
   width = width.substring(1, width.length - 2)
   return `${width}\u00D7${height} 厘米`
 }
-const specialDesc = configExcel['其他'][3]['修篁树石图'][1]['作品简介'].split('\n')[0]
-
-function onClickMenuItem(menuItemName) {
-  // const targetIdx = poemList.findIndex((item) => {
-  //   return item['朝代'] === menuItemName
-  // })
-  // swiper.slideTo(targetIdx)
-  // isShowMenu.value = false
+const paintingWidthWhenDesign = 240
+const paintingMarginWhenDesin = 75
+const specialDescWidthWhenDesin = 444
+function getHiddenContentWidth(paintingGroup, ageName) {
+  let temp = paintingGroup.length * (paintingWidthWhenDesign + paintingMarginWhenDesin) + paintingMarginWhenDesin
+  if (ageName === '宋') {
+    temp += specialDescWidthWhenDesin
+  }
+  return `${temp / windowSizeWhenDesignForRef.value * Number(windowSizeInCssForRef.value.substring(0, windowSizeInCssForRef.value.length - 2))}px`
 }
+const expandedAgeNameList = ref(new Set())
+function onClickAge(ageName) {
+  if (expandedAgeNameList.value.has(ageName)) {
+    expandedAgeNameList.value.delete(ageName)
+  } else {
+    expandedAgeNameList.value.add(ageName)
+  }
+}
+const specialDesc = configExcel['其他'][3]['修篁树石图'][1]['作品简介'].split('\n')[0]
 
 const isShowOperationTip = ref(true)
 watch(menuElScrollLeft, (v) => {
@@ -146,6 +186,160 @@ watch(menuElScrollLeft, (v) => {
   width: 100%;
   height: 100%;
   background-color: #99ab8e;
+  >ul{
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    overflow: auto;
+    >.menu-item{
+      flex: 0 0 auto;
+      height: 100%;
+      display: flex;
+      align-items: center;
+      >.cover{
+        flex: 0 0 auto;
+        height: 100%;
+        padding-left: calc(22 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        padding-right: calc(22 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        writing-mode: vertical-lr;
+        >.age{
+          margin-top: calc(334 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-family: KingHwa_OldSong, KingHwa_OldSong;
+          font-weight: 400;
+          font-size: calc(34 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          color: #fff;
+          line-height: calc(40 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+        >.age-en{
+          margin-top: calc(334 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-family: KingHwa_OldSong, KingHwa_OldSong;
+          font-weight: 400;
+          font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          color: #FFFFFF;
+          line-height: calc(23 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+        >.author-list{
+          margin-top: calc(334 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-family: KaiTi, KaiTi;
+          font-weight: 400;
+          font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          color: #FFFFFF;
+          line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          letter-spacing: 0.2em;
+          height: 20em;
+          overflow: hidden;
+          white-space: pre;
+          text-overflow: ellipsis;
+        }
+      }
+      >.splitter{
+        height: calc(534 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        width: 1px;
+        background-color: #fff;
+      }
+      >.hidden-content{
+        transition: width 1s;
+        overflow: hidden;
+        display: flex;
+        background-color: #f9f7f2;
+        height: 100%;
+        >.special-desc{
+          flex: 0 0 auto;
+          >img.logo{
+
+          }
+          >p{
+
+          }
+          >button.see-more{
+
+          }
+        }
+        >.painting-item:last-of-type {
+          margin-right: calc(v-bind('paintingMarginWhenDesin') / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+        >.painting-item{
+          flex: 0 0 auto;
+          margin-left: calc(v-bind('paintingMarginWhenDesin') / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          width: calc(v-bind('paintingWidthWhenDesign') / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          >.top-wrap{
+            height: 0;
+            width: 0;
+            margin-top: calc(297 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            margin-bottom: calc(29 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            position: relative;
+            >.author{
+              writing-mode: vertical-lr;
+              font-family: KingHwa_OldSong, KingHwa_OldSong;
+              font-weight: 400;
+              font-size: calc(34 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+              color: #474747;
+              white-space: pre;
+              position: absolute;
+              right: 0;
+              bottom: calc(18 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            }
+            >.title{
+              writing-mode: vertical-lr;
+              font-family: KingHwa_OldSong, KingHwa_OldSong;
+              font-weight: 400;
+              font-size: calc(13 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+              color: #474747;
+              white-space: pre;
+              position: absolute;
+              left: calc(11 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+              bottom: 0;
+            }
+            >.type{
+              writing-mode: vertical-lr;
+              font-family: KingHwa_OldSong, KingHwa_OldSong;
+              font-weight: 400;
+              font-size: calc(13 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+              color: #474747;
+              white-space: pre;
+              position: absolute;
+              left: calc(31 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+              bottom: calc(0 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            }
+          }
+          >.img-wrap{
+            width: calc(240 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            height: calc(240 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            border-radius: 50%;
+            border: calc(4 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef')) solid #50361E;
+            overflow: hidden;
+            margin-bottom: calc(21 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            >img{
+              width: 100%;
+              height: 100%;
+              object-fit: cover;
+            }
+          }
+          >.size{
+            font-family: KingHwa_OldSong, KingHwa_OldSong;
+            font-weight: 400;
+            font-size: 13px;
+            color: #474747;
+            line-height: 15px;
+            margin-bottom: 0.5em;
+          }
+          >.position{
+            font-family: KingHwa_OldSong, KingHwa_OldSong;
+            font-weight: 400;
+            font-size: 13px;
+            color: #474747;
+            line-height: 15px;
+          }
+        }
+      }
+    }
+  }
   >.operation-tip{
     position: absolute;
     right: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));

+ 1 - 0
src/views/PoemList.vue

@@ -207,6 +207,7 @@ function onClickMenuItem(menuItemName) {
   top: 0;
   width: 100%;
   height: 100%;
+  background-color: #dde6db;
   ::-webkit-scrollbar { width: 0; height: 0; }
   >.bg{
     position: absolute;