<template>
<view class="pages">
<!-- #ifndef H5 -->
<statusBar></statusBar>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<uni-nav-bar :statusBar="true" :border="false"></uni-nav-bar>
<!-- #endif -->
<!-- 顶部导航 -->
<view class="nav">
<scroll-view class="nav-scroll" scroll-x="true" :show-scrollbar="false"
style="width: 100%; height: 90rpx; white-space: nowrap;">
<view class="tab-item" v-for="(item, index) in navItems" :key="index"
:style="{ minWidth: navItemWidth + 'rpx' }" :class="{ active: currentNav === index }"
@tap="switchNav(index)">
{{ item.name }}
</view>
</scroll-view>
</view>
<template v-if="!isHotCategory">
<!-- 搜索框-->
<view class="uni-search-box">
<!-- #ifdef MP-WEIXIN -->
<uni-search-bar style="width: 100%" v-model="keyword" ref="searchBar" radius="100" cancelButton="none"
disabled :placeholder="inputPlaceholder" />
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<uni-search-bar v-model="keyword" ref="searchBar" radius="100" cancelButton="none" disabled
:placeholder="inputPlaceholder" />
<!-- #endif -->
<view class="cover-search-bar" @click="searchClick"></view>
</view>
</template>
<uni-grid class="grid" :column="4" :showBorder="false" :square="true" v-if="currentNav === 3">
<uni-grid-item class="item" v-for="(item,index) in gridList" @click.native="tapGrid(index)" :key="index">
<image class="grid-image" :src="item.image" mode="aspectFit"></image>
<text class="text">{{item.text}}</text>
</uni-grid-item>
</uni-grid>
<!-- banner区域 -->
<template v-if="currentNav === 0">
<unicloud-db ref="bannerdb" v-slot:default="{data, loading, error, options}" collection="opendb-banner"
field="_id,bannerfile,open_url,title" @load="onqueryload">
<image v-if="!(loading || data.length)" class="banner-image" src="/static/uni-center/headers.png"
mode="aspectFill" :draggable="false" />
<view v-else>
<swiper class="swiper-box" :style="{ height: '300rpx' }"
:autoplay="true"
:interval="3000"
:circular="true">
<swiper-item v-for="(item, index) in data" :key="item._id">
<image class="banner-image" :src="item.bannerfile.url" mode="scaleToFill"
style="width: 100%; height: 100%;" />
</swiper-item>
</swiper>
<!-- 自定义指示点 -->
<view class="custom-indicator">
<view v-for="(item, index) in data" :key="index" class="indicator-dot"
:class="{ active: current === index }" @click="switchBanner(index)"></view>
</view>
</view>
</unicloud-db>
</template>
<!-- 萌宠明星区域 -->
<template v-if="currentNav === 0">
<view class="star-section">
<view class="section-header">
<uni-icons type="vip" size="24" color="#ffcc00" style="margin-top: 2rpx;">
<text class="title">萌宠明星</text>
</uni-icons>
<text class="more" @click="navigateToMore">全部 ></text>
</view>
<view class="star-wrapper">
<view class="star-item" v-for="(star, index) in starList.slice(0,3)" :key="index">
<view class="avatar-wrap">
<image :src="star.avatar" mode="aspectFill" class="star-avatar" />
<view :class="['star-tag', getTagClass(index)]">{{ getTagText(index) }}</view>
</view>
<text class="star-name">{{ star.pet_name }}</text>
<view class="popularity">
<uni-icons type="fire" size="14" color="#FF6B6B" />
<text>{{ star.popularity }}</text>
</view>
</view>
</view>
</view>
</template>
<!-- 文章列表 -->
<template v-if="!isHotCategory">
<unicloud-db ref="udb" v-slot:default="{ data, pagination, hasMore, loading, error, options }"
@error="onqueryerror" :collection="colList" :page-size="10">
<template v-if="currentNav === 0">
<view class="section-header">
<uni-icons type="wallet" size="24" color="#ffcc00" style="margin-left: 20rpx;">
<text class="title">萌宠日记</text>
</uni-icons>
<text class="more" @click="navigateToMore">全部 ></text>
</view>
</template>
<uni-list class="uni-list" :border="false" :style="{ height: listHight }">
<uni-list-item :to="'/pages/list/detail?id=' + item._id + '&title=' + item.title"
v-for="(item, index) in data" :key="index">
<template v-slot:header>
<image class="avatar" :src="item.avatar" mode="aspectFill"></image>
</template>
<template v-slot:body>
<view class="main">
<text class="title">{{ item.title }}</text>
<view class="info">
<text class="author">{{ item.user_id[0] ? item.user_id[0].nickname : '' }}</text>
<uni-dateformat class="last_modify_date" :date="item.last_modify_date"
format="yyyy-MM-dd" :threshold="[60000, 2592000000]" />
</view>
</view>
</template>
</uni-list-item>
<uni-load-state :state="{ data, pagination, hasMore, loading, error }">
<template v-slot:loading>
<view class="loading-text">正在加载{{ navItems[currentNav]?.name }}的内容...</view>
</template>
</uni-load-state>
</uni-list>
</unicloud-db>
</template>
<!-- 视频列表 -->
<template v-else>
<!-- 添加视频搜索框 -->
<view class="uni-search-box video-search">
<uni-search-bar v-model="videoKeyword" radius="100" cancelButton="none" :placeholder="videoPlaceholder"
@confirm="handleVideoSearch" @clear="clearVideoSearch" />
</view>
<unicloud-db ref="videoUdb" v-slot:default="{data}" :collection="videoColList">
<uni-list class="uni-list">
<uni-list-item v-for="item in data" :key="item._id">
<template v-slot:header>
<view class="video-cover-wrapper" @click="navigateToDetail(item._id)">
<image class="video-cover" :src="item.cover_url" mode="aspectFill"
style="width: 240rpx; height: 160rpx; border-radius: 8rpx;" />
<view class="play-icon">
<uni-icons type="videocam" size="24" color="#fff"></uni-icons>
</view>
</view>
</template>
<template v-slot:body>
<view class="video-info">
<!-- 第一行:标题 + 播放次数 -->
<view class="flex-row justify-between align-center mb-8">
<text class="title line-clamp-1">{{ item.title }}</text>
<text class="play-count">{{ item.play_count }}次播放</text>
</view>
<!-- 第二行:作者 + 创建时间 -->
<view class="flex-row justify-between align-center">
<text class="author">{{ item.user_id[0]?.nickname || '未知用户' }}</text>
<text class="create-time">{{ formatDate(item.create_date) }}</text>
</view>
</view>
</template>
</uni-list-item>
</uni-list>
</unicloud-db>
</template>
</view>
</template>
<script>
let cdbRef;
import statusBar from "@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar";
import Gps from '@/uni_modules/json-gps/js_sdk/gps.js';
const gps = new Gps();
const db = uniCloud.database();
export default {
components: {
statusBar
},
computed: {
inputPlaceholder() {
return uni.getStorageSync('CURRENT_LANG') == "en" ? 'Please enter the search content' : '请输入搜索内容';
},
colList() {
return [
db.collection('opendb-news-articles').where(this.where).field(
'avatar,title,last_modify_date,user_id,comments,collections,shares,category_id').getTemp(),
db.collection('uni-id-users').field('_id,nickname').getTemp()
];
},
// 视频查询列表
videoColList() {
const db = uniCloud.database()
let query = {}
if (this.videoKeyword) {
query.title = new RegExp(this.videoKeyword, 'i')
}
return [
db.collection('pet-videos')
.where(query)
.field('title,cover_url,play_count,create_date,user_id')
.getTemp(),
db.collection('uni-id-users')
.field('_id,nickname')
.getTemp()
]
},
videoPlaceholder() {
return uni.getStorageSync('CURRENT_LANG') == "en" ?
'Search videos...' :
'搜索视频...'
}
},
data() {
return {
navItemWidth: 160, // 导航项基准宽度
coverWidth: 340, // 封面基准宽度
navItems: [],
currentNav: 0,
currentCategoryId: '',
where: '',
videoKeyword: '',
starList: [],
current: 0, // 新增当前banner索引
hotCategoryId: '6828846d6e5d2d42e61ece39', // 替换为你的热门分类ID
isHotCategory: false,
gridList: [{
"text": "精选",
"image": "/static/pet-icons/羊.png" // Update with your actual image path
},
{
"text": "好物",
"image": "/static/pet-icons/边牧.png" // Update with your actual image path
},
{
"text": "话题",
"image": "/static/pet-icons/奶牛猫.png" // Update with your actual image path
},
{
"text": "问答",
"image": "/static/pet-icons/黑猫.png" // Update with your actual image path
}
],
};
},
watch: {
keyword(keyword, oldValue) {
let where = '"article_status" == 1 ';
if (keyword) {
this.where = where + `&& /${keyword}/.test(title)`;
} else {
this.where = where;
}
}
},
async onReady() {
// #ifdef APP-NVUE
this.listHight = uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 50 +
'px';
// #endif
// #ifndef APP-NVUE
this.listHight = 'auto';
// #endif
cdbRef = this.$refs.udb;
},
async onShow() {
this.keyword = getApp().globalData.searchText;
getApp().globalData.searchText = '';
this.fetchStarPets();
},
async onLoad() {
await this.fetchNavItems();
if (this.navItems.length > 0) {
this.currentCategoryId = this.navItems[0]._id;
this.updateArticleList(this.currentCategoryId);
}
},
methods: {
// 视频搜索处理方法
handleVideoSearch() {
this.$refs.videoUdb.loadData({
clear: true
})
},
clearVideoSearch() {
this.videoKeyword = ''
this.handleVideoSearch()
},
// 点击跳转方法
navigateToDetail(videoId) {
uni.navigateTo({
url: `/pages/list/video-detail?id=${videoId}`
})
},
// 切换banner
changeSwiper(e) {
this.current = e.detail.current;
},
// 点击指示点
switchBanner(index) {
this.current = index;
},
async fetchNavItems() {
try {
const res = await db.collection('opendb-news-categories').get();
this.navItems = res.result.data;
} catch (error) {
console.error('获取导航栏数据失败', error);
uni.showToast({
title: '分类加载失败',
icon: 'none'
});
}
},
updateArticleList(categoryId) {
this.where = `article_status == 1 && category_id == "${categoryId}"`;
this.$nextTick(() => {
this.$refs.udb.loadData({
clear: true
});
});
},
switchNav(index) {
this.currentNav = index;
const category = this.navItems[index];
this.currentCategoryId = category._id;
this.isHotCategory = category._id === this.hotCategoryId;
if (this.isHotCategory) {
this.$nextTick(() => {
this.$refs.videoUdb.loadData({
clear: true
});
});
} else {
this.updateArticleList(this.currentCategoryId);
}
},
async updatePlayCount(videoId) {
const db = uniCloud.database()
await db.collection('pet-videos')
.doc(videoId)
.update({
play_count: db.command.inc(1)
})
},
// 时间格式化
formatDate(timestamp) {
return new Date(timestamp).toISOString().split('T')[0]
},
async fetchStarPets() {
try {
const res = await db.collection('pets-star')
.field('avatar, pet_name, popularity')
.orderBy('popularity', 'desc')
.limit(3)
.get();
this.starList = res.result.data;
} catch (error) {
console.error('获取萌宠明星数据失败', error);
}
},
getTagClass(index) {
const tagClasses = ['tag-popular', 'tag-charm', 'tag-active'];
return tagClasses[index] || '';
},
getTagText(index) {
const tagTexts = ['人气之星', '魅力之星', '活跃之星'];
return tagTexts[index] || '';
},
navigateToMore() {
uni.navigateTo({
url: '/pages/list/pets-stardetail'
});
},
searchClick() {
uni.hideKeyboard();
uni.navigateTo({
url: '/pages/list/search/search',
animationType: 'fade-in'
});
},
loadMore() {
cdbRef.loadMore();
},
onPullDownRefresh() {
this.refresh();
},
onReachBottom() {
this.loadMore();
}
}
};
</script>
<style scoped>
/* #ifndef APP-NVUE */
view {
display: flex;
box-sizing: border-box;
flex-direction: column;
}
/* #endif */
/* #ifdef APP-PLUS */
page {
width: 100%;
min-height: 100%;
display: flex;
}
/* #endif */
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
/* 通用样式 */
.flex-row {
display: flex;
flex-direction: row;
align-items: center;
}
.justify-between {
justify-content: space-between;
}
/* 视频信息容器 */
.video-info {
padding: 0 20px;
/* 左右边距 */
flex: 1;
}
/* 标题行 */
.title-row {
margin-bottom: 8px;
}
.title {
flex: 1;
font-size: 16px;
color: #333;
margin-right: 16px;
max-width: 70%;
/* 防止播放次数换行 */
}
.play-count {
font-size: 12px;
color: #666;
white-space: nowrap;
}
/* 作者行 */
.author {
font-size: 12px;
color: #666;
}
.create-time {
margin-top: 50px;
font-size: 12px;
color: #999;
white-space: nowrap;
}
/* 文字截断 */
.line-clamp-1 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.meta {
display: flex;
justify-content: space-between;
align-items: center;
}
.title {
font-size: 14px;
font-weight: 500;
flex: 1;
}
.stat,
.date {
font-size: 12px;
color: #999;
}
.author {
font-size: 12px;
color: #333;
}
.play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
padding: 8rpx;
}
.pages {
background-color: #FFFFFF;
}
.avatar {
width: 200rpx;
height: 200rpx;
margin-right: 10rpx;
}
.main {
justify-content: space-between;
flex: 1;
}
.title {
font-size: 16px;
}
.info {
flex-direction: row;
justify-content: space-between;
}
.author,
.last_modify_date {
font-size: 14px;
color: #999999;
}
.cover-search-bar {
height: 50px;
position: relative;
top: -50px;
margin-bottom: -50px;
/* #ifndef APP-NVUE */
z-index: 999;
/* #endif */
}
.load-state {
justify-content: center;
width: 750rpx;
}
/* banner指示点样式 */
.banner-image {
width: 100%;
height: 100%;
}
.custom-indicator {
position: absolute;
bottom: 30rpx;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: row;
z-index: 999;
}
.indicator-dot {
width: 14rpx;
height: 14rpx;
background: rgba(255, 255, 255, 0.6);
border-radius: 50%;
margin: 0 8rpx;
transition: all 0.3s;
}
.indicator-dot.active {
width: 14rpx;
background: orange;
border-radius: 8rpx;
}
/* 导航栏容器 */
.nav {
height: 90rpx;
background: #fff;
border-bottom: 1rpx solid #f5f5f5;
}
/* 滚动容器 */
.nav-scroll {
height: 100%;
height: 100%;
}
/* 每个导航项 */
.tab-item {
flex: 1;
min-width: 200rpx;
height: 100%;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
color: #666;
position: relative;
flex-shrink: 0;
padding: 0 30rpx;
}
/* 激活状态 */
.tab-item.active {
color: #FF9A3C;
font-weight: bold;
}
.tab-item.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background: #FF9A3C;
border-radius: 2rpx;
}
/* 萌宠明星区域 */
.section-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
}
.title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.more {
font-size: 28rpx;
color: #999;
flex-shrink: 0;
padding-left: 30rpx;
cursor: pointer;
}
.star-section {
width: 100%;
padding: 20rpx;
background-color: #fff;
margin: 20rpx 0;
border-radius: 16rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
.star-wrapper {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 0 20rpx;
}
.star-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
margin: 0 10rpx;
min-width: 0;
}
.avatar-wrap {
position: relative;
margin-bottom: 15rpx
}
.star-avatar {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.12)
}
.star-tag {
position: absolute;
bottom: -10rpx;
left: 50%;
transform: translateX(-50%);
font-size: 24rpx;
padding: 8rpx 20rpx;
border-radius: 40rpx;
color: #fff;
white-space: nowrap
}
.star-name {
font-size: 28rpx;
font-weight: 500;
color: #333;
margin: 15rpx 0 10rpx;
}
.popularity {
display: flex;
align-items: center;
font-size: 24rpx;
color: #FF6B6B;
background: #FFF2F2;
padding: 6rpx 20rpx;
border-radius: 40rpx;
}
.tag-popular {
background: linear-gradient(135deg, #FF9A3C, #FF6F61);
}
.tag-charm {
background: linear-gradient(135deg, #4ECDC4, #45B7AF);
}
.tag-active {
background: linear-gradient(135deg, #FF6B6B, #FF4757);
}
.grid {
border-radius: 20rpx;
margin-top: -50rpx;
}
.grid-image {
width: 50rpx;
height: 50rpx;
}
.uni-grid .text {
font-size: 26rpx;
color: #333;
margin-top: 10rpx;
}
.uni-grid .item ::v-deep .uni-grid-item__box {
justify-content: center;
align-items: center;
padding: 0rpx 0;
}
/* 视频搜索框样式 */
.video-search {
padding: 0rpx 10rpx;
background-color: #fff;
border-bottom: 1px solid #f5f5f5;
}
/* #ifdef APP-NVUE */
/* 新增/修改的样式 */
.nav-scroll {
height: 100%;
/* 修复安卓滚动条问题 */
/* #ifdef APP-NVUE */
scrollbar-width: none;
/* #endif */
}
.swiper-box {
height: 300rpx !important; /* 保持固定高度 */
border-radius: 16rpx; /* 添加圆角 */
overflow: hidden; /* 防止内容溢出 */
margin: 0 20rpx; /* 增加左右边距 */
}
.star-item {
flex: 1;
min-width: 220rpx; /* 防止内容挤压 */
padding: 0 15rpx; /* 增加内边距 */
}
.star-avatar {
width: 180rpx !important; /* 固定尺寸 */
height: 180rpx !important; /* 固定尺寸 */
}
.video-cover {
width: 240rpx !important; /* 固定视频封面尺寸 */
height: 160rpx !important; /* 固定视频封面尺寸 */
flex-shrink: 0; /* 防止图片压缩 */
}
.title {
font-size: 30rpx; /* 统一标题字号 */
max-width: 450rpx; /* 增加标题最大宽度 */
/* #ifndef APP-NVUE */
white-space: nowrap; /* 防止文字换行 */
overflow: hidden; /* 隐藏溢出内容 */
text-overflow: ellipsis; /* 显示省略号 */
/* #endif */
}
/* 新增安卓专属样式 */
/* #ifdef H5 || MP-WEIXIN || APP-ANDROID */
.tab-item {
padding: 0 40rpx; /* 增加导航项内边距 */
font-size: 32rpx; /* 加大导航文字 */
}
.grid-image {
width: 64rpx !important; /* 加大网格图标 */
height: 64rpx !important; /* 加大网格图标 */
}
/* #endif */
/* #endif */
</style>
为什么在模拟器导航栏还是竖排,字体大,萌宠区域的图片文字看不见。修改