142 lines
5.1 KiB
JavaScript
142 lines
5.1 KiB
JavaScript
import React, { useEffect, useMemo, useState } from 'react';
|
|
import { Button, Input, InputNumber, Space, Switch, Table, Tag, Typography, message } from 'antd';
|
|
import { ReloadOutlined, SaveOutlined, UndoOutlined } from '@ant-design/icons';
|
|
import { SycmCard } from '../../components/Common';
|
|
import { getSystemConfig, updateSystemConfig } from '../../api/admin';
|
|
import { DEFAULT_SIDEBAR_CONFIG, parseSidebarConfig } from '../../config/sidebarNavigation';
|
|
|
|
const { Text } = Typography;
|
|
|
|
const clone = (value) => JSON.parse(JSON.stringify(value));
|
|
|
|
const SidebarSettings = () => {
|
|
const [config, setConfig] = useState(() => clone(DEFAULT_SIDEBAR_CONFIG));
|
|
const [loading, setLoading] = useState(false);
|
|
const [saving, setSaving] = useState(false);
|
|
|
|
const loadConfig = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const result = await getSystemConfig();
|
|
setConfig(parseSidebarConfig(result?.sidebar_navigation));
|
|
} catch (error) {
|
|
message.error(error.response?.data?.error || '加载侧边栏设置失败');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
loadConfig();
|
|
}, []);
|
|
|
|
const rows = useMemo(() => config.entries.flatMap((entry) => [
|
|
{ ...entry, rowKey: entry.key, depth: 0 },
|
|
...(entry.children || []).map((child) => ({ ...child, rowKey: `${entry.key}:${child.key}`, parentKey: entry.key, depth: 1, type: 'item' })),
|
|
]), [config.entries]);
|
|
|
|
const updateRow = (record, patch) => {
|
|
setConfig((current) => ({
|
|
...current,
|
|
entries: current.entries.map((entry) => {
|
|
if (!record.parentKey) return entry.key === record.key ? { ...entry, ...patch } : entry;
|
|
if (entry.key !== record.parentKey) return entry;
|
|
return {
|
|
...entry,
|
|
children: (entry.children || []).map((child) => child.key === record.key ? { ...child, ...patch } : child),
|
|
};
|
|
}),
|
|
}));
|
|
};
|
|
|
|
const handleSave = async () => {
|
|
try {
|
|
setSaving(true);
|
|
await updateSystemConfig({ sidebar_navigation: JSON.stringify(config) });
|
|
message.success('侧边栏设置已保存,刷新页面后生效');
|
|
} catch (error) {
|
|
message.error(error.response?.data?.error || '保存侧边栏设置失败');
|
|
} finally {
|
|
setSaving(false);
|
|
}
|
|
};
|
|
|
|
const columns = [
|
|
{
|
|
title: '菜单名称',
|
|
dataIndex: 'label',
|
|
width: 280,
|
|
render: (value, record) => (
|
|
<div style={{ paddingLeft: record.depth ? 24 : 0 }}>
|
|
<Input value={value} onChange={(event) => updateRow(record, { label: event.target.value })} />
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
title: '类型',
|
|
dataIndex: 'type',
|
|
width: 110,
|
|
render: (value, record) => <Tag>{record.depth ? '子菜单' : value === 'group' ? '分组' : value === 'section' ? '分隔标题' : '菜单'}</Tag>,
|
|
},
|
|
{
|
|
title: '标识',
|
|
dataIndex: 'key',
|
|
width: 170,
|
|
render: (value) => <Text code>{value}</Text>,
|
|
},
|
|
{
|
|
title: '顺序',
|
|
dataIndex: 'order',
|
|
width: 110,
|
|
render: (value, record) => <InputNumber min={0} max={999} value={value} onChange={(next) => updateRow(record, { order: next ?? 0 })} />,
|
|
},
|
|
{
|
|
title: '显示',
|
|
dataIndex: 'visible',
|
|
width: 90,
|
|
render: (value, record) => <Switch checked={value !== false} onChange={(checked) => updateRow(record, { visible: checked })} />,
|
|
},
|
|
{
|
|
title: '默认展开',
|
|
dataIndex: 'defaultExpanded',
|
|
width: 110,
|
|
render: (value, record) => record.type === 'group'
|
|
? <Switch checked={Boolean(value)} onChange={(checked) => updateRow(record, { defaultExpanded: checked })} />
|
|
: '-',
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div className="settings-tab-page">
|
|
<SycmCard bodyStyle={{ padding: 16 }}>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 16, marginBottom: 16, flexWrap: 'wrap' }}>
|
|
<Space wrap>
|
|
<Text strong>侧栏默认状态</Text>
|
|
<Switch
|
|
checked={!config.collapsedByDefault}
|
|
checkedChildren="展开"
|
|
unCheckedChildren="收起"
|
|
onChange={(expanded) => setConfig((current) => ({ ...current, collapsedByDefault: !expanded }))}
|
|
/>
|
|
<Text strong style={{ marginLeft: 12 }}>默认暗黑模式</Text>
|
|
<Switch
|
|
checked={Boolean(config.darkModeByDefault)}
|
|
checkedChildren="开启"
|
|
unCheckedChildren="关闭"
|
|
onChange={(checked) => setConfig((current) => ({ ...current, darkModeByDefault: checked }))}
|
|
/>
|
|
</Space>
|
|
<Space wrap>
|
|
<Button icon={<ReloadOutlined />} onClick={loadConfig} loading={loading}>刷新</Button>
|
|
<Button icon={<UndoOutlined />} onClick={() => setConfig(clone(DEFAULT_SIDEBAR_CONFIG))}>恢复默认</Button>
|
|
<Button type="primary" icon={<SaveOutlined />} onClick={handleSave} loading={saving}>保存设置</Button>
|
|
</Space>
|
|
</div>
|
|
<Table rowKey="rowKey" columns={columns} dataSource={rows} loading={loading} pagination={false} scroll={{ x: 960 }} />
|
|
</SycmCard>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SidebarSettings;
|