公告增加每次显示模式
This commit is contained in:
@@ -357,6 +357,7 @@ interface StandaloneSourceScript {
|
||||
interface SiteConfig {
|
||||
SiteName: string;
|
||||
Announcement: string;
|
||||
AnnouncementDisplayMode?: 'once' | 'every';
|
||||
SearchDownstreamMaxPage: number;
|
||||
SiteInterfaceCacheTime: number;
|
||||
DoubanProxyType: string;
|
||||
@@ -10150,6 +10151,7 @@ const SiteConfigComponent = ({
|
||||
const [siteSettings, setSiteSettings] = useState<SiteConfig>({
|
||||
SiteName: '',
|
||||
Announcement: '',
|
||||
AnnouncementDisplayMode: 'once',
|
||||
SearchDownstreamMaxPage: 1,
|
||||
SiteInterfaceCacheTime: 7200,
|
||||
DoubanProxyType: 'cmliussss-cdn-tencent',
|
||||
@@ -10304,6 +10306,10 @@ const SiteConfigComponent = ({
|
||||
config.SiteConfig.MagnetAcgripReverseProxy || '',
|
||||
MagnetNyaaReverseProxy: config.SiteConfig.MagnetNyaaReverseProxy || '',
|
||||
EnableComments: config.SiteConfig.EnableComments || false,
|
||||
AnnouncementDisplayMode:
|
||||
config.SiteConfig.AnnouncementDisplayMode === 'every'
|
||||
? 'every'
|
||||
: 'once',
|
||||
});
|
||||
}
|
||||
}, [config]);
|
||||
@@ -10462,6 +10468,51 @@ const SiteConfigComponent = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 公告显示模式 */}
|
||||
<div>
|
||||
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
|
||||
公告显示模式
|
||||
</label>
|
||||
<div className='flex gap-4'>
|
||||
<label className='inline-flex items-center gap-2 cursor-pointer'>
|
||||
<input
|
||||
type='radio'
|
||||
name='announcementDisplayMode'
|
||||
value='once'
|
||||
checked={siteSettings.AnnouncementDisplayMode !== 'every'}
|
||||
onChange={() =>
|
||||
setSiteSettings((prev) => ({
|
||||
...prev,
|
||||
AnnouncementDisplayMode: 'once',
|
||||
}))
|
||||
}
|
||||
className='text-green-600 focus:ring-green-500'
|
||||
/>
|
||||
<span className='text-sm text-gray-700 dark:text-gray-300'>
|
||||
单次显示
|
||||
</span>
|
||||
</label>
|
||||
<label className='inline-flex items-center gap-2 cursor-pointer'>
|
||||
<input
|
||||
type='radio'
|
||||
name='announcementDisplayMode'
|
||||
value='every'
|
||||
checked={siteSettings.AnnouncementDisplayMode === 'every'}
|
||||
onChange={() =>
|
||||
setSiteSettings((prev) => ({
|
||||
...prev,
|
||||
AnnouncementDisplayMode: 'every',
|
||||
}))
|
||||
}
|
||||
className='text-green-600 focus:ring-green-500'
|
||||
/>
|
||||
<span className='text-sm text-gray-700 dark:text-gray-300'>
|
||||
每次显示
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 豆瓣数据源设置 */}
|
||||
<div className='space-y-3'>
|
||||
<div>
|
||||
|
||||
@@ -31,6 +31,7 @@ export async function POST(request: NextRequest) {
|
||||
const {
|
||||
SiteName,
|
||||
Announcement,
|
||||
AnnouncementDisplayMode,
|
||||
SearchDownstreamMaxPage,
|
||||
SiteInterfaceCacheTime,
|
||||
DoubanProxyType,
|
||||
@@ -85,6 +86,7 @@ export async function POST(request: NextRequest) {
|
||||
} = body as {
|
||||
SiteName: string;
|
||||
Announcement: string;
|
||||
AnnouncementDisplayMode?: 'once' | 'every';
|
||||
SearchDownstreamMaxPage: number;
|
||||
SiteInterfaceCacheTime: number;
|
||||
DoubanProxyType: string;
|
||||
@@ -142,6 +144,9 @@ export async function POST(request: NextRequest) {
|
||||
if (
|
||||
typeof SiteName !== 'string' ||
|
||||
typeof Announcement !== 'string' ||
|
||||
(AnnouncementDisplayMode !== undefined &&
|
||||
AnnouncementDisplayMode !== 'once' &&
|
||||
AnnouncementDisplayMode !== 'every') ||
|
||||
typeof SearchDownstreamMaxPage !== 'number' ||
|
||||
typeof SiteInterfaceCacheTime !== 'number' ||
|
||||
typeof DoubanProxyType !== 'string' ||
|
||||
@@ -238,6 +243,7 @@ export async function POST(request: NextRequest) {
|
||||
adminConfig.SiteConfig = {
|
||||
SiteName,
|
||||
Announcement,
|
||||
AnnouncementDisplayMode,
|
||||
SearchDownstreamMaxPage,
|
||||
SiteInterfaceCacheTime,
|
||||
DoubanProxyType,
|
||||
|
||||
@@ -58,6 +58,9 @@ export default async function RootLayout({
|
||||
let announcement =
|
||||
process.env.ANNOUNCEMENT ||
|
||||
'本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。';
|
||||
// 公告显示模式:从环境变量读取,数据库模式下由管理面板配置覆盖
|
||||
let announcementDisplayMode: 'once' | 'every' =
|
||||
process.env.ANNOUNCEMENT_DISPLAY_MODE === 'every' ? 'every' : 'once';
|
||||
|
||||
let doubanProxyType =
|
||||
process.env.NEXT_PUBLIC_DOUBAN_PROXY_TYPE || 'cmliussss-cdn-tencent';
|
||||
@@ -136,6 +139,8 @@ export default async function RootLayout({
|
||||
const config = await getConfig();
|
||||
siteName = config.SiteConfig.SiteName;
|
||||
announcement = config.SiteConfig.Announcement;
|
||||
announcementDisplayMode =
|
||||
config.SiteConfig.AnnouncementDisplayMode === 'every' ? 'every' : 'once';
|
||||
|
||||
doubanProxyType = config.SiteConfig.DoubanProxyType;
|
||||
doubanProxy = config.SiteConfig.DoubanProxy;
|
||||
@@ -346,6 +351,7 @@ export default async function RootLayout({
|
||||
<SiteProvider
|
||||
siteName={siteName}
|
||||
announcement={announcement}
|
||||
announcementDisplayMode={announcementDisplayMode}
|
||||
tmdbApiKey={tmdbApiKey}
|
||||
>
|
||||
<WatchRoomProvider>
|
||||
|
||||
+14
-2
@@ -53,7 +53,7 @@ function HomeClient() {
|
||||
BangumiCalendarData[]
|
||||
>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const { announcement } = useSite();
|
||||
const { announcement, announcementDisplayMode } = useSite();
|
||||
// 首页模块配置状态
|
||||
const [homeModules, setHomeModules] = useState<HomeModule[]>([
|
||||
{ id: 'hotMovies', name: '热门电影', enabled: true, order: 0 },
|
||||
@@ -362,6 +362,17 @@ function HomeClient() {
|
||||
// 检查公告弹窗状态
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined' && announcement) {
|
||||
// 会话级标记:只在首次访问站点时弹出,导航切回首页不重复弹
|
||||
if (sessionStorage.getItem('announcementShown')) {
|
||||
return;
|
||||
}
|
||||
// 每次显示模式:每次新会话首次访问弹出一次
|
||||
if (announcementDisplayMode === 'every') {
|
||||
setShowAnnouncement(true);
|
||||
sessionStorage.setItem('announcementShown', '1');
|
||||
return;
|
||||
}
|
||||
// 单次显示模式:localStorage 记住已看过的公告文本,换公告则重新弹出
|
||||
const hasSeenAnnouncement = localStorage.getItem('hasSeenAnnouncement');
|
||||
if (hasSeenAnnouncement !== announcement) {
|
||||
setShowAnnouncement(true);
|
||||
@@ -369,7 +380,8 @@ function HomeClient() {
|
||||
setShowAnnouncement(Boolean(!hasSeenAnnouncement && announcement));
|
||||
}
|
||||
}
|
||||
}, [announcement]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [announcement, announcementDisplayMode]);
|
||||
|
||||
useEffect(() => {
|
||||
const CACHE_DURATION = 60 * 60 * 1000; // 1小时
|
||||
|
||||
@@ -5,12 +5,14 @@ import { createContext, ReactNode, useContext } from 'react';
|
||||
const SiteContext = createContext<{
|
||||
siteName: string;
|
||||
announcement?: string;
|
||||
announcementDisplayMode?: 'once' | 'every';
|
||||
tmdbApiKey?: string;
|
||||
}>({
|
||||
// 默认值
|
||||
siteName: 'MoonTVPlus',
|
||||
announcement:
|
||||
'本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。',
|
||||
announcementDisplayMode: 'once',
|
||||
tmdbApiKey: '',
|
||||
});
|
||||
|
||||
@@ -20,15 +22,19 @@ export function SiteProvider({
|
||||
children,
|
||||
siteName,
|
||||
announcement,
|
||||
announcementDisplayMode,
|
||||
tmdbApiKey,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
siteName: string;
|
||||
announcement?: string;
|
||||
announcementDisplayMode?: 'once' | 'every';
|
||||
tmdbApiKey?: string;
|
||||
}) {
|
||||
return (
|
||||
<SiteContext.Provider value={{ siteName, announcement, tmdbApiKey }}>
|
||||
<SiteContext.Provider
|
||||
value={{ siteName, announcement, announcementDisplayMode, tmdbApiKey }}
|
||||
>
|
||||
{children}
|
||||
</SiteContext.Provider>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,8 @@ export interface AdminConfig {
|
||||
SiteConfig: {
|
||||
SiteName: string;
|
||||
Announcement: string;
|
||||
// 公告显示模式:once=单次显示(每个用户每条公告仅显示一次,换公告则重新显示);every=每次显示(每次打开首页都显示)
|
||||
AnnouncementDisplayMode?: 'once' | 'every';
|
||||
SearchDownstreamMaxPage: number;
|
||||
SiteInterfaceCacheTime: number;
|
||||
DoubanProxyType: string;
|
||||
|
||||
@@ -265,6 +265,10 @@ async function getInitConfig(
|
||||
Announcement:
|
||||
process.env.ANNOUNCEMENT ||
|
||||
'本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。',
|
||||
AnnouncementDisplayMode:
|
||||
process.env.ANNOUNCEMENT_DISPLAY_MODE === 'every'
|
||||
? 'every'
|
||||
: 'once',
|
||||
SearchDownstreamMaxPage:
|
||||
Number(process.env.NEXT_PUBLIC_SEARCH_MAX_PAGE) || 5,
|
||||
SiteInterfaceCacheTime: cfgFile.cache_time || 7200,
|
||||
@@ -555,6 +559,11 @@ export function configSelfCheck(adminConfig: AdminConfig): AdminConfig {
|
||||
if (adminConfig.SiteConfig.EnableComments === undefined) {
|
||||
adminConfig.SiteConfig.EnableComments = false;
|
||||
}
|
||||
// 确保公告显示模式存在
|
||||
if (adminConfig.SiteConfig.AnnouncementDisplayMode === undefined) {
|
||||
adminConfig.SiteConfig.AnnouncementDisplayMode =
|
||||
process.env.ANNOUNCEMENT_DISPLAY_MODE === 'every' ? 'every' : 'once';
|
||||
}
|
||||
if (adminConfig.SiteConfig.EnableRegistration === undefined) {
|
||||
adminConfig.SiteConfig.EnableRegistration = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user