Browse Source

顶部结构修改 (#1307)

* fix: 隐藏demo底部栏,修改高度
ailululu 3 years ago
parent
commit
8e16b0d0fa

+ 1 - 0
package.json

@@ -71,6 +71,7 @@
   },
   "dependencies": {
     "sass": "^1.50.0",
+    "vscode": "^1.1.37",
     "vue-router": "^4.0.12"
   },
   "devDependencies": {

+ 9 - 2
src/sites/assets/styles/md-style.scss

@@ -3,8 +3,8 @@
 .doc-content-document {
   position: relative;
   background: #fff;
-  padding-top: 48px;
-  padding-bottom: 48px;
+  padding-top: 40px;
+  padding-bottom: 40px;
   padding-left: 40px;
   padding-right: 445px;
   .card {
@@ -44,6 +44,12 @@
     }
   }
 
+  &.isComponent {
+    h1 {
+      display: none;
+    }
+  }
+
   h1 {
     margin: 0 0 30px;
     font-size: 30px;
@@ -51,6 +57,7 @@
     font-weight: bold;
     position: relative;
     margin-bottom: 56px;
+    // display: none;
     &:after {
       content: '';
       position: absolute;

+ 1 - 1
src/sites/doc/App.vue

@@ -19,6 +19,6 @@ export default defineComponent({
   width: 100%;
   display: flex;
   flex-direction: column;
-  padding-top: $doc-header-height;
+  // padding-top: $doc-header-height;
 }
 </style>

+ 43 - 5
src/sites/doc/components/DemoPreview.vue

@@ -1,14 +1,48 @@
 <template>
   <div class="doc-demo-preview">
-    <iframe :src="url" frameborder="0"></iframe>
+    <iframe :src="url" frameborder="0" ref="demoIframe"></iframe>
+    <demo-icon @refresh="onRefresh()" @goHome="onGoHome()"></demo-icon>
   </div>
 </template>
 <script lang="ts">
-import { defineComponent } from 'vue';
+import { defineComponent, ref } from 'vue';
+import Icon from '@/sites/doc/components/Icon.vue';
 export default defineComponent({
   name: 'doc-demo-preview',
+  components: {
+    [Icon.name]: Icon
+  },
   props: {
     url: String
+  },
+  setup(props: any, { emit }: any) {
+    const demoIframe = ref(null);
+    const onRefresh = () => {
+      const iframe = demoIframe?.value?.contentWindow;
+      iframe.postMessage(
+        {
+          cmd: 'refresh',
+          params: {
+            state: true
+          }
+        },
+        '*'
+      );
+    };
+    const onGoHome = () => {
+      const iframe = demoIframe?.value?.contentWindow;
+      iframe.postMessage(
+        {
+          cmd: 'goHome',
+          params: {
+            state: true
+          }
+        },
+        '*'
+      );
+    };
+
+    return { demoIframe, onRefresh, onGoHome };
   }
 });
 </script>
@@ -19,15 +53,19 @@ export default defineComponent({
     height: 667px;
     // height: 637px;
     width: 375px;
-    position: fixed;
+    position: absolute;
     right: 30px;
-    top: 100px;
+    top: 240px;
     // top: 135px;
     box-shadow: #ebedf0 0 4px 12px;
     border-radius: 12px;
     overflow: hidden;
-
+    &.fixed {
+      position: fixed;
+      top: 120px;
+    }
     iframe {
+      // height: calc(100% - 40px);
       height: 100%;
       width: 100%;
     }

+ 1 - 1
src/sites/doc/components/Header.vue

@@ -86,7 +86,7 @@ export default defineComponent({
 <style lang="scss">
 .doc {
   &-header {
-    position: fixed;
+    // position: fixed;
     z-index: 2;
     top: 0;
     left: 0;

+ 117 - 0
src/sites/doc/components/Icon.vue

@@ -0,0 +1,117 @@
+<template>
+  <div class="icon-moudle">
+    <div class="item home" @click="goHome">
+      <nut-icon name="home"></nut-icon>
+    </div>
+    <div class="item refresh" @click="refresh">
+      <nut-icon name="refresh"></nut-icon>
+    </div>
+    <div class="item category" @click="toCategory($event)">
+      <nut-icon name="category"></nut-icon>
+    </div>
+    <div class="qrcodepart" v-if="showCode" ref="codeRef" @click="stopClick($event)">
+      <div class="qrcode"> </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive, ref, onMounted, toRefs } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+export default defineComponent({
+  name: 'demo-icon',
+  components: {},
+  emits: ['refresh', 'goHome'],
+  setup(props: any, { emit }: any) {
+    const router = useRouter();
+    const route = useRoute();
+
+    const state = reactive({
+      showCode: false
+    });
+
+    const codeRef = ref(null);
+
+    onMounted(() => {
+      document.addEventListener('click', (e: any) => {
+        state.showCode = false; // 点击其他区域关闭
+      });
+      // console.log('route', route)
+    });
+
+    // 返回demo 首页页
+    const goHome = () => {
+      // router.push('/');
+      emit('goHome');
+    };
+
+    // 刷新
+    const refresh = () => {
+      // router.go(0);
+      emit('refresh');
+    };
+
+    // 二维码
+    const toCategory = (e: any) => {
+      state.showCode = !state.showCode;
+      e.stopPropagation(); // 阻止事件向上冒泡
+    };
+
+    const stopClick = (e: any) => {
+      e.stopPropagation(); // 阻止事件向上冒泡
+    };
+
+    return reactive({
+      ...toRefs(state),
+      codeRef,
+      goHome,
+      refresh,
+      toCategory,
+      stopClick
+    });
+  }
+});
+</script>
+<style lang="scss" scoped>
+.icon-moudle {
+  display: flex;
+  justify-content: flex-end;
+  position: absolute;
+  z-index: 10;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 40px;
+  padding: 0 22px;
+  color: #666;
+  border-top: 1px solid #e6e6e6;
+  background: #fff;
+  .item {
+    margin-left: 12px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+  }
+}
+.qrcodepart {
+  // display: none;
+  position: absolute;
+  right: 9px;
+  bottom: 48px;
+  width: 110px;
+  padding: 6px 7px;
+  border-radius: 6px;
+  background: rgba(255, 255, 255, 1);
+  box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.11);
+  box-sizing: border-box;
+  .qrcode {
+    width: 96px;
+    height: 96px;
+    margin: 0 auto;
+    background: url(https://img12.360buyimg.com/imagetools/jfs/t1/162421/39/13392/9425/6052ea60E592310a9/264bdff23ef5fe95.png)
+      no-repeat;
+    background-size: cover;
+  }
+}
+</style>

+ 3 - 21
src/sites/doc/components/Issue.vue

@@ -56,9 +56,9 @@ export default defineComponent({
 
 <style lang="scss" scoped>
 .doc-content-issue {
-  position: absolute;
-  right: 605px;
-  top: 51px;
+  // position: absolute;
+  // right: 605px;
+  // top: 51px;
   display: flex;
   align-items: center;
   z-index: 1;
@@ -72,7 +72,6 @@ export default defineComponent({
   .issue-item {
     display: flex;
     align-items: center;
-
     border-radius: var(--border-radius);
     transition: all 0.2s ease 0s;
     display: flex;
@@ -95,22 +94,5 @@ export default defineComponent({
       background: rgba(64, 69, 82, 0.1);
     }
   }
-  &.fixed {
-    position: fixed;
-    right: 30px;
-    top: 80px;
-  }
-  &.vertical {
-    position: fixed;
-    right: 420px;
-    top: 220px;
-    flex-wrap: wrap;
-    width: 100px;
-    z-index: 9;
-    height: auto;
-    .issue-item {
-      width: 100%;
-    }
-  }
 }
 </style>

+ 33 - 9
src/sites/doc/components/Nav.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="doc-nav">
+  <div class="doc-nav" :class="{ fixed: fixed }">
     <ol v-for="_nav in nav" :key="_nav">
       <li>{{ _nav.name }}</li>
       <ul>
@@ -15,20 +15,37 @@
   </div>
 </template>
 <script lang="ts">
-import { defineComponent, reactive, computed, onMounted } from 'vue';
+import { defineComponent, reactive, computed, onMounted, toRefs } from 'vue';
 import { RefData } from '@/sites/assets/util/ref';
 import { nav, docs } from '@/config.json';
 export default defineComponent({
   name: 'doc-nav',
   setup() {
+    const state = reactive({
+      fixed: false
+    });
     const isActive = computed(() => {
       return function (name: string) {
         const currentValue = RefData.getInstance().currentRoute.value;
         let value = currentValue.indexOf('-taro') > -1 ? currentValue.split('-taro')[0] : currentValue;
-        return value.includes(name.toLowerCase());
+        return value == name.toLowerCase();
       };
     });
+
+    onMounted(() => {
+      document.addEventListener('scroll', scrollNav);
+    });
+    const scrollNav = () => {
+      let top = document.documentElement.scrollTop;
+      // console.log('a', top)
+      if (top > 64) {
+        state.fixed = true;
+      } else {
+        state.fixed = false;
+      }
+    };
     return {
+      ...toRefs(state),
       isActive,
       nav: reactive(nav),
       docs: reactive(docs),
@@ -41,16 +58,21 @@ export default defineComponent({
 <style lang="scss">
 .doc {
   &-nav {
-    position: fixed;
-    top: $doc-header-height + 50;
+    position: absolute;
+    top: $doc-header-height;
     left: 0;
     bottom: 0;
     z-index: 1;
     background: $white;
     width: 290px;
+    height: 100vh;
     border-right: 1px solid #eee;
     overflow: auto;
     padding-left: 35px;
+    &.fixed {
+      position: fixed;
+      top: 0;
+    }
     ol {
       &.introduce {
         padding-left: 5px;
@@ -89,6 +111,7 @@ export default defineComponent({
         li {
           padding-left: 29px;
           cursor: pointer;
+
           &:hover {
             a {
               color: $doc-default-color;
@@ -100,16 +123,17 @@ export default defineComponent({
               color: $doc-default-color !important;
             }
 
+            &:link,
+            &:visited {
+              color: $title-color;
+            }
+
             &:hover {
               color: $doc-default-color;
               &:visited {
                 color: $doc-default-color;
               }
             }
-            &:link,
-            &:visited {
-              color: $title-color;
-            }
 
             height: 100%;
             b {

+ 160 - 29
src/sites/doc/views/Index.vue

@@ -3,8 +3,13 @@
     <doc-header></doc-header>
     <doc-nav></doc-nav>
     <div class="doc-content">
-      <div class="doc-content-document">
-        <!-- <doc-issue></doc-issue> -->
+      <div class="doc-title" v-if="isShow()">
+        <div class="doc-title-position" :class="{ fixed: fixed, hidden: hidden }">
+          <div class="title">{{ componentName.name }}&nbsp;{{ componentName.cName }}</div>
+          <doc-issue class=""></doc-issue>
+        </div>
+      </div>
+      <div class="doc-content-document" :class="{ isComponent: isShow() }">
         <div class="doc-content-tabs" v-if="isShow() && isShowTaroDoc">
           <div
             class="tab-item"
@@ -15,14 +20,12 @@
             >{{ item.text }}</div
           >
         </div>
-        <div class="doc-content-tabs" v-if="isShow() && !isShowTaroDoc">
-          <div class="tab-item cur">vue/taro</div>
+        <div class="doc-content-tabs single" v-if="isShow() && !isShowTaroDoc">
+          <div class="tab-item cur">vue / taro</div>
         </div>
         <router-view />
       </div>
-      <!-- <doc-issue class="fixed"></doc-issue> -->
-      <!-- <doc-issue class="vertical"></doc-issue> -->
-      <doc-demo-preview :url="demoUrl"></doc-demo-preview>
+      <doc-demo-preview v-if="isShow()" :url="demoUrl" :class="{ fixed: fixed }"></doc-demo-preview>
     </div>
   </div>
 </template>
@@ -49,6 +52,15 @@ export default defineComponent({
     const router = useRouter();
     initSiteLang();
     const excludeTaro = ['/intro', '/start', '/theme', '/joinus', '/starttaro', '/contributing'];
+    const state = reactive({
+      fixed: false, // 是否吸顶
+      hidden: false, // 是否隐藏
+      // 组件名称
+      componentName: {
+        name: '',
+        cName: ''
+      }
+    });
     const data = reactive({
       demoUrl: 'demo.html',
       curKey: 'vue',
@@ -83,7 +95,8 @@ export default defineComponent({
     };
 
     const isShow = () => {
-      return !excludeTaro.includes(route.path);
+      // return !excludeTaro.includes(route.path);
+      return route.path != '/zh-CN/';
     };
 
     const isShowTaroDoc = computed(() => {
@@ -97,27 +110,70 @@ export default defineComponent({
       data.demoUrl = url.replace('/zh-CN', '').replace('/en-US', '');
     };
 
-    const watchDocMd = () => {
+    const watchDocMd = (curKey: string) => {
       const path = route.path;
-      router.replace(isTaro(route) ? path.substr(0, path.length - 5) : `${path}-taro`);
+      // router.replace(isTaro(route) ? path.substr(0, path.length - 5) : `${path}-taro`);
+      if (curKey.includes('taro')) {
+        router.replace(isTaro(route) ? path : `${path}-taro`);
+      } else {
+        router.replace(isTaro(route) ? path.substr(0, path.length - 5) : path);
+      }
     };
 
     const handleTabs = (curKey: string) => {
       data.curKey = curKey;
-      watchDocMd();
+      watchDocMd(curKey);
     };
 
     onMounted(() => {
+      componentTitle();
       watchDemoUrl(route);
       data.curKey = isTaro(route) ? 'taro' : 'vue';
+      document.addEventListener('scroll', scrollTitle);
     });
 
+    const scrollTitle = () => {
+      let top = document.documentElement.scrollTop;
+      // console.log('state.hidden', state.hidden)
+      if (top > 127) {
+        state.fixed = true;
+        if (top < 142) {
+          state.hidden = true;
+        } else {
+          state.hidden = false;
+        }
+      } else {
+        state.fixed = false;
+        state.hidden = false;
+      }
+    };
+
+    // 获得组件名称
+    const componentTitle = (to?: any) => {
+      if (to?.path) {
+        state.componentName.name = to.path.split('/zh-CN/')[1];
+      } else {
+        state.componentName.name = route.path.split('/zh-CN/')[1];
+      }
+      nav.forEach((item: any) => {
+        item.packages.forEach((sItem: any) => {
+          if (sItem.name.toLowerCase() == state.componentName.name) {
+            state.componentName.name = sItem.name;
+            state.componentName.cName = sItem.cName;
+            return;
+          }
+        });
+      });
+    };
+
     onBeforeRouteUpdate((to) => {
       watchDemoUrl(to);
       data.curKey = isTaro(to) ? 'taro' : 'vue';
+      componentTitle(to);
     });
 
     return {
+      ...toRefs(state),
       ...toRefs(data),
       handleTabs,
       isShow,
@@ -128,6 +184,7 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
+$doc-title-height: 137px;
 .doc {
   &-content {
     margin-left: 290px;
@@ -136,42 +193,116 @@ export default defineComponent({
 
     &-document {
       min-height: 800px;
+
+      .markdown-body {
+        min-height: 600px;
+      }
     }
     &-tabs {
       position: absolute;
-      right: 445px;
+      right: 475px;
       top: 48px;
       display: flex;
-      height: 50px;
+      height: 40px;
       align-items: center;
-      margin-bottom: 20px;
+      justify-content: space-between;
       z-index: 1;
+      padding: 2px;
+      box-sizing: border-box;
+
+      border-radius: 2px;
+      background: #eee;
+      box-shadow: rgb(0 0 0 / 15%) 0px 2px 4px;
+      &.single {
+        padding: 0;
+        .tab-item {
+          line-height: 40px;
+          cursor: auto;
+        }
+      }
       .tab-item {
         position: relative;
-        padding: 10px 25px;
-        height: 100%;
+        padding: 0 10px;
+        line-height: 36px;
         cursor: pointer;
         font-size: 16px;
         color: #323232;
         text-align: center;
-        border-radius: 4px;
+        border-radius: 2px;
+        background: #eee;
         &.cur {
-          color: #fa2c19;
-          &:after {
-            content: ' ';
-            position: absolute;
-            bottom: 0;
-            left: 0;
-            width: 100%;
-            height: 3px;
-            background-color: #fa2c19;
-          }
+          font-weight: bold;
+          color: #323232;
+          background: #fff;
         }
-        &:hover {
-          background-color: #f7f8fa;
+      }
+    }
+    &-contributors {
+      margin: 50px 0;
+      a {
+        position: relative;
+      }
+      img {
+        height: 26px;
+        height: 26px;
+        border-radius: 50%;
+        margin-left: 8px;
+      }
+      .contributors-hover {
+        display: none;
+        padding: 5px 10px;
+        color: #fff;
+        font-size: 12px;
+        background-color: #000;
+        border-radius: 5px;
+        position: absolute;
+        /* min-width:150px; */
+        white-space: nowrap;
+        top: -200%;
+        transform: translateX(-55%);
+      }
+      a:hover {
+        .contributors-hover {
+          display: inline-block;
         }
       }
     }
   }
+  &-title {
+    width: 100%;
+    height: $doc-title-height;
+    z-index: 2;
+    &-position {
+      top: 0px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: 40px;
+      // line-height: 56px;
+      border-bottom: 1px solid #eee;
+      background: #fff;
+      visibility: visible;
+      opacity: 1;
+      // transition: opacity 0.8s linear, visibility 0.8s linear;
+      transition: opacity 0.8s;
+      &.fixed {
+        width: calc(100% - 290px);
+        position: fixed;
+        padding: 24px 48px;
+        .title {
+          font-size: 24px;
+          font-weight: bold;
+        }
+      }
+      &.hidden {
+        visibility: hidden;
+        opacity: 0;
+      }
+      .title {
+        font-size: 40px;
+        font-weight: bold;
+      }
+    }
+  }
 }
 </style>

+ 26 - 4
src/sites/mobile/App.vue

@@ -12,7 +12,7 @@
     </div>
   </div>
   <router-view />
-  <demo-icon></demo-icon>
+  <!-- <demo-icon></demo-icon> -->
 </template>
 <script lang="ts">
 import { defineComponent, ref, watch, computed, onMounted } from 'vue';
@@ -38,8 +38,27 @@ export default defineComponent({
         window.top.location.href = `${origin}/3x/index.html${hash}`;
         window.location.href = `${origin}/3x/demo.html${hash}`;
       }
+      // 接收数据
+      window.addEventListener('message', handledemoFromParent);
     });
 
+    const handledemoFromParent = (event: any) => {
+      var data = event.data;
+      console.log('data', data);
+      switch (data.cmd) {
+        case 'refresh':
+          if (data.params.state) {
+            router.go(0);
+          }
+          break;
+        case 'goHome':
+          if (data.params.state) {
+            router.push('/');
+          }
+          break;
+      }
+    };
+
     useThemeEditor();
 
     //返回demo页
@@ -131,13 +150,16 @@ body {
   }
 
   .demo {
-    height: 100%;
+    // height: 100%;
+    min-height: 100vh;
     background: #f7f8fa;
     overflow-x: hidden;
     overflow-y: auto;
-    padding: 57px 17px 46px 17px;
+    padding: 57px 17px 15px;
+    box-sizing: border-box;
     &.full {
-      padding: 57px 0 46px 0;
+      min-height: 100vh;
+      padding: 57px 0 0;
       h2 {
         padding-left: 27px;
       }