diff --git a/web/src/components/layout/headerbar/HeaderLogo.jsx b/web/src/components/layout/headerbar/HeaderLogo.jsx index 71984b3..6fc0209 100644 --- a/web/src/components/layout/headerbar/HeaderLogo.jsx +++ b/web/src/components/layout/headerbar/HeaderLogo.jsx @@ -17,11 +17,12 @@ along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ -import React, { useCallback } from 'react'; +import React, { useCallback, useContext } from 'react'; import { Link, useLocation, useNavigate } from 'react-router-dom'; import { Typography, Tag } from '@douyinfe/semi-ui'; import SkeletonWrapper from '../components/SkeletonWrapper'; import { userIsSupplierUser, showInfo, isAdmin } from '../../../helpers'; +import { StatusContext } from '../../../context/Status'; /** * 顶栏申请入口:浅色用 #409EFF 系。 @@ -49,6 +50,24 @@ const HeaderLogo = ({ const location = useLocation(); const navigate = useNavigate(); const user = userState?.user; + const [statusState] = useContext(StatusContext); + + const isSupplierApplyEnabled = React.useMemo(() => { + try { + const roleModulesRaw = statusState?.status?.SidebarModulesByRole; + if (!roleModulesRaw) return true; + const roleConfig = JSON.parse(roleModulesRaw); + const userRole = String(user?.role ?? 0); + const config = roleConfig[userRole]; + if (!config) return true; + const consoleSection = config.console; + if (!consoleSection) return true; + if (consoleSection.enabled === false) return false; + return consoleSection.supplierApply !== false; + } catch { + return true; + } + }, [statusState?.status?.SidebarModulesByRole, user?.role]); /** 未登录且已在登录页时:提示先登录,并同步 redirect 到目标申请页 */ const handleApplyEntryClick = useCallback( @@ -72,7 +91,7 @@ const HeaderLogo = ({ /** 管理员不展示;已是供应商则隐藏「提供算力」 */ const hideApplyLinks = isAdmin(); - const showSupplierApply = !hideApplyLinks && !userIsSupplierUser(user); + const showSupplierApply = !hideApplyLinks && !userIsSupplierUser(user) && isSupplierApplyEnabled; const supplierTo = user ? supplierApplyPath diff --git a/web/src/components/layout/headerbar/MobileSiteNavDropdown.jsx b/web/src/components/layout/headerbar/MobileSiteNavDropdown.jsx index 6665fd4..777a08d 100644 --- a/web/src/components/layout/headerbar/MobileSiteNavDropdown.jsx +++ b/web/src/components/layout/headerbar/MobileSiteNavDropdown.jsx @@ -22,6 +22,7 @@ import { useLocation, useNavigate } from 'react-router-dom'; import { Button, Dropdown } from '@douyinfe/semi-ui'; import { ChevronDown } from 'lucide-react'; import SkeletonWrapper from '../components/SkeletonWrapper'; +import { StatusContext } from '../../../context/Status'; import { isAdmin, userIsSupplierUser } from '../../../helpers'; /** 主站入口顺序(与桌面顶栏一致) */ @@ -42,6 +43,7 @@ const MobileSiteNavDropdown = ({ const location = useLocation(); const navigate = useNavigate(); const user = userState?.user; + const [statusState] = React.useContext(StatusContext); const byNavKey = useMemo( () => Object.fromEntries(mainNavLinks.map((l) => [l.itemKey, l])), @@ -59,17 +61,33 @@ const MobileSiteNavDropdown = ({ const applyEntries = useMemo(() => { const hideApplyLinks = isAdmin(); - const showSupplierApply = !hideApplyLinks && !userIsSupplierUser(user); - - if (!showSupplierApply) return []; - return [ - { - itemKey: 'supplier-apply', - text: t('提供算力'), - redirectPath: supplierApplyPath, - }, - ]; - }, [user, t]); + if (!hideApplyLinks && !userIsSupplierUser(user)) { + try { + const roleModulesRaw = statusState?.status?.SidebarModulesByRole; + if (roleModulesRaw) { + const roleConfig = JSON.parse(roleModulesRaw); + const userRole = String(user?.role ?? 0); + const config = roleConfig[userRole]; + if (config) { + const consoleSection = config.console; + if (consoleSection) { + if (consoleSection.enabled === false || consoleSection.supplierApply === false) { + return []; + } + } + } + } + } catch {} + return [ + { + itemKey: 'supplier-apply', + text: t('提供算力'), + redirectPath: supplierApplyPath, + }, + ]; + } + return []; + }, [user, t, statusState?.status?.SidebarModulesByRole]); const currentPageLabel = useMemo(() => { const p = location.pathname; diff --git a/web/src/hooks/common/useSidebar.js b/web/src/hooks/common/useSidebar.js index d21fcbf..ac430f1 100644 --- a/web/src/hooks/common/useSidebar.js +++ b/web/src/hooks/common/useSidebar.js @@ -1,4 +1,4 @@ -/* +/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify @@ -40,6 +40,7 @@ export const DEFAULT_SIDEBAR_CONFIG = { log: true, midjourney: true, task: true, + 'supplierApply': true, }, personal: { enabled: true, diff --git a/web/src/pages/Setting/Operation/SettingsSidebarModulesAdmin.jsx b/web/src/pages/Setting/Operation/SettingsSidebarModulesAdmin.jsx index 8dbfc07..7137fe5 100644 --- a/web/src/pages/Setting/Operation/SettingsSidebarModulesAdmin.jsx +++ b/web/src/pages/Setting/Operation/SettingsSidebarModulesAdmin.jsx @@ -1,4 +1,4 @@ -/* +/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify @@ -65,6 +65,7 @@ const sectionConfigs = [ desc_key: '绘图任务记录', }, { key: 'task', title_key: '任务日志', desc_key: '系统任务记录' }, + { key: 'supplierApply', title_key: '提供算力按钮', desc_key: '普通用户前端提供算力按钮显示权限' }, ], }, {