From 0916e4ff08c53bedf918eaa009434353009f6a28 Mon Sep 17 00:00:00 2001 From: mtvpls Date: Wed, 22 Apr 2026 16:22:17 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=BB=84=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- src/app/admin/page.tsx | 181 ++++++++++++++---- src/app/api/acg/acgrip/route.ts | 3 +- src/app/api/acg/dmhy/route.ts | 3 +- src/app/api/acg/download/route.ts | 3 +- src/app/api/acg/mikan/route.ts | 3 +- src/app/api/admin/ai/route.ts | 4 - src/app/api/admin/user/route.ts | 7 +- src/app/api/ai/chat/route.ts | 24 +-- src/app/api/emby/cms-proxy/[token]/route.ts | 4 +- src/app/api/emby/detail/route.ts | 3 + .../api/emby/image/[token]/[itemId]/route.ts | 9 +- src/app/api/emby/list/route.ts | 3 + .../api/emby/play/[token]/[filename]/route.ts | 9 +- src/app/api/emby/sources/route.ts | 7 +- src/app/api/emby/views/route.ts | 3 + src/app/api/live/channels/route.ts | 3 + src/app/api/live/epg/route.ts | 3 + src/app/api/live/precheck/route.ts | 5 +- src/app/api/live/sources/route.ts | 3 + src/app/api/manga/_utils.ts | 6 + src/app/api/music/audio-proxy/route.ts | 3 + src/app/api/music/playlists/route.ts | 9 + src/app/api/music/playlists/songs/route.ts | 7 + src/app/api/music/playrecords/route.ts | 7 + src/app/api/music/proxy/route.ts | 3 + src/app/api/music/route.ts | 45 +++-- .../api/netdisk/quark/instant-play/route.ts | 4 + src/app/api/netdisk/quark/transfer/route.ts | 4 + src/app/api/openlist/check/route.ts | 3 + .../api/openlist/cms-proxy/[token]/route.ts | 4 +- src/app/api/openlist/correct/route.ts | 3 + src/app/api/openlist/delete/route.ts | 3 + src/app/api/openlist/detail/route.ts | 3 + src/app/api/openlist/list/route.ts | 3 + src/app/api/openlist/play/[token]/route.ts | 9 +- src/app/api/openlist/play/route.ts | 3 + src/app/api/openlist/refresh-video/route.ts | 3 + src/app/api/openlist/refresh/route.ts | 3 + src/app/api/openlist/scan-progress/route.ts | 3 + src/app/api/pansou/search/route.ts | 8 + src/app/api/tvbox/subscribe/route.ts | 8 +- .../api/web-live/proxy/[filename]/route.ts | 4 + src/app/api/web-live/sources/route.ts | 3 + src/app/api/web-live/stream/route.ts | 4 + src/app/api/xiaoya/browse/route.ts | 3 + src/app/api/xiaoya/play/route.ts | 3 + src/app/api/xiaoya/search/route.ts | 3 + src/app/layout.tsx | 43 ++++- src/app/live/page.tsx | 13 +- src/app/manga/page.tsx | 6 + src/app/music/page.tsx | 6 + src/app/play/page.tsx | 31 ++- src/app/private-library/page.tsx | 6 + src/app/search/page.tsx | 32 +++- src/components/MobileBottomNav.tsx | 29 ++- src/components/Sidebar.tsx | 19 +- src/lib/admin.types.ts | 7 +- src/lib/feature-permissions.ts | 36 ++++ src/lib/music-v2-api.ts | 6 + src/lib/permissions.ts | 101 ++++++++++ 61 files changed, 617 insertions(+), 165 deletions(-) create mode 100644 src/lib/feature-permissions.ts create mode 100644 src/lib/permissions.ts diff --git a/.gitignore b/.gitignore index abcf28e..2a5ecbe 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ public/workbox-*.js public/workbox-*.js.map /.claude +/.codex /.vscode # SQLite 开发数据库 .data/ @@ -66,4 +67,4 @@ public/workbox-*.js.map # local scripts scripts/tvbox/ -scripts/test \ No newline at end of file +scripts/test diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 849ecba..0eb5a4b 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -51,6 +51,7 @@ import { createPortal } from 'react-dom'; import { AdminConfig, AdminConfigResult } from '@/lib/admin.types'; import { getAuthInfoFromBrowserCookie } from '@/lib/auth'; +import { FEATURE_PERMISSION_OPTIONS } from '@/lib/feature-permissions'; import AnimeSubscriptionComponent from '@/components/AnimeSubscriptionComponent'; import CorrectDialog from '@/components/CorrectDialog'; @@ -505,10 +506,12 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP const [newUserGroup, setNewUserGroup] = useState({ name: '', enabledApis: [] as string[], + permissions: FEATURE_PERMISSION_OPTIONS.map((item) => item.key) as string[], }); const [editingUserGroup, setEditingUserGroup] = useState<{ name: string; enabledApis: string[]; + permissions: string[]; } | null>(null); const [showConfigureApisModal, setShowConfigureApisModal] = useState(false); const [selectedUser, setSelectedUser] = useState<{ @@ -577,7 +580,8 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP const handleUserGroupAction = async ( action: 'add' | 'edit' | 'delete', groupName: string, - enabledApis?: string[] + enabledApis?: string[], + permissions?: string[] ) => { return withLoading(`userGroup_${action}_${groupName}`, async () => { try { @@ -589,6 +593,7 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP groupAction: action, groupName, enabledApis, + permissions, }), }); @@ -600,7 +605,11 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP await refreshConfig(); if (action === 'add') { - setNewUserGroup({ name: '', enabledApis: [] }); + setNewUserGroup({ + name: '', + enabledApis: [], + permissions: FEATURE_PERMISSION_OPTIONS.map((item) => item.key), + }); setShowAddUserGroupForm(false); } else if (action === 'edit') { setEditingUserGroup(null); @@ -624,7 +633,12 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP const handleAddUserGroup = () => { if (!newUserGroup.name.trim()) return; - handleUserGroupAction('add', newUserGroup.name, newUserGroup.enabledApis); + handleUserGroupAction( + 'add', + newUserGroup.name, + newUserGroup.enabledApis, + newUserGroup.permissions + ); }; const handleEditUserGroup = () => { @@ -632,7 +646,8 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP handleUserGroupAction( 'edit', editingUserGroup.name, - editingUserGroup.enabledApis + editingUserGroup.enabledApis, + editingUserGroup.permissions ); }; @@ -668,8 +683,12 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP const handleStartEditUserGroup = (group: { name: string; enabledApis: string[]; + permissions?: string[]; }) => { - setEditingUserGroup({ ...group }); + setEditingUserGroup({ + ...group, + permissions: group.permissions || [], + }); setShowEditUserGroupForm(true); setShowAddUserGroupForm(false); }; @@ -1101,6 +1120,9 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP 可用视频源 + + 功能权限 + 操作 @@ -1124,6 +1146,13 @@ const UserConfig = ({ config, role, refreshConfig, usersV2, userPage, userTotalP + + + {group.permissions && group.permissions.length > 0 + ? `${group.permissions.length} 项` + : '无'} + + {/* 网盘搜索按钮 */} - + {netdiskSearchEnabled && ( + + )} {/* AI问片按钮 */} {aiEnabled && detail && (