修正观影室管理面板设置
This commit is contained in:
@@ -8,7 +8,8 @@
|
|||||||
"WebFetch(domain:github.com)",
|
"WebFetch(domain:github.com)",
|
||||||
"WebFetch(domain:www.artplayer.org)",
|
"WebFetch(domain:www.artplayer.org)",
|
||||||
"WebFetch(domain:m.douban.com)",
|
"WebFetch(domain:m.douban.com)",
|
||||||
"WebFetch(domain:movie.douban.com)"
|
"WebFetch(domain:movie.douban.com)",
|
||||||
|
"Bash(cat:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
129
server.js
129
server.js
@@ -11,6 +11,82 @@ const port = parseInt(process.env.PORT || '3000', 10);
|
|||||||
const app = next({ dev, hostname, port });
|
const app = next({ dev, hostname, port });
|
||||||
const handle = app.getRequestHandler();
|
const handle = app.getRequestHandler();
|
||||||
|
|
||||||
|
// 读取观影室配置的辅助函数
|
||||||
|
async function getWatchRoomConfig() {
|
||||||
|
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
|
||||||
|
|
||||||
|
// 如果使用 localStorage,无法在服务器端读取,返回默认配置(不启用)
|
||||||
|
if (storageType === 'localstorage') {
|
||||||
|
console.log('[WatchRoom] Using localStorage storage type.');
|
||||||
|
// 在 localStorage 模式下,可以通过环境变量控制是否启用观影室
|
||||||
|
const enabled = process.env.WATCH_ROOM_ENABLED === 'true';
|
||||||
|
console.log(`[WatchRoom] Watch room ${enabled ? 'enabled' : 'disabled'} via environment variable.`);
|
||||||
|
return { enabled, serverType: 'internal' };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (storageType === 'redis') {
|
||||||
|
// 检查 Redis 配置
|
||||||
|
const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
|
||||||
|
console.log('[WatchRoom] Attempting to read config from Redis...');
|
||||||
|
|
||||||
|
const { createClient } = require('redis');
|
||||||
|
const client = createClient({ url: redisUrl });
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
const configStr = await client.get('admin:config'); // 注意:使用冒号而不是下划线
|
||||||
|
await client.disconnect();
|
||||||
|
|
||||||
|
if (configStr) {
|
||||||
|
const config = JSON.parse(configStr);
|
||||||
|
return config.WatchRoomConfig || { enabled: false, serverType: 'internal' };
|
||||||
|
}
|
||||||
|
} else if (storageType === 'upstash') {
|
||||||
|
// 检查 Upstash 环境变量
|
||||||
|
if (!process.env.UPSTASH_REDIS_REST_URL || !process.env.UPSTASH_REDIS_REST_TOKEN) {
|
||||||
|
console.log('[WatchRoom] Upstash credentials not configured. Socket.IO disabled by default.');
|
||||||
|
return { enabled: false, serverType: 'internal' };
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[WatchRoom] Attempting to read config from Upstash...');
|
||||||
|
const { Redis } = require('@upstash/redis');
|
||||||
|
const redis = new Redis({
|
||||||
|
url: process.env.UPSTASH_REDIS_REST_URL,
|
||||||
|
token: process.env.UPSTASH_REDIS_REST_TOKEN,
|
||||||
|
});
|
||||||
|
|
||||||
|
const configStr = await redis.get('admin:config'); // 注意:使用冒号而不是下划线
|
||||||
|
|
||||||
|
if (configStr) {
|
||||||
|
const config = typeof configStr === 'string' ? JSON.parse(configStr) : configStr;
|
||||||
|
return config.WatchRoomConfig || { enabled: false, serverType: 'internal' };
|
||||||
|
}
|
||||||
|
} else if (storageType === 'kvrocks') {
|
||||||
|
// 检查 Kvrocks 配置
|
||||||
|
const kvrocksUrl = process.env.KVROCKS_URL || 'redis://localhost:6666';
|
||||||
|
console.log('[WatchRoom] Attempting to read config from Kvrocks...');
|
||||||
|
|
||||||
|
const { createClient } = require('redis');
|
||||||
|
const client = createClient({ url: kvrocksUrl });
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
const configStr = await client.get('admin:config'); // 注意:使用冒号而不是下划线
|
||||||
|
await client.disconnect();
|
||||||
|
|
||||||
|
if (configStr) {
|
||||||
|
const config = JSON.parse(configStr);
|
||||||
|
return config.WatchRoomConfig || { enabled: false, serverType: 'internal' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[WatchRoom] Failed to read config from storage:', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认不启用观影室
|
||||||
|
console.log('[WatchRoom] No config found or error occurred. Socket.IO disabled by default.');
|
||||||
|
return { enabled: false, serverType: 'internal' };
|
||||||
|
}
|
||||||
|
|
||||||
// 观影室服务器类
|
// 观影室服务器类
|
||||||
class WatchRoomServer {
|
class WatchRoomServer {
|
||||||
constructor(io) {
|
constructor(io) {
|
||||||
@@ -443,7 +519,7 @@ class WatchRoomServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.prepare().then(() => {
|
app.prepare().then(async () => {
|
||||||
const httpServer = createServer(async (req, res) => {
|
const httpServer = createServer(async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const parsedUrl = parse(req.url, true);
|
const parsedUrl = parse(req.url, true);
|
||||||
@@ -455,18 +531,35 @@ app.prepare().then(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化 Socket.IO
|
// 读取观影室配置
|
||||||
const io = new Server(httpServer, {
|
const watchRoomConfig = await getWatchRoomConfig();
|
||||||
path: '/socket.io',
|
console.log('[WatchRoom] Config:', watchRoomConfig);
|
||||||
cors: {
|
|
||||||
origin: '*',
|
|
||||||
methods: ['GET', 'POST'],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 初始化观影室服务器
|
let watchRoomServer = null;
|
||||||
const watchRoomServer = new WatchRoomServer(io);
|
|
||||||
console.log('[WatchRoom] Socket.IO server initialized');
|
// 只在启用观影室且使用内部服务器时初始化 Socket.IO
|
||||||
|
if (watchRoomConfig.enabled && watchRoomConfig.serverType === 'internal') {
|
||||||
|
console.log('[WatchRoom] Initializing Socket.IO server...');
|
||||||
|
|
||||||
|
// 初始化 Socket.IO
|
||||||
|
const io = new Server(httpServer, {
|
||||||
|
path: '/socket.io',
|
||||||
|
cors: {
|
||||||
|
origin: '*',
|
||||||
|
methods: ['GET', 'POST'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化观影室服务器
|
||||||
|
watchRoomServer = new WatchRoomServer(io);
|
||||||
|
console.log('[WatchRoom] Socket.IO server initialized');
|
||||||
|
} else {
|
||||||
|
if (!watchRoomConfig.enabled) {
|
||||||
|
console.log('[WatchRoom] Watch room is disabled');
|
||||||
|
} else if (watchRoomConfig.serverType === 'external') {
|
||||||
|
console.log('[WatchRoom] Using external watch room server');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
httpServer
|
httpServer
|
||||||
.once('error', (err) => {
|
.once('error', (err) => {
|
||||||
@@ -475,13 +568,17 @@ app.prepare().then(() => {
|
|||||||
})
|
})
|
||||||
.listen(port, () => {
|
.listen(port, () => {
|
||||||
console.log(`> Ready on http://${hostname}:${port}`);
|
console.log(`> Ready on http://${hostname}:${port}`);
|
||||||
console.log(`> Socket.IO ready on ws://${hostname}:${port}`);
|
if (watchRoomConfig.enabled && watchRoomConfig.serverType === 'internal') {
|
||||||
|
console.log(`> Socket.IO ready on ws://${hostname}:${port}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 优雅关闭
|
// 优雅关闭
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', () => {
|
||||||
console.log('\n[Server] Shutting down...');
|
console.log('\n[Server] Shutting down...');
|
||||||
watchRoomServer.destroy();
|
if (watchRoomServer) {
|
||||||
|
watchRoomServer.destroy();
|
||||||
|
}
|
||||||
httpServer.close(() => {
|
httpServer.close(() => {
|
||||||
console.log('[Server] Server closed');
|
console.log('[Server] Server closed');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
@@ -490,7 +587,9 @@ app.prepare().then(() => {
|
|||||||
|
|
||||||
process.on('SIGTERM', () => {
|
process.on('SIGTERM', () => {
|
||||||
console.log('\n[Server] Shutting down...');
|
console.log('\n[Server] Shutting down...');
|
||||||
watchRoomServer.destroy();
|
if (watchRoomServer) {
|
||||||
|
watchRoomServer.destroy();
|
||||||
|
}
|
||||||
httpServer.close(() => {
|
httpServer.close(() => {
|
||||||
console.log('[Server] Server closed');
|
console.log('[Server] Server closed');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
|||||||
49
src/app/api/debug/watch-room-config/route.ts
Normal file
49
src/app/api/debug/watch-room-config/route.ts
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
import { getConfig } from '@/lib/config';
|
||||||
|
|
||||||
|
export const runtime = 'nodejs';
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
|
||||||
|
|
||||||
|
// 调试信息
|
||||||
|
const debugInfo = {
|
||||||
|
storageType,
|
||||||
|
envVars: {
|
||||||
|
hasRedisUrl: !!process.env.REDIS_URL,
|
||||||
|
hasUpstashUrl: !!process.env.UPSTASH_REDIS_REST_URL,
|
||||||
|
hasUpstashToken: !!process.env.UPSTASH_REDIS_REST_TOKEN,
|
||||||
|
hasKvrocksUrl: !!process.env.KVROCKS_URL,
|
||||||
|
},
|
||||||
|
watchRoomConfig: null as any,
|
||||||
|
configReadError: null as string | null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 尝试读取配置
|
||||||
|
try {
|
||||||
|
const config = await getConfig();
|
||||||
|
debugInfo.watchRoomConfig = config.WatchRoomConfig || null;
|
||||||
|
} catch (error) {
|
||||||
|
debugInfo.configReadError = (error as Error).message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(debugInfo, {
|
||||||
|
headers: {
|
||||||
|
'Cache-Control': 'no-store',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Debug API error:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: 'Failed to get debug info',
|
||||||
|
details: (error as Error).message,
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,11 +10,38 @@ export const runtime = 'nodejs';
|
|||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
console.log('server-config called: ', request.url);
|
console.log('server-config called: ', request.url);
|
||||||
|
|
||||||
|
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
|
||||||
|
|
||||||
|
// 如果使用 localStorage,返回默认配置
|
||||||
|
if (storageType === 'localstorage') {
|
||||||
|
return NextResponse.json({
|
||||||
|
SiteName: process.env.NEXT_PUBLIC_SITE_NAME || 'MoonTV',
|
||||||
|
StorageType: 'localstorage',
|
||||||
|
Version: CURRENT_VERSION,
|
||||||
|
// localStorage 模式下,返回默认观影室配置
|
||||||
|
// 可以通过环境变量控制是否启用
|
||||||
|
WatchRoom: {
|
||||||
|
enabled: process.env.WATCH_ROOM_ENABLED === 'true',
|
||||||
|
serverType: 'internal',
|
||||||
|
externalServerUrl: undefined,
|
||||||
|
externalServerAuth: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非 localStorage 模式,从数据库读取配置
|
||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const result = {
|
const result = {
|
||||||
SiteName: config.SiteConfig.SiteName,
|
SiteName: config.SiteConfig.SiteName,
|
||||||
StorageType: process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage',
|
StorageType: storageType,
|
||||||
Version: CURRENT_VERSION,
|
Version: CURRENT_VERSION,
|
||||||
|
// 添加观影室配置(供所有用户访问)
|
||||||
|
WatchRoom: {
|
||||||
|
enabled: config.WatchRoomConfig?.enabled ?? false,
|
||||||
|
serverType: config.WatchRoomConfig?.serverType ?? 'internal',
|
||||||
|
externalServerUrl: config.WatchRoomConfig?.externalServerUrl,
|
||||||
|
externalServerAuth: config.WatchRoomConfig?.externalServerAuth,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return NextResponse.json(result);
|
return NextResponse.json(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import Link from 'next/link';
|
|||||||
import { usePathname, useSearchParams } from 'next/navigation';
|
import { usePathname, useSearchParams } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { useWatchRoomContextSafe } from './WatchRoomProvider';
|
||||||
|
|
||||||
interface MobileBottomNavProps {
|
interface MobileBottomNavProps {
|
||||||
/**
|
/**
|
||||||
* 主动指定当前激活的路径。当未提供时,自动使用 usePathname() 获取的路径。
|
* 主动指定当前激活的路径。当未提供时,自动使用 usePathname() 获取的路径。
|
||||||
@@ -17,6 +19,7 @@ interface MobileBottomNavProps {
|
|||||||
const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
|
const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
const watchRoomContext = useWatchRoomContextSafe();
|
||||||
|
|
||||||
// 直接使用当前路由状态,确保立即响应路由变化
|
// 直接使用当前路由状态,确保立即响应路由变化
|
||||||
const getCurrentFullPath = () => {
|
const getCurrentFullPath = () => {
|
||||||
@@ -52,26 +55,61 @@ const MobileBottomNav = ({ activePath }: MobileBottomNavProps) => {
|
|||||||
label: '直播',
|
label: '直播',
|
||||||
href: '/live',
|
href: '/live',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: Users,
|
|
||||||
label: '观影室',
|
|
||||||
href: '/watch-room',
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const runtimeConfig = (window as any).RUNTIME_CONFIG;
|
const runtimeConfig = (window as any).RUNTIME_CONFIG;
|
||||||
if (runtimeConfig?.CUSTOM_CATEGORIES?.length > 0) {
|
|
||||||
setNavItems((prevItems) => [
|
// 基础导航项(不包括观影室)
|
||||||
...prevItems,
|
let items = [
|
||||||
{
|
{ icon: Home, label: '首页', href: '/' },
|
||||||
icon: Star,
|
{
|
||||||
label: '自定义',
|
icon: Film,
|
||||||
href: '/douban?type=custom',
|
label: '电影',
|
||||||
},
|
href: '/douban?type=movie',
|
||||||
]);
|
},
|
||||||
|
{
|
||||||
|
icon: Tv,
|
||||||
|
label: '剧集',
|
||||||
|
href: '/douban?type=tv',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Cat,
|
||||||
|
label: '动漫',
|
||||||
|
href: '/douban?type=anime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Clover,
|
||||||
|
label: '综艺',
|
||||||
|
href: '/douban?type=show',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Radio,
|
||||||
|
label: '直播',
|
||||||
|
href: '/live',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 如果启用观影室,添加观影室入口
|
||||||
|
if (watchRoomContext?.isEnabled) {
|
||||||
|
items.push({
|
||||||
|
icon: Users,
|
||||||
|
label: '观影室',
|
||||||
|
href: '/watch-room',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
|
||||||
|
// 添加自定义分类(如果有)
|
||||||
|
if (runtimeConfig?.CUSTOM_CATEGORIES?.length > 0) {
|
||||||
|
items.push({
|
||||||
|
icon: Star,
|
||||||
|
label: '自定义',
|
||||||
|
href: '/douban?type=custom',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setNavItems(items);
|
||||||
|
}, [watchRoomContext?.isEnabled]);
|
||||||
|
|
||||||
const isActive = (href: string) => {
|
const isActive = (href: string) => {
|
||||||
const typeMatch = href.match(/type=([^&]+)/)?.[1];
|
const typeMatch = href.match(/type=([^&]+)/)?.[1];
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
import { useSite } from './SiteProvider';
|
import { useSite } from './SiteProvider';
|
||||||
|
import { useWatchRoomContextSafe } from './WatchRoomProvider';
|
||||||
|
|
||||||
interface SidebarContextType {
|
interface SidebarContextType {
|
||||||
isCollapsed: boolean;
|
isCollapsed: boolean;
|
||||||
@@ -59,6 +60,7 @@ declare global {
|
|||||||
const Sidebar = ({ onToggle, activePath = '/' }: SidebarProps) => {
|
const Sidebar = ({ onToggle, activePath = '/' }: SidebarProps) => {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
const watchRoomContext = useWatchRoomContextSafe();
|
||||||
// 若同一次 SPA 会话中已经读取过折叠状态,则直接复用,避免闪烁
|
// 若同一次 SPA 会话中已经读取过折叠状态,则直接复用,避免闪烁
|
||||||
const [isCollapsed, setIsCollapsed] = useState<boolean>(() => {
|
const [isCollapsed, setIsCollapsed] = useState<boolean>(() => {
|
||||||
if (
|
if (
|
||||||
@@ -143,26 +145,60 @@ const Sidebar = ({ onToggle, activePath = '/' }: SidebarProps) => {
|
|||||||
label: '直播',
|
label: '直播',
|
||||||
href: '/live',
|
href: '/live',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: Users,
|
|
||||||
label: '观影室',
|
|
||||||
href: '/watch-room',
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const runtimeConfig = (window as any).RUNTIME_CONFIG;
|
const runtimeConfig = (window as any).RUNTIME_CONFIG;
|
||||||
if (runtimeConfig?.CUSTOM_CATEGORIES?.length > 0) {
|
|
||||||
setMenuItems((prevItems) => [
|
// 基础菜单项(不包括观影室)
|
||||||
...prevItems,
|
let items = [
|
||||||
{
|
{
|
||||||
icon: Star,
|
icon: Film,
|
||||||
label: '自定义',
|
label: '电影',
|
||||||
href: '/douban?type=custom',
|
href: '/douban?type=movie',
|
||||||
},
|
},
|
||||||
]);
|
{
|
||||||
|
icon: Tv,
|
||||||
|
label: '剧集',
|
||||||
|
href: '/douban?type=tv',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Cat,
|
||||||
|
label: '动漫',
|
||||||
|
href: '/douban?type=anime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Clover,
|
||||||
|
label: '综艺',
|
||||||
|
href: '/douban?type=show',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Radio,
|
||||||
|
label: '直播',
|
||||||
|
href: '/live',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 如果启用观影室,添加观影室入口
|
||||||
|
if (watchRoomContext?.isEnabled) {
|
||||||
|
items.push({
|
||||||
|
icon: Users,
|
||||||
|
label: '观影室',
|
||||||
|
href: '/watch-room',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
|
||||||
|
// 添加自定义分类(如果有)
|
||||||
|
if (runtimeConfig?.CUSTOM_CATEGORIES?.length > 0) {
|
||||||
|
items.push({
|
||||||
|
icon: Star,
|
||||||
|
label: '自定义',
|
||||||
|
href: '/douban?type=custom',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setMenuItems(items);
|
||||||
|
}, [watchRoomContext?.isEnabled]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarContext.Provider value={contextValue}>
|
<SidebarContext.Provider value={contextValue}>
|
||||||
|
|||||||
@@ -109,43 +109,47 @@ export function WatchRoomProvider({ children }: WatchRoomProviderProps) {
|
|||||||
// 加载配置
|
// 加载配置
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadConfig = async () => {
|
const loadConfig = async () => {
|
||||||
// 默认配置:启用内部服务器
|
|
||||||
const defaultConfig: WatchRoomConfig = {
|
|
||||||
enabled: true,
|
|
||||||
serverType: 'internal',
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/admin/config');
|
// 使用公共 API 获取观影室配置(不需要管理员权限)
|
||||||
|
const response = await fetch('/api/server-config');
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
// API 返回格式: { SiteName, StorageType, Version, WatchRoom }
|
||||||
const watchRoomConfig: WatchRoomConfig = {
|
const watchRoomConfig: WatchRoomConfig = {
|
||||||
enabled: data.watchRoom?.enabled ?? true,
|
enabled: data.WatchRoom?.enabled ?? false, // 默认不启用
|
||||||
serverType: data.watchRoom?.serverType ?? 'internal',
|
serverType: data.WatchRoom?.serverType ?? 'internal',
|
||||||
externalServerUrl: data.watchRoom?.externalServerUrl,
|
externalServerUrl: data.WatchRoom?.externalServerUrl,
|
||||||
externalServerAuth: data.watchRoom?.externalServerAuth,
|
externalServerAuth: data.WatchRoom?.externalServerAuth,
|
||||||
};
|
};
|
||||||
setConfig(watchRoomConfig);
|
setConfig(watchRoomConfig);
|
||||||
setIsEnabled(watchRoomConfig.enabled);
|
setIsEnabled(watchRoomConfig.enabled);
|
||||||
|
|
||||||
// 如果启用了观影室,自动连接
|
// 只在启用了观影室时才连接
|
||||||
if (watchRoomConfig.enabled) {
|
if (watchRoomConfig.enabled) {
|
||||||
console.log('[WatchRoom] Connecting with config:', watchRoomConfig);
|
console.log('[WatchRoom] Connecting with config:', watchRoomConfig);
|
||||||
await watchRoom.connect(watchRoomConfig);
|
await watchRoom.connect(watchRoomConfig);
|
||||||
|
} else {
|
||||||
|
console.log('[WatchRoom] Watch room is disabled, skipping connection');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Failed to load config');
|
console.error('[WatchRoom] Failed to load config:', response.status);
|
||||||
|
// 加载配置失败时,不连接,保持禁用状态
|
||||||
|
const defaultConfig: WatchRoomConfig = {
|
||||||
|
enabled: false,
|
||||||
|
serverType: 'internal',
|
||||||
|
};
|
||||||
|
setConfig(defaultConfig);
|
||||||
|
setIsEnabled(false);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('[WatchRoom] Using default config (internal server enabled)');
|
console.error('[WatchRoom] Error loading config:', error);
|
||||||
|
// 加载配置失败时,不连接,保持禁用状态
|
||||||
|
const defaultConfig: WatchRoomConfig = {
|
||||||
|
enabled: false,
|
||||||
|
serverType: 'internal',
|
||||||
|
};
|
||||||
setConfig(defaultConfig);
|
setConfig(defaultConfig);
|
||||||
setIsEnabled(true);
|
setIsEnabled(false);
|
||||||
|
|
||||||
try {
|
|
||||||
await watchRoom.connect(defaultConfig);
|
|
||||||
} catch (connectError) {
|
|
||||||
console.error('[WatchRoom] Failed to connect:', connectError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user