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