优化:底部导航菜单
This commit is contained in:
@@ -30,6 +30,7 @@ const Index = () => {
|
||||
// 当前栏目信息
|
||||
if (navs) {
|
||||
setNavigation(navs);
|
||||
Taro.setNavigationBarTitle({title: `${navs.title}`})
|
||||
}
|
||||
// 获取子级栏目
|
||||
if (childCateogry) {
|
||||
|
||||
209
src/components/SimpleH5TabBar.scss
Normal file
209
src/components/SimpleH5TabBar.scss
Normal file
@@ -0,0 +1,209 @@
|
||||
/* H5专用TabBar样式 */
|
||||
.simple-h5-tabbar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
background-color: #ffffff;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
|
||||
|
||||
.h5-tabbar-container {
|
||||
display: flex;
|
||||
height: 60px;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
padding: 0 16px;
|
||||
width: 100%;
|
||||
|
||||
.h5-tabbar-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
// 普通图标样式
|
||||
.h5-normal-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin-bottom: 4px;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
.h5-icon-emoji {
|
||||
font-size: 20px;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
// 特殊AI按钮样式
|
||||
.h5-special-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: -8px;
|
||||
|
||||
.h5-ai-circle {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
background: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
top: -20px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
.h5-ai-text {
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
// 光晕效果
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
left: -4px;
|
||||
right: -4px;
|
||||
bottom: -4px;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 文字样式
|
||||
.h5-tabbar-text {
|
||||
font-size: 12px;
|
||||
color: #8a8a8a;
|
||||
transition: color 0.3s ease;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
|
||||
&.selected {
|
||||
color: #d81e06;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&.special-text {
|
||||
color: #ff6b35;
|
||||
font-weight: 500;
|
||||
margin-top: -12px;
|
||||
}
|
||||
}
|
||||
|
||||
// 选中状态
|
||||
&.selected {
|
||||
.h5-normal-icon {
|
||||
transform: translateY(-2px);
|
||||
|
||||
.h5-icon-emoji {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 特殊项目样式
|
||||
&.special {
|
||||
.h5-special-icon .h5-ai-circle {
|
||||
&::before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
.h5-special-icon .h5-ai-circle {
|
||||
background: linear-gradient(135deg, #ff6b35 0%, #ff4500 100%);
|
||||
box-shadow: 0 6px 16px rgba(255, 69, 0, 0.5);
|
||||
|
||||
&::before {
|
||||
background: linear-gradient(135deg, rgba(255, 107, 53, 0.5) 0%, rgba(255, 69, 0, 0.5) 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 点击效果
|
||||
&:active {
|
||||
.h5-tabbar-text {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// H5全屏适配 - 移除PC端限制,因为项目只用于H5端
|
||||
|
||||
// 暗色主题支持
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.simple-h5-tabbar {
|
||||
background-color: #1a1a1a;
|
||||
border-top-color: #333;
|
||||
|
||||
.h5-tabbar-container .h5-tabbar-item {
|
||||
.h5-tabbar-text {
|
||||
color: #999;
|
||||
|
||||
&.selected {
|
||||
color: #d81e06;
|
||||
}
|
||||
|
||||
&.special-text {
|
||||
color: #ff6b35;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 动画效果
|
||||
@keyframes h5-bounce {
|
||||
0%, 20%, 50%, 80%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
40% {
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
60% {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
// 选中时的弹跳效果
|
||||
.simple-h5-tabbar .h5-tabbar-container .h5-tabbar-item.selected .h5-normal-icon {
|
||||
animation: h5-bounce 0.6s ease;
|
||||
}
|
||||
|
||||
// AI按钮的脉冲效果
|
||||
@keyframes h5-pulse {
|
||||
0% {
|
||||
box-shadow: 0 4px 12px rgba(255, 107, 53, 0.4);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 4px 20px rgba(255, 107, 53, 0.6);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 4px 12px rgba(255, 107, 53, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.simple-h5-tabbar .h5-tabbar-container .h5-tabbar-item.special.selected .h5-special-icon .h5-ai-circle {
|
||||
animation: h5-pulse 2s infinite;
|
||||
}
|
||||
95
src/components/SimpleH5TabBar.tsx
Normal file
95
src/components/SimpleH5TabBar.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
import {useState, useEffect} from 'react';
|
||||
import {View, Text} from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import './SimpleH5TabBar.scss';
|
||||
import {Image} from '@nutui/nutui-react-taro'
|
||||
|
||||
interface TabBarProps {
|
||||
current?: number;
|
||||
}
|
||||
|
||||
interface TabBarItem {
|
||||
pagePath: string;
|
||||
text: string;
|
||||
icon: string;
|
||||
isSpecial?: boolean;
|
||||
}
|
||||
|
||||
const tabBarData: TabBarItem[] = [
|
||||
{
|
||||
pagePath: 'pages/index/index',
|
||||
text: '首页',
|
||||
icon: 'https://oss.wsdns.cn/20250711/3f000045aac44a0480b4be0a2c225fe1.png',
|
||||
},
|
||||
{
|
||||
pagePath: 'pages/ai/index',
|
||||
text: 'AI问答',
|
||||
icon: 'https://oss.wsdns.cn/20250711/86fdc1ad45a041d797b582ba42c34698.png',
|
||||
isSpecial: true,
|
||||
},
|
||||
{
|
||||
pagePath: 'pages/user/user',
|
||||
text: '我的',
|
||||
icon: 'https://oss.wsdns.cn/20250711/2baaec717bca49e7b58f36a3bd75fc14.png',
|
||||
},
|
||||
];
|
||||
|
||||
function SimpleH5TabBar({current}: TabBarProps) {
|
||||
const [selected, setSelected] = useState(current || 0);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('SimpleH5TabBar 组件已挂载, current:', current);
|
||||
if (typeof current === 'number') {
|
||||
setSelected(current);
|
||||
}
|
||||
}, [current]);
|
||||
|
||||
const switchTab = (index: number) => {
|
||||
console.log('SimpleH5TabBar 点击项目:', index);
|
||||
setSelected(index);
|
||||
|
||||
const urls = [
|
||||
'/pages/index/index',
|
||||
'/pages/ai/index',
|
||||
'/pages/user/user'
|
||||
];
|
||||
|
||||
Taro.switchTab({
|
||||
url: urls[index],
|
||||
success: () => console.log('跳转成功:', urls[index]),
|
||||
fail: (error) => console.error('跳转失败:', error)
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<View className="simple-h5-tabbar">
|
||||
<View className="h5-tabbar-container">
|
||||
{tabBarData.map((item, index) => (
|
||||
<View
|
||||
key={index}
|
||||
className={`h5-tabbar-item ${selected === index ? 'selected' : ''} ${item.isSpecial ? 'special' : ''}`}
|
||||
onClick={() => switchTab(index)}
|
||||
>
|
||||
{item.isSpecial ? (
|
||||
<View className="h5-special-icon">
|
||||
<View className="h5-ai-circle">
|
||||
<Image src={item.icon} width={'24px'} height={'24px'}/>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View className="h5-normal-icon">
|
||||
<Image src={item.icon} width={'24px'} height={'24px'}/>
|
||||
</View>
|
||||
)}
|
||||
<Text
|
||||
className={`h5-tabbar-text ${selected === index ? 'selected' : ''} ${item.isSpecial ? 'special-text' : ''}`}>
|
||||
{item.text}
|
||||
</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
export default SimpleH5TabBar;
|
||||
@@ -1,5 +0,0 @@
|
||||
import SimpleTabBar from '../components/SimpleTabBar';
|
||||
|
||||
export default function CustomTabBarWrapper() {
|
||||
return <SimpleTabBar />;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '红色资源'
|
||||
})
|
||||
@@ -1,75 +0,0 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {pageCmsArticle} from "@/api/cms/cmsArticle";
|
||||
import {CmsArticle} from "@/api/cms/cmsArticle/model";
|
||||
import Taro from '@tarojs/taro'
|
||||
import {useRouter} from '@tarojs/taro'
|
||||
import {Image} from '@nutui/nutui-react-taro'
|
||||
import {getCmsNavigation} from "@/api/cms/cmsNavigation";
|
||||
import {CmsNavigation} from "@/api/cms/cmsNavigation/model";
|
||||
|
||||
/**
|
||||
* 文章终极列表
|
||||
* @constructor
|
||||
*/
|
||||
const Article = () => {
|
||||
const {params} = useRouter();
|
||||
const [navigation, setNavigation] = useState<CmsNavigation>()
|
||||
const [list, setList] = useState<CmsArticle[]>([])
|
||||
|
||||
const reload = async () => {
|
||||
const categoryId = Number(params.id);
|
||||
const nav = await getCmsNavigation(categoryId);
|
||||
const articles = await pageCmsArticle({categoryId});
|
||||
|
||||
if(nav){
|
||||
setNavigation(nav);
|
||||
}
|
||||
if(articles){
|
||||
setList(articles?.list)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="mobile-container">
|
||||
<Image
|
||||
src={navigation?.style}
|
||||
style={{width: '100%', height: 'auto'}}
|
||||
mode="widthFix"
|
||||
/>
|
||||
<div className={'bg-white rounded-lg py-3 px-2'}>
|
||||
{/* 宫格布局容器 */}
|
||||
<div className={'grid grid-cols-3'}>
|
||||
{
|
||||
list.map((item, index) => {
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={'flex flex-col items-center cursor-pointer my-1'}
|
||||
onClick={() => Taro.navigateTo({url: `/pages/article/detail?id=${item.articleId}`})}
|
||||
>
|
||||
{/* 图片容器 */}
|
||||
<div className={'w-full mb-2 flex justify-center'}>
|
||||
<img
|
||||
className={'object-cover rounded-lg'}
|
||||
src={item.image}
|
||||
alt={item.title || ''}
|
||||
/>
|
||||
</div>
|
||||
{/* 标题 */}
|
||||
<div className={'text-xs text-center text-gray-800 leading-tight px-1'}>
|
||||
{item.title}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Article
|
||||
@@ -32,6 +32,7 @@ const Index = () => {
|
||||
const navs = await getCmsNavigation(categoryId);
|
||||
if (navs) {
|
||||
setNavigation(navs);
|
||||
Taro.setNavigationBarTitle({title: `${navs.title}`})
|
||||
}
|
||||
|
||||
// 加载第一页数据
|
||||
|
||||
@@ -30,6 +30,7 @@ const Index = () => {
|
||||
// 当前栏目信息
|
||||
if (navs) {
|
||||
setNavigation(navs);
|
||||
Taro.setNavigationBarTitle({title: `${navs.title}`})
|
||||
}
|
||||
// 获取子级栏目
|
||||
if (childCateogry) {
|
||||
|
||||
@@ -29,6 +29,7 @@ const List = () => {
|
||||
const navs = await getCmsNavigation(categoryId);
|
||||
if (navs) {
|
||||
setNavigation(navs);
|
||||
Taro.setNavigationBarTitle({title: `${navs.title}`})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ const List = () => {
|
||||
const nextPage = page + 1;
|
||||
console.log('honor/list 加载更多 - 下一页:', nextPage);
|
||||
setPage(nextPage);
|
||||
reload(nextPage);
|
||||
reload(nextPage).then();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@@ -72,7 +73,7 @@ const List = () => {
|
||||
setList([]);
|
||||
setHasMore(true);
|
||||
// 加载第一页数据
|
||||
reload(1);
|
||||
reload(1).then();
|
||||
}, [])
|
||||
|
||||
return (
|
||||
|
||||
@@ -30,6 +30,7 @@ const Index = () => {
|
||||
// 当前栏目信息
|
||||
if (navs) {
|
||||
setNavigation(navs);
|
||||
Taro.setNavigationBarTitle({title: `${navs.title}`})
|
||||
}
|
||||
// 获取子级栏目
|
||||
if (childCateogry) {
|
||||
@@ -42,7 +43,7 @@ const Index = () => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
reload().then()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
|
||||
@@ -28,6 +28,7 @@ const Index = () => {
|
||||
// 当前栏目信息
|
||||
if (navs) {
|
||||
setNavigation(navs);
|
||||
Taro.setNavigationBarTitle({title: `${navs.title}`})
|
||||
}
|
||||
// 新闻列表
|
||||
if (articles) {
|
||||
@@ -36,7 +37,7 @@ const Index = () => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
reload().then()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user