feat: implement custom config

This commit is contained in:
shinya
2025-07-31 01:07:59 +08:00
parent fc24055bdc
commit 7b6867ed58
13 changed files with 967 additions and 49 deletions

View File

@@ -1,8 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client';
import { Clover, Film, Home, Search, Tv } from 'lucide-react';
import { Clover, Film, Home, Search, Star, Tv } from 'lucide-react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useEffect, useState } from 'react';
interface MobileBottomNavProps {
/**
@@ -17,7 +20,7 @@ const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
// 当前激活路径:优先使用传入的 activePath否则回退到浏览器地址
const currentActive = activePath ?? pathname;
const navItems = [
const [navItems, setNavItems] = useState([
{ icon: Home, label: '首页', href: '/' },
{ icon: Search, label: '搜索', href: '/search' },
{
@@ -35,10 +38,27 @@ const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
label: '综艺',
href: '/douban?type=show',
},
];
]);
useEffect(() => {
const runtimeConfig = (window as any).RUNTIME_CONFIG;
if (runtimeConfig?.CUSTOM_CATEGORIES) {
setNavItems((prevItems) => [
...prevItems,
...runtimeConfig.CUSTOM_CATEGORIES.map((category: any) => ({
icon: Star,
label: category.name || category.query,
href: `/douban?type=${category.type}&tag=${category.query}${
category.name ? `&name=${category.name}` : ''
}&custom=true`,
})),
]);
}
}, []);
const isActive = (href: string) => {
const typeMatch = href.match(/type=([^&]+)/)?.[1];
const tagMatch = href.match(/tag=([^&]+)/)?.[1];
// 解码URL以进行正确的比较
const decodedActive = decodeURIComponent(currentActive);
@@ -47,7 +67,9 @@ const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
return (
decodedActive === decodedItemHref ||
(decodedActive.startsWith('/douban') &&
decodedActive.includes(`type=${typeMatch}`))
decodedActive.includes(`type=${typeMatch}`) &&
tagMatch &&
decodedActive.includes(`tag=${tagMatch}`))
);
};
@@ -61,11 +83,11 @@ const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
minHeight: 'calc(3.5rem + env(safe-area-inset-bottom))',
}}
>
<ul className='flex items-center'>
<ul className='flex items-center overflow-x-auto scrollbar-hide'>
{navItems.map((item) => {
const active = isActive(item.href);
return (
<li key={item.href} className='flex-shrink-0 w-1/5'>
<li key={item.href} className='flex-shrink-0 w-20 min-w-20'>
<Link
href={item.href}
className='flex flex-col items-center justify-center w-full h-14 gap-1 text-xs'