diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 11df295..ebb3fbe 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -46,6 +46,48 @@ import { getAuthInfoFromBrowserCookie } from '@/lib/auth'; import DataMigration from '@/components/DataMigration'; import PageLayout from '@/components/PageLayout'; +// 统一按钮样式系统 +const buttonStyles = { + // 主要操作按钮(蓝色)- 用于配置、设置、确认等 + primary: 'px-3 py-1.5 text-sm font-medium bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-700 text-white rounded-lg transition-colors', + // 成功操作按钮(绿色)- 用于添加、启用、保存等 + success: 'px-3 py-1.5 text-sm font-medium bg-green-600 hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-700 text-white rounded-lg transition-colors', + // 危险操作按钮(红色)- 用于删除、禁用、重置等 + danger: 'px-3 py-1.5 text-sm font-medium bg-red-600 hover:bg-red-700 dark:bg-red-600 dark:hover:bg-red-700 text-white rounded-lg transition-colors', + // 次要操作按钮(灰色)- 用于取消、关闭等 + secondary: 'px-3 py-1.5 text-sm font-medium bg-gray-600 hover:bg-gray-700 dark:bg-gray-600 dark:hover:bg-gray-700 text-white rounded-lg transition-colors', + // 警告操作按钮(黄色)- 用于批量禁用等 + warning: 'px-3 py-1.5 text-sm font-medium bg-yellow-600 hover:bg-yellow-700 dark:bg-yellow-600 dark:hover:bg-yellow-700 text-white rounded-lg transition-colors', + // 小尺寸主要按钮 + primarySmall: 'px-2 py-1 text-xs font-medium bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-700 text-white rounded-md transition-colors', + // 小尺寸成功按钮 + successSmall: 'px-2 py-1 text-xs font-medium bg-green-600 hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-700 text-white rounded-md transition-colors', + // 小尺寸危险按钮 + dangerSmall: 'px-2 py-1 text-xs font-medium bg-red-600 hover:bg-red-700 dark:bg-red-600 dark:hover:bg-red-700 text-white rounded-md transition-colors', + // 小尺寸次要按钮 + secondarySmall: 'px-2 py-1 text-xs font-medium bg-gray-600 hover:bg-gray-700 dark:bg-gray-600 dark:hover:bg-gray-700 text-white rounded-md transition-colors', + // 小尺寸警告按钮 + warningSmall: 'px-2 py-1 text-xs font-medium bg-yellow-600 hover:bg-yellow-700 dark:bg-yellow-600 dark:hover:bg-yellow-700 text-white rounded-md transition-colors', + // 圆角小按钮(用于表格操作) + roundedPrimary: 'inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800 hover:bg-blue-200 dark:bg-blue-900/40 dark:hover:bg-blue-900/60 dark:text-blue-200 transition-colors', + roundedSuccess: 'inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-green-100 text-green-800 hover:bg-green-200 dark:bg-green-900/40 dark:hover:bg-green-900/60 dark:text-green-200 transition-colors', + roundedDanger: 'inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-red-100 text-red-800 hover:bg-red-200 dark:bg-red-900/40 dark:hover:bg-red-900/60 dark:text-red-200 transition-colors', + roundedSecondary: 'inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800 hover:bg-gray-200 dark:bg-gray-700/40 dark:hover:bg-gray-700/60 dark:text-gray-200 transition-colors', + roundedWarning: 'inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800 hover:bg-yellow-200 dark:bg-yellow-900/40 dark:hover:bg-yellow-900/60 dark:text-yellow-200 transition-colors', + roundedPurple: 'inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800 hover:bg-purple-200 dark:bg-purple-900/40 dark:hover:bg-purple-900/60 dark:text-purple-200 transition-colors', + // 禁用状态 + disabled: 'px-3 py-1.5 text-sm font-medium bg-gray-400 dark:bg-gray-600 cursor-not-allowed text-white rounded-lg transition-colors', + disabledSmall: 'px-2 py-1 text-xs font-medium bg-gray-400 dark:bg-gray-600 cursor-not-allowed text-white rounded-md transition-colors', + // 开关按钮样式 + toggleOn: 'bg-green-600 dark:bg-green-600', + toggleOff: 'bg-gray-200 dark:bg-gray-700', + toggleThumb: 'bg-white', + toggleThumbOn: 'translate-x-6', + toggleThumbOff: 'translate-x-1', + // 快速操作按钮样式 + quickAction: 'px-3 py-1.5 text-xs font-medium text-gray-600 dark:text-gray-400 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-md transition-colors', +}; + // 通用弹窗组件 interface AlertModalProps { isOpen: boolean; @@ -130,7 +172,7 @@ const AlertModal = ({ {showConfirm && ( @@ -706,7 +748,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setEditingUserGroup(null); } }} - className='px-3 py-1 bg-blue-600 hover:bg-blue-700 text-white text-sm rounded-lg transition-colors' + className={showAddUserGroupForm ? buttonStyles.secondary : buttonStyles.primary} > {showAddUserGroupForm ? '取消' : '添加用户组'} @@ -746,13 +788,13 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { @@ -787,7 +829,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { @@ -803,7 +845,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setChangePasswordUser({ username: '', password: '' }); } }} - className='px-3 py-1 bg-green-600 hover:bg-green-700 text-white text-sm rounded-lg transition-colors' + className={showAddUserForm ? buttonStyles.secondary : buttonStyles.success} > {showAddUserForm ? '取消' : '添加用户'} @@ -857,7 +899,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { @@ -895,7 +937,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { @@ -904,7 +946,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setShowChangePasswordForm(false); setChangePasswordUser({ username: '', password: '' }); }} - className='w-full sm:w-auto px-4 py-2 bg-gray-600 hover:bg-gray-700 text-white rounded-lg transition-colors' + className={`w-full sm:w-auto ${buttonStyles.secondary}`} > 取消 @@ -1076,7 +1118,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { user.username === currentUsername))) && ( @@ -1097,7 +1139,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { user.username === currentUsername))) && ( @@ -1111,7 +1153,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { onClick={() => handleShowChangePasswordForm(user.username) } - className='inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800 hover:bg-blue-200 dark:bg-blue-900/40 dark:hover:bg-blue-900/60 dark:text-blue-200 transition-colors' + className={buttonStyles.roundedPrimary} > 修改密码 @@ -1122,7 +1164,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { {user.role === 'user' && ( @@ -1132,7 +1174,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { onClick={() => handleRemoveAdmin(user.username) } - className='inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800 hover:bg-gray-200 dark:bg-gray-700/40 dark:hover:bg-gray-700/60 dark:text-gray-200 transition-colors' + className={buttonStyles.roundedSecondary} > 取消管理 @@ -1141,7 +1183,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { (!user.banned ? ( @@ -1150,7 +1192,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { onClick={() => handleUnbanUser(user.username) } - className='inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-green-100 text-green-800 hover:bg-green-200 dark:bg-green-900/40 dark:hover:bg-green-900/60 dark:text-green-300 transition-colors' + className={buttonStyles.roundedSuccess} > 解封 @@ -1161,7 +1203,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { {canDeleteUser && ( @@ -1260,7 +1302,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => {
@@ -1269,7 +1311,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { const allApis = config?.SourceConfig?.filter(source => !source.disabled).map(s => s.key) || []; setSelectedApis(allApis); }} - className='px-3 py-1.5 text-xs font-medium text-gray-600 dark:text-gray-400 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-md transition-colors' + className={buttonStyles.quickAction} > 全选 @@ -1289,13 +1331,13 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setSelectedUser(null); setSelectedApis([]); }} - className='px-6 py-2.5 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg transition-colors' + className={`px-6 py-2.5 text-sm font-medium ${buttonStyles.secondary}`} > 取消 @@ -1392,7 +1434,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => {
@@ -1401,7 +1443,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { const allApis = config?.SourceConfig?.filter(source => !source.disabled).map(s => s.key) || []; setNewUserGroup(prev => ({ ...prev, enabledApis: allApis })); }} - className='px-3 py-1.5 text-xs font-medium text-gray-600 dark:text-gray-400 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-md transition-colors' + className={buttonStyles.quickAction} > 全选 @@ -1415,14 +1457,14 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setShowAddUserGroupForm(false); setNewUserGroup({ name: '', enabledApis: [] }); }} - className='px-6 py-2.5 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg transition-colors' + className={`px-6 py-2.5 text-sm font-medium ${buttonStyles.secondary}`} > 取消 @@ -1504,7 +1546,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => {
@@ -1513,7 +1555,7 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { const allApis = config?.SourceConfig?.filter(source => !source.disabled).map(s => s.key) || []; setEditingUserGroup(prev => prev ? { ...prev, enabledApis: allApis } : null); }} - className='px-3 py-1.5 text-xs font-medium text-gray-600 dark:text-gray-400 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-md transition-colors' + className={buttonStyles.quickAction} > 全选 @@ -1527,13 +1569,13 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setShowEditUserGroupForm(false); setEditingUserGroup(null); }} - className='px-6 py-2.5 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg transition-colors' + className={`px-6 py-2.5 text-sm font-medium ${buttonStyles.secondary}`} > 取消 @@ -1623,13 +1665,13 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setSelectedUserForGroup(null); setSelectedUserGroups([]); }} - className='px-6 py-2.5 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg transition-colors' + className={`px-6 py-2.5 text-sm font-medium ${buttonStyles.secondary}`} > 取消 @@ -1722,13 +1764,13 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setShowDeleteUserGroupModal(false); setDeletingUserGroup(null); }} - className='px-6 py-2.5 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg transition-colors' + className={`px-6 py-2.5 text-sm font-medium ${buttonStyles.secondary}`} > 取消 @@ -1786,13 +1828,13 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setShowDeleteUserModal(false); setDeletingUser(null); }} - className='px-6 py-2.5 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg transition-colors' + className={`px-6 py-2.5 text-sm font-medium ${buttonStyles.secondary}`} > 取消 @@ -1873,13 +1915,13 @@ const UserConfig = ({ config, role, refreshConfig }: UserConfigProps) => { setShowBatchUserGroupModal(false); setSelectedUserGroup(''); }} - className='px-6 py-2.5 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg transition-colors' + className={`px-6 py-2.5 text-sm font-medium ${buttonStyles.secondary}`} > 取消 @@ -2284,8 +2326,8 @@ const VideoSourceConfig = ({ @@ -2399,19 +2441,19 @@ const VideoSourceConfig = ({ @@ -2423,8 +2465,8 @@ const VideoSourceConfig = ({ onClick={() => setShowValidationModal(true)} disabled={isValidating} className={`px-3 py-1 text-sm rounded-lg transition-colors flex items-center space-x-1 ${isValidating - ? 'bg-gray-400 cursor-not-allowed text-gray-200' - : 'bg-blue-600 hover:bg-blue-700 text-white' + ? buttonStyles.disabled + : buttonStyles.primary }`} > {isValidating ? ( @@ -2438,7 +2480,7 @@ const VideoSourceConfig = ({ @@ -2489,7 +2531,7 @@ const VideoSourceConfig = ({ @@ -2562,7 +2604,7 @@ const VideoSourceConfig = ({
@@ -2598,7 +2640,7 @@ const VideoSourceConfig = ({ @@ -2649,13 +2691,13 @@ const VideoSourceConfig = ({
@@ -2855,8 +2897,8 @@ const CategoryConfig = ({ handleToggleEnable(category.query, category.type) } className={`inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium ${!category.disabled - ? 'bg-red-100 dark:bg-red-900/40 text-red-800 dark:text-red-300 hover:bg-red-200 dark:hover:bg-red-900/60' - : 'bg-green-100 dark:bg-green-900/40 text-green-800 dark:text-green-300 hover:bg-green-200 dark:hover:bg-green-900/60' + ? buttonStyles.roundedDanger + : buttonStyles.roundedSuccess } transition-colors`} > {!category.disabled ? '禁用' : '启用'} @@ -2864,7 +2906,7 @@ const CategoryConfig = ({ {category.from !== 'config' && ( @@ -2891,7 +2933,7 @@ const CategoryConfig = ({ @@ -2936,7 +2978,7 @@ const CategoryConfig = ({ @@ -2996,7 +3038,7 @@ const CategoryConfig = ({
@@ -3156,8 +3198,8 @@ const ConfigFileComponent = ({ config, refreshConfig }: { config: AdminConfig | onClick={handleFetchConfig} disabled={fetching || !subscriptionUrl.trim()} className={`w-full px-6 py-3 rounded-lg font-medium transition-all duration-200 ${fetching || !subscriptionUrl.trim() - ? 'bg-gray-300 dark:bg-gray-600 cursor-not-allowed text-gray-500 dark:text-gray-400' - : 'bg-green-600 hover:bg-green-700 text-white shadow-sm hover:shadow-md transform hover:-translate-y-0.5' + ? buttonStyles.disabled + : buttonStyles.success }`} > {fetching ? ( @@ -3186,14 +3228,14 @@ const ConfigFileComponent = ({ config, refreshConfig }: { config: AdminConfig | onClick={() => setAutoUpdate(!autoUpdate)} disabled={false} className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 ${autoUpdate - ? 'bg-green-600' - : 'bg-gray-200 dark:bg-gray-700' + ? buttonStyles.toggleOn + : buttonStyles.toggleOff }`} > @@ -3227,8 +3269,8 @@ const ConfigFileComponent = ({ config, refreshConfig }: { config: AdminConfig | onClick={handleSave} disabled={saving} className={`px-4 py-2 rounded-lg transition-colors ${saving - ? 'bg-gray-400 cursor-not-allowed text-white' - : 'bg-green-600 hover:bg-green-700 text-white' + ? buttonStyles.disabled + : buttonStyles.success }`} > {saving ? '保存中…' : '保存'} @@ -3736,14 +3778,14 @@ const SiteConfigComponent = ({ config, refreshConfig }: { config: AdminConfig | })) } className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 ${siteSettings.DisableYellowFilter - ? 'bg-green-600' - : 'bg-gray-200 dark:bg-gray-700' + ? buttonStyles.toggleOn + : buttonStyles.toggleOff }`} > @@ -3770,14 +3812,14 @@ const SiteConfigComponent = ({ config, refreshConfig }: { config: AdminConfig | })) } className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 ${siteSettings.FluidSearch - ? 'bg-green-600' - : 'bg-gray-200 dark:bg-gray-700' + ? buttonStyles.toggleOn + : buttonStyles.toggleOff }`} > @@ -3794,9 +3836,9 @@ const SiteConfigComponent = ({ config, refreshConfig }: { config: AdminConfig | onClick={handleSave} disabled={saving} className={`px-4 py-2 ${saving - ? 'bg-gray-400 cursor-not-allowed' - : 'bg-green-600 hover:bg-green-700' - } text-white rounded-lg transition-colors`} + ? buttonStyles.disabled + : buttonStyles.success + } rounded-lg transition-colors`} > {saving ? '保存中…' : '保存'} @@ -3932,7 +3974,7 @@ function AdminPageClient() { {config && role === 'owner' && ( @@ -4085,13 +4127,13 @@ function AdminPageClient() {
diff --git a/src/components/VideoCard.tsx b/src/components/VideoCard.tsx index df500f4..d3dece8 100644 --- a/src/components/VideoCard.tsx +++ b/src/components/VideoCard.tsx @@ -376,7 +376,11 @@ const VideoCard = forwardRef(function VideoCard actions.push({ id: 'favorite', label: currentFavorited ? '取消收藏' : '添加收藏', - icon: , + icon: currentFavorited ? ( + + ) : ( + + ), onClick: () => { const mockEvent = { preventDefault: () => { }, @@ -401,7 +405,11 @@ const VideoCard = forwardRef(function VideoCard actions.push({ id: 'favorite', label: currentFavorited ? '取消收藏' : '添加收藏', - icon: , + icon: currentFavorited ? ( + + ) : ( + + ), onClick: () => { const mockEvent = { preventDefault: () => { }, @@ -555,7 +563,7 @@ const VideoCard = forwardRef(function VideoCard {/* 悬浮遮罩 */}
(function VideoCard }} /> )} - {config.showHeart && ( + {config.showHeart && from !== 'search' && ( (function VideoCard target='_blank' rel='noopener noreferrer' onClick={(e) => e.stopPropagation()} - className='absolute top-2 left-2 opacity-0 -translate-x-2 transition-all duration-300 ease-in-out delay-100 group-hover:opacity-100 group-hover:translate-x-0' + className='absolute top-2 left-2 opacity-0 -translate-x-2 transition-all duration-300 ease-in-out delay-100 sm:group-hover:opacity-100 sm:group-hover:translate-x-0' style={{ WebkitUserSelect: 'none', userSelect: 'none', @@ -764,7 +772,7 @@ const VideoCard = forwardRef(function VideoCard return (