Procházet zdrojové kódy

📦 传承与文旅页搭建

imengyu před 2 týdny
rodič
revize
e919e94323
39 změnil soubory, kde provedl 1068 přidání a 645 odebrání
  1. 1 1
      src/common/components/tabs/tabbar.vue
  2. 3 0
      src/common/scss/common.scss
  3. 1 0
      src/common/scss/define/colors.scss
  4. 1 0
      src/common/scss/global/base.scss
  5. 6 0
      src/common/scss/global/flex.scss
  6. 3 0
      src/common/scss/global/grid.scss
  7. 228 541
      src/common/scss/global/margin-padding.scss
  8. 7 5
      src/common/scss/global/shadow.scss
  9. 1 1
      src/common/scss/global/size.scss
  10. 45 68
      src/pages/discover.vue
  11. 13 25
      src/pages/home.vue
  12. 298 2
      src/pages/inhert.vue
  13. 26 0
      src/pages/parts/Box1AudioPlay.vue
  14. 21 0
      src/pages/parts/Box2LineImageRightShadow.vue
  15. 97 0
      src/pages/parts/Box2LineLargeImageUserShadow.vue
  16. 23 0
      src/pages/parts/Box2LinePlayRightArrow.vue
  17. 22 0
      src/pages/parts/Box2LineRightShadow.vue
  18. 16 0
      src/pages/parts/Box2LineRightSlot.vue
  19. 33 0
      src/pages/parts/HomeTitle.vue
  20. 223 2
      src/pages/travel.vue
  21. binární
      src/static/images/inhert/IconLocation.png
  22. binární
      src/static/images/inhert/IconStar.png
  23. binární
      src/static/images/inhert/IconTime.png
  24. binární
      src/static/images/inhert/PlayVideo.png
  25. binární
      src/static/images/inhert/TestImage1.jpg
  26. binární
      src/static/images/inhert/TestImage2.jpg
  27. binární
      src/static/images/inhert/TestImage3.jpg
  28. binární
      src/static/images/inhert/TestImage4.jpg
  29. binární
      src/static/images/inhert/TestImage5.jpg
  30. binární
      src/static/images/inhert/TestVideoImage.png
  31. binární
      src/static/images/inhert/Title.png
  32. binární
      src/static/images/travel/Banner.png
  33. binární
      src/static/images/travel/CategoryIcon1.png
  34. binární
      src/static/images/travel/CategoryIcon2.png
  35. binární
      src/static/images/travel/CategoryIcon3.png
  36. binární
      src/static/images/travel/CategoryIcon4.png
  37. binární
      src/static/images/travel/CategoryIcon5.png
  38. binární
      src/static/images/travel/CategoryIcon6.png
  39. binární
      src/static/images/travel/Title.png

+ 1 - 1
src/common/components/tabs/tabbar.vue

@@ -57,7 +57,7 @@ export default {
   right: 0;
   z-index: 999;
   height: auto;
-  background-color: #ffffff;
+  background-color: #f7f3e8;
   box-shadow: 0 -2rpx 4rpx rgba(0, 0, 0, 0.1);
 
   display: flex;

+ 3 - 0
src/common/scss/common.scss

@@ -17,6 +17,9 @@
     justify-content: space-between;
     align-items: baseline;
   }
+  &.in-wing {
+    margin-bottom: 0;
+  }
 }
 .home-container {
   padding-bottom: 200rpx;

+ 1 - 0
src/common/scss/define/colors.scss

@@ -2,6 +2,7 @@ $colors: (
   primary: #d9492e,
   primary-text: #D9492E,
   primary-second-text: rgba(217, 73, 46, 0.6),
+  title-text: #432A04,
   second-text: #e6927e,
   light-blue: #0059ff,
   light-primary: #d9492e35,

+ 1 - 0
src/common/scss/global/base.scss

@@ -9,6 +9,7 @@
 @use './shadow.scss' as *;
 @use './wing-space-height.scss' as *;
 @use './margin-padding.scss' as *;
+@use './grid.scss' as *;
 
 .position {
 	&-relative {

+ 6 - 0
src/common/scss/global/flex.scss

@@ -68,6 +68,9 @@
 	&-around {
 		justify-content: space-around;
 	}
+	&-stretch {
+		justify-content: stretch;
+	}
 }
 .align {
 	&-start {
@@ -82,6 +85,9 @@
   &-baseline {
     align-items: baseline;
   }
+  &-stretch {
+    align-items: stretch;
+  }
 }
 .full {
 	&-width {

+ 3 - 0
src/common/scss/global/grid.scss

@@ -0,0 +1,3 @@
+.d-grid {
+  display: grid;
+} 

+ 228 - 541
src/common/scss/global/margin-padding.scss

@@ -1,5 +1,233 @@
 @use '../define/margin-padding.scss' as *;
 
+
+$common-level-sizes: (
+  0: 0,
+  1: 0.25rem,
+  2: 0.5rem,
+  25: 0.75rem,
+  3: 1rem,
+  35: 1.25rem,
+  4: 1.5rem,
+  45: 1.75rem,
+  5: 3rem,
+);
+
+.m {
+  &-auto {
+    margin: auto!important;
+  }
+	@each $key, $size in $common-level-sizes {
+    &-#{$key} {
+      margin: $size;
+    }
+  }
+
+  &l {
+    &-auto {
+      margin-left: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        margin-left: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        margin-left: -$size!important;
+      }
+    }
+  }
+  &r {
+    &-auto {
+      margin-right: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        margin-right: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        margin-right: -$size!important;
+      }
+    }
+  }
+  &t {
+    &-auto {
+      margin-top: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        margin-top: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        margin-top: -$size!important;
+      }
+    }
+  }
+  &b {
+    &-auto {
+      margin-bottom: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        margin-bottom: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        margin-bottom: -$size!important;
+      }
+    }
+  }
+  &x {
+    &-auto {
+      margin-left: auto!important;
+      margin-right: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        margin-left: $size!important;
+        margin-right: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        margin-left: -$size!important;
+        margin-right: -$size!important;
+      }
+    }
+  }
+  &y {
+    &-auto {
+      margin-top: auto!important;
+      margin-bottom: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        margin-top: $size!important;
+        margin-bottom: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        margin-top: -$size!important;
+        margin-bottom: -$size!important;
+      }
+    }
+  }
+}
+.p {
+  &-auto {
+    padding: auto!important;
+  }
+	@each $key, $size in $common-level-sizes {
+    &-#{$key} {
+      padding: $size;
+    }
+  }
+
+  &l {
+    &-auto {
+      padding-left: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        padding-left: -$size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        padding-left: -$size!important;
+      }
+    }
+  }
+  &r {
+    &-auto {
+      padding-right: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        padding-right: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        padding-right: -$size!important;
+      }
+    }
+  }
+  &t {
+    &-auto {
+      padding-top: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        padding-top: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        padding-top: -$size!important;
+      }
+    }
+  }
+  &b {
+    &-auto {
+      padding-bottom: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        padding-bottom: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        padding-bottom: -$size!important;
+      }
+    }
+  }
+  &x {
+    &-auto {
+      padding-left: auto!important;
+      padding-right: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        padding-left: $size!important;
+        padding-right: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        padding-left: -$size!important;
+        padding-right: -$size!important;
+      }
+    }
+  }
+  &y {
+    &-auto {
+      padding-top: auto!important;
+      padding-bottom: auto!important;
+    }
+    @each $key, $size in $common-level-sizes {
+      &-#{$key} {
+        padding-top: $size!important;
+        padding-bottom: $size!important;
+      }
+    }
+    @each $key, $size in $common-level-sizes {
+      &-n#{$key} {
+        padding-top: -$size!important;
+        padding-bottom: -$size!important;
+      }
+    }
+  }
+}
+
 .h-100vh {
   height: 100vh;
 }
@@ -18,547 +246,6 @@
 .b-0 {
   bottom: 0;
 }
-.m-0 {
-  margin: 0 !important;
-}
-
-.m-1 {
-  margin: 0.25rem !important;
-}
-
-.m-2 {
-  margin: 0.5rem !important;
-}
-
-.m-3 {
-  margin: 1rem !important;
-}
-
-.m-4 {
-  margin: 1.5rem !important;
-}
-
-.m-5 {
-  margin: 3rem !important;
-}
-
-.m-auto {
-  margin: auto !important;
-}
-
-.mx-0 {
-  margin-right: 0 !important;
-  margin-left: 0 !important;
-}
-
-.mx-1 {
-  margin-right: 0.25rem !important;
-  margin-left: 0.25rem !important;
-}
-
-.mx-2 {
-  margin-right: 0.5rem !important;
-  margin-left: 0.5rem !important;
-}
-
-.mx-3 {
-  margin-right: 1rem !important;
-  margin-left: 1rem !important;
-}
-
-.mx-4 {
-  margin-right: 1.5rem !important;
-  margin-left: 1.5rem !important;
-}
-
-.mx-5 {
-  margin-right: 3rem !important;
-  margin-left: 3rem !important;
-}
-
-.mx-auto {
-  margin-right: auto !important;
-  margin-left: auto !important;
-}
-
-.my-0 {
-  margin-top: 0 !important;
-  margin-bottom: 0 !important;
-}
-
-.my-1 {
-  margin-top: 0.25rem !important;
-  margin-bottom: 0.25rem !important;
-}
-
-.my-2 {
-  margin-top: 0.5rem !important;
-  margin-bottom: 0.5rem !important;
-}
-
-.my-3 {
-  margin-top: 1rem !important;
-  margin-bottom: 1rem !important;
-}
-
-.my-4 {
-  margin-top: 1.5rem !important;
-  margin-bottom: 1.5rem !important;
-}
-
-.my-5 {
-  margin-top: 3rem !important;
-  margin-bottom: 3rem !important;
-}
-
-.my-auto {
-  margin-top: auto !important;
-  margin-bottom: auto !important;
-}
-
-.mt-0 {
-  margin-top: 0 !important;
-}
-
-.mt-1 {
-  margin-top: 0.25rem !important;
-}
-
-.mt-2 {
-  margin-top: 0.5rem !important;
-}
-
-.mt-3 {
-  margin-top: 1rem !important;
-}
-
-.mt-4 {
-  margin-top: 1.5rem !important;
-}
-
-.mt-5 {
-  margin-top: 3rem !important;
-}
-
-.mt-auto {
-  margin-top: auto !important;
-}
-
-.mr-0 {
-  margin-right: 0 !important;
-}
-
-.mr-1 {
-  margin-right: 0.25rem !important;
-}
-
-.mr-2 {
-  margin-right: 0.5rem !important;
-}
-
-.mr-3 {
-  margin-right: 1rem !important;
-}
-
-.mr-4 {
-  margin-right: 1.5rem !important;
-}
-
-.mr-5 {
-  margin-right: 3rem !important;
-}
-
-.mr-auto {
-  margin-right: auto !important;
-}
-
-.mb-0 {
-  margin-bottom: 0 !important;
-}
-
-.mb-1 {
-  margin-bottom: 0.25rem !important;
-}
-
-.mb-2 {
-  margin-bottom: 0.5rem !important;
-}
-
-.mb-3 {
-  margin-bottom: 1rem !important;
-}
-
-.mb-4 {
-  margin-bottom: 1.5rem !important;
-}
-
-.mb-5 {
-  margin-bottom: 3rem !important;
-}
-
-.mb-auto {
-  margin-bottom: auto !important;
-}
-
-.ml-0 {
-  margin-left: 0 !important;
-}
-
-.ml-1 {
-  margin-left: 0.25rem !important;
-}
-
-.ml-2 {
-  margin-left: 0.5rem !important;
-}
-
-.ml-3 {
-  margin-left: 1rem !important;
-}
-
-.ml-4 {
-  margin-left: 1.5rem !important;
-}
-
-.ml-5 {
-  margin-left: 3rem !important;
-}
-
-.ml-auto {
-  margin-left: auto !important;
-}
-
-.m-n1 {
-  margin: -0.25rem !important;
-}
-
-.m-n2 {
-  margin: -0.5rem !important;
-}
-
-.m-n3 {
-  margin: -1rem !important;
-}
-
-.m-n4 {
-  margin: -1.5rem !important;
-}
-
-.m-n5 {
-  margin: -3rem !important;
-}
-
-.mx-n1 {
-  margin-right: -0.25rem !important;
-  margin-left: -0.25rem !important;
-}
-
-.mx-n2 {
-  margin-right: -0.5rem !important;
-  margin-left: -0.5rem !important;
-}
-
-.mx-n3 {
-  margin-right: -1rem !important;
-  margin-left: -1rem !important;
-}
-
-.mx-n4 {
-  margin-right: -1.5rem !important;
-  margin-left: -1.5rem !important;
-}
-
-.mx-n5 {
-  margin-right: -3rem !important;
-  margin-left: -3rem !important;
-}
-
-.my-n1 {
-  margin-top: -0.25rem !important;
-  margin-bottom: -0.25rem !important;
-}
-
-.my-n2 {
-  margin-top: -0.5rem !important;
-  margin-bottom: -0.5rem !important;
-}
-
-.my-n3 {
-  margin-top: -1rem !important;
-  margin-bottom: -1rem !important;
-}
-
-.my-n4 {
-  margin-top: -1.5rem !important;
-  margin-bottom: -1.5rem !important;
-}
-
-.my-n5 {
-  margin-top: -3rem !important;
-  margin-bottom: -3rem !important;
-}
-
-.mt-n1 {
-  margin-top: -0.25rem !important;
-}
-
-.mt-n2 {
-  margin-top: -0.5rem !important;
-}
-
-.mt-n3 {
-  margin-top: -1rem !important;
-}
-
-.mt-n4 {
-  margin-top: -1.5rem !important;
-}
-
-.mt-n5 {
-  margin-top: -3rem !important;
-}
-
-.mr-n1 {
-  margin-right: -0.25rem !important;
-}
-
-.mr-n2 {
-  margin-right: -0.5rem !important;
-}
-
-.mr-n3 {
-  margin-right: -1rem !important;
-}
-
-.mr-n4 {
-  margin-right: -1.5rem !important;
-}
-
-.mr-n5 {
-  margin-right: -3rem !important;
-}
-
-.mb-n1 {
-  margin-bottom: -0.25rem !important;
-}
-
-.mb-n2 {
-  margin-bottom: -0.5rem !important;
-}
-
-.mb-n3 {
-  margin-bottom: -1rem !important;
-}
-
-.mb-n4 {
-  margin-bottom: -1.5rem !important;
-}
-
-.mb-n5 {
-  margin-bottom: -3rem !important;
-}
-
-.ml-n1 {
-  margin-left: -0.25rem !important;
-}
-
-.ml-n2 {
-  margin-left: -0.5rem !important;
-}
-
-.ml-n3 {
-  margin-left: -1rem !important;
-}
-
-.ml-n4 {
-  margin-left: -1.5rem !important;
-}
-
-.ml-n5 {
-  margin-left: -3rem !important;
-}
-
-.p-0 {
-  padding: 0 !important;
-}
-
-.p-1 {
-  padding: 0.25rem !important;
-}
-
-.p-2 {
-  padding: 0.5rem !important;
-}
-
-.p-3 {
-  padding: 1rem !important;
-}
-
-.p-4 {
-  padding: 1.5rem !important;
-}
-
-.p-5 {
-  padding: 3rem !important;
-}
-
-.px-0 {
-  padding-right: 0 !important;
-  padding-left: 0 !important;
-}
-
-.px-1 {
-  padding-right: 0.25rem !important;
-  padding-left: 0.25rem !important;
-}
-
-.px-2 {
-  padding-right: 0.5rem !important;
-  padding-left: 0.5rem !important;
-}
-
-.px-3 {
-  padding-right: 1rem !important;
-  padding-left: 1rem !important;
-}
-
-.px-4 {
-  padding-right: 1.5rem !important;
-  padding-left: 1.5rem !important;
-}
-
-.px-5 {
-  padding-right: 3rem !important;
-  padding-left: 3rem !important;
-}
-
-.py-0 {
-  padding-top: 0 !important;
-  padding-bottom: 0 !important;
-}
-
-.py-1 {
-  padding-top: 0.25rem !important;
-  padding-bottom: 0.25rem !important;
-}
-
-.py-2 {
-  padding-top: 0.5rem !important;
-  padding-bottom: 0.5rem !important;
-}
-
-.py-3 {
-  padding-top: 1rem !important;
-  padding-bottom: 1rem !important;
-}
-
-.py-4 {
-  padding-top: 1.5rem !important;
-  padding-bottom: 1.5rem !important;
-}
-
-.py-5 {
-  padding-top: 3rem !important;
-  padding-bottom: 3rem !important;
-}
-
-.pt-0 {
-  padding-top: 0 !important;
-}
-
-.pt-1 {
-  padding-top: 0.25rem !important;
-}
-
-.pt-2 {
-  padding-top: 0.5rem !important;
-}
-
-.pt-3 {
-  padding-top: 1rem !important;
-}
-
-.pt-4 {
-  padding-top: 1.5rem !important;
-}
-
-.pt-5 {
-  padding-top: 3rem !important;
-}
-
-.pr-0 {
-  padding-right: 0 !important;
-}
-
-.pr-1 {
-  padding-right: 0.25rem !important;
-}
-
-.pr-2 {
-  padding-right: 0.5rem !important;
-}
-
-.pr-3 {
-  padding-right: 1rem !important;
-}
-
-.pr-4 {
-  padding-right: 1.5rem !important;
-}
-
-.pr-5 {
-  padding-right: 3rem !important;
-}
-
-.pb-0 {
-  padding-bottom: 0 !important;
-}
-
-.pb-1 {
-  padding-bottom: 0.25rem !important;
-}
-
-.pb-2 {
-  padding-bottom: 0.5rem !important;
-}
-
-.pb-3 {
-  padding-bottom: 1rem !important;
-}
-
-.pb-4 {
-  padding-bottom: 1.5rem !important;
-}
-
-.pb-5 {
-  padding-bottom: 3rem !important;
-}
-
-.pl-0 {
-  padding-left: 0 !important;
-}
-
-.pl-1 {
-  padding-left: 0.25rem !important;
-}
-
-.pl-2 {
-  padding-left: 0.5rem !important;
-}
-
-.pl-3 {
-  padding-left: 1rem !important;
-}
-
-.pl-4 {
-  padding-left: 1.5rem !important;
-}
-
-.pl-5 {
-  padding-left: 3rem !important;
-}
-
-
 
 .margin {
 	&-all {	

+ 7 - 5
src/common/scss/global/shadow.scss

@@ -1,21 +1,23 @@
+
+
 .shadow-sm {
-  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;
+  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.055) !important;
 }
 
 .shadow-s {
-  box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.075) !important;
+  box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.055) !important;
 }
 
 .shadow {
-  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
+  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.075) !important;
 }
 
 .shadow-l {
-  box-shadow: 0 0.75rem 2rem rgba(0, 0, 0, 0.175) !important;
+  box-shadow: 0 0.75rem 2rem rgba(0, 0, 0, 0.100) !important;
 }
 
 .shadow-lg {
-  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;
+  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.150) !important;
 }
 
 .shadow-none {

+ 1 - 1
src/common/scss/global/size.scss

@@ -46,7 +46,7 @@ $full-width: 750rpx;
 	//数字形式: width-1-2 表示 二分之一; width-4-9 表示 9分之4,等等
 	@for $i from 2 to 10 {
 		&-1-#{$i} {
-			width: math.div($full-width, $i);
+			width: math.percentage(math.div(1, $i));
 		}
 		
 		@for $j from 2 to $i {

+ 45 - 68
src/pages/discover.vue

@@ -8,9 +8,7 @@
     <view class="content d-flex flex-col wing-l">
       
       <!-- 文化百科 -->
-      <view class="home-title">
-        <text>文化百科</text>
-      </view>
+      <HomeTitle title="文化百科" />
       <view class="d-flex flex-row justify-between">
         <view 
           v-for="(item, i) in categories" 
@@ -26,70 +24,47 @@
       <view class="home-title">
         <text>闽南语猜猜猜</text>
       </view>
-      <view class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base mt-3 mb-3 p-2">
-        <image class="width-100 height-100 radius-base" src="/static/images/discover/PlayButtonLarge.png" mode="aspectFill" />
-        <view class="d-flex flex-col ml-3 flex-one">
-          <text class="color-primary">听语音猜词语</text>
-          <text class="color-primary-second-text">每日更新,赢取积分</text>
-        </view>
-        <text class="iconfont icon-arrow-right color-primary" />
-      </view>
+      <Box2LinePlayRightArrow 
+        title="听语音猜词语"
+        desc="每日更新,赢取积分"
+      />
 
       <!-- 文化挑战 -->
-      <view class="home-title">
-        <text>文化挑战</text>
-      </view>
-      <view class="d-flex w-100 flex-row align-center justify-between bg-light-light-primary radius-base mt-1 p-2 pt-3 pb-3">
-        <view class="d-flex flex-col ml-3 flex-one">
-          <text class="color-primary">方言配音大赛</text>
-          <text class="color-primary-second-text">参与人数:1,234</text>
-        </view>
+      <HomeTitle title="文化挑战" />
+      <Box2LineRightSlot 
+        title="方言配音大赛"
+        desc="参与人数:1,234"
+      >
         <image class="width-60 height-60 radius-base" src="/static/images/discover/IconCup.png" mode="aspectFill" />
-      </view>
-      <view class="d-flex w-100 flex-row align-center justify-between bg-light-light-primary radius-base mt-3 p-2 pt-3 pb-3">
-        <view class="d-flex flex-col ml-3 flex-one">
-          <text class="color-primary">闽南知识问答</text>
-          <text class="color-primary-second-text">可获积分:500</text>
-        </view>
+      </Box2LineRightSlot>
+      <Box2LineRightSlot
+        title="闽南知识问答"
+        desc="可获积分:500"
+      >
         <view class="width-1-5">
           <u-button shape="circle" type="primary">立即报名</u-button>
         </view>
-      </view>
+      </Box2LineRightSlot>
 
       <!-- 文化社区 -->
-      <view class="home-title">
-        <text>文化社区</text>
-      </view>
+      <HomeTitle title="文化社区" />
       
       <view class="d-flex w-100 flex-row flex-wrap align-center justify-between">
-        <view 
+        <Box2LineLargeImageUserShadow 
           v-for="(item, i) in communityData"
           :key="i"
-          class="grid4-item shadow radius-l bg-base p-2 mb-2"
-        >
-          <image class="w-100 radius-base" :src="item.image" mode="widthFix" />
-          <view class="d-flex flex-row align-center mt-2">
-            <image class="width-60 mr-2" :src="item.userHead" mode="widthFix" />
-            <text class="size-s">{{ item.userName }}</text>
-          </view>
-          <text class="color-primary">{{ item.userInfo }}</text>
-          <view class="d-flex flex-row mt-2">
-            <image class="width-40 mr-2" :src="IconHeart" mode="widthFix" />
-            <text class="size-s mr-3">{{ item.likes }}</text>
-            <image class="width-40 mr-2" :src="IconChat" mode="widthFix" />
-            <text class="size-s">{{ item.comment }}</text>
-          </view>
-        </view>
+          :title="item.title"
+          :desc="item.desc"
+          :image="item.image"
+          :userName="item.userName"
+          :userHead="item.userHead"
+          :likes="item.likes"
+          :comment="item.comment"
+        />
       </view>
 
       <!-- 老照片 -->
-      <view class="home-title has-more">
-        <text>老照片</text>
-        <text class="more">
-          查看全部
-          <text class="iconfont icon-arrow-right ml-2" />
-        </text>
-      </view>
+      <HomeTitle title="老照片" showMore />
       <scroll-view scroll-x>
         <view class="d-flex flex-row">
           <view v-for="(item, i) in imagesData" :key="i" class="mr-2">
@@ -99,20 +74,15 @@
       </scroll-view>
 
       <!-- 热门话题 -->
-      <view class="home-title">
-        <text>热门话题</text>
-      </view>
+      <HomeTitle title="热门话题" />
       <view class="d-flex flex-col">
-        <view 
+        <Box2LineRightShadow 
           v-for="(item, i) in topicsData" 
           :key="i" 
-          class="d-flex flex-row justify-between shadow-s radius-base mt-3 p-2 pt-3 pb-3">
-          <view class="d-flex flex-col ml-3 flex-one">
-            <text class="color-primary">{{ item.title }}</text>
-            <text class="color-second mt-2">{{ item.desc }}</text>
-          </view>
-          <text class="color-primary-second-text size-ss">{{ item.right }}</text>
-        </view>
+          :title="item.title"
+          :desc="item.desc"
+          :right="item.right"
+        />
       </view>
 
     </view>
@@ -131,9 +101,12 @@ import ImageTest2 from '/static/images/home/ImageTest2.png';
 import ImageTest3 from '/static/images/home/ImageTest3.png';
 import ImageTest4 from '/static/images/home/ImageTest4.png';
 import ImageTest5 from '/static/images/home/ImageTest5.png';
-import IconHeart from '/static/images/discover/IconHeart.png';
-import IconChat from '/static/images/discover/IconChat.png';
 import UserHead from '/static/images/home/UserHead.png';
+import Box2LineRightShadow from './parts/Box2LineRightShadow.vue';
+import Box2LinePlayRightArrow from './parts/Box2LinePlayRightArrow.vue';
+import Box2LineRightSlot from './parts/Box2LineRightSlot.vue';
+import Box2LineLargeImageUserShadow from './parts/Box2LineLargeImageUserShadow.vue';
+import HomeTitle from './parts/HomeTitle.vue';
 
 const categories = [
   { name: '民俗文化', icon: CategoryIcon1 },
@@ -145,6 +118,7 @@ const categories = [
 const communityData = [
   { 
     title: '茶艺传承作坊', 
+    desc: '',
     image: ImageTest4,
     likes: 123,
     comment: 66,
@@ -153,6 +127,7 @@ const communityData = [
   },
   { 
     title: '茶艺传承作坊', 
+    desc: '', 
     image: ImageTest2,
     likes: 123,
     comment: 66,
@@ -160,7 +135,8 @@ const communityData = [
     userName: 'Regular',
   },
   { 
-    title: '茶艺传承作坊', 
+    title: '茶艺传承作坊',  
+    desc: '',
     image: ImageTest3,
     likes: 123,
     comment: 66,
@@ -168,7 +144,8 @@ const communityData = [
     userName: 'Regular',
   },
   { 
-    title: '茶艺传承作坊', 
+    title: '茶艺传承作坊',  
+    desc: '',
     image: ImageTest5,
     likes: 123,
     comment: 66,
@@ -215,7 +192,7 @@ const topicsData = [
   }
 
   .grid4-item {
-    width: 300rpx;
+    width: 330rpx;
   }
 }
 </style>

+ 13 - 25
src/pages/home.vue

@@ -13,7 +13,7 @@
     <view class="content d-flex flex-col wing-l">
 
       <!-- 分栏 -->
-      <view class="shadow-lg radius-l bg-base p-3">
+      <view class="shadow-l radius-l bg-base p-3">
         <image 
           class="w-100"
           src="/static/images/home/MainBanner.jpg"
@@ -29,14 +29,7 @@
             <text class="color-second-text mt-2">{{ tab.name }}</text>
           </view>
 
-          <view class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base mt-3 mb-3 p-3">
-            <image class="width-150 height-150 radius-base" src="/static/images/home/ImageTest.png" mode="aspectFill" />
-            <view class="d-flex flex-col ml-3 flex-one">
-              <text class="color-second-text">里厚吖:你好呀</text>
-              <image class="width-50 height-50 mt-3" src="/static/images/home/PlayButtonSmall.png" />
-            </view>
-            <text class="iconfont icon-arrow-right color-primary" />
-          </view>
+          <Box1AudioPlay class="w-100 mt-3 mb-3" title="里厚吖:你好呀" />
 
           <view  
             v-for="(tab, k) in subTabs2" 
@@ -50,9 +43,7 @@
       </view>
 
       <!-- 文化地图 -->
-      <view class="home-title">
-        <text class="font-SongtiSCBlack">文化地图</text>
-      </view>
+      <HomeTitle title="文化地图" />
       <view class="position-relative radius-l overflow-hidden">
         <map 
           class="w-100 height-400"
@@ -74,11 +65,8 @@
       </view>
 
       <!-- 近期活动 -->
-      <view class="home-title">
-        <text>近期活动</text>
-      </view>
-
-      <view class="d-flex flex-col shadow-lg radius-l bg-base p-3">
+      <HomeTitle title="近期活动" />
+      <view class="d-flex flex-col shadow-l radius-l bg-base p-3">
         <image 
           class="w-100 radius-base"
           src="/static/images/home/ImageTest.png"
@@ -90,10 +78,10 @@
         </view>
         <view class="d-flex flex-row justify-between align-center mt-3">
           <view class="d-flex flex-one flex-col">
-            <text class="color-second size-l">
-              <text class="iconfont icon-read mr-2" />
-              湖里创新园
-            </text>
+            <view class="d-flex flex-row align-center">
+              <image :src="IconLocation" class="width-30 height-30 mr-3" />
+              <text class="color-second size-l">湖里创新园</text>
+            </view>
             <text class="color-second">
               <text class="iconfont icon-time mr-2" />
               2025年06月16日 12:00
@@ -106,10 +94,7 @@
       </view>
 
       <!-- 精彩推荐 -->
-      <view class="home-title">
-        <text>精彩推荐</text>
-      </view>
-
+      <HomeTitle title="精彩推荐" />
       <view class="d-flex flex-row justify-between flex-wrap">
         <view 
           v-for="(tab, k) in recommend"
@@ -148,6 +133,9 @@ import ImageTest2 from '/static/images/home/ImageTest2.png';
 import ImageTest3 from '/static/images/home/ImageTest3.png';
 import ImageTest4 from '/static/images/home/ImageTest4.png';
 import ImageTest5 from '/static/images/home/ImageTest5.png';
+import HomeTitle from './parts/HomeTitle.vue';
+import IconLocation from '/static/images/inhert/IconLocation.png';
+import Box1AudioPlay from './parts/Box1AudioPlay.vue';
 
 const subTabs1 = [
   { name: '闽南语', icon: MainBoxIcon1 },

+ 298 - 2
src/pages/inhert.vue

@@ -1,11 +1,307 @@
 <template>
-  <view class="d-flex flex-col">
+  <view class="home-container page-inhert d-flex flex-col bg-base">
+    <image 
+      class="position-absolute title"
+      src="/static/images/inhert/Title.png"
+      mode="widthFix"
+    />
+    <view class="content d-flex flex-col ">
+      
+      <!-- 文物 -->
+      <HomeTitle title="文物" showMore inWing />
+      <scroll-view scroll-x>
+        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in artifactData"
+            classNames="width-2-5 mr-2"
+            titleColor="title-text"
+            :key="i"
+            :title="item.title"
+            :image="item.image"
+            :likes="item.likes"
+            :comment="item.comment"
+          />
+        </view>
+      </scroll-view>
+
+      <!-- 非遗 -->
+      <HomeTitle title="非遗" showMore inWing />
+      <scroll-view scroll-x>
+        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in intangibleData"
+            classNames="width-2-3 mr-2"
+            titleColor="title-text"
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+            :bottomLocate="item.bottomLocate"
+            :bottomScore="item.bottomScore"
+          />
+        </view>
+      </scroll-view>
+
+      <!-- 闽南语在线课程 -->
+      <HomeTitle title="闽南语在线课程" showMore inWing />
+      <scroll-view scroll-x>
+        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in corseData"
+            classNames="width-2-3 mr-2"
+            titleColor="title-text"
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+            :videoMark="true"
+          />
+        </view>
+      </scroll-view>
+
+      <view class="d-flex flex-col wing-l">
+        <!-- 闽南语原创歌曲 -->
+        <HomeTitle title="闽南语原创歌曲" showMore />
+        <Box1AudioPlay class="w-100 mt-3" title="里厚吖:你好呀" />
+        <Box1AudioPlay class="w-100 mt-3" title="里厚吖:你好呀" />
+
+        <!-- 方言故事音频库 -->
+        <HomeTitle title="方言故事音频库" showMore />
+        <Box2LinePlayRightArrow 
+          title="方言故事"
+          desc="简介简介简介"
+        />
+        <Box2LinePlayRightArrow 
+          title="方言故事"
+          desc="简介简介简介"
+        />
+
+        <!-- 热门话题 -->
+        <HomeTitle title="热门话题" showMore />
+        <view class="d-flex flex-row flex-wrap column-gap-ss">
+          <Box2LinePlayRightArrow style="width:calc(50% - 20rpx)" title="市井声" />
+          <Box2LinePlayRightArrow style="width:calc(50% - 20rpx)" title="叫卖声" />
+          <Box2LinePlayRightArrow style="width:calc(50% - 20rpx)" title="市井声" />
+          <Box2LinePlayRightArrow style="width:calc(50% - 20rpx)" title="叫卖声" />
+        </view>
+      </view>
+
+      <!-- 童趣记忆 -->
+      <HomeTitle title="童趣记忆" showMore inWing />
+      <scroll-view scroll-x>
+        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in memoryData"
+            classNames="width-2-3 mr-2"
+            titleColor="title-text"
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+          />
+        </view>
+      </scroll-view>
+      
+      <!-- 老字号 -->
+      <HomeTitle title="老字号" showMore inWing />
+      <scroll-view scroll-x>
+        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in oldData"
+            classNames="width-2-3 mr-2"
+            titleColor="title-text"
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+            :bottomLocate="item.bottomLocate"
+            :bottomScore="item.bottomScore"
+          />
+        </view>
+      </scroll-view>
+
+      <!-- 古早味知识百科 -->
+      <view class="d-flex flex-col wing-l">
+        <HomeTitle title="古早味知识百科" showMore />
+        <Box2LineRightShadow
+          v-for="(item, i) in topicsData" 
+          :key="i" 
+          :title="item.title"
+          :desc="item.desc"
+        />
+      </view>
+
+    </view>
   </view>
   <tabbar :current="2"></tabbar>
 </template>
 
 <script setup lang="ts">
 import Tabbar from '@/common/components/tabs/tabbar.vue';
+import HomeTitle from './parts/HomeTitle.vue';
+import TestImage1 from '@/static/images/inhert/TestImage1.jpg';
+import TestImage2 from '@/static/images/inhert/TestImage2.jpg';
+import TestImage3 from '@/static/images/inhert/TestImage3.jpg';
+import TestImage4 from '@/static/images/inhert/TestImage4.jpg';
+import TestImage5 from '@/static/images/inhert/TestVideoImage.png';
+import Box2LineLargeImageUserShadow from './parts/Box2LineLargeImageUserShadow.vue';
+import Box2LinePlayRightArrow from './parts/Box2LinePlayRightArrow.vue';
+import Box1AudioPlay from './parts/Box1AudioPlay.vue';
+import Box2LineRightShadow from './parts/Box2LineRightShadow.vue';
 
+const artifactData = [
+  { 
+    title: '闽南漆线雕', 
+    desc: '',
+    image: TestImage1,
+    likes: 123,
+    comment: 66,
+  },
+  { 
+    title: '茶艺传承作坊', 
+    desc: '', 
+    image: TestImage2,
+    likes: 123,
+    comment: 66,
+  },
+  { 
+    title: '闽南漆线雕', 
+    desc: '',
+    image: TestImage1,
+    likes: 123,
+    comment: 66,
+  },
+  { 
+    title: '茶艺传承作坊', 
+    desc: '', 
+    image: TestImage2,
+    likes: 123,
+    comment: 66,
+  },
+]
+const intangibleData = [
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage4,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage4,
+  },
+]
+const corseData = [
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    image: TestImage5,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    image: TestImage5,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    image: TestImage5,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    image: TestImage5,
+  },
+]
+const memoryData = [
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    image: TestImage4,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    image: TestImage4,
+  },
+]
+const oldData = [
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage4,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage4,
+  },
+]
+const topicsData = [
+  {
+    title: '古早味',
+    desc: '是闽南人用来形容古旧的味道的一个词',
+  },
+  {
+    title: '古早味',
+    desc: '是闽南人用来形容古旧的味道的一个词',
+  },
+]
+</script>
 
-</script>
+<style lang="scss">
+.page-inhert {
+  > .content {
+    margin-top: 10vh;
+  }
+  > .title {
+    width: 100rpx;
+  }
+}
+</style>

+ 26 - 0
src/pages/parts/Box1AudioPlay.vue

@@ -0,0 +1,26 @@
+<template>
+    <view class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base p-25">
+    <image class="width-150 height-150 radius-base" :src="image" mode="aspectFill" />
+    <view class="d-flex flex-col ml-25 flex-one">
+      <text class="color-second-text">{{ title }}</text>
+      <image class="width-50 height-50 mt-3" src="/static/images/home/PlayButtonSmall.png" />
+    </view>
+    <text class="iconfont icon-arrow-right color-primary" />
+  </view>
+</template>
+
+<script setup lang="ts">
+import ImageTest from '/static/images/home/ImageTest.png';
+
+defineProps({
+  title: {
+    type: String,
+    default: '',
+  },
+  image: {
+    type: String,
+    default: ImageTest,
+  }
+})
+
+</script>

+ 21 - 0
src/pages/parts/Box2LineImageRightShadow.vue

@@ -0,0 +1,21 @@
+<template>
+  <view class="d-flex flex-row justify-between shadow-s radius-base mt-3 p-2 pt-3 pb-3">
+    <view class="d-flex flex-row">
+      <image class="width-100 height-100 radius-base" :src="image" mode="aspectFill" />
+      <view class="d-flex flex-col ml-3 flex-one">
+        <text class="color-primary">{{ title }}</text>
+        <text class="color-second mt-2">{{ desc }}</text>
+      </view>
+    </view>
+    <text class="color-primary-second-text size-ss">{{ right }}</text>
+  </view>
+</template>
+
+<script setup lang="ts">
+defineProps({
+  title: String,
+  desc: String,
+  right: String,
+  image: String,
+})
+</script>

+ 97 - 0
src/pages/parts/Box2LineLargeImageUserShadow.vue

@@ -0,0 +1,97 @@
+<template>
+  <view :class="'position-relative grid4-item d-flex flex-col shadow radius-l bg-base p-2 mb-2 ' + classNames">
+    <image class="w-100 height-300 radius-base" :src="image" mode="aspectFill" />
+    <image 
+      v-if="videoMark" 
+      class="width-60 mr-2 video-mark" 
+      :src="PlayVideo" mode="widthFix" 
+    />
+    <view v-if="userName" class="d-flex flex-row align-center mt-2">
+      <image class="width-60 mr-2" :src="userHead" mode="widthFix" />
+      <text class="size-s">{{ userName }}</text>
+    </view>
+    <text :class="`color-${titleColor}`">{{ title }}</text>
+    <text v-if="desc" class="color-second mt-2">{{ desc }}</text>
+    <view v-if="likes !== undefined && comment !== undefined" class="d-flex flex-row mt-2">
+      <image class="width-40 mr-2" :src="IconHeart" mode="widthFix" />
+      <text class="size-s mr-3">{{ likes }}</text>
+      <image class="width-40 mr-2" :src="IconChat" mode="widthFix" />
+      <text class="size-s">{{ comment }}</text>
+    </view>
+    <view v-if="bottomTime" class="d-flex flex-row mt-2">
+      <image class="width-40 mr-2" :src="IconTime" mode="widthFix" />
+      <text class="size-s mr-3">{{ bottomTime }}</text>
+    </view>
+    <view v-if="bottomLocate" class="d-flex flex-row justify-between mt-2">
+      <view class="d-flex flex-row align-center">
+        <image class="width-40 mr-2" :src="IconLocation" mode="widthFix" />
+        <text class="size-s">{{ bottomLocate }}</text>
+      </view>
+      <view class="d-flex flex-row align-center">
+        <image class="width-40 mr-2" :src="IconStar" mode="widthFix" />
+        <text class="size-s">{{ bottomScore }}</text>
+      </view>
+    </view> 
+  </view>
+</template>
+
+<script setup lang="ts">
+import IconHeart from '/static/images/discover/IconHeart.png';
+import IconChat from '/static/images/discover/IconChat.png';
+import IconLocation from '/static/images/inhert/IconLocation.png';
+import IconTime from '/static/images/inhert/IconTime.png';
+import IconStar from '/static/images/inhert/IconStar.png';
+import PlayVideo from '/static/images/inhert/PlayVideo.png';
+
+defineProps({
+  classNames: {
+    type: String,
+  },
+  title: {
+    type: String,
+  },
+  titleColor: {
+    type: String,
+    default: 'primary',
+  },
+  videoMark: {
+    type: Boolean,
+    default: false,
+  },
+  desc: {
+    type: String,
+  },
+  image: {
+    type: String,
+  },
+  likes: {
+    type: Number,
+  },
+  comment: {
+    type: Number,
+  },
+  userHead: {
+    type: String,
+  },
+  userName: {
+    type: String,
+  },
+  bottomLocate: {
+    type: String,
+  },
+  bottomScore: {
+    type: String,
+  },
+  bottomTime: {
+    type: String,
+  },
+})
+</script>
+
+<style scoped>
+.video-mark {
+  position: absolute;
+  left: calc(50% - 20rpx);
+  top: 145rpx
+}
+</style>

+ 23 - 0
src/pages/parts/Box2LinePlayRightArrow.vue

@@ -0,0 +1,23 @@
+<template>
+  <view class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base mt-2 p-2">
+    <image class="width-100 height-100 radius-base" src="/static/images/discover/PlayButtonLarge.png" mode="aspectFill" />
+    <view class="d-flex flex-col ml-3 flex-one">
+      <text class="color-primary">{{ title }}</text>
+      <text v-if="desc" class="color-primary-second-text">{{ desc }}</text>
+    </view>
+    <text class="iconfont icon-arrow-right color-primary" />
+  </view>
+</template>
+
+<script setup lang="ts">
+defineProps({
+  title: {
+    type: String,
+    default: ''
+  },
+  desc: {
+    type: String,
+    default: ''
+  }
+})
+</script>

+ 22 - 0
src/pages/parts/Box2LineRightShadow.vue

@@ -0,0 +1,22 @@
+<template>
+  <view class="d-flex flex-row justify-between shadow-s radius-base mt-3 p-2">
+   <view class="d-flex flex-row">
+      <slot name="left" />
+      <view class="d-flex flex-col ml-3 flex-one">
+        <text class="color-primary">{{ title }}</text>
+        <text class="color-second mt-2">{{ desc }}</text>
+      </view>
+    </view>
+    <text v-if="right" class="color-primary-second-text size-ss">{{ right }}</text>
+    <text v-else class="color-title-text iconfont icon-arrow-right"></text>
+  
+  </view>
+</template>
+
+<script setup lang="ts">
+defineProps({
+  title: String,
+  desc: String,
+  right: String,
+})
+</script>

+ 16 - 0
src/pages/parts/Box2LineRightSlot.vue

@@ -0,0 +1,16 @@
+<template>
+  <view class="d-flex w-100 flex-row align-center bg-light-light-primary radius-base mt-2 p-2 pb-3 pt-3">
+    <view class="d-flex flex-col ml-3 flex-one">
+      <text class="color-primary">{{ title }}</text>
+      <text class="color-primary-second-text">{{ desc }}</text>
+    </view>
+    <slot />
+  </view>
+</template>
+
+<script setup lang="ts">
+defineProps({
+  title: String,
+  desc: String,
+})
+</script>

+ 33 - 0
src/pages/parts/HomeTitle.vue

@@ -0,0 +1,33 @@
+<template>
+  <view 
+    :class="[
+      'home-title',
+      showMore ? 'has-more' : '',
+      inWing ? 'wing-l in-wing' : '',
+    ]"
+  >
+    <text>{{ title }}</text>
+    <text v-if="showMore" class="more" @click="$emit('clickMore')">
+      查看全部
+      <text class="iconfont icon-arrow-right ml-2" />
+    </text>
+  </view>
+</template>
+
+<script setup lang="ts">
+defineProps({	
+  title: {
+    type: String,
+    default: '',
+  },
+  inWing: {
+    type: Boolean,
+    default: false,
+  },
+  showMore: {
+    type: Boolean,
+    default: false,
+  }
+})
+defineEmits(['clickMore'])
+</script>

+ 223 - 2
src/pages/travel.vue

@@ -1,11 +1,232 @@
 <template>
-  <view class="d-flex flex-col">
+  <view class="home-container page-travel d-flex flex-col bg-base">
+    <image 
+      class="position-absolute title"
+      src="/static/images/travel/Title.png"
+      mode="widthFix"
+    />
+    <view class="content d-flex flex-col">
+      
+      <view class="content d-flex flex-col wing-l">
+        <!-- 大图 -->
+        <image 
+          class="w-100"
+          src="/static/images/travel/Banner.png"
+          mode="widthFix" 
+        />
+
+        <!-- 分栏 -->
+        <view 
+          class="position-relative d-grid mt-3"
+          style="grid: repeat(2, 3fr) / auto-flow; grid-gap: 20rpx;"
+        >
+          <view  
+            v-for="(tab, k) in subTabs" 
+            :key="k"
+            class="d-flex bg-light-light-primary radius-base p-2 flex-column align-center"
+          >
+            <image class="width-100" :src="tab.icon" mode="widthFix" />
+            <text class="color-title-text mt-2">{{ tab.name }}</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 精品路线 -->
+      <HomeTitle title="精品路线" showMore inWing />
+      <scroll-view scroll-x>
+        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in routeData"
+            classNames="width-2-3 mr-2"
+            titleColor="title-text"
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+            :bottomTime="item.bottomTime"
+          />
+        </view>
+      </scroll-view>
+
+      <!-- 精选推荐 -->
+      <HomeTitle title="精选推荐" showMore inWing />
+      <scroll-view scroll-x>
+        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in recommendData"
+            classNames="width-2-3 mr-2"
+            titleColor="title-text"
+            :key="i"
+            :title="item.title"
+            :desc="item.desc"
+            :image="item.image"
+            :bottomLocate="item.bottomLocate"
+            :bottomScore="item.bottomScore"
+          />
+        </view>
+      </scroll-view>
+
+      <!-- 文创好物 -->
+      <HomeTitle title="文创好物" showMore inWing />
+      <scroll-view scroll-x>
+        <view class="padding-wing-l pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
+          <Box2LineLargeImageUserShadow
+            v-for="(item, i) in creativeData"
+            classNames="width-2-3 mr-2"
+            titleColor="title-text"
+            :key="i"
+            :title="item.title"
+            :image="item.image"
+          />
+        </view>
+      </scroll-view>
+
+      <!-- 近期活动 -->
+      <view class="d-flex flex-col wing-l">
+        <HomeTitle title="近期活动" showMore />
+        <Box2LineRightShadow
+          v-for="(item, i) in activityData" 
+          :key="i" 
+          :title="item.title"
+          :desc="item.desc"
+          :right="item.right"
+        >
+          <template #left>
+            <view class="d-flex flex-col justify-center align-center radius-base bg-light-light-primary p-25 pt-2 pb-2">
+              <text class="color-primary size-s">12月</text>
+              <text class="color-primary size-base text-bold">28</text>
+            </view>
+          </template>
+        </Box2LineRightShadow>
+      </view>
+    </view>
+
+
   </view>
   <tabbar :current="3"></tabbar>
 </template>
 
 <script setup lang="ts">
 import Tabbar from '@/common/components/tabs/tabbar.vue';
+import CategoryIcon1 from '@/static/images/travel/CategoryIcon1.png';
+import CategoryIcon2 from '@/static/images/travel/CategoryIcon2.png';
+import CategoryIcon3 from '@/static/images/travel/CategoryIcon3.png';
+import CategoryIcon4 from '@/static/images/travel/CategoryIcon4.png';
+import CategoryIcon5 from '@/static/images/travel/CategoryIcon5.png';
+import CategoryIcon6 from '@/static/images/travel/CategoryIcon6.png';
+import TestImage1 from '@/static/images/inhert/TestImage1.jpg';
+import TestImage2 from '@/static/images/inhert/TestImage2.jpg';
+import TestImage3 from '@/static/images/inhert/TestImage3.jpg';
+import TestImage4 from '@/static/images/inhert/TestImage4.jpg';
+import Box2LineLargeImageUserShadow from './parts/Box2LineLargeImageUserShadow.vue';
+import Box2LineRightShadow from './parts/Box2LineRightShadow.vue';
+import HomeTitle from './parts/HomeTitle.vue';
+
+const subTabs = [
+  { name: '节庆日历', icon: CategoryIcon1 },
+  { name: '文化景区', icon: CategoryIcon2 },
+  { name: '旅游路线', icon: CategoryIcon3 },
+  { name: '文化产品', icon: CategoryIcon4 },
+  { name: '示范点', icon: CategoryIcon5 },
+  { name: '闽南歌曲', icon: CategoryIcon6 },
+]
+const routeData = [
+  { 
+    title: '古城文化之旅', 
+    desc: '千年古镇风情',
+    bottomTime: '123',
+    image: TestImage3,
+  },
+  { 
+    title: '古城文化之旅', 
+    desc: '千年古镇风情',
+    bottomTime: '123',
+    image: TestImage4,
+  },
+  { 
+    title: '古城文化之旅', 
+    desc: '千年古镇风情',
+    bottomTime: '123',
+    image: TestImage3,
+  },
+  { 
+    title: '古城文化之旅', 
+    desc: '千年古镇风情',
+    bottomTime: '123',
+    image: TestImage4,
+  },
+]
+const recommendData = [
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage4,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    desc: '千年古镇风情',
+    bottomLocate: '泉州市',
+    bottomScore: '5.0',
+    image: TestImage4,
+  },
+]
+const creativeData = [
+  { 
+    title: '南安水头', 
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    image: TestImage4,
+  },
+  { 
+    title: '南安水头', 
+    image: TestImage3,
+  },
+  { 
+    title: '南安水头', 
+    image: TestImage4,
+  },
+]
+const activityData = [
+  {
+    title: '闽南文化节',
+    desc: '泉州市区',
+    right: '报名中',
+  },
+  {
+    title: '泉州市区',
+    desc: '泉州市区',
+    right: '已截至',
+  },
+]
 
+</script>
 
-</script>
+<style lang="scss">
+.page-travel {
+     
+  > .content {
+    margin-top: 10vh;
+  }
+  > .title {
+    width: 100rpx;
+  } 
+}
+</style>

binární
src/static/images/inhert/IconLocation.png


binární
src/static/images/inhert/IconStar.png


binární
src/static/images/inhert/IconTime.png


binární
src/static/images/inhert/PlayVideo.png


binární
src/static/images/inhert/TestImage1.jpg


binární
src/static/images/inhert/TestImage2.jpg


binární
src/static/images/inhert/TestImage3.jpg


binární
src/static/images/inhert/TestImage4.jpg


binární
src/static/images/inhert/TestImage5.jpg


binární
src/static/images/inhert/TestVideoImage.png


binární
src/static/images/inhert/Title.png


binární
src/static/images/travel/Banner.png


binární
src/static/images/travel/CategoryIcon1.png


binární
src/static/images/travel/CategoryIcon2.png


binární
src/static/images/travel/CategoryIcon3.png


binární
src/static/images/travel/CategoryIcon4.png


binární
src/static/images/travel/CategoryIcon5.png


binární
src/static/images/travel/CategoryIcon6.png


binární
src/static/images/travel/Title.png