Pārlūkot izejas kodu

Merge branch 'master' of http://www.sysuimars.cn:3000/feiniao/adopt-mini-h5

lxf 1 nedēļu atpakaļ
vecāks
revīzija
bb86994301

+ 0 - 5
src/App.vue

@@ -1,12 +1,7 @@
 <template>
   <router-view />
-  <BaseFooter />
 </template>
 
-<script setup lang="ts">
-import BaseFooter from '@/components/BaseFooter.vue'
-</script>
-
 <style lang="less">
 #app {
   height: 100%;

+ 31 - 60
src/components/BaseFooter.vue

@@ -1,33 +1,31 @@
 <template>
-  <Teleport to="body">
-    <div v-if="visible" class="footer-wrap">
-      <nav class="footer" :class="{ isWhite }">
-        <div
-          v-for="item in tabs"
-          :key="item.id"
-          class="footer-item"
-          :class="{ active: currentTab === item.id }"
-          @click="refresh(item.id)"
-        >
-          <template v-if="!isRefreshing(item.id)">
-            <div class="icon-placeholder">
-              <img
-                class="icon-img"
-                :src="currentTab === item.id ? item.iconActive : item.icon"
-                :alt="item.label"
-              />
-            </div>
-            <span class="label" :class="{ active: currentTab === item.id }">{{ item.label }}</span>
-          </template>
-        </div>
-      </nav>
-    </div>
-  </Teleport>
+  <div v-if="visible" class="footer-wrap">
+    <nav class="footer" :class="{ isWhite }">
+      <div
+        v-for="item in tabs"
+        :key="item.id"
+        class="footer-item"
+        :class="{ active: currentTab === item.id }"
+        @click="refresh(item.id)"
+      >
+        <template v-if="!isRefreshing(item.id)">
+          <div class="icon-placeholder">
+            <img
+              class="icon-img"
+              :src="currentTab === item.id ? item.iconActive : item.icon"
+              :alt="item.label"
+            />
+          </div>
+          <span class="label" :class="{ active: currentTab === item.id }">{{ item.label }}</span>
+        </template>
+      </div>
+    </nav>
+  </div>
 </template>
 
 <script setup lang="ts">
-import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
-import { useRoute, useRouter } from 'vue-router'
+import { onMounted, onUnmounted, ref } from 'vue'
+import { useRouter } from 'vue-router'
 import bus, { EVENT_KEY } from '@/utils/bus'
 import tab1 from '@/assets/img/tabbar/tab-1.png'
 import tabAct1 from '@/assets/img/tabbar/tab-act-1.png'
@@ -42,15 +40,8 @@ const props = defineProps({
 })
 
 const router = useRouter()
-const route = useRoute()
 const currentTab = ref(props.initTab)
-/** douyin:bus 控制;扩展:仅 footerTab 路由 + 首页子层可隐藏 */
-const panelVisible = ref(true)
-const fullscreenHidden = ref(false)
-const hasFooterTab = computed(() => route.meta.footerTab != null)
-const visible = computed(
-  () => hasFooterTab.value && panelVisible.value && !fullscreenHidden.value,
-)
+const visible = ref(true)
 
 const tabs = [
   {
@@ -76,16 +67,6 @@ const tabs = [
   },
 ]
 
-function syncTabFromRoute() {
-  const tab = route.meta.footerTab as number | undefined
-  if (tab) {
-    currentTab.value = tab
-    return
-  }
-  const item = tabs.find((t) => t.path === route.path)
-  if (item) currentTab.value = item.id
-}
-
 const isRefresh1 = ref(false)
 const isRefresh2 = ref(false)
 const isRefresh3 = ref(false)
@@ -107,7 +88,7 @@ function tab(index: number) {
   const item = tabs.find((t) => t.id === index)
   if (!item) return
   currentTab.value = index
-  if (route.path !== item.path) {
+  if (router.currentRoute.value.path !== item.path) {
     router.push(item.path)
   }
 }
@@ -124,25 +105,15 @@ function refresh(index: number) {
   }
 }
 
-watch(
-  () => route.path,
-  () => {
-    panelVisible.value = true
-    fullscreenHidden.value = false
-    syncTabFromRoute()
-  },
-)
-
 onMounted(() => {
-  syncTabFromRoute()
   bus.on('setFooterVisible', (e) => {
-    panelVisible.value = e as boolean
+    visible.value = e as boolean
   })
   bus.on(EVENT_KEY.ENTER_FULLSCREEN, () => {
-    fullscreenHidden.value = true
+    visible.value = false
   })
   bus.on(EVENT_KEY.EXIT_FULLSCREEN, () => {
-    fullscreenHidden.value = false
+    visible.value = true
   })
 })
 
@@ -155,12 +126,12 @@ onUnmounted(() => {
 
 <style scoped lang="less">
 .footer-wrap {
-  position: fixed;
+  position: absolute;
   left: 50%;
   bottom: var(--footer-bottom-offset, 30rem);
   z-index: 10;
   transform: translateX(-50%);
-  width: calc(100vw - 32rem);
+  width: calc(100% - 32rem);
   max-width: 360rem;
   pointer-events: none;
   box-sizing: border-box;

+ 74 - 1
src/components/UserPanel.vue

@@ -17,6 +17,21 @@
         <div class="adopt-friends">{{ adoptFriendsText }}</div>
         <div class="guard-btn" @click="onGuard">我要守护</div>
       </div>
+
+      <div class="works-section">
+        <div class="works-tabs">
+          <span class="tab active">农场美景</span>
+        </div>
+        <div class="works-grid">
+          <div
+            v-for="v in 8"
+            :key="v"
+            class="grid-item"
+          >
+            <img src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" class="cover" alt="" />
+          </div>
+        </div>
+      </div>
     </div>
   </div>
 </template>
@@ -25,7 +40,7 @@
 import { Icon } from '@iconify/vue'
 import { computed } from 'vue'
 import { useRouter } from 'vue-router'
-import { _checkImgUrl, _notice } from '@/utils/index'
+import { _notice } from '@/utils'
 
 type PanelItem = {
   farmName?: string
@@ -189,6 +204,64 @@ defineExpose({
         cursor: pointer;
       }
     }
+
+    .works-section {
+      margin-top: 12rem;
+      margin-left: -18rem;
+      margin-right: -18rem;
+
+      .works-tabs {
+        padding: 10rem 18rem 0;
+        background: #fff;
+
+        .tab {
+          display: inline-block;
+          font-size: 15rem;
+          font-weight: 500;
+          color: #b0b0b0;
+          padding-bottom: 10rem;
+          position: relative;
+
+          &.active {
+            color: #1d2129;
+            font-weight: 600;
+
+            &::after {
+              content: '';
+              position: absolute;
+              left: 0;
+              bottom: 0;
+              width: 100%;
+              height: 3rem;
+              background: #1d2129;
+              border-radius: 2rem;
+            }
+          }
+        }
+      }
+
+      .works-grid {
+        display: grid;
+        grid-template-columns: repeat(3, 1fr);
+        gap: 2rem;
+        padding: 2rem 0;
+        background: #161616;
+
+        .grid-item {
+          aspect-ratio: 3 / 4;
+          overflow: hidden;
+          background: #2a2a2a;
+          cursor: pointer;
+
+          .cover {
+            width: 100%;
+            height: 100%;
+            object-fit: cover;
+            display: block;
+          }
+        }
+      }
+    }
   }
 }
 </style>

+ 1 - 1
src/router/globalRoutes.js

@@ -2,7 +2,7 @@ export default [
   {
     path: '/',
     name: 'FarmScenery',
-    meta: { title: '农场美景', footerTab: 1 },
+    meta: { title: '农场美景' },
     component: () => import('@/views/home/index.vue'),
   },
   {

+ 5 - 5
src/router/mainRoutes.js

@@ -1,9 +1,9 @@
 export default [
     {
-        path: '/adopt_map',
-        name: 'AdoptMap',
-        meta: { title: '守护地图', footerTab: 2 },
-        component: () => import('@/views/adopt_map/index.vue'),
+        path: '/guard-map',
+        name: 'GuardMap',
+        meta: { title: '守护地图' },
+        component: () => import('@/views/guard-map/index.vue'),
     },
     {
         path: '/adopt_map_select',
@@ -14,7 +14,7 @@ export default [
     {
         path: '/my-guard',
         name: 'MyGuard',
-        meta: { title: '我的守护', footerTab: 3 },
+        meta: { title: '我的守护' },
         component: () => import('@/views/my-guard/index.vue'),
     },
 ]

+ 47 - 0
src/views/guard-map/index.vue

@@ -0,0 +1,47 @@
+<template>
+  <div class="tab-page">
+    <div class="page-body">
+      <h1>守护地图</h1>
+      <p class="desc">地图功能开发中</p>
+    </div>
+    <BaseFooter :init-tab="2" />
+  </div>
+</template>
+
+<script setup lang="ts">
+import BaseFooter from '@/components/BaseFooter.vue'
+</script>
+
+<style scoped lang="less">
+.tab-page {
+  width: 100%;
+  height: 100%;
+  min-height: calc(var(--vh, 1vh) * 100);
+  background: var(--main-bg);
+  position: relative;
+  overflow: hidden;
+}
+
+.page-body {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: calc(var(--vh, 1vh) * 100 - 80rem);
+  padding: 20rem;
+  box-sizing: border-box;
+
+  h1 {
+    margin: 0 0 12rem;
+    font-size: 20rem;
+    color: #fff;
+    font-weight: 500;
+  }
+
+  .desc {
+    margin: 0;
+    font-size: 14rem;
+    color: rgba(255, 255, 255, 0.5);
+  }
+}
+</style>

+ 2 - 0
src/views/home/index.vue

@@ -110,6 +110,7 @@
           <Slide4 :active="state.navIndex === 1 && state.baseIndex === 1" />
         </SlideHorizontal>
 
+        <BaseFooter :init-tab="1" />
         <BaseMask
           v-if="state.baseIndex === 0"
           mode="white"
@@ -153,6 +154,7 @@ import Slide0 from './slide/Slide0.vue'
 import Slide4 from './slide/Slide4.vue'
 import { _no, _notice } from '@/utils'
 import BaseMask from '@/components/BaseMask.vue'
+import BaseFooter from '@/components/BaseFooter.vue'
 import { miniPrograms, recentUsers, recommendVideos } from '@/mock/homeData'
 
 const route = useRoute()

+ 5 - 0
src/views/my-guard/index.vue

@@ -4,9 +4,14 @@
       <h1>我的守护</h1>
       <p class="desc">守护记录开发中</p>
     </div>
+    <BaseFooter :init-tab="3" />
   </div>
 </template>
 
+<script setup lang="ts">
+import BaseFooter from '@/components/BaseFooter.vue'
+</script>
+
 <style scoped lang="less">
 .tab-page {
   width: 100%;