From df4dd9f030ac4e830d93f2f64e2379a9b7dad278 Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期三, 25 六月 2025 20:41:20 +0800
Subject: [PATCH] 自定义顶部组件、顶部tab对应页面接入该组件
---
pages.json | 34 +++---
pages/mine/activity/reportActivity.vue | 25 ++++
components/TopBar.vue | 142 ++++++++++++++++++++++++++++
pages/health/healthVideo.vue | 8 +
pages/tabbar/index/home.vue | 21 ++++
pages/commodity-square/commoditySquare.vue | 27 ++++
6 files changed, 234 insertions(+), 23 deletions(-)
diff --git a/components/TopBar.vue b/components/TopBar.vue
new file mode 100644
index 0000000..64913f8
--- /dev/null
+++ b/components/TopBar.vue
@@ -0,0 +1,142 @@
+<template>
+ <view class="top-bar" :style="{paddingTop: statusBarHeight + 'px'}">
+ <view class="top-bar-content">
+ <!-- 鏍囬鍒楄〃 -->
+ <scroll-view class="title-scroll" scroll-x="true" scroll-with-animation :scroll-left="scrollLeft">
+ <view class="title-container">
+ <view
+ v-for="(item, index) in titleList"
+ :key="index"
+ :class="{active: selectedTitleIndex === item.index, 'title-item': true}"
+ @click="changeTab(item)"
+ >
+ <text>{{item.title}}</text>
+ <view class="underline" v-if="selectedTitleIndex === item.index"></view>
+ </view>
+ </view>
+ </scroll-view>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ name:"TopBar",
+ props: {
+ selectedTitleIndex: {
+ type: String,
+ default: 'home'
+ }
+ },
+ data() {
+ return {
+ statusBarHeight: 0,
+ scrollLeft: 0,
+ titleList: [
+ {
+ index: 'home',
+ pagePath: '/pages/tabbar/index/home',
+ title: '鎺ㄨ崘'
+ },
+ {
+ index: 'shop',
+ pagePath: '/pages/commodity-square/commoditySquare',
+ title: '鍟嗗搧骞垮満'
+ },
+ {
+ index: 'activity',
+ pagePath: '/pages/mine/activity/reportActivity',
+ title: '娲诲姩'
+ },
+ {
+ index: 'health',
+ pagePath: '/pages/health/healthVideo',
+ title: '澶у仴搴�'
+ }
+ ]
+ };
+ },
+ created() {
+ // 鑾峰彇鐘舵�佹爮楂樺害
+ const systemInfo = uni.getSystemInfoSync();
+ this.statusBarHeight = systemInfo.statusBarHeight;
+ },
+ methods: {
+ changeTab(titleObj) {
+ console.log("鐐瑰嚮椤堕儴瀵艰埅", titleObj);
+ if (titleObj.index !== this.selectedTitleIndex) {
+ this.$emit("changeTab", titleObj);
+ // 璁$畻婊氬姩浣嶇疆浣垮綋鍓嶉�変腑椤瑰眳涓�
+ this.$nextTick(() => {
+ const query = uni.createSelectorQuery().in(this);
+ query.select(`.title-item[data-index="${titleObj.index}"]`).boundingClientRect();
+ query.select('.title-scroll').boundingClientRect();
+ query.exec(res => {
+ if (res[0] && res[1]) {
+ const itemLeft = res[0].left;
+ const scrollWidth = res[1].width;
+ const itemWidth = res[0].width;
+ this.scrollLeft = itemLeft - (scrollWidth - itemWidth) / 2;
+ }
+ });
+ });
+ }
+ }
+ }
+ }
+</script>
+
+<style>
+ .top-bar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 999;
+ }
+
+ .top-bar .top-bar-content {
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ }
+
+ .top-bar .title-scroll {
+ width: 100%;
+ height: 80rpx;
+ white-space: nowrap;
+ }
+
+ .top-bar .title-scroll .title-container {
+ display: inline-flex;
+ height: 100%;
+ align-items: center;
+ }
+
+ .top-bar .title-scroll .title-container .title-item {
+ position: relative;
+ padding: 0 24rpx;
+ font-size: 32rpx;
+ color: white;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ }
+
+ .top-bar .title-scroll .title-container .title-item.active {
+ font-weight: 500;
+ }
+
+ .top-bar .title-scroll .title-container .title-item.active .underline {
+ position: absolute;
+ bottom: 4rpx;
+ left: 50%;
+ transform: translateX(-50%);
+ width: calc(100% - 76rpx);
+ height: 4rpx;
+ background-color: white;
+ border-radius: 4rpx;
+ }
+</style>
\ No newline at end of file
diff --git a/pages.json b/pages.json
index a606eaf..49495a3 100644
--- a/pages.json
+++ b/pages.json
@@ -65,10 +65,10 @@
{
// "path": "pages/tabbar/category/category",
"path": "pages/commodity-square/commoditySquare",
-
+
"style": {
"navigationBarTitleText": "鍟嗗搧骞垮満",
- // "navigationStyle": "custom", // 闅愯棌绯荤粺瀵艰埅鏍�
+ "navigationStyle": "custom", // 闅愯棌绯荤粺瀵艰埅鏍�
"navigationBarTextStyle": "black",
// "disableScroll": true,
"bounce": "none",
@@ -749,6 +749,7 @@
"style": {
"navigationBarTitleText": "娲诲姩",
"enablePullDownRefresh": true, //涓嬫媺鍒锋柊
+ "navigationStyle": "custom", // 闅愯棌椤堕儴瀵艰埅鏍�
"componentPlaceholder": {
"u-form": "view",
"u-form-item": "view",
@@ -987,7 +988,7 @@
},
{
"path" : "video-goods-detail",
- "style" :
+ "style" :
{
"navigationBarTitleText" : "瑙嗛鎺ㄨ崘鍟嗗搧",
"componentPlaceholder": {
@@ -1435,7 +1436,8 @@
"pages": [{
"path": "healthVideo",
"style": {
- "navigationBarTitleText": "澶у仴搴�"
+ "navigationBarTitleText": "澶у仴搴�",
+ "navigationStyle": "custom"
}
}]
},
@@ -1452,13 +1454,13 @@
"root": "pages/supplier",
"pages": [{
"path" : "suppler-order/suppler-order",
- "style" :
+ "style" :
{
"navigationBarTitleText" : ""
}
}]
}
-
+
// ,
// {
// "root": "pages/commodity-square",
@@ -1496,13 +1498,13 @@
"selectedIconPath": "static/tabbar/home-s.png",
"text": "棣栭〉"
},
- {
- // "pagePath": "pages/tabbar/category/category",
- "pagePath": "pages/commodity-square/commoditySquare",
- "iconPath": "static/tabbar/category.png",
- "selectedIconPath": "static/tabbar/category-s.png",
- "text": "鍟嗗煄"
- },
+ // {
+ // // "pagePath": "pages/tabbar/category/category",
+ // "pagePath": "pages/commodity-square/commoditySquare",
+ // "iconPath": "static/tabbar/category.png",
+ // "selectedIconPath": "static/tabbar/category-s.png",
+ // "text": "鍟嗗煄"
+ // },
{
"pagePath": "pages/tabbar/video/video",
"iconPath": "static/tabbar/video.png",
@@ -1522,11 +1524,11 @@
}
]
},
- // #todo 涓轰粈涔堣娉ㄩ噴condition涓嬩唬鐮侊紵
+ // #todo 涓轰粈涔堣娉ㄩ噴condition涓嬩唬鐮侊紵
// IOS plus.runtime.arguments 娣诲姞 condition鑺傜偣鍚庯紝 妗嗘灦浼氫慨鏀� runtime.arguments
// 浼氬奖鍝嶄粈涔堝姛鑳斤紵
// -鍦╤5涓敜閱抋pp浼氫竴鐩磋繑鍥為粯璁ゅ�� {"name":"","path":"","query":"","id":0}
- "condition": { //妯″紡閰嶇疆锛屼粎寮�鍙戞湡闂寸敓鏁�
+ "condition": { //妯″紡閰嶇疆锛屼粎寮�鍙戞湡闂寸敓鏁�
// "current": 0, //褰撳墠婵�娲荤殑妯″紡(list 鐨勭储寮曢」)
// "list": [{
// "name": "", //妯″紡鍚嶇О
@@ -1534,4 +1536,4 @@
// "query": "" //鍚姩鍙傛暟锛屽湪椤甸潰鐨刼nLoad鍑芥暟閲岄潰寰楀埌
// }]
}
-}
\ No newline at end of file
+}
diff --git a/pages/commodity-square/commoditySquare.vue b/pages/commodity-square/commoditySquare.vue
index d7c7fad..e83e4e5 100644
--- a/pages/commodity-square/commoditySquare.vue
+++ b/pages/commodity-square/commoditySquare.vue
@@ -1,5 +1,6 @@
<template>
<view class="container">
+ <top-bar selectedTitleIndex="shop" @changeTab="topBarChange" class="topBar"></top-bar>
<input type="text" v-show="false" v-model="flushDom" />
<view class="search">
<u-search class="nav-search" @blur='searchGoods' placeholder="鎼滅储鍟嗗搧" :show-action="false"></u-search>
@@ -12,7 +13,7 @@
:controls="false" object-fit="contain" :show-play-btn="false" :show-center-play-btn="false"
@loadedmetadata="getvideoInfo($event,'goodsList1',index)" :ref="'video'+item.id"
:style="{width:item.width,height:item.height}"></video> -->
- <image :src="item.thumbnail"
+ <image :src="item.thumbnail"
mode="aspectFill" class="goodsImg">
</image>
<view class="goodsInfo">
@@ -31,7 +32,7 @@
:controls="false" object-fit="contain" :show-play-btn="false" :show-center-play-btn="false"
@loadedmetadata="getvideoInfo($event,'goodsList2',index)" :ref="'video'+item.id"
:style="{width:item.width,height:item.height}"></video> -->
- <image :src="item.thumbnail"
+ <image :src="item.thumbnail"
mode="aspectFill" class="goodsImg">
</image>
<view class="goodsInfo">
@@ -60,11 +61,11 @@
</view>
<view style="display: flex;align-items: center;justify-content: center;margin-top: 20rpx;" v-if="canLoadMore">
娌℃湁鏇村鏁版嵁浜�.................</view>
- <custom-tabbar bgColor="#ffffff" selected="shop"></custom-tabbar>
</view>
</template>
<script>
+ import TopBar from "@/components/TopBar.vue";
import {
getCategoryList,
getGoodsList
@@ -73,6 +74,7 @@
getSTSToken
} from '@/api/common.js'
export default {
+ components: {TopBar},
data() {
return {
//璁板綍涓ゅ垪楂樺害
@@ -104,6 +106,17 @@
}
},
methods: {
+ topBarChange(titleObj) {
+ if (titleObj.index === 'home') {
+ uni.switchTab({
+ url: titleObj.pagePath
+ });
+ } else {
+ uni.redirectTo({
+ url: titleObj.pagePath
+ });
+ }
+ },
async searchGoods(keyWard) {
this.getGoodsParam.keyword = keyWard
this.getGoodsParam.pageNumber = 1
@@ -393,4 +406,10 @@
color: red;
font-weight: bold;
}
-</style>
\ No newline at end of file
+ .topBar {
+ position: fixed;
+ top: 20rpx;
+ left: 20rpx;
+ z-index: 1000
+ }
+</style>
diff --git a/pages/health/healthVideo.vue b/pages/health/healthVideo.vue
index 34d7f92..4ac5030 100644
--- a/pages/health/healthVideo.vue
+++ b/pages/health/healthVideo.vue
@@ -1,5 +1,6 @@
<template>
<view class="video-container">
+ <top-bar selectedTitleIndex="health" @changeTab="topBarChange" class="topBar"></top-bar>
<!-- 瑙嗛鍔犺浇 -->
<zero-loading v-show="videoLoading" type="circle" color="#0ebd57" text=""></zero-loading>
<!-- 瑙嗛鍒楄〃 -->
@@ -241,6 +242,7 @@
</template>
<script>
+import TopBar from "@/components/TopBar.vue";
import { getHealthRecommendVideos, savePlayRecord, subscribe, getVideoComments, addVideoComment, thubmsUpComment, cancelThubmsUpComment } from "@/api/video.js";
import { changeCollect } from "@/api/collect.js";
import { saveShare, saveShareClickRecord } from "@/api/share.js";
@@ -1361,4 +1363,10 @@
.custom-share-btn::after {
border: none;
}
+ .topBar {
+ position: fixed;
+ top: 20rpx;
+ left: 20rpx;
+ z-index: 1000
+ }
</style>
diff --git a/pages/mine/activity/reportActivity.vue b/pages/mine/activity/reportActivity.vue
index b035663..017f929 100644
--- a/pages/mine/activity/reportActivity.vue
+++ b/pages/mine/activity/reportActivity.vue
@@ -1,7 +1,7 @@
<template>
<view class="wrapper">
-
-
+ <top-bar selectedTitleIndex="activity" @changeTab="topBarChange" class="topBar"></top-bar>
+
<view style="height: 100rpx"></view>
<!-- 鍐呭鍖哄煙 -->
<scroll-view scroll-y class="content" style="height: 40vh;" @scrolltolower="loadMore" :lower-threshold="100">
@@ -47,9 +47,11 @@
</template>
<script>
+ import TopBar from "@/components/TopBar.vue";
import '@/components/uview-components/uview-ui';
import {getActivityReportList} from '@/api/activity.js';
export default {
+ components: {TopBar},
data() {
return {
columns: [
@@ -74,6 +76,17 @@
this.getActivityList();
},
methods: {
+ topBarChange(titleObj) {
+ if (titleObj.index === 'home') {
+ uni.switchTab({
+ url: titleObj.pagePath
+ });
+ } else {
+ uni.redirectTo({
+ url: titleObj.pagePath
+ });
+ }
+ },
/**
* 涓嬫媺鍒锋柊鏃�
*/
@@ -367,4 +380,10 @@
font-size: 28rpx;
}
}
-</style>
\ No newline at end of file
+ .topBar {
+ position: fixed;
+ top: 20rpx;
+ left: 20rpx;
+ z-index: 1000
+ }
+</style>
diff --git a/pages/tabbar/index/home.vue b/pages/tabbar/index/home.vue
index a2cf82d..4e2f810 100644
--- a/pages/tabbar/index/home.vue
+++ b/pages/tabbar/index/home.vue
@@ -1,5 +1,6 @@
<template>
<view class="video-container">
+ <top-bar selectedTitleIndex="home" @changeTab="topBarChange" class="topBar"></top-bar>
<!-- 瑙嗛鍔犺浇 -->
<zero-loading v-show="videoLoading" type="circle" color="#0ebd57" text=""></zero-loading>
<!-- 瑙嗛鍒楄〃 -->
@@ -247,7 +248,10 @@
import { silentLogin } from "@/api/connect.js";
import { getUserInfo } from "@/api/members";
import storage from "@/utils/storage.js";
+import TopBar from "@/components/TopBar.vue";
+
export default {
+ components: {TopBar},
computed: {
hasPlayTime() {
return this.sliderFormatTime(this.progress > 0 ? this.duration * this.progress / 100 : 0);
@@ -379,6 +383,17 @@
}
},
methods: {
+ topBarChange(titleObj) {
+ if (titleObj.index === 'home') {
+ uni.switchTab({
+ url: titleObj.pagePath
+ });
+ } else {
+ uni.redirectTo({
+ url: titleObj.pagePath
+ });
+ }
+ },
// 闈欓粯鐧诲綍
wxSilentLogin(callback) {
//鑾峰彇code
@@ -1361,4 +1376,10 @@
.custom-share-btn::after {
border: none;
}
+ .topBar {
+ position: fixed;
+ top: 20rpx;
+ left: 20rpx;
+ z-index: 1000
+ }
</style>
--
Gitblit v1.8.0