| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import React, { useState, useEffect, useContext } from 'react'; |
| | import { useTranslation } from 'react-i18next'; |
| | import { |
| | Card, |
| | Form, |
| | Button, |
| | Switch, |
| | Row, |
| | Col, |
| | Typography, |
| | } from '@douyinfe/semi-ui'; |
| | import { API, showSuccess, showError } from '../../../helpers'; |
| | import { StatusContext } from '../../../context/Status'; |
| |
|
| | const { Text } = Typography; |
| |
|
| | export default function SettingsSidebarModulesAdmin(props) { |
| | const { t } = useTranslation(); |
| | const [loading, setLoading] = useState(false); |
| | const [statusState, statusDispatch] = useContext(StatusContext); |
| |
|
| | |
| | const [sidebarModulesAdmin, setSidebarModulesAdmin] = useState({ |
| | chat: { |
| | enabled: true, |
| | playground: true, |
| | chat: true, |
| | }, |
| | console: { |
| | enabled: true, |
| | detail: true, |
| | token: true, |
| | log: true, |
| | midjourney: true, |
| | task: true, |
| | }, |
| | personal: { |
| | enabled: true, |
| | topup: true, |
| | personal: true, |
| | }, |
| | admin: { |
| | enabled: true, |
| | channel: true, |
| | models: true, |
| | redemption: true, |
| | user: true, |
| | setting: true, |
| | }, |
| | }); |
| |
|
| | |
| | function handleSectionChange(sectionKey) { |
| | return (checked) => { |
| | const newModules = { |
| | ...sidebarModulesAdmin, |
| | [sectionKey]: { |
| | ...sidebarModulesAdmin[sectionKey], |
| | enabled: checked, |
| | }, |
| | }; |
| | setSidebarModulesAdmin(newModules); |
| | }; |
| | } |
| |
|
| | |
| | function handleModuleChange(sectionKey, moduleKey) { |
| | return (checked) => { |
| | const newModules = { |
| | ...sidebarModulesAdmin, |
| | [sectionKey]: { |
| | ...sidebarModulesAdmin[sectionKey], |
| | [moduleKey]: checked, |
| | }, |
| | }; |
| | setSidebarModulesAdmin(newModules); |
| | }; |
| | } |
| |
|
| | |
| | function resetSidebarModules() { |
| | const defaultModules = { |
| | chat: { |
| | enabled: true, |
| | playground: true, |
| | chat: true, |
| | }, |
| | console: { |
| | enabled: true, |
| | detail: true, |
| | token: true, |
| | log: true, |
| | midjourney: true, |
| | task: true, |
| | }, |
| | personal: { |
| | enabled: true, |
| | topup: true, |
| | personal: true, |
| | }, |
| | admin: { |
| | enabled: true, |
| | channel: true, |
| | models: true, |
| | redemption: true, |
| | user: true, |
| | setting: true, |
| | }, |
| | }; |
| | setSidebarModulesAdmin(defaultModules); |
| | showSuccess(t('已重置为默认配置')); |
| | } |
| |
|
| | |
| | async function onSubmit() { |
| | setLoading(true); |
| | try { |
| | const res = await API.put('/api/option/', { |
| | key: 'SidebarModulesAdmin', |
| | value: JSON.stringify(sidebarModulesAdmin), |
| | }); |
| | const { success, message } = res.data; |
| | if (success) { |
| | showSuccess(t('保存成功')); |
| |
|
| | |
| | statusDispatch({ |
| | type: 'set', |
| | payload: { |
| | ...statusState.status, |
| | SidebarModulesAdmin: JSON.stringify(sidebarModulesAdmin), |
| | }, |
| | }); |
| |
|
| | |
| | if (props.refresh) { |
| | await props.refresh(); |
| | } |
| | } else { |
| | showError(message); |
| | } |
| | } catch (error) { |
| | showError(t('保存失败,请重试')); |
| | } finally { |
| | setLoading(false); |
| | } |
| | } |
| |
|
| | useEffect(() => { |
| | |
| | if (props.options && props.options.SidebarModulesAdmin) { |
| | try { |
| | const modules = JSON.parse(props.options.SidebarModulesAdmin); |
| | setSidebarModulesAdmin(modules); |
| | } catch (error) { |
| | |
| | const defaultModules = { |
| | chat: { enabled: true, playground: true, chat: true }, |
| | console: { |
| | enabled: true, |
| | detail: true, |
| | token: true, |
| | log: true, |
| | midjourney: true, |
| | task: true, |
| | }, |
| | personal: { enabled: true, topup: true, personal: true }, |
| | admin: { |
| | enabled: true, |
| | channel: true, |
| | models: true, |
| | redemption: true, |
| | user: true, |
| | setting: true, |
| | }, |
| | }; |
| | setSidebarModulesAdmin(defaultModules); |
| | } |
| | } |
| | }, [props.options]); |
| |
|
| | |
| | const sectionConfigs = [ |
| | { |
| | key: 'chat', |
| | title: t('聊天区域'), |
| | description: t('操练场和聊天功能'), |
| | modules: [ |
| | { |
| | key: 'playground', |
| | title: t('操练场'), |
| | description: t('AI模型测试环境'), |
| | }, |
| | { key: 'chat', title: t('聊天'), description: t('聊天会话管理') }, |
| | ], |
| | }, |
| | { |
| | key: 'console', |
| | title: t('控制台区域'), |
| | description: t('数据管理和日志查看'), |
| | modules: [ |
| | { key: 'detail', title: t('数据看板'), description: t('系统数据统计') }, |
| | { key: 'token', title: t('令牌管理'), description: t('API令牌管理') }, |
| | { key: 'log', title: t('使用日志'), description: t('API使用记录') }, |
| | { |
| | key: 'midjourney', |
| | title: t('绘图日志'), |
| | description: t('绘图任务记录'), |
| | }, |
| | { key: 'task', title: t('任务日志'), description: t('系统任务记录') }, |
| | ], |
| | }, |
| | { |
| | key: 'personal', |
| | title: t('个人中心区域'), |
| | description: t('用户个人功能'), |
| | modules: [ |
| | { key: 'topup', title: t('钱包管理'), description: t('余额充值管理') }, |
| | { |
| | key: 'personal', |
| | title: t('个人设置'), |
| | description: t('个人信息设置'), |
| | }, |
| | ], |
| | }, |
| | { |
| | key: 'admin', |
| | title: t('管理员区域'), |
| | description: t('系统管理功能'), |
| | modules: [ |
| | { key: 'channel', title: t('渠道管理'), description: t('API渠道配置') }, |
| | { key: 'models', title: t('模型管理'), description: t('AI模型配置') }, |
| | { |
| | key: 'redemption', |
| | title: t('兑换码管理'), |
| | description: t('兑换码生成管理'), |
| | }, |
| | { key: 'user', title: t('用户管理'), description: t('用户账户管理') }, |
| | { |
| | key: 'setting', |
| | title: t('系统设置'), |
| | description: t('系统参数配置'), |
| | }, |
| | ], |
| | }, |
| | ]; |
| |
|
| | return ( |
| | <Card> |
| | <Form.Section |
| | text={t('侧边栏管理(全局控制)')} |
| | extraText={t( |
| | '全局控制侧边栏区域和功能显示,管理员隐藏的功能用户无法启用', |
| | )} |
| | > |
| | {sectionConfigs.map((section) => ( |
| | <div key={section.key} style={{ marginBottom: '32px' }}> |
| | {/* 区域标题和总开关 */} |
| | <div |
| | style={{ |
| | display: 'flex', |
| | justifyContent: 'space-between', |
| | alignItems: 'center', |
| | marginBottom: '16px', |
| | padding: '12px 16px', |
| | backgroundColor: 'var(--semi-color-fill-0)', |
| | borderRadius: '8px', |
| | border: '1px solid var(--semi-color-border)', |
| | }} |
| | > |
| | <div> |
| | <div |
| | style={{ |
| | fontWeight: '600', |
| | fontSize: '16px', |
| | color: 'var(--semi-color-text-0)', |
| | marginBottom: '4px', |
| | }} |
| | > |
| | {section.title} |
| | </div> |
| | <Text |
| | type='secondary' |
| | size='small' |
| | style={{ |
| | fontSize: '12px', |
| | color: 'var(--semi-color-text-2)', |
| | lineHeight: '1.4', |
| | }} |
| | > |
| | {section.description} |
| | </Text> |
| | </div> |
| | <Switch |
| | checked={sidebarModulesAdmin[section.key]?.enabled} |
| | onChange={handleSectionChange(section.key)} |
| | size='default' |
| | /> |
| | </div> |
| | |
| | {/* 功能模块网格 */} |
| | <Row gutter={[16, 16]}> |
| | {section.modules.map((module) => ( |
| | <Col key={module.key} xs={24} sm={12} md={8} lg={6} xl={6}> |
| | <Card |
| | bodyStyle={{ padding: '16px' }} |
| | hoverable |
| | style={{ |
| | opacity: sidebarModulesAdmin[section.key]?.enabled |
| | ? 1 |
| | : 0.5, |
| | transition: 'opacity 0.2s', |
| | }} |
| | > |
| | <div |
| | style={{ |
| | display: 'flex', |
| | justifyContent: 'space-between', |
| | alignItems: 'center', |
| | height: '100%', |
| | }} |
| | > |
| | <div style={{ flex: 1, textAlign: 'left' }}> |
| | <div |
| | style={{ |
| | fontWeight: '600', |
| | fontSize: '14px', |
| | color: 'var(--semi-color-text-0)', |
| | marginBottom: '4px', |
| | }} |
| | > |
| | {module.title} |
| | </div> |
| | <Text |
| | type='secondary' |
| | size='small' |
| | style={{ |
| | fontSize: '12px', |
| | color: 'var(--semi-color-text-2)', |
| | lineHeight: '1.4', |
| | display: 'block', |
| | }} |
| | > |
| | {module.description} |
| | </Text> |
| | </div> |
| | <div style={{ marginLeft: '16px' }}> |
| | <Switch |
| | checked={ |
| | sidebarModulesAdmin[section.key]?.[module.key] |
| | } |
| | onChange={handleModuleChange(section.key, module.key)} |
| | size='default' |
| | disabled={!sidebarModulesAdmin[section.key]?.enabled} |
| | /> |
| | </div> |
| | </div> |
| | </Card> |
| | </Col> |
| | ))} |
| | </Row> |
| | </div> |
| | ))} |
| | |
| | <div |
| | style={{ |
| | display: 'flex', |
| | gap: '12px', |
| | justifyContent: 'flex-start', |
| | alignItems: 'center', |
| | paddingTop: '8px', |
| | borderTop: '1px solid var(--semi-color-border)', |
| | }} |
| | > |
| | <Button |
| | size='default' |
| | type='tertiary' |
| | onClick={resetSidebarModules} |
| | style={{ |
| | borderRadius: '6px', |
| | fontWeight: '500', |
| | }} |
| | > |
| | {t('重置为默认')} |
| | </Button> |
| | <Button |
| | size='default' |
| | type='primary' |
| | onClick={onSubmit} |
| | loading={loading} |
| | style={{ |
| | borderRadius: '6px', |
| | fontWeight: '500', |
| | minWidth: '100px', |
| | }} |
| | > |
| | {t('保存设置')} |
| | </Button> |
| | </div> |
| | </Form.Section> |
| | </Card> |
| | ); |
| | } |
| |
|