/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import React, { useState, useEffect, useContext } from 'react'; import { useTranslation } from 'react-i18next'; import { Card, Form, Button, Switch, Row, Col, Typography, RadioGroup, Radio, } from '@douyinfe/semi-ui'; import { API, showSuccess, showError } from '../../../helpers'; import { StatusContext } from '../../../context/Status'; import { USER_ROLES, USER_ROLE_NAMES } from '../../../constants/user.constants'; const { Text } = Typography; // 区域配置数据(不依赖组件 state/props,提取到外部避免 Temporal Dead Zone) const sectionConfigs = [ { key: 'chat', title_key: '聊天区域', desc_key: '操练场和聊天功能', modules: [ { key: 'playground', title_key: '操练场', desc_key: 'AI模型测试环境', }, { key: 'chat', title_key: '聊天', desc_key: '聊天会话管理' }, ], }, { key: 'console', title_key: '控制台区域', desc_key: '数据管理和日志查看', modules: [ { key: 'detail', title_key: '数据看板', desc_key: '系统数据统计' }, { key: 'token', title_key: '令牌管理', desc_key: 'API令牌管理' }, { key: 'log', title_key: '使用日志', desc_key: 'API使用记录' }, { key: 'midjourney', title_key: '绘图日志', desc_key: '绘图任务记录', }, { key: 'task', title_key: '任务日志', desc_key: '系统任务记录' }, ], }, { key: 'personal', title_key: '个人中心区域', desc_key: '用户个人功能', modules: [ { key: 'topup', title_key: '钱包管理', desc_key: '余额充值管理' }, { key: 'personal', title_key: '个人设置', desc_key: '个人信息设置', }, { key: 'supplier', title_key: '供应商', desc_key: '供应商申请', }, { key: 'supplier-apply', title_key: '供应商-申请', desc_key: '供应商申请', }, { key: 'supplier-channel', title_key: '供应商-渠道管理', desc_key: '供应商渠道管理', }, { key: 'supplier-pricing-settings', title_key: '供应商-定价设置', desc_key: '供应商定价设置', }, { key: 'supplier-dashboard', title_key: '供应商-数据看板', desc_key: '供应商数据看板', }, { key: 'distributor_center', title_key: '代理分销', desc_key: '代理邀请与收益', }, ], }, { key: 'admin', title_key: '管理员区域', desc_key: '系统管理功能', adminOnly: true, modules: [ { key: 'channel', title_key: '渠道管理', desc_key: 'API渠道配置' }, { key: 'models', title_key: '模型管理', desc_key: 'AI模型配置' }, { key: 'deployment', title_key: '模型部署', desc_key: '模型部署管理', }, { key: 'subscription', title_key: '订阅管理', desc_key: '订阅套餐管理', }, { key: 'redemption', title_key: '兑换码管理', desc_key: '兑换码生成管理', }, { key: 'user', title_key: '用户管理', desc_key: '用户账户管理' }, { key: 'operation-log', title_key: '操作记录', desc_key: '系统操作日志审计', }, { key: 'model-heat', title_key: '热度配置', desc_key: '模型热度排行配置', }, { key: 'distributor', title_key: '代理管理', desc_key: '代理申请与人员管理', }, { key: 'supplier-management', title_key: '供应商管理', desc_key: '供应商相关管理', }, { key: 'supplier-application-approval', title_key: '申请审批', desc_key: '供应商申请审批管理', }, { key: 'supplier-list', title_key: '供应商列表', desc_key: '管理所有供应商信息', }, { key: 'supplier-dashboard', title_key: '数据看板', desc_key: '查看供应商模型聚合统计', }, { key: 'setting', title_key: '系统设置', desc_key: '系统参数配置', }, ], }, ]; // 基于区域配置生成默认值(所有模块开启) const buildDefaultRoleConfig = () => { const config = {}; sectionConfigs.forEach((section) => { config[section.key] = { enabled: true }; section.modules.forEach((module) => { config[section.key][module.key] = true; }); }); return config; }; export default function SettingsSidebarModulesAdmin(props) { const { t } = useTranslation(); const [loading, setLoading] = useState(false); const [statusState, statusDispatch] = useContext(StatusContext); // 翻译 sectionConfigs 的 title/description const translatedSections = sectionConfigs.map((section) => ({ ...section, title: t(section.title_key), description: t(section.desc_key), modules: section.modules.map((module) => ({ ...module, title: t(module.title_key), description: t(module.desc_key), })), })); // 角色配置 const [roleModulesConfig, setRoleModulesConfig] = useState({ [USER_ROLES.USER]: buildDefaultRoleConfig(), [USER_ROLES.ADMIN]: buildDefaultRoleConfig(), [USER_ROLES.ROOT]: buildDefaultRoleConfig(), }); const [selectedRole, setSelectedRole] = useState(String(USER_ROLES.USER)); // 将已保存的角色配置与默认配置合并(确保新增模块自动出现) const mergeWithDefaults = (saved) => { const defaults = buildDefaultRoleConfig(); if (!saved || typeof saved !== 'object') return defaults; const merged = { ...defaults }; for (const [sectionKey, sectionConfig] of Object.entries(saved)) { if (!sectionConfig || typeof sectionConfig !== 'object') continue; merged[sectionKey] = { ...(merged[sectionKey] || {}), ...sectionConfig }; } return merged; }; // 加载角色配置 useEffect(() => { if (props.options && props.options.SidebarModulesByRole) { try { const config = JSON.parse(props.options.SidebarModulesByRole); setRoleModulesConfig({ [USER_ROLES.USER]: mergeWithDefaults(config[USER_ROLES.USER]), [USER_ROLES.ADMIN]: mergeWithDefaults(config[USER_ROLES.ADMIN]), [USER_ROLES.ROOT]: mergeWithDefaults(config[USER_ROLES.ROOT]), }); } catch (error) { // 使用默认值 } } }, [props.options]); // 当前选中角色 const currentRole = Number(selectedRole); const currentUserRoleConfig = roleModulesConfig[currentRole] || {}; // 是否为管理员/超级管理员角色 — 显示管理员区域 const showAdminSection = currentRole === USER_ROLES.ADMIN || currentRole === USER_ROLES.ROOT; // 处理角色模块开关变更 function handleRoleModuleChange(sectionKey, moduleKey) { return (checked) => { setRoleModulesConfig((prev) => ({ ...prev, [currentRole]: { ...(prev[currentRole] || {}), [sectionKey]: { ...(prev[currentRole]?.[sectionKey] || {}), [moduleKey]: checked, }, }, })); }; } // 重置当前角色配置为默认 function resetCurrentRoleConfig() { setRoleModulesConfig((prev) => ({ ...prev, [currentRole]: buildDefaultRoleConfig(), })); showSuccess(t('已重置角色配置')); } // 保存角色配置(唯一保存入口) async function onSubmit() { setLoading(true); try { const res = await API.put('/api/option/', { key: 'SidebarModulesByRole', value: JSON.stringify(roleModulesConfig), }); const { success, message } = res.data; if (success) { showSuccess(t('保存成功')); statusDispatch({ type: 'set', payload: { ...statusState.status, SidebarModulesByRole: JSON.stringify(roleModulesConfig), }, }); if (props.refresh) { await props.refresh(); } } else { showError(message); } } catch (error) { showError(t('保存失败,请重试')); } finally { setLoading(false); } } // 根据当前角色过滤需要显示的区域(普通用户不显示admin区域) const visibleSections = translatedSections.filter( (section) => !section.adminOnly || showAdminSection, ); return ( {/* 角色选择 */}
{t('选择角色')}: setSelectedRole(e.target.value)} > {USER_ROLE_NAMES[USER_ROLES.USER]} {USER_ROLE_NAMES[USER_ROLES.ADMIN]} {USER_ROLE_NAMES[USER_ROLES.ROOT]}
{/* 角色模块配置 */} {visibleSections.map((section) => (
{section.title}
{section.description}
{section.modules.map((module) => (
{module.title}
{module.description}
))}
))} {/* 操作按钮 */}
); }