生态应用
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
+209
-2
@@ -22,6 +22,7 @@ import {
|
||||
Monitor,
|
||||
MoveDown,
|
||||
MoveUp,
|
||||
Package,
|
||||
Rss,
|
||||
Settings,
|
||||
Shield,
|
||||
@@ -65,6 +66,7 @@ export const UserMenu: React.FC = () => {
|
||||
const [isFavoritesPanelOpen, setIsFavoritesPanelOpen] = useState(false);
|
||||
const [isEmailSettingsOpen, setIsEmailSettingsOpen] = useState(false);
|
||||
const [isDeviceManagementOpen, setIsDeviceManagementOpen] = useState(false);
|
||||
const [isEcoAppsOpen, setIsEcoAppsOpen] = useState(false);
|
||||
const [authInfo, setAuthInfo] = useState<AuthInfo | null>(null);
|
||||
const [storageType, setStorageType] = useState<string>('localstorage');
|
||||
const [mounted, setMounted] = useState(false);
|
||||
@@ -78,7 +80,7 @@ export const UserMenu: React.FC = () => {
|
||||
|
||||
// Body 滚动锁定 - 使用 overflow 方式避免布局问题
|
||||
useEffect(() => {
|
||||
if (isSettingsOpen || isChangePasswordOpen || isSubscribeOpen || isOfflineDownloadPanelOpen || isEmailSettingsOpen || isDeviceManagementOpen) {
|
||||
if (isSettingsOpen || isChangePasswordOpen || isSubscribeOpen || isOfflineDownloadPanelOpen || isEmailSettingsOpen || isDeviceManagementOpen || isEcoAppsOpen) {
|
||||
const body = document.body;
|
||||
const html = document.documentElement;
|
||||
|
||||
@@ -97,7 +99,7 @@ export const UserMenu: React.FC = () => {
|
||||
html.style.overflow = originalHtmlOverflow;
|
||||
};
|
||||
}
|
||||
}, [isSettingsOpen, isChangePasswordOpen, isSubscribeOpen, isOfflineDownloadPanelOpen, isEmailSettingsOpen, isDeviceManagementOpen]);
|
||||
}, [isSettingsOpen, isChangePasswordOpen, isSubscribeOpen, isOfflineDownloadPanelOpen, isEmailSettingsOpen, isDeviceManagementOpen, isEcoAppsOpen]);
|
||||
|
||||
// 设置相关状态
|
||||
const [defaultAggregateSearch, setDefaultAggregateSearch] = useState(true);
|
||||
@@ -1285,6 +1287,18 @@ export const UserMenu: React.FC = () => {
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* 生态应用按钮 */}
|
||||
<button
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
setIsEcoAppsOpen(true);
|
||||
}}
|
||||
className='w-full px-3 py-2 text-left flex items-center gap-2.5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors text-sm'
|
||||
>
|
||||
<Package className='w-4 h-4 text-gray-500 dark:text-gray-400' />
|
||||
<span className='font-medium'>生态应用</span>
|
||||
</button>
|
||||
|
||||
{/* 分割线 */}
|
||||
<div className='my-1 border-t border-gray-200 dark:border-gray-700'></div>
|
||||
|
||||
@@ -2859,6 +2873,194 @@ export const UserMenu: React.FC = () => {
|
||||
</>
|
||||
);
|
||||
|
||||
// 生态应用面板内容
|
||||
const ecoAppsPanel = (
|
||||
<>
|
||||
{/* 背景遮罩 */}
|
||||
<div
|
||||
className='fixed inset-0 bg-black/50 backdrop-blur-sm z-[1000]'
|
||||
onClick={() => setIsEcoAppsOpen(false)}
|
||||
onTouchMove={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
onWheel={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
style={{
|
||||
touchAction: 'none',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 生态应用面板 */}
|
||||
<div
|
||||
className='fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-2xl bg-white dark:bg-gray-900 rounded-xl shadow-xl z-[1001] overflow-hidden'
|
||||
>
|
||||
<div
|
||||
className='h-full max-h-[85vh] flex flex-col'
|
||||
data-panel-content
|
||||
onTouchMove={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
style={{
|
||||
touchAction: 'auto',
|
||||
}}
|
||||
>
|
||||
{/* 标题栏 */}
|
||||
<div className='flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700'>
|
||||
<h3 className='text-xl font-bold text-gray-800 dark:text-gray-200'>
|
||||
生态应用
|
||||
</h3>
|
||||
<button
|
||||
onClick={() => setIsEcoAppsOpen(false)}
|
||||
className='w-8 h-8 p-1 rounded-full flex items-center justify-center text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors'
|
||||
aria-label='Close'
|
||||
>
|
||||
<X className='w-full h-full' />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 应用列表 */}
|
||||
<div className='flex-1 overflow-y-auto p-6'>
|
||||
<div className='grid gap-6 md:grid-cols-1'>
|
||||
{/* MoonTVPlus-PC 客户端 */}
|
||||
<div className='bg-gray-50 dark:bg-gray-800 rounded-lg p-5 border border-gray-200 dark:border-gray-700'>
|
||||
<div className='flex items-start gap-4'>
|
||||
<div className='flex-shrink-0 relative'>
|
||||
<img
|
||||
src='/logo.png'
|
||||
alt='MoonTVPlus-PC'
|
||||
className='w-16 h-16 rounded-xl object-cover'
|
||||
/>
|
||||
<div className='absolute -bottom-1 -right-1 w-6 h-6 bg-blue-500 rounded-full flex items-center justify-center shadow-lg'>
|
||||
<Monitor className='w-3.5 h-3.5 text-white' />
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex-1 min-w-0'>
|
||||
<h4 className='text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2'>
|
||||
MoonTVPlus-PC客户端
|
||||
</h4>
|
||||
<p className='text-sm text-gray-600 dark:text-gray-400 mb-3'>
|
||||
专为Windows开发的客户端,完美支持私人影库mkv视频
|
||||
</p>
|
||||
<a
|
||||
href='https://github.com/mtvpls/MoonTVPlus-PC/releases'
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='inline-flex items-center gap-2 px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white text-sm font-medium rounded-lg transition-colors'
|
||||
>
|
||||
<Download className='w-4 h-4' />
|
||||
下载
|
||||
<ExternalLink className='w-3 h-3' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Selene 跨平台客户端 */}
|
||||
<div className='bg-gray-50 dark:bg-gray-800 rounded-lg p-5 border border-gray-200 dark:border-gray-700'>
|
||||
<div className='flex items-start gap-4'>
|
||||
<div className='flex-shrink-0 relative'>
|
||||
<img
|
||||
src='/icons/Selene.png'
|
||||
alt='Selene'
|
||||
className='w-16 h-16 rounded-xl object-cover'
|
||||
/>
|
||||
<span className='absolute -top-1 -right-1 px-1.5 py-0.5 bg-orange-500 text-white text-[10px] font-bold rounded'>
|
||||
二开
|
||||
</span>
|
||||
</div>
|
||||
<div className='flex-1 min-w-0'>
|
||||
<h4 className='text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2'>
|
||||
Selene 跨平台客户端
|
||||
</h4>
|
||||
<p className='text-sm text-gray-600 dark:text-gray-400 mb-3'>
|
||||
多平台客户端
|
||||
</p>
|
||||
<div className='flex flex-wrap gap-2'>
|
||||
<a
|
||||
href='https://github.com/mtvpls/MoonTVPlus/releases/tag/Selene_Beta4'
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='inline-flex items-center gap-2 px-4 py-2 bg-green-500 hover:bg-green-600 text-white text-sm font-medium rounded-lg transition-colors'
|
||||
>
|
||||
<Download className='w-4 h-4' />
|
||||
安卓下载
|
||||
<ExternalLink className='w-3 h-3' />
|
||||
</a>
|
||||
<button
|
||||
onClick={() => {
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
let targetUrl = 'https://github.com/mtvpls/Selene-Build/actions/workflows/build.yml';
|
||||
|
||||
// 根据 UA 判断平台
|
||||
if (ua.includes('windows')) {
|
||||
targetUrl = 'https://github.com/mtvpls/Selene-Build/actions/workflows/build.yml';
|
||||
} else if (ua.includes('mac')) {
|
||||
targetUrl = 'https://github.com/mtvpls/Selene-Build/actions/workflows/build.yml';
|
||||
} else if (ua.includes('linux')) {
|
||||
targetUrl = 'https://github.com/mtvpls/Selene-Build/actions/workflows/build.yml';
|
||||
}
|
||||
|
||||
window.open(targetUrl, '_blank');
|
||||
}}
|
||||
className='inline-flex items-center gap-2 px-4 py-2 bg-purple-500 hover:bg-purple-600 text-white text-sm font-medium rounded-lg transition-colors'
|
||||
>
|
||||
<Download className='w-4 h-4' />
|
||||
其他平台
|
||||
<ExternalLink className='w-3 h-3' />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* OrionTV TV专用客户端 */}
|
||||
<div className='bg-gray-50 dark:bg-gray-800 rounded-lg p-5 border border-gray-200 dark:border-gray-700'>
|
||||
<div className='flex items-start gap-4'>
|
||||
<div className='flex-shrink-0 relative'>
|
||||
<img
|
||||
src='/icons/OrionTV.png'
|
||||
alt='OrionTV'
|
||||
className='w-16 h-16 rounded-xl object-cover'
|
||||
/>
|
||||
<span className='absolute -top-1 -right-1 px-1.5 py-0.5 bg-orange-500 text-white text-[10px] font-bold rounded'>
|
||||
二开
|
||||
</span>
|
||||
</div>
|
||||
<div className='flex-1 min-w-0'>
|
||||
<h4 className='text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2'>
|
||||
OrionTV TV专用客户端
|
||||
</h4>
|
||||
<p className='text-sm text-gray-600 dark:text-gray-400 mb-3'>
|
||||
tv专用
|
||||
</p>
|
||||
<a
|
||||
href='https://github.com/mtvpls/MoonTVPlus/releases/tag/OrionTV%E9%80%82%E9%85%8D%E7%89%882'
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='inline-flex items-center gap-2 px-4 py-2 bg-indigo-500 hover:bg-indigo-600 text-white text-sm font-medium rounded-lg transition-colors'
|
||||
>
|
||||
<Download className='w-4 h-4' />
|
||||
下载
|
||||
<ExternalLink className='w-3 h-3' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 底部说明 */}
|
||||
<div className='p-6 pt-4 border-t border-gray-200 dark:border-gray-700'>
|
||||
<p className='text-xs text-gray-500 dark:text-gray-400 text-center'>
|
||||
选择适合您设备的客户端下载使用
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='relative'>
|
||||
@@ -2942,6 +3144,11 @@ export const UserMenu: React.FC = () => {
|
||||
mounted &&
|
||||
createPortal(deviceManagementPanel, document.body)}
|
||||
|
||||
{/* 使用 Portal 将生态应用面板渲染到 document.body */}
|
||||
{isEcoAppsOpen &&
|
||||
mounted &&
|
||||
createPortal(ecoAppsPanel, document.body)}
|
||||
|
||||
{/* 确认对话框 */}
|
||||
{confirmDialog.isOpen &&
|
||||
mounted &&
|
||||
|
||||
Reference in New Issue
Block a user