Files
new-api-oiss/web/src/pages/Setting/Operation/SettingsHeaderNavModules.jsx
F。 d0d6168e2f 顶栏和侧边栏管理
增加用户体验
2025-08-31 07:07:40 +08:00

327 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
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 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 <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import React, { useEffect, useState, useContext } from 'react';
import { Button, Card, Col, Form, Row, Switch, Typography } from '@douyinfe/semi-ui';
import { API, showError, showSuccess } from '../../../helpers';
import { useTranslation } from 'react-i18next';
import { StatusContext } from '../../../context/Status';
const { Text } = Typography;
export default function SettingsHeaderNavModules(props) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [statusState, statusDispatch] = useContext(StatusContext);
// 顶栏模块管理状态
const [headerNavModules, setHeaderNavModules] = useState({
home: true,
console: true,
pricing: {
enabled: true,
requireAuth: false // 默认不需要登录鉴权
},
docs: true,
about: true,
});
// 处理顶栏模块配置变更
function handleHeaderNavModuleChange(moduleKey) {
return (checked) => {
const newModules = { ...headerNavModules };
if (moduleKey === 'pricing') {
// 对于pricing模块只更新enabled属性
newModules[moduleKey] = {
...newModules[moduleKey],
enabled: checked
};
} else {
newModules[moduleKey] = checked;
}
setHeaderNavModules(newModules);
};
}
// 处理模型广场权限控制变更
function handlePricingAuthChange(checked) {
const newModules = { ...headerNavModules };
newModules.pricing = {
...newModules.pricing,
requireAuth: checked
};
setHeaderNavModules(newModules);
}
// 重置顶栏模块为默认配置
function resetHeaderNavModules() {
const defaultModules = {
home: true,
console: true,
pricing: {
enabled: true,
requireAuth: false
},
docs: true,
about: true,
};
setHeaderNavModules(defaultModules);
showSuccess(t('已重置为默认配置'));
}
// 保存配置
async function onSubmit() {
setLoading(true);
try {
const res = await API.put('/api/option/', {
key: 'HeaderNavModules',
value: JSON.stringify(headerNavModules),
});
const { success, message } = res.data;
if (success) {
showSuccess(t('保存成功'));
// 立即更新StatusContext中的状态
statusDispatch({
type: 'set',
payload: {
...statusState.status,
HeaderNavModules: JSON.stringify(headerNavModules)
}
});
// 刷新父组件状态
if (props.refresh) {
await props.refresh();
}
} else {
showError(message);
}
} catch (error) {
showError(t('保存失败,请重试'));
} finally {
setLoading(false);
}
}
useEffect(() => {
// 从 props.options 中获取配置
if (props.options && props.options.HeaderNavModules) {
try {
const modules = JSON.parse(props.options.HeaderNavModules);
// 处理向后兼容性如果pricing是boolean转换为对象格式
if (typeof modules.pricing === 'boolean') {
modules.pricing = {
enabled: modules.pricing,
requireAuth: false // 默认不需要登录鉴权
};
}
setHeaderNavModules(modules);
} catch (error) {
// 使用默认配置
const defaultModules = {
home: true,
console: true,
pricing: {
enabled: true,
requireAuth: false
},
docs: true,
about: true,
};
setHeaderNavModules(defaultModules);
}
}
}, [props.options]);
// 模块配置数据
const moduleConfigs = [
{
key: 'home',
title: t('首页'),
description: t('用户主页,展示系统信息')
},
{
key: 'console',
title: t('控制台'),
description: t('用户控制面板,管理账户')
},
{
key: 'pricing',
title: t('模型广场'),
description: t('模型定价,需要登录访问'),
hasSubConfig: true // 标识该模块有子配置
},
{
key: 'docs',
title: t('文档'),
description: t('系统文档和帮助信息')
},
{
key: 'about',
title: t('关于'),
description: t('关于系统的详细信息')
}
];
return (
<Card>
<Form.Section text={t('顶栏管理')} extraText={t('控制顶栏模块显示状态,全局生效')}>
<Row gutter={[16, 16]} style={{ marginBottom: '24px' }}>
{moduleConfigs.map((module) => (
<Col key={module.key} xs={24} sm={12} md={6} lg={6} xl={6}>
<Card
style={{
borderRadius: '8px',
border: '1px solid var(--semi-color-border)',
transition: 'all 0.2s ease',
background: 'var(--semi-color-bg-1)',
minHeight: '80px'
}}
bodyStyle={{ padding: '16px' }}
hoverable
>
<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={module.key === 'pricing' ? headerNavModules[module.key]?.enabled : headerNavModules[module.key]}
onChange={handleHeaderNavModuleChange(module.key)}
size="default"
/>
</div>
</div>
{/* 为模型广场添加权限控制子开关 */}
{module.key === 'pricing' && (module.key === 'pricing' ? headerNavModules[module.key]?.enabled : headerNavModules[module.key]) && (
<div style={{
borderTop: '1px solid var(--semi-color-border)',
marginTop: '12px',
paddingTop: '12px'
}}>
<div style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}>
<div style={{ flex: 1, textAlign: 'left' }}>
<div style={{
fontWeight: '500',
fontSize: '12px',
color: 'var(--semi-color-text-1)',
marginBottom: '2px'
}}>
{t('需要登录访问')}
</div>
<Text
type="secondary"
size="small"
style={{
fontSize: '11px',
color: 'var(--semi-color-text-2)',
lineHeight: '1.4',
display: 'block'
}}
>
{t('开启后未登录用户无法访问模型广场')}
</Text>
</div>
<div style={{ marginLeft: '16px' }}>
<Switch
checked={headerNavModules.pricing?.requireAuth || false}
onChange={handlePricingAuthChange}
size="small"
/>
</div>
</div>
</div>
)}
</Card>
</Col>
))}
</Row>
<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={resetHeaderNavModules}
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>
);
}